blob: 7f5bc9ac4cd42bb05d8952151200ca961e3f14ff [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
Nicolas Geoffray818f2102014-02-18 16:43:35 +000017#ifndef ART_COMPILER_UTILS_ARENA_ALLOCATOR_H_
18#define ART_COMPILER_UTILS_ARENA_ALLOCATOR_H_
buzbee862a7602013-04-05 10:58:54 -070019
20#include <stdint.h>
21#include <stddef.h>
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -070022
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000023#include "base/macros.h"
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -070024#include "base/mutex.h"
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -070025#include "mem_map.h"
Andreas Gampe66018822014-05-05 20:47:19 -070026#include "utils.h"
Vladimir Marko8081d2b2014-07-31 15:33:43 +010027#include "utils/debug_stack.h"
buzbee862a7602013-04-05 10:58:54 -070028
29namespace art {
30
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -070031class Arena;
32class ArenaPool;
33class ArenaAllocator;
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000034class ArenaStack;
35class ScopedArenaAllocator;
36class MemStats;
37
Vladimir Marko8081d2b2014-07-31 15:33:43 +010038template <typename T>
39class ArenaAllocatorAdapter;
40
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000041static constexpr bool kArenaAllocatorCountAllocations = false;
42
43// Type of allocation for memory tuning.
44enum ArenaAllocKind {
45 kArenaAllocMisc,
46 kArenaAllocBB,
Vladimir Markoe39c54e2014-09-22 14:50:02 +010047 kArenaAllocBBList,
48 kArenaAllocBBPredecessors,
49 kArenaAllocDfsPreOrder,
50 kArenaAllocDfsPostOrder,
51 kArenaAllocDomPostOrder,
52 kArenaAllocTopologicalSortOrder,
53 kArenaAllocLoweringInfo,
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000054 kArenaAllocLIR,
Vladimir Marko8dea81c2014-06-06 14:50:36 +010055 kArenaAllocLIRResourceMask,
Vladimir Markoe39c54e2014-09-22 14:50:02 +010056 kArenaAllocSwitchTable,
57 kArenaAllocFillArrayData,
58 kArenaAllocSlowPaths,
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000059 kArenaAllocMIR,
60 kArenaAllocDFInfo,
61 kArenaAllocGrowableArray,
62 kArenaAllocGrowableBitMap,
Vladimir Markoe39c54e2014-09-22 14:50:02 +010063 kArenaAllocSSAToDalvikMap,
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000064 kArenaAllocDalvikToSSAMap,
65 kArenaAllocDebugInfo,
66 kArenaAllocSuccessor,
67 kArenaAllocRegAlloc,
68 kArenaAllocData,
69 kArenaAllocPredecessors,
70 kArenaAllocSTL,
71 kNumArenaAllocKinds
72};
73
74template <bool kCount>
75class ArenaAllocatorStatsImpl;
76
77template <>
78class ArenaAllocatorStatsImpl<false> {
79 public:
80 ArenaAllocatorStatsImpl() = default;
81 ArenaAllocatorStatsImpl(const ArenaAllocatorStatsImpl& other) = default;
82 ArenaAllocatorStatsImpl& operator = (const ArenaAllocatorStatsImpl& other) = delete;
83
84 void Copy(const ArenaAllocatorStatsImpl& other) { UNUSED(other); }
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070085 void RecordAlloc(size_t bytes, ArenaAllocKind kind) { UNUSED(bytes, kind); }
Vladimir Marko83cc7ae2014-02-12 18:02:05 +000086 size_t NumAllocations() const { return 0u; }
87 size_t BytesAllocated() const { return 0u; }
88 void Dump(std::ostream& os, const Arena* first, ssize_t lost_bytes_adjustment) const {
89 UNUSED(os); UNUSED(first); UNUSED(lost_bytes_adjustment);
90 }
91};
92
93template <bool kCount>
94class ArenaAllocatorStatsImpl {
95 public:
96 ArenaAllocatorStatsImpl();
97 ArenaAllocatorStatsImpl(const ArenaAllocatorStatsImpl& other) = default;
98 ArenaAllocatorStatsImpl& operator = (const ArenaAllocatorStatsImpl& other) = delete;
99
100 void Copy(const ArenaAllocatorStatsImpl& other);
101 void RecordAlloc(size_t bytes, ArenaAllocKind kind);
102 size_t NumAllocations() const;
103 size_t BytesAllocated() const;
104 void Dump(std::ostream& os, const Arena* first, ssize_t lost_bytes_adjustment) const;
105
106 private:
107 size_t num_allocations_;
108 // TODO: Use std::array<size_t, kNumArenaAllocKinds> from C++11 when we upgrade the STL.
109 size_t alloc_stats_[kNumArenaAllocKinds]; // Bytes used by various allocation kinds.
Vladimir Markobd9e9db2014-03-07 19:41:05 +0000110
Vladimir Marko8dea81c2014-06-06 14:50:36 +0100111 static const char* const kAllocNames[];
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000112};
113
114typedef ArenaAllocatorStatsImpl<kArenaAllocatorCountAllocations> ArenaAllocatorStats;
buzbee862a7602013-04-05 10:58:54 -0700115
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700116class Arena {
117 public:
118 static constexpr size_t kDefaultSize = 128 * KB;
119 explicit Arena(size_t size = kDefaultSize);
120 ~Arena();
121 void Reset();
122 uint8_t* Begin() {
123 return memory_;
buzbee862a7602013-04-05 10:58:54 -0700124 }
125
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700126 uint8_t* End() {
127 return memory_ + size_;
128 }
129
130 size_t Size() const {
131 return size_;
132 }
133
134 size_t RemainingSpace() const {
135 return Size() - bytes_allocated_;
136 }
137
Mathieu Chartier49285c52014-12-02 15:43:48 -0800138 size_t GetBytesAllocated() const {
139 return bytes_allocated_;
140 }
141
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700142 private:
143 size_t bytes_allocated_;
144 uint8_t* memory_;
145 size_t size_;
146 MemMap* map_;
147 Arena* next_;
148 friend class ArenaPool;
149 friend class ArenaAllocator;
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000150 friend class ArenaStack;
151 friend class ScopedArenaAllocator;
152 template <bool kCount> friend class ArenaAllocatorStatsImpl;
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700153 DISALLOW_COPY_AND_ASSIGN(Arena);
154};
155
156class ArenaPool {
157 public:
158 ArenaPool();
159 ~ArenaPool();
Mathieu Chartier49285c52014-12-02 15:43:48 -0800160 Arena* AllocArena(size_t size) LOCKS_EXCLUDED(lock_);
161 void FreeArenaChain(Arena* first) LOCKS_EXCLUDED(lock_);
162 size_t GetBytesAllocated() const LOCKS_EXCLUDED(lock_);
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700163
164 private:
Mathieu Chartier49285c52014-12-02 15:43:48 -0800165 mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700166 Arena* free_arenas_ GUARDED_BY(lock_);
167 DISALLOW_COPY_AND_ASSIGN(ArenaPool);
168};
169
Vladimir Marko8081d2b2014-07-31 15:33:43 +0100170class ArenaAllocator : private DebugStackRefCounter, private ArenaAllocatorStats {
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700171 public:
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700172 explicit ArenaAllocator(ArenaPool* pool);
173 ~ArenaAllocator();
174
Vladimir Marko8081d2b2014-07-31 15:33:43 +0100175 // Get adapter for use in STL containers. See arena_containers.h .
176 ArenaAllocatorAdapter<void> Adapter(ArenaAllocKind kind = kArenaAllocSTL);
177
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700178 // Returns zeroed memory.
179 void* Alloc(size_t bytes, ArenaAllocKind kind) ALWAYS_INLINE {
Mathieu Chartier75165d02013-09-12 14:00:31 -0700180 if (UNLIKELY(running_on_valgrind_)) {
181 return AllocValgrind(bytes, kind);
182 }
Vladimir Marko22a0ef82014-06-10 14:47:51 +0100183 bytes = RoundUp(bytes, 8);
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700184 if (UNLIKELY(ptr_ + bytes > end_)) {
185 // Obtain a new block.
186 ObtainNewArenaForAllocation(bytes);
187 if (UNLIKELY(ptr_ == nullptr)) {
188 return nullptr;
189 }
190 }
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000191 ArenaAllocatorStats::RecordAlloc(bytes, kind);
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700192 uint8_t* ret = ptr_;
193 ptr_ += bytes;
194 return ret;
195 }
196
Nicolas Geoffraya7062e02014-05-22 12:50:17 +0100197 template <typename T> T* AllocArray(size_t length) {
198 return static_cast<T*>(Alloc(length * sizeof(T), kArenaAllocMisc));
199 }
200
Mathieu Chartier75165d02013-09-12 14:00:31 -0700201 void* AllocValgrind(size_t bytes, ArenaAllocKind kind);
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700202 void ObtainNewArenaForAllocation(size_t allocation_size);
203 size_t BytesAllocated() const;
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000204 MemStats GetMemStats() const;
buzbee862a7602013-04-05 10:58:54 -0700205
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700206 private:
207 void UpdateBytesAllocated();
buzbee862a7602013-04-05 10:58:54 -0700208
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700209 ArenaPool* pool_;
210 uint8_t* begin_;
211 uint8_t* end_;
212 uint8_t* ptr_;
213 Arena* arena_head_;
Mathieu Chartier75165d02013-09-12 14:00:31 -0700214 bool running_on_valgrind_;
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700215
Vladimir Marko8081d2b2014-07-31 15:33:43 +0100216 template <typename U>
217 friend class ArenaAllocatorAdapter;
218
Mathieu Chartierf6c4b3b2013-08-24 16:11:37 -0700219 DISALLOW_COPY_AND_ASSIGN(ArenaAllocator);
buzbee862a7602013-04-05 10:58:54 -0700220}; // ArenaAllocator
221
Vladimir Marko83cc7ae2014-02-12 18:02:05 +0000222class MemStats {
223 public:
224 MemStats(const char* name, const ArenaAllocatorStats* stats, const Arena* first_arena,
225 ssize_t lost_bytes_adjustment = 0);
226 void Dump(std::ostream& os) const;
227
228 private:
229 const char* const name_;
230 const ArenaAllocatorStats* const stats_;
231 const Arena* const first_arena_;
232 const ssize_t lost_bytes_adjustment_;
Brian Carlstrom7934ac22013-07-26 10:54:15 -0700233}; // MemStats
buzbee862a7602013-04-05 10:58:54 -0700234
235} // namespace art
236
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000237#endif // ART_COMPILER_UTILS_ARENA_ALLOCATOR_H_