• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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