blob: 36393e73877ee79c60036a1ff0ae637e5fb53270 [file] [log] [blame]
buzbee862a7602013-04-05 10:58:54 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "compiler_internals.h"
18#include "dex_file-inl.h"
19#include "arena_allocator.h"
20#include "base/logging.h"
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -070021#include "base/mutex.h"
buzbee862a7602013-04-05 10:58:54 -070022
23namespace art {
24
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -070025// Memmap is a bit slower than malloc according to my measurements.
26static constexpr bool kUseMemMap = false;
27static constexpr bool kUseMemSet = true && kUseMemMap;
28
buzbee862a7602013-04-05 10:58:54 -070029static const char* alloc_names[ArenaAllocator::kNumAllocKinds] = {
30 "Misc ",
31 "BasicBlock ",
32 "LIR ",
33 "MIR ",
34 "DataFlow ",
35 "GrowList ",
36 "GrowBitMap ",
37 "Dalvik2SSA ",
38 "DebugInfo ",
39 "Successor ",
40 "RegAlloc ",
41 "Data ",
42 "Preds ",
43};
44
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -070045Arena::Arena(size_t size)
46 : bytes_allocated_(0),
47 map_(nullptr),
48 next_(nullptr) {
49 if (kUseMemMap) {
50 map_ = MemMap::MapAnonymous("dalvik-arena", NULL, size, PROT_READ | PROT_WRITE);
51 memory_ = map_->Begin();
52 size_ = map_->Size();
53 } else {
54 memory_ = reinterpret_cast<uint8_t*>(calloc(1, size));
55 size_ = size;
Ian Rogerse7a5b7d2013-04-18 20:09:02 -070056 }
Ian Rogerse7a5b7d2013-04-18 20:09:02 -070057}
58
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -070059Arena::~Arena() {
60 if (kUseMemMap) {
61 delete map_;
62 } else {
63 free(reinterpret_cast<void*>(memory_));
64 }
buzbee862a7602013-04-05 10:58:54 -070065}
66
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -070067void Arena::Reset() {
68 if (bytes_allocated_) {
69 if (kUseMemSet || !kUseMemMap) {
70 memset(Begin(), 0, bytes_allocated_);
buzbeea5abf702013-04-12 14:39:29 -070071 } else {
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -070072 madvise(Begin(), bytes_allocated_, MADV_DONTNEED);
buzbeea5abf702013-04-12 14:39:29 -070073 }
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -070074 bytes_allocated_ = 0;
buzbee862a7602013-04-05 10:58:54 -070075 }
buzbee862a7602013-04-05 10:58:54 -070076}
77
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -070078ArenaPool::ArenaPool()
79 : lock_("Arena pool lock"),
80 free_arenas_(nullptr) {
81}
82
83ArenaPool::~ArenaPool() {
84 while (free_arenas_ != nullptr) {
85 auto* arena = free_arenas_;
86 free_arenas_ = free_arenas_->next_;
87 delete arena;
88 }
89}
90
91Arena* ArenaPool::AllocArena(size_t size) {
92 Thread* self = Thread::Current();
93 Arena* ret = nullptr;
94 {
95 MutexLock lock(self, lock_);
96 if (free_arenas_ != nullptr && LIKELY(free_arenas_->Size() >= size)) {
97 ret = free_arenas_;
98 free_arenas_ = free_arenas_->next_;
99 }
100 }
101 if (ret == nullptr) {
102 ret = new Arena(size);
103 }
104 ret->Reset();
105 return ret;
106}
107
108void ArenaPool::FreeArena(Arena* arena) {
109 Thread* self = Thread::Current();
110 {
111 MutexLock lock(self, lock_);
112 arena->next_ = free_arenas_;
113 free_arenas_ = arena;
114 }
115}
116
117size_t ArenaAllocator::BytesAllocated() const {
buzbee862a7602013-04-05 10:58:54 -0700118 size_t total = 0;
119 for (int i = 0; i < kNumAllocKinds; i++) {
120 total += alloc_stats_[i];
121 }
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700122 return total;
123}
124
125ArenaAllocator::ArenaAllocator(ArenaPool* pool)
126 : pool_(pool),
127 begin_(nullptr),
128 end_(nullptr),
129 ptr_(nullptr),
130 arena_head_(nullptr),
131 num_allocations_(0) {
132 memset(&alloc_stats_[0], 0, sizeof(alloc_stats_));
133}
134
135void ArenaAllocator::UpdateBytesAllocated() {
136 if (arena_head_ != nullptr) {
137 // Update how many bytes we have allocated into the arena so that the arena pool knows how
138 // much memory to zero out.
139 arena_head_->bytes_allocated_ = ptr_ - begin_;
140 }
141}
142
143ArenaAllocator::~ArenaAllocator() {
144 // Reclaim all the arenas by giving them back to the thread pool.
145 UpdateBytesAllocated();
146 while (arena_head_ != nullptr) {
147 Arena* arena = arena_head_;
148 arena_head_ = arena_head_->next_;
149 pool_->FreeArena(arena);
150 }
151}
152
153void ArenaAllocator::ObtainNewArenaForAllocation(size_t allocation_size) {
154 UpdateBytesAllocated();
155 Arena* new_arena = pool_->AllocArena(std::max(Arena::kDefaultSize, allocation_size));
156 new_arena->next_ = arena_head_;
157 arena_head_ = new_arena;
158 // Update our internal data structures.
159 ptr_ = begin_ = new_arena->Begin();
160 end_ = new_arena->End();
161}
162
163// Dump memory usage stats.
164void ArenaAllocator::DumpMemStats(std::ostream& os) const {
165 size_t malloc_bytes = 0;
166 // Start out with how many lost bytes we have in the arena we are currently allocating into.
167 size_t lost_bytes(end_ - ptr_);
168 size_t num_arenas = 0;
169 for (Arena* arena = arena_head_; arena != nullptr; arena = arena->next_) {
170 malloc_bytes += arena->Size();
171 if (arena != arena_head_) {
172 lost_bytes += arena->RemainingSpace();
173 }
174 ++num_arenas;
175 }
176 const size_t bytes_allocated = BytesAllocated();
177 os << " MEM: used: " << bytes_allocated << ", allocated: " << malloc_bytes
178 << ", lost: " << lost_bytes << "\n";
179 if (num_allocations_ != 0) {
180 os << "Number of arenas allocated: " << num_arenas << ", Number of allocations: "
181 << num_allocations_ << ", avg size: " << bytes_allocated / num_allocations_ << "\n";
182 }
buzbee862a7602013-04-05 10:58:54 -0700183 os << "===== Allocation by kind\n";
184 for (int i = 0; i < kNumAllocKinds; i++) {
185 os << alloc_names[i] << std::setw(10) << alloc_stats_[i] << "\n";
186 }
187}
188
189} // namespace art