1 /* 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 #ifndef ART_COMPILER_UTILS_ARENA_ALLOCATOR_H_ 18 #define ART_COMPILER_UTILS_ARENA_ALLOCATOR_H_ 19 20 #include <stdint.h> 21 #include <stddef.h> 22 23 #include "base/macros.h" 24 #include "base/mutex.h" 25 #include "mem_map.h" 26 #include "utils.h" 27 #include "utils/debug_stack.h" 28 29 namespace art { 30 31 class Arena; 32 class ArenaPool; 33 class ArenaAllocator; 34 class ArenaStack; 35 class ScopedArenaAllocator; 36 class MemStats; 37 38 template <typename T> 39 class ArenaAllocatorAdapter; 40 41 static constexpr bool kArenaAllocatorCountAllocations = false; 42 43 // Type of allocation for memory tuning. 44 enum ArenaAllocKind { 45 kArenaAllocMisc, 46 kArenaAllocBB, 47 kArenaAllocLIR, 48 kArenaAllocLIRResourceMask, 49 kArenaAllocMIR, 50 kArenaAllocDFInfo, 51 kArenaAllocGrowableArray, 52 kArenaAllocGrowableBitMap, 53 kArenaAllocDalvikToSSAMap, 54 kArenaAllocDebugInfo, 55 kArenaAllocSuccessor, 56 kArenaAllocRegAlloc, 57 kArenaAllocData, 58 kArenaAllocPredecessors, 59 kArenaAllocSTL, 60 kNumArenaAllocKinds 61 }; 62 63 template <bool kCount> 64 class ArenaAllocatorStatsImpl; 65 66 template <> 67 class ArenaAllocatorStatsImpl<false> { 68 public: 69 ArenaAllocatorStatsImpl() = default; 70 ArenaAllocatorStatsImpl(const ArenaAllocatorStatsImpl& other) = default; 71 ArenaAllocatorStatsImpl& operator = (const ArenaAllocatorStatsImpl& other) = delete; 72 Copy(const ArenaAllocatorStatsImpl & other)73 void Copy(const ArenaAllocatorStatsImpl& other) { UNUSED(other); } RecordAlloc(size_t bytes,ArenaAllocKind kind)74 void RecordAlloc(size_t bytes, ArenaAllocKind kind) { UNUSED(bytes); UNUSED(kind); } NumAllocations()75 size_t NumAllocations() const { return 0u; } BytesAllocated()76 size_t BytesAllocated() const { return 0u; } Dump(std::ostream & os,const Arena * first,ssize_t lost_bytes_adjustment)77 void Dump(std::ostream& os, const Arena* first, ssize_t lost_bytes_adjustment) const { 78 UNUSED(os); UNUSED(first); UNUSED(lost_bytes_adjustment); 79 } 80 }; 81 82 template <bool kCount> 83 class ArenaAllocatorStatsImpl { 84 public: 85 ArenaAllocatorStatsImpl(); 86 ArenaAllocatorStatsImpl(const ArenaAllocatorStatsImpl& other) = default; 87 ArenaAllocatorStatsImpl& operator = (const ArenaAllocatorStatsImpl& other) = delete; 88 89 void Copy(const ArenaAllocatorStatsImpl& other); 90 void RecordAlloc(size_t bytes, ArenaAllocKind kind); 91 size_t NumAllocations() const; 92 size_t BytesAllocated() const; 93 void Dump(std::ostream& os, const Arena* first, ssize_t lost_bytes_adjustment) const; 94 95 private: 96 size_t num_allocations_; 97 // TODO: Use std::array<size_t, kNumArenaAllocKinds> from C++11 when we upgrade the STL. 98 size_t alloc_stats_[kNumArenaAllocKinds]; // Bytes used by various allocation kinds. 99 100 static const char* const kAllocNames[]; 101 }; 102 103 typedef ArenaAllocatorStatsImpl<kArenaAllocatorCountAllocations> ArenaAllocatorStats; 104 105 class Arena { 106 public: 107 static constexpr size_t kDefaultSize = 128 * KB; 108 explicit Arena(size_t size = kDefaultSize); 109 ~Arena(); 110 void Reset(); Begin()111 uint8_t* Begin() { 112 return memory_; 113 } 114 End()115 uint8_t* End() { 116 return memory_ + size_; 117 } 118 Size()119 size_t Size() const { 120 return size_; 121 } 122 RemainingSpace()123 size_t RemainingSpace() const { 124 return Size() - bytes_allocated_; 125 } 126 127 private: 128 size_t bytes_allocated_; 129 uint8_t* memory_; 130 size_t size_; 131 MemMap* map_; 132 Arena* next_; 133 friend class ArenaPool; 134 friend class ArenaAllocator; 135 friend class ArenaStack; 136 friend class ScopedArenaAllocator; 137 template <bool kCount> friend class ArenaAllocatorStatsImpl; 138 DISALLOW_COPY_AND_ASSIGN(Arena); 139 }; 140 141 class ArenaPool { 142 public: 143 ArenaPool(); 144 ~ArenaPool(); 145 Arena* AllocArena(size_t size); 146 void FreeArenaChain(Arena* first); 147 148 private: 149 Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; 150 Arena* free_arenas_ GUARDED_BY(lock_); 151 DISALLOW_COPY_AND_ASSIGN(ArenaPool); 152 }; 153 154 class ArenaAllocator : private DebugStackRefCounter, private ArenaAllocatorStats { 155 public: 156 explicit ArenaAllocator(ArenaPool* pool); 157 ~ArenaAllocator(); 158 159 // Get adapter for use in STL containers. See arena_containers.h . 160 ArenaAllocatorAdapter<void> Adapter(ArenaAllocKind kind = kArenaAllocSTL); 161 162 // Returns zeroed memory. Alloc(size_t bytes,ArenaAllocKind kind)163 void* Alloc(size_t bytes, ArenaAllocKind kind) ALWAYS_INLINE { 164 if (UNLIKELY(running_on_valgrind_)) { 165 return AllocValgrind(bytes, kind); 166 } 167 bytes = RoundUp(bytes, 8); 168 if (UNLIKELY(ptr_ + bytes > end_)) { 169 // Obtain a new block. 170 ObtainNewArenaForAllocation(bytes); 171 if (UNLIKELY(ptr_ == nullptr)) { 172 return nullptr; 173 } 174 } 175 ArenaAllocatorStats::RecordAlloc(bytes, kind); 176 uint8_t* ret = ptr_; 177 ptr_ += bytes; 178 return ret; 179 } 180 AllocArray(size_t length)181 template <typename T> T* AllocArray(size_t length) { 182 return static_cast<T*>(Alloc(length * sizeof(T), kArenaAllocMisc)); 183 } 184 185 void* AllocValgrind(size_t bytes, ArenaAllocKind kind); 186 void ObtainNewArenaForAllocation(size_t allocation_size); 187 size_t BytesAllocated() const; 188 MemStats GetMemStats() const; 189 190 private: 191 void UpdateBytesAllocated(); 192 193 ArenaPool* pool_; 194 uint8_t* begin_; 195 uint8_t* end_; 196 uint8_t* ptr_; 197 Arena* arena_head_; 198 bool running_on_valgrind_; 199 200 template <typename U> 201 friend class ArenaAllocatorAdapter; 202 203 DISALLOW_COPY_AND_ASSIGN(ArenaAllocator); 204 }; // ArenaAllocator 205 206 class MemStats { 207 public: 208 MemStats(const char* name, const ArenaAllocatorStats* stats, const Arena* first_arena, 209 ssize_t lost_bytes_adjustment = 0); 210 void Dump(std::ostream& os) const; 211 212 private: 213 const char* const name_; 214 const ArenaAllocatorStats* const stats_; 215 const Arena* const first_arena_; 216 const ssize_t lost_bytes_adjustment_; 217 }; // MemStats 218 219 } // namespace art 220 221 #endif // ART_COMPILER_UTILS_ARENA_ALLOCATOR_H_ 222