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 GetBytesAllocated()127 size_t GetBytesAllocated() const { 128 return bytes_allocated_; 129 } 130 131 private: 132 size_t bytes_allocated_; 133 uint8_t* memory_; 134 size_t size_; 135 MemMap* map_; 136 Arena* next_; 137 friend class ArenaPool; 138 friend class ArenaAllocator; 139 friend class ArenaStack; 140 friend class ScopedArenaAllocator; 141 template <bool kCount> friend class ArenaAllocatorStatsImpl; 142 DISALLOW_COPY_AND_ASSIGN(Arena); 143 }; 144 145 class ArenaPool { 146 public: 147 ArenaPool(); 148 ~ArenaPool(); 149 Arena* AllocArena(size_t size) LOCKS_EXCLUDED(lock_); 150 void FreeArenaChain(Arena* first) LOCKS_EXCLUDED(lock_); 151 size_t GetBytesAllocated() const LOCKS_EXCLUDED(lock_); 152 153 private: 154 mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER; 155 Arena* free_arenas_ GUARDED_BY(lock_); 156 DISALLOW_COPY_AND_ASSIGN(ArenaPool); 157 }; 158 159 class ArenaAllocator : private DebugStackRefCounter, private ArenaAllocatorStats { 160 public: 161 explicit ArenaAllocator(ArenaPool* pool); 162 ~ArenaAllocator(); 163 164 // Get adapter for use in STL containers. See arena_containers.h . 165 ArenaAllocatorAdapter<void> Adapter(ArenaAllocKind kind = kArenaAllocSTL); 166 167 // Returns zeroed memory. Alloc(size_t bytes,ArenaAllocKind kind)168 void* Alloc(size_t bytes, ArenaAllocKind kind) ALWAYS_INLINE { 169 if (UNLIKELY(running_on_valgrind_)) { 170 return AllocValgrind(bytes, kind); 171 } 172 bytes = RoundUp(bytes, 8); 173 if (UNLIKELY(ptr_ + bytes > end_)) { 174 // Obtain a new block. 175 ObtainNewArenaForAllocation(bytes); 176 if (UNLIKELY(ptr_ == nullptr)) { 177 return nullptr; 178 } 179 } 180 ArenaAllocatorStats::RecordAlloc(bytes, kind); 181 uint8_t* ret = ptr_; 182 ptr_ += bytes; 183 return ret; 184 } 185 AllocArray(size_t length)186 template <typename T> T* AllocArray(size_t length) { 187 return static_cast<T*>(Alloc(length * sizeof(T), kArenaAllocMisc)); 188 } 189 190 void* AllocValgrind(size_t bytes, ArenaAllocKind kind); 191 void ObtainNewArenaForAllocation(size_t allocation_size); 192 size_t BytesAllocated() const; 193 MemStats GetMemStats() const; 194 195 private: 196 void UpdateBytesAllocated(); 197 198 ArenaPool* pool_; 199 uint8_t* begin_; 200 uint8_t* end_; 201 uint8_t* ptr_; 202 Arena* arena_head_; 203 bool running_on_valgrind_; 204 205 template <typename U> 206 friend class ArenaAllocatorAdapter; 207 208 DISALLOW_COPY_AND_ASSIGN(ArenaAllocator); 209 }; // ArenaAllocator 210 211 class MemStats { 212 public: 213 MemStats(const char* name, const ArenaAllocatorStats* stats, const Arena* first_arena, 214 ssize_t lost_bytes_adjustment = 0); 215 void Dump(std::ostream& os) const; 216 217 private: 218 const char* const name_; 219 const ArenaAllocatorStats* const stats_; 220 const Arena* const first_arena_; 221 const ssize_t lost_bytes_adjustment_; 222 }; // MemStats 223 224 } // namespace art 225 226 #endif // ART_COMPILER_UTILS_ARENA_ALLOCATOR_H_ 227