blob: 6bf56c8c51d7f39518e91db77e984d6cd671ee95 [file] [log] [blame]
Vladimir Marko3e0e7172016-04-22 18:07:13 +01001/*
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
Andreas Gampe121f1482017-05-12 10:28:35 -070017#include "base/arena_allocator-inl.h"
Vladimir Marko3e0e7172016-04-22 18:07:13 +010018#include "base/arena_bit_vector.h"
Andreas Gampe6206da52016-08-22 19:14:29 -070019#include "base/memory_tool.h"
Vladimir Marko3e0e7172016-04-22 18:07:13 +010020#include "gtest/gtest.h"
21
22namespace art {
23
24class ArenaAllocatorTest : public testing::Test {
25 protected:
Vladimir Markoe764d2e2017-10-05 14:35:55 +010026 size_t NumberOfArenas(ArenaAllocator* allocator) {
Vladimir Marko3e0e7172016-04-22 18:07:13 +010027 size_t result = 0u;
Vladimir Markoe764d2e2017-10-05 14:35:55 +010028 for (Arena* a = allocator->arena_head_; a != nullptr; a = a->next_) {
Vladimir Marko3e0e7172016-04-22 18:07:13 +010029 ++result;
30 }
31 return result;
32 }
33};
34
35TEST_F(ArenaAllocatorTest, Test) {
36 ArenaPool pool;
37 ArenaAllocator arena(&pool);
38 ArenaBitVector bv(&arena, 10, true);
39 bv.SetBit(5);
40 EXPECT_EQ(1U, bv.GetStorageSize());
41 bv.SetBit(35);
42 EXPECT_EQ(2U, bv.GetStorageSize());
43}
44
Vladimir Marko3f84f2c2016-04-25 19:40:34 +010045TEST_F(ArenaAllocatorTest, MakeDefined) {
46 // Regression test to make sure we mark the allocated area defined.
47 ArenaPool pool;
48 static constexpr size_t kSmallArraySize = 10;
49 static constexpr size_t kLargeArraySize = 50;
50 uint32_t* small_array;
51 {
52 // Allocate a small array from an arena and release it.
53 ArenaAllocator arena(&pool);
54 small_array = arena.AllocArray<uint32_t>(kSmallArraySize);
55 ASSERT_EQ(0u, small_array[kSmallArraySize - 1u]);
56 }
57 {
58 // Reuse the previous arena and allocate more than previous allocation including red zone.
59 ArenaAllocator arena(&pool);
60 uint32_t* large_array = arena.AllocArray<uint32_t>(kLargeArraySize);
61 ASSERT_EQ(0u, large_array[kLargeArraySize - 1u]);
62 // Verify that the allocation was made on the same arena.
63 ASSERT_EQ(small_array, large_array);
64 }
65}
66
Vladimir Marko3e0e7172016-04-22 18:07:13 +010067TEST_F(ArenaAllocatorTest, LargeAllocations) {
Andreas Gampe121f1482017-05-12 10:28:35 -070068 if (arena_allocator::kArenaAllocatorPreciseTracking) {
69 printf("WARNING: TEST DISABLED FOR precise arena tracking\n");
70 return;
71 }
72
Vladimir Marko3e0e7172016-04-22 18:07:13 +010073 {
74 ArenaPool pool;
75 ArenaAllocator arena(&pool);
76 // Note: Leaving some space for memory tool red zones.
Andreas Gampe121f1482017-05-12 10:28:35 -070077 void* alloc1 = arena.Alloc(arena_allocator::kArenaDefaultSize * 5 / 8);
78 void* alloc2 = arena.Alloc(arena_allocator::kArenaDefaultSize * 2 / 8);
Vladimir Marko3e0e7172016-04-22 18:07:13 +010079 ASSERT_NE(alloc1, alloc2);
80 ASSERT_EQ(1u, NumberOfArenas(&arena));
81 }
82 {
83 ArenaPool pool;
84 ArenaAllocator arena(&pool);
Andreas Gampe121f1482017-05-12 10:28:35 -070085 void* alloc1 = arena.Alloc(arena_allocator::kArenaDefaultSize * 13 / 16);
86 void* alloc2 = arena.Alloc(arena_allocator::kArenaDefaultSize * 11 / 16);
Vladimir Marko3e0e7172016-04-22 18:07:13 +010087 ASSERT_NE(alloc1, alloc2);
88 ASSERT_EQ(2u, NumberOfArenas(&arena));
Andreas Gampe121f1482017-05-12 10:28:35 -070089 void* alloc3 = arena.Alloc(arena_allocator::kArenaDefaultSize * 7 / 16);
Vladimir Marko3e0e7172016-04-22 18:07:13 +010090 ASSERT_NE(alloc1, alloc3);
91 ASSERT_NE(alloc2, alloc3);
92 ASSERT_EQ(3u, NumberOfArenas(&arena));
93 }
94 {
95 ArenaPool pool;
96 ArenaAllocator arena(&pool);
Andreas Gampe121f1482017-05-12 10:28:35 -070097 void* alloc1 = arena.Alloc(arena_allocator::kArenaDefaultSize * 13 / 16);
98 void* alloc2 = arena.Alloc(arena_allocator::kArenaDefaultSize * 9 / 16);
Vladimir Marko3e0e7172016-04-22 18:07:13 +010099 ASSERT_NE(alloc1, alloc2);
100 ASSERT_EQ(2u, NumberOfArenas(&arena));
101 // Note: Leaving some space for memory tool red zones.
Andreas Gampe121f1482017-05-12 10:28:35 -0700102 void* alloc3 = arena.Alloc(arena_allocator::kArenaDefaultSize * 5 / 16);
Vladimir Marko3e0e7172016-04-22 18:07:13 +0100103 ASSERT_NE(alloc1, alloc3);
104 ASSERT_NE(alloc2, alloc3);
105 ASSERT_EQ(2u, NumberOfArenas(&arena));
106 }
107 {
108 ArenaPool pool;
109 ArenaAllocator arena(&pool);
Andreas Gampe121f1482017-05-12 10:28:35 -0700110 void* alloc1 = arena.Alloc(arena_allocator::kArenaDefaultSize * 9 / 16);
111 void* alloc2 = arena.Alloc(arena_allocator::kArenaDefaultSize * 13 / 16);
Vladimir Marko3e0e7172016-04-22 18:07:13 +0100112 ASSERT_NE(alloc1, alloc2);
113 ASSERT_EQ(2u, NumberOfArenas(&arena));
114 // Note: Leaving some space for memory tool red zones.
Andreas Gampe121f1482017-05-12 10:28:35 -0700115 void* alloc3 = arena.Alloc(arena_allocator::kArenaDefaultSize * 5 / 16);
Vladimir Marko3e0e7172016-04-22 18:07:13 +0100116 ASSERT_NE(alloc1, alloc3);
117 ASSERT_NE(alloc2, alloc3);
118 ASSERT_EQ(2u, NumberOfArenas(&arena));
119 }
120 {
121 ArenaPool pool;
122 ArenaAllocator arena(&pool);
123 // Note: Leaving some space for memory tool red zones.
124 for (size_t i = 0; i != 15; ++i) {
Andreas Gampe121f1482017-05-12 10:28:35 -0700125 arena.Alloc(arena_allocator::kArenaDefaultSize * 1 / 16); // Allocate 15 times from the same arena.
Vladimir Marko3e0e7172016-04-22 18:07:13 +0100126 ASSERT_EQ(i + 1u, NumberOfArenas(&arena));
Andreas Gampe121f1482017-05-12 10:28:35 -0700127 arena.Alloc(arena_allocator::kArenaDefaultSize * 17 / 16); // Allocate a separate arena.
Vladimir Marko3e0e7172016-04-22 18:07:13 +0100128 ASSERT_EQ(i + 2u, NumberOfArenas(&arena));
129 }
130 }
131}
132
Andreas Gampec134ee72016-08-22 14:03:10 -0700133TEST_F(ArenaAllocatorTest, AllocAlignment) {
134 ArenaPool pool;
135 ArenaAllocator arena(&pool);
136 for (size_t iterations = 0; iterations <= 10; ++iterations) {
137 for (size_t size = 1; size <= ArenaAllocator::kAlignment + 1; ++size) {
138 void* allocation = arena.Alloc(size);
139 EXPECT_TRUE(IsAligned<ArenaAllocator::kAlignment>(allocation))
140 << reinterpret_cast<uintptr_t>(allocation);
141 }
142 }
143}
144
Andreas Gampe6206da52016-08-22 19:14:29 -0700145TEST_F(ArenaAllocatorTest, ReallocReuse) {
146 // Realloc does not reuse arenas when running under sanitization. So we cannot do those
147 if (RUNNING_ON_MEMORY_TOOL != 0) {
148 printf("WARNING: TEST DISABLED FOR MEMORY_TOOL\n");
149 return;
150 }
151
152 {
153 // Case 1: small aligned allocation, aligned extend inside arena.
154 ArenaPool pool;
155 ArenaAllocator arena(&pool);
156
157 const size_t original_size = ArenaAllocator::kAlignment * 2;
158 void* original_allocation = arena.Alloc(original_size);
159
160 const size_t new_size = ArenaAllocator::kAlignment * 3;
161 void* realloc_allocation = arena.Realloc(original_allocation, original_size, new_size);
162 EXPECT_EQ(original_allocation, realloc_allocation);
163 }
164
165 {
166 // Case 2: small aligned allocation, non-aligned extend inside arena.
167 ArenaPool pool;
168 ArenaAllocator arena(&pool);
169
170 const size_t original_size = ArenaAllocator::kAlignment * 2;
171 void* original_allocation = arena.Alloc(original_size);
172
173 const size_t new_size = ArenaAllocator::kAlignment * 2 + (ArenaAllocator::kAlignment / 2);
174 void* realloc_allocation = arena.Realloc(original_allocation, original_size, new_size);
175 EXPECT_EQ(original_allocation, realloc_allocation);
176 }
177
178 {
179 // Case 3: small non-aligned allocation, aligned extend inside arena.
180 ArenaPool pool;
181 ArenaAllocator arena(&pool);
182
183 const size_t original_size = ArenaAllocator::kAlignment * 2 + (ArenaAllocator::kAlignment / 2);
184 void* original_allocation = arena.Alloc(original_size);
185
186 const size_t new_size = ArenaAllocator::kAlignment * 4;
187 void* realloc_allocation = arena.Realloc(original_allocation, original_size, new_size);
188 EXPECT_EQ(original_allocation, realloc_allocation);
189 }
190
191 {
192 // Case 4: small non-aligned allocation, aligned non-extend inside arena.
193 ArenaPool pool;
194 ArenaAllocator arena(&pool);
195
196 const size_t original_size = ArenaAllocator::kAlignment * 2 + (ArenaAllocator::kAlignment / 2);
197 void* original_allocation = arena.Alloc(original_size);
198
199 const size_t new_size = ArenaAllocator::kAlignment * 3;
200 void* realloc_allocation = arena.Realloc(original_allocation, original_size, new_size);
201 EXPECT_EQ(original_allocation, realloc_allocation);
202 }
203
204 // The next part is brittle, as the default size for an arena is variable, and we don't know about
205 // sanitization.
206
207 {
208 // Case 5: large allocation, aligned extend into next arena.
209 ArenaPool pool;
210 ArenaAllocator arena(&pool);
211
Andreas Gampe121f1482017-05-12 10:28:35 -0700212 const size_t original_size = arena_allocator::kArenaDefaultSize -
213 ArenaAllocator::kAlignment * 5;
Andreas Gampe6206da52016-08-22 19:14:29 -0700214 void* original_allocation = arena.Alloc(original_size);
215
Andreas Gampe121f1482017-05-12 10:28:35 -0700216 const size_t new_size = arena_allocator::kArenaDefaultSize + ArenaAllocator::kAlignment * 2;
Andreas Gampe6206da52016-08-22 19:14:29 -0700217 void* realloc_allocation = arena.Realloc(original_allocation, original_size, new_size);
218 EXPECT_NE(original_allocation, realloc_allocation);
219 }
220
221 {
222 // Case 6: large allocation, non-aligned extend into next arena.
223 ArenaPool pool;
224 ArenaAllocator arena(&pool);
225
Andreas Gampe121f1482017-05-12 10:28:35 -0700226 const size_t original_size = arena_allocator::kArenaDefaultSize -
Andreas Gampe6206da52016-08-22 19:14:29 -0700227 ArenaAllocator::kAlignment * 4 -
228 ArenaAllocator::kAlignment / 2;
229 void* original_allocation = arena.Alloc(original_size);
230
Andreas Gampe121f1482017-05-12 10:28:35 -0700231 const size_t new_size = arena_allocator::kArenaDefaultSize +
Andreas Gampe6206da52016-08-22 19:14:29 -0700232 ArenaAllocator::kAlignment * 2 +
233 ArenaAllocator::kAlignment / 2;
234 void* realloc_allocation = arena.Realloc(original_allocation, original_size, new_size);
235 EXPECT_NE(original_allocation, realloc_allocation);
236 }
237}
238
Andreas Gampec134ee72016-08-22 14:03:10 -0700239TEST_F(ArenaAllocatorTest, ReallocAlignment) {
240 {
241 // Case 1: small aligned allocation, aligned extend inside arena.
242 ArenaPool pool;
243 ArenaAllocator arena(&pool);
244
245 const size_t original_size = ArenaAllocator::kAlignment * 2;
246 void* original_allocation = arena.Alloc(original_size);
247 ASSERT_TRUE(IsAligned<ArenaAllocator::kAlignment>(original_allocation));
248
249 const size_t new_size = ArenaAllocator::kAlignment * 3;
250 void* realloc_allocation = arena.Realloc(original_allocation, original_size, new_size);
251 EXPECT_TRUE(IsAligned<ArenaAllocator::kAlignment>(realloc_allocation));
Andreas Gampec134ee72016-08-22 14:03:10 -0700252
253 void* after_alloc = arena.Alloc(1);
254 EXPECT_TRUE(IsAligned<ArenaAllocator::kAlignment>(after_alloc));
255 }
256
257 {
258 // Case 2: small aligned allocation, non-aligned extend inside arena.
259 ArenaPool pool;
260 ArenaAllocator arena(&pool);
261
262 const size_t original_size = ArenaAllocator::kAlignment * 2;
263 void* original_allocation = arena.Alloc(original_size);
264 ASSERT_TRUE(IsAligned<ArenaAllocator::kAlignment>(original_allocation));
265
266 const size_t new_size = ArenaAllocator::kAlignment * 2 + (ArenaAllocator::kAlignment / 2);
267 void* realloc_allocation = arena.Realloc(original_allocation, original_size, new_size);
268 EXPECT_TRUE(IsAligned<ArenaAllocator::kAlignment>(realloc_allocation));
Andreas Gampec134ee72016-08-22 14:03:10 -0700269
270 void* after_alloc = arena.Alloc(1);
271 EXPECT_TRUE(IsAligned<ArenaAllocator::kAlignment>(after_alloc));
272 }
273
274 {
275 // Case 3: small non-aligned allocation, aligned extend inside arena.
276 ArenaPool pool;
277 ArenaAllocator arena(&pool);
278
279 const size_t original_size = ArenaAllocator::kAlignment * 2 + (ArenaAllocator::kAlignment / 2);
280 void* original_allocation = arena.Alloc(original_size);
281 ASSERT_TRUE(IsAligned<ArenaAllocator::kAlignment>(original_allocation));
282
283 const size_t new_size = ArenaAllocator::kAlignment * 4;
284 void* realloc_allocation = arena.Realloc(original_allocation, original_size, new_size);
285 EXPECT_TRUE(IsAligned<ArenaAllocator::kAlignment>(realloc_allocation));
Andreas Gampec134ee72016-08-22 14:03:10 -0700286
287 void* after_alloc = arena.Alloc(1);
288 EXPECT_TRUE(IsAligned<ArenaAllocator::kAlignment>(after_alloc));
289 }
290
291 {
292 // Case 4: small non-aligned allocation, aligned non-extend inside arena.
293 ArenaPool pool;
294 ArenaAllocator arena(&pool);
295
296 const size_t original_size = ArenaAllocator::kAlignment * 2 + (ArenaAllocator::kAlignment / 2);
297 void* original_allocation = arena.Alloc(original_size);
298 ASSERT_TRUE(IsAligned<ArenaAllocator::kAlignment>(original_allocation));
299
300 const size_t new_size = ArenaAllocator::kAlignment * 3;
301 void* realloc_allocation = arena.Realloc(original_allocation, original_size, new_size);
302 EXPECT_TRUE(IsAligned<ArenaAllocator::kAlignment>(realloc_allocation));
Andreas Gampec134ee72016-08-22 14:03:10 -0700303
304 void* after_alloc = arena.Alloc(1);
305 EXPECT_TRUE(IsAligned<ArenaAllocator::kAlignment>(after_alloc));
306 }
307
308 // The next part is brittle, as the default size for an arena is variable, and we don't know about
309 // sanitization.
310
311 {
312 // Case 5: large allocation, aligned extend into next arena.
313 ArenaPool pool;
314 ArenaAllocator arena(&pool);
315
Andreas Gampe121f1482017-05-12 10:28:35 -0700316 const size_t original_size = arena_allocator::kArenaDefaultSize -
317 ArenaAllocator::kAlignment * 5;
Andreas Gampec134ee72016-08-22 14:03:10 -0700318 void* original_allocation = arena.Alloc(original_size);
319 ASSERT_TRUE(IsAligned<ArenaAllocator::kAlignment>(original_allocation));
320
Andreas Gampe121f1482017-05-12 10:28:35 -0700321 const size_t new_size = arena_allocator::kArenaDefaultSize + ArenaAllocator::kAlignment * 2;
Andreas Gampec134ee72016-08-22 14:03:10 -0700322 void* realloc_allocation = arena.Realloc(original_allocation, original_size, new_size);
323 EXPECT_TRUE(IsAligned<ArenaAllocator::kAlignment>(realloc_allocation));
Andreas Gampec134ee72016-08-22 14:03:10 -0700324
325 void* after_alloc = arena.Alloc(1);
326 EXPECT_TRUE(IsAligned<ArenaAllocator::kAlignment>(after_alloc));
327 }
328
329 {
330 // Case 6: large allocation, non-aligned extend into next arena.
331 ArenaPool pool;
332 ArenaAllocator arena(&pool);
333
Andreas Gampe121f1482017-05-12 10:28:35 -0700334 const size_t original_size = arena_allocator::kArenaDefaultSize -
Andreas Gampec134ee72016-08-22 14:03:10 -0700335 ArenaAllocator::kAlignment * 4 -
336 ArenaAllocator::kAlignment / 2;
337 void* original_allocation = arena.Alloc(original_size);
338 ASSERT_TRUE(IsAligned<ArenaAllocator::kAlignment>(original_allocation));
339
Andreas Gampe121f1482017-05-12 10:28:35 -0700340 const size_t new_size = arena_allocator::kArenaDefaultSize +
Andreas Gampec134ee72016-08-22 14:03:10 -0700341 ArenaAllocator::kAlignment * 2 +
342 ArenaAllocator::kAlignment / 2;
343 void* realloc_allocation = arena.Realloc(original_allocation, original_size, new_size);
344 EXPECT_TRUE(IsAligned<ArenaAllocator::kAlignment>(realloc_allocation));
Andreas Gampec134ee72016-08-22 14:03:10 -0700345
346 void* after_alloc = arena.Alloc(1);
347 EXPECT_TRUE(IsAligned<ArenaAllocator::kAlignment>(after_alloc));
348 }
349}
350
351
Vladimir Marko3e0e7172016-04-22 18:07:13 +0100352} // namespace art