1 /*
2  * Copyright (C) 2011 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_RUNTIME_GC_SPACE_SPACE_TEST_H_
18 #define ART_RUNTIME_GC_SPACE_SPACE_TEST_H_
19 
20 #include <stdint.h>
21 #include <memory>
22 
23 #include "common_runtime_test.h"
24 #include "globals.h"
25 #include "mirror/array-inl.h"
26 #include "mirror/class-inl.h"
27 #include "mirror/class_loader.h"
28 #include "mirror/object-inl.h"
29 #include "scoped_thread_state_change.h"
30 #include "zygote_space.h"
31 
32 namespace art {
33 namespace gc {
34 namespace space {
35 
36 class SpaceTest : public CommonRuntimeTest {
37  public:
38   jobject byte_array_class_;
39 
SpaceTest()40   SpaceTest() : byte_array_class_(nullptr) {
41   }
42 
43   void AddSpace(ContinuousSpace* space, bool revoke = true) {
44     Heap* heap = Runtime::Current()->GetHeap();
45     if (revoke) {
46       heap->RevokeAllThreadLocalBuffers();
47     }
48     heap->AddSpace(space);
49     heap->SetSpaceAsDefault(space);
50   }
51 
GetByteArrayClass(Thread * self)52   mirror::Class* GetByteArrayClass(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
53     StackHandleScope<1> hs(self);
54     auto null_loader(hs.NewHandle<mirror::ClassLoader>(nullptr));
55     if (byte_array_class_ == nullptr) {
56       mirror::Class* byte_array_class =
57           Runtime::Current()->GetClassLinker()->FindClass(self, "[B", null_loader);
58       EXPECT_TRUE(byte_array_class != nullptr);
59       byte_array_class_ = self->GetJniEnv()->NewLocalRef(byte_array_class);
60       EXPECT_TRUE(byte_array_class_ != nullptr);
61     }
62     return reinterpret_cast<mirror::Class*>(self->DecodeJObject(byte_array_class_));
63   }
64 
Alloc(space::MallocSpace * alloc_space,Thread * self,size_t bytes,size_t * bytes_allocated,size_t * usable_size,size_t * bytes_tl_bulk_allocated)65   mirror::Object* Alloc(space::MallocSpace* alloc_space, Thread* self, size_t bytes,
66                         size_t* bytes_allocated, size_t* usable_size,
67                         size_t* bytes_tl_bulk_allocated)
68       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
69     StackHandleScope<1> hs(self);
70     Handle<mirror::Class> byte_array_class(hs.NewHandle(GetByteArrayClass(self)));
71     mirror::Object* obj = alloc_space->Alloc(self, bytes, bytes_allocated, usable_size,
72                                              bytes_tl_bulk_allocated);
73     if (obj != nullptr) {
74       InstallClass(obj, byte_array_class.Get(), bytes);
75     }
76     return obj;
77   }
78 
AllocWithGrowth(space::MallocSpace * alloc_space,Thread * self,size_t bytes,size_t * bytes_allocated,size_t * usable_size,size_t * bytes_tl_bulk_allocated)79   mirror::Object* AllocWithGrowth(space::MallocSpace* alloc_space, Thread* self, size_t bytes,
80                                   size_t* bytes_allocated, size_t* usable_size,
81                                   size_t* bytes_tl_bulk_allocated)
82       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
83     StackHandleScope<1> hs(self);
84     Handle<mirror::Class> byte_array_class(hs.NewHandle(GetByteArrayClass(self)));
85     mirror::Object* obj = alloc_space->AllocWithGrowth(self, bytes, bytes_allocated, usable_size,
86                                                        bytes_tl_bulk_allocated);
87     if (obj != nullptr) {
88       InstallClass(obj, byte_array_class.Get(), bytes);
89     }
90     return obj;
91   }
92 
InstallClass(mirror::Object * o,mirror::Class * byte_array_class,size_t size)93   void InstallClass(mirror::Object* o, mirror::Class* byte_array_class, size_t size)
94       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
95     // Note the minimum size, which is the size of a zero-length byte array.
96     EXPECT_GE(size, SizeOfZeroLengthByteArray());
97     EXPECT_TRUE(byte_array_class != nullptr);
98     o->SetClass(byte_array_class);
99     if (kUseBakerOrBrooksReadBarrier) {
100       // Like the proper heap object allocation, install and verify
101       // the correct read barrier pointer.
102       if (kUseBrooksReadBarrier) {
103         o->SetReadBarrierPointer(o);
104       }
105       o->AssertReadBarrierPointer();
106     }
107     mirror::Array* arr = o->AsArray<kVerifyNone>();
108     size_t header_size = SizeOfZeroLengthByteArray();
109     int32_t length = size - header_size;
110     arr->SetLength(length);
111     EXPECT_EQ(arr->SizeOf<kVerifyNone>(), size);
112   }
113 
SizeOfZeroLengthByteArray()114   static size_t SizeOfZeroLengthByteArray() {
115     return mirror::Array::DataOffset(Primitive::ComponentSize(Primitive::kPrimByte)).Uint32Value();
116   }
117 
118   typedef MallocSpace* (*CreateSpaceFn)(const std::string& name, size_t initial_size, size_t growth_limit,
119                                         size_t capacity, uint8_t* requested_begin);
120   void InitTestBody(CreateSpaceFn create_space);
121   void ZygoteSpaceTestBody(CreateSpaceFn create_space);
122   void AllocAndFreeTestBody(CreateSpaceFn create_space);
123   void AllocAndFreeListTestBody(CreateSpaceFn create_space);
124 
125   void SizeFootPrintGrowthLimitAndTrimBody(MallocSpace* space, intptr_t object_size,
126                                            int round, size_t growth_limit);
127   void SizeFootPrintGrowthLimitAndTrimDriver(size_t object_size, CreateSpaceFn create_space);
128 };
129 
test_rand(size_t * seed)130 static inline size_t test_rand(size_t* seed) {
131   *seed = *seed * 1103515245 + 12345;
132   return *seed;
133 }
134 
InitTestBody(CreateSpaceFn create_space)135 void SpaceTest::InitTestBody(CreateSpaceFn create_space) {
136   // This will lead to error messages in the log.
137   ScopedLogSeverity sls(LogSeverity::FATAL);
138 
139   {
140     // Init < max == growth
141     std::unique_ptr<Space> space(create_space("test", 16 * MB, 32 * MB, 32 * MB, nullptr));
142     EXPECT_TRUE(space.get() != nullptr);
143   }
144   {
145     // Init == max == growth
146     std::unique_ptr<Space> space(create_space("test", 16 * MB, 16 * MB, 16 * MB, nullptr));
147     EXPECT_TRUE(space.get() != nullptr);
148   }
149   {
150     // Init > max == growth
151     std::unique_ptr<Space> space(create_space("test", 32 * MB, 16 * MB, 16 * MB, nullptr));
152     EXPECT_TRUE(space.get() == nullptr);
153   }
154   {
155     // Growth == init < max
156     std::unique_ptr<Space> space(create_space("test", 16 * MB, 16 * MB, 32 * MB, nullptr));
157     EXPECT_TRUE(space.get() != nullptr);
158   }
159   {
160     // Growth < init < max
161     std::unique_ptr<Space> space(create_space("test", 16 * MB, 8 * MB, 32 * MB, nullptr));
162     EXPECT_TRUE(space.get() == nullptr);
163   }
164   {
165     // Init < growth < max
166     std::unique_ptr<Space> space(create_space("test", 8 * MB, 16 * MB, 32 * MB, nullptr));
167     EXPECT_TRUE(space.get() != nullptr);
168   }
169   {
170     // Init < max < growth
171     std::unique_ptr<Space> space(create_space("test", 8 * MB, 32 * MB, 16 * MB, nullptr));
172     EXPECT_TRUE(space.get() == nullptr);
173   }
174 }
175 
176 // TODO: This test is not very good, we should improve it.
177 // The test should do more allocations before the creation of the ZygoteSpace, and then do
178 // allocations after the ZygoteSpace is created. The test should also do some GCs to ensure that
179 // the GC works with the ZygoteSpace.
ZygoteSpaceTestBody(CreateSpaceFn create_space)180 void SpaceTest::ZygoteSpaceTestBody(CreateSpaceFn create_space) {
181   size_t dummy;
182   MallocSpace* space(create_space("test", 4 * MB, 16 * MB, 16 * MB, nullptr));
183   ASSERT_TRUE(space != nullptr);
184 
185   // Make space findable to the heap, will also delete space when runtime is cleaned up
186   AddSpace(space);
187   Thread* self = Thread::Current();
188   ScopedObjectAccess soa(self);
189 
190   // Succeeds, fits without adjusting the footprint limit.
191   size_t ptr1_bytes_allocated, ptr1_usable_size, ptr1_bytes_tl_bulk_allocated;
192   StackHandleScope<3> hs(soa.Self());
193   MutableHandle<mirror::Object> ptr1(
194       hs.NewHandle(Alloc(space, self, 1 * MB, &ptr1_bytes_allocated, &ptr1_usable_size,
195                          &ptr1_bytes_tl_bulk_allocated)));
196   EXPECT_TRUE(ptr1.Get() != nullptr);
197   EXPECT_LE(1U * MB, ptr1_bytes_allocated);
198   EXPECT_LE(1U * MB, ptr1_usable_size);
199   EXPECT_LE(ptr1_usable_size, ptr1_bytes_allocated);
200   EXPECT_EQ(ptr1_bytes_tl_bulk_allocated, ptr1_bytes_allocated);
201 
202   // Fails, requires a higher footprint limit.
203   mirror::Object* ptr2 = Alloc(space, self, 8 * MB, &dummy, nullptr, &dummy);
204   EXPECT_TRUE(ptr2 == nullptr);
205 
206   // Succeeds, adjusts the footprint.
207   size_t ptr3_bytes_allocated, ptr3_usable_size, ptr3_bytes_tl_bulk_allocated;
208   MutableHandle<mirror::Object> ptr3(
209       hs.NewHandle(AllocWithGrowth(space, self, 8 * MB, &ptr3_bytes_allocated, &ptr3_usable_size,
210                                    &ptr3_bytes_tl_bulk_allocated)));
211   EXPECT_TRUE(ptr3.Get() != nullptr);
212   EXPECT_LE(8U * MB, ptr3_bytes_allocated);
213   EXPECT_LE(8U * MB, ptr3_usable_size);
214   EXPECT_LE(ptr3_usable_size, ptr3_bytes_allocated);
215   EXPECT_EQ(ptr3_bytes_tl_bulk_allocated, ptr3_bytes_allocated);
216 
217   // Fails, requires a higher footprint limit.
218   mirror::Object* ptr4 = space->Alloc(self, 8 * MB, &dummy, nullptr, &dummy);
219   EXPECT_TRUE(ptr4 == nullptr);
220 
221   // Also fails, requires a higher allowed footprint.
222   mirror::Object* ptr5 = space->AllocWithGrowth(self, 8 * MB, &dummy, nullptr, &dummy);
223   EXPECT_TRUE(ptr5 == nullptr);
224 
225   // Release some memory.
226   size_t free3 = space->AllocationSize(ptr3.Get(), nullptr);
227   EXPECT_EQ(free3, ptr3_bytes_allocated);
228   EXPECT_EQ(free3, space->Free(self, ptr3.Assign(nullptr)));
229   EXPECT_LE(8U * MB, free3);
230 
231   // Succeeds, now that memory has been freed.
232   size_t ptr6_bytes_allocated, ptr6_usable_size, ptr6_bytes_tl_bulk_allocated;
233   Handle<mirror::Object> ptr6(
234       hs.NewHandle(AllocWithGrowth(space, self, 9 * MB, &ptr6_bytes_allocated, &ptr6_usable_size,
235                                    &ptr6_bytes_tl_bulk_allocated)));
236   EXPECT_TRUE(ptr6.Get() != nullptr);
237   EXPECT_LE(9U * MB, ptr6_bytes_allocated);
238   EXPECT_LE(9U * MB, ptr6_usable_size);
239   EXPECT_LE(ptr6_usable_size, ptr6_bytes_allocated);
240   EXPECT_EQ(ptr6_bytes_tl_bulk_allocated, ptr6_bytes_allocated);
241 
242   // Final clean up.
243   size_t free1 = space->AllocationSize(ptr1.Get(), nullptr);
244   space->Free(self, ptr1.Assign(nullptr));
245   EXPECT_LE(1U * MB, free1);
246 
247   // Make sure that the zygote space isn't directly at the start of the space.
248   EXPECT_TRUE(space->Alloc(self, 1U * MB, &dummy, nullptr, &dummy) != nullptr);
249 
250   gc::Heap* heap = Runtime::Current()->GetHeap();
251   space::Space* old_space = space;
252   heap->RemoveSpace(old_space);
253   heap->RevokeAllThreadLocalBuffers();
254   space::ZygoteSpace* zygote_space = space->CreateZygoteSpace("alloc space",
255                                                               heap->IsLowMemoryMode(),
256                                                               &space);
257   delete old_space;
258   // Add the zygote space.
259   AddSpace(zygote_space, false);
260 
261   // Make space findable to the heap, will also delete space when runtime is cleaned up
262   AddSpace(space, false);
263 
264   // Succeeds, fits without adjusting the footprint limit.
265   ptr1.Assign(Alloc(space, self, 1 * MB, &ptr1_bytes_allocated, &ptr1_usable_size,
266                     &ptr1_bytes_tl_bulk_allocated));
267   EXPECT_TRUE(ptr1.Get() != nullptr);
268   EXPECT_LE(1U * MB, ptr1_bytes_allocated);
269   EXPECT_LE(1U * MB, ptr1_usable_size);
270   EXPECT_LE(ptr1_usable_size, ptr1_bytes_allocated);
271   EXPECT_EQ(ptr1_bytes_tl_bulk_allocated, ptr1_bytes_allocated);
272 
273   // Fails, requires a higher footprint limit.
274   ptr2 = Alloc(space, self, 8 * MB, &dummy, nullptr, &dummy);
275   EXPECT_TRUE(ptr2 == nullptr);
276 
277   // Succeeds, adjusts the footprint.
278   ptr3.Assign(AllocWithGrowth(space, self, 2 * MB, &ptr3_bytes_allocated, &ptr3_usable_size,
279                               &ptr3_bytes_tl_bulk_allocated));
280   EXPECT_TRUE(ptr3.Get() != nullptr);
281   EXPECT_LE(2U * MB, ptr3_bytes_allocated);
282   EXPECT_LE(2U * MB, ptr3_usable_size);
283   EXPECT_LE(ptr3_usable_size, ptr3_bytes_allocated);
284   EXPECT_EQ(ptr3_bytes_tl_bulk_allocated, ptr3_bytes_allocated);
285   space->Free(self, ptr3.Assign(nullptr));
286 
287   // Final clean up.
288   free1 = space->AllocationSize(ptr1.Get(), nullptr);
289   space->Free(self, ptr1.Assign(nullptr));
290   EXPECT_LE(1U * MB, free1);
291 }
292 
AllocAndFreeTestBody(CreateSpaceFn create_space)293 void SpaceTest::AllocAndFreeTestBody(CreateSpaceFn create_space) {
294   size_t dummy = 0;
295   MallocSpace* space(create_space("test", 4 * MB, 16 * MB, 16 * MB, nullptr));
296   ASSERT_TRUE(space != nullptr);
297   Thread* self = Thread::Current();
298   ScopedObjectAccess soa(self);
299 
300   // Make space findable to the heap, will also delete space when runtime is cleaned up
301   AddSpace(space);
302 
303   // Succeeds, fits without adjusting the footprint limit.
304   size_t ptr1_bytes_allocated, ptr1_usable_size, ptr1_bytes_tl_bulk_allocated;
305   StackHandleScope<3> hs(soa.Self());
306   MutableHandle<mirror::Object> ptr1(
307       hs.NewHandle(Alloc(space, self, 1 * MB, &ptr1_bytes_allocated, &ptr1_usable_size,
308                          &ptr1_bytes_tl_bulk_allocated)));
309   EXPECT_TRUE(ptr1.Get() != nullptr);
310   EXPECT_LE(1U * MB, ptr1_bytes_allocated);
311   EXPECT_LE(1U * MB, ptr1_usable_size);
312   EXPECT_LE(ptr1_usable_size, ptr1_bytes_allocated);
313   EXPECT_EQ(ptr1_bytes_tl_bulk_allocated, ptr1_bytes_allocated);
314 
315   // Fails, requires a higher footprint limit.
316   mirror::Object* ptr2 = Alloc(space, self, 8 * MB, &dummy, nullptr, &dummy);
317   EXPECT_TRUE(ptr2 == nullptr);
318 
319   // Succeeds, adjusts the footprint.
320   size_t ptr3_bytes_allocated, ptr3_usable_size, ptr3_bytes_tl_bulk_allocated;
321   MutableHandle<mirror::Object> ptr3(
322       hs.NewHandle(AllocWithGrowth(space, self, 8 * MB, &ptr3_bytes_allocated, &ptr3_usable_size,
323                                    &ptr3_bytes_tl_bulk_allocated)));
324   EXPECT_TRUE(ptr3.Get() != nullptr);
325   EXPECT_LE(8U * MB, ptr3_bytes_allocated);
326   EXPECT_LE(8U * MB, ptr3_usable_size);
327   EXPECT_LE(ptr3_usable_size, ptr3_bytes_allocated);
328   EXPECT_EQ(ptr3_bytes_tl_bulk_allocated, ptr3_bytes_allocated);
329 
330   // Fails, requires a higher footprint limit.
331   mirror::Object* ptr4 = Alloc(space, self, 8 * MB, &dummy, nullptr, &dummy);
332   EXPECT_TRUE(ptr4 == nullptr);
333 
334   // Also fails, requires a higher allowed footprint.
335   mirror::Object* ptr5 = AllocWithGrowth(space, self, 8 * MB, &dummy, nullptr, &dummy);
336   EXPECT_TRUE(ptr5 == nullptr);
337 
338   // Release some memory.
339   size_t free3 = space->AllocationSize(ptr3.Get(), nullptr);
340   EXPECT_EQ(free3, ptr3_bytes_allocated);
341   space->Free(self, ptr3.Assign(nullptr));
342   EXPECT_LE(8U * MB, free3);
343 
344   // Succeeds, now that memory has been freed.
345   size_t ptr6_bytes_allocated, ptr6_usable_size, ptr6_bytes_tl_bulk_allocated;
346   Handle<mirror::Object> ptr6(
347       hs.NewHandle(AllocWithGrowth(space, self, 9 * MB, &ptr6_bytes_allocated, &ptr6_usable_size,
348                                    &ptr6_bytes_tl_bulk_allocated)));
349   EXPECT_TRUE(ptr6.Get() != nullptr);
350   EXPECT_LE(9U * MB, ptr6_bytes_allocated);
351   EXPECT_LE(9U * MB, ptr6_usable_size);
352   EXPECT_LE(ptr6_usable_size, ptr6_bytes_allocated);
353   EXPECT_EQ(ptr6_bytes_tl_bulk_allocated, ptr6_bytes_allocated);
354 
355   // Final clean up.
356   size_t free1 = space->AllocationSize(ptr1.Get(), nullptr);
357   space->Free(self, ptr1.Assign(nullptr));
358   EXPECT_LE(1U * MB, free1);
359 }
360 
AllocAndFreeListTestBody(CreateSpaceFn create_space)361 void SpaceTest::AllocAndFreeListTestBody(CreateSpaceFn create_space) {
362   MallocSpace* space(create_space("test", 4 * MB, 16 * MB, 16 * MB, nullptr));
363   ASSERT_TRUE(space != nullptr);
364 
365   // Make space findable to the heap, will also delete space when runtime is cleaned up
366   AddSpace(space);
367   Thread* self = Thread::Current();
368   ScopedObjectAccess soa(self);
369 
370   // Succeeds, fits without adjusting the max allowed footprint.
371   mirror::Object* lots_of_objects[1024];
372   for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
373     size_t allocation_size, usable_size, bytes_tl_bulk_allocated;
374     size_t size_of_zero_length_byte_array = SizeOfZeroLengthByteArray();
375     lots_of_objects[i] = Alloc(space, self, size_of_zero_length_byte_array, &allocation_size,
376                                &usable_size, &bytes_tl_bulk_allocated);
377     EXPECT_TRUE(lots_of_objects[i] != nullptr);
378     size_t computed_usable_size;
379     EXPECT_EQ(allocation_size, space->AllocationSize(lots_of_objects[i], &computed_usable_size));
380     EXPECT_EQ(usable_size, computed_usable_size);
381     EXPECT_TRUE(bytes_tl_bulk_allocated == 0 ||
382                 bytes_tl_bulk_allocated >= allocation_size);
383   }
384 
385   // Release memory.
386   space->FreeList(self, arraysize(lots_of_objects), lots_of_objects);
387 
388   // Succeeds, fits by adjusting the max allowed footprint.
389   for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
390     size_t allocation_size, usable_size, bytes_tl_bulk_allocated;
391     lots_of_objects[i] = AllocWithGrowth(space, self, 1024, &allocation_size, &usable_size,
392                                          &bytes_tl_bulk_allocated);
393     EXPECT_TRUE(lots_of_objects[i] != nullptr);
394     size_t computed_usable_size;
395     EXPECT_EQ(allocation_size, space->AllocationSize(lots_of_objects[i], &computed_usable_size));
396     EXPECT_EQ(usable_size, computed_usable_size);
397     EXPECT_TRUE(bytes_tl_bulk_allocated == 0 ||
398                 bytes_tl_bulk_allocated >= allocation_size);
399   }
400 
401   // Release memory.
402   space->FreeList(self, arraysize(lots_of_objects), lots_of_objects);
403 }
404 
SizeFootPrintGrowthLimitAndTrimBody(MallocSpace * space,intptr_t object_size,int round,size_t growth_limit)405 void SpaceTest::SizeFootPrintGrowthLimitAndTrimBody(MallocSpace* space, intptr_t object_size,
406                                                     int round, size_t growth_limit) {
407   if (((object_size > 0 && object_size >= static_cast<intptr_t>(growth_limit))) ||
408       ((object_size < 0 && -object_size >= static_cast<intptr_t>(growth_limit)))) {
409     // No allocation can succeed
410     return;
411   }
412 
413   // The space's footprint equals amount of resources requested from system
414   size_t footprint = space->GetFootprint();
415 
416   // The space must at least have its book keeping allocated
417   EXPECT_GT(footprint, 0u);
418 
419   // But it shouldn't exceed the initial size
420   EXPECT_LE(footprint, growth_limit);
421 
422   // space's size shouldn't exceed the initial size
423   EXPECT_LE(space->Size(), growth_limit);
424 
425   // this invariant should always hold or else the space has grown to be larger than what the
426   // space believes its size is (which will break invariants)
427   EXPECT_GE(space->Size(), footprint);
428 
429   // Fill the space with lots of small objects up to the growth limit
430   size_t max_objects = (growth_limit / (object_size > 0 ? object_size : 8)) + 1;
431   std::unique_ptr<mirror::Object*[]> lots_of_objects(new mirror::Object*[max_objects]);
432   size_t last_object = 0;  // last object for which allocation succeeded
433   size_t amount_allocated = 0;  // amount of space allocated
434   Thread* self = Thread::Current();
435   ScopedObjectAccess soa(self);
436   size_t rand_seed = 123456789;
437   for (size_t i = 0; i < max_objects; i++) {
438     size_t alloc_fails = 0;  // number of failed allocations
439     size_t max_fails = 30;  // number of times we fail allocation before giving up
440     for (; alloc_fails < max_fails; alloc_fails++) {
441       size_t alloc_size;
442       if (object_size > 0) {
443         alloc_size = object_size;
444       } else {
445         alloc_size = test_rand(&rand_seed) % static_cast<size_t>(-object_size);
446         // Note the minimum size, which is the size of a zero-length byte array.
447         size_t size_of_zero_length_byte_array = SizeOfZeroLengthByteArray();
448         if (alloc_size < size_of_zero_length_byte_array) {
449           alloc_size = size_of_zero_length_byte_array;
450         }
451       }
452       StackHandleScope<1> hs(soa.Self());
453       auto object(hs.NewHandle<mirror::Object>(nullptr));
454       size_t bytes_allocated = 0;
455       size_t bytes_tl_bulk_allocated;
456       if (round <= 1) {
457         object.Assign(Alloc(space, self, alloc_size, &bytes_allocated, nullptr,
458                             &bytes_tl_bulk_allocated));
459       } else {
460         object.Assign(AllocWithGrowth(space, self, alloc_size, &bytes_allocated, nullptr,
461                                       &bytes_tl_bulk_allocated));
462       }
463       footprint = space->GetFootprint();
464       EXPECT_GE(space->Size(), footprint);  // invariant
465       if (object.Get() != nullptr) {  // allocation succeeded
466         lots_of_objects[i] = object.Get();
467         size_t allocation_size = space->AllocationSize(object.Get(), nullptr);
468         EXPECT_EQ(bytes_allocated, allocation_size);
469         if (object_size > 0) {
470           EXPECT_GE(allocation_size, static_cast<size_t>(object_size));
471         } else {
472           EXPECT_GE(allocation_size, 8u);
473         }
474         EXPECT_TRUE(bytes_tl_bulk_allocated == 0 ||
475                     bytes_tl_bulk_allocated >= allocation_size);
476         amount_allocated += allocation_size;
477         break;
478       }
479     }
480     if (alloc_fails == max_fails) {
481       last_object = i;
482       break;
483     }
484   }
485   CHECK_NE(last_object, 0u);  // we should have filled the space
486   EXPECT_GT(amount_allocated, 0u);
487 
488   // We shouldn't have gone past the growth_limit
489   EXPECT_LE(amount_allocated, growth_limit);
490   EXPECT_LE(footprint, growth_limit);
491   EXPECT_LE(space->Size(), growth_limit);
492 
493   // footprint and size should agree with amount allocated
494   EXPECT_GE(footprint, amount_allocated);
495   EXPECT_GE(space->Size(), amount_allocated);
496 
497   // Release storage in a semi-adhoc manner
498   size_t free_increment = 96;
499   while (true) {
500     {
501       ScopedThreadStateChange tsc(self, kNative);
502       // Give the space a haircut.
503       space->Trim();
504     }
505 
506     // Bounds sanity
507     footprint = space->GetFootprint();
508     EXPECT_LE(amount_allocated, growth_limit);
509     EXPECT_GE(footprint, amount_allocated);
510     EXPECT_LE(footprint, growth_limit);
511     EXPECT_GE(space->Size(), amount_allocated);
512     EXPECT_LE(space->Size(), growth_limit);
513 
514     if (free_increment == 0) {
515       break;
516     }
517 
518     // Free some objects
519     for (size_t i = 0; i < last_object; i += free_increment) {
520       mirror::Object* object = lots_of_objects.get()[i];
521       if (object == nullptr) {
522         continue;
523       }
524       size_t allocation_size = space->AllocationSize(object, nullptr);
525       if (object_size > 0) {
526         EXPECT_GE(allocation_size, static_cast<size_t>(object_size));
527       } else {
528         EXPECT_GE(allocation_size, 8u);
529       }
530       space->Free(self, object);
531       lots_of_objects.get()[i] = nullptr;
532       amount_allocated -= allocation_size;
533       footprint = space->GetFootprint();
534       EXPECT_GE(space->Size(), footprint);  // invariant
535     }
536 
537     free_increment >>= 1;
538   }
539 
540   // The space has become empty here before allocating a large object
541   // below. For RosAlloc, revoke thread-local runs, which are kept
542   // even when empty for a performance reason, so that they won't
543   // cause the following large object allocation to fail due to
544   // potential fragmentation. Note they are normally revoked at each
545   // GC (but no GC here.)
546   space->RevokeAllThreadLocalBuffers();
547 
548   // All memory was released, try a large allocation to check freed memory is being coalesced
549   StackHandleScope<1> hs(soa.Self());
550   auto large_object(hs.NewHandle<mirror::Object>(nullptr));
551   size_t three_quarters_space = (growth_limit / 2) + (growth_limit / 4);
552   size_t bytes_allocated = 0;
553   size_t bytes_tl_bulk_allocated;
554   if (round <= 1) {
555     large_object.Assign(Alloc(space, self, three_quarters_space, &bytes_allocated, nullptr,
556                               &bytes_tl_bulk_allocated));
557   } else {
558     large_object.Assign(AllocWithGrowth(space, self, three_quarters_space, &bytes_allocated,
559                                         nullptr, &bytes_tl_bulk_allocated));
560   }
561   EXPECT_TRUE(large_object.Get() != nullptr);
562 
563   // Sanity check footprint
564   footprint = space->GetFootprint();
565   EXPECT_LE(footprint, growth_limit);
566   EXPECT_GE(space->Size(), footprint);
567   EXPECT_LE(space->Size(), growth_limit);
568 
569   // Clean up
570   space->Free(self, large_object.Assign(nullptr));
571 
572   // Sanity check footprint
573   footprint = space->GetFootprint();
574   EXPECT_LE(footprint, growth_limit);
575   EXPECT_GE(space->Size(), footprint);
576   EXPECT_LE(space->Size(), growth_limit);
577 }
578 
SizeFootPrintGrowthLimitAndTrimDriver(size_t object_size,CreateSpaceFn create_space)579 void SpaceTest::SizeFootPrintGrowthLimitAndTrimDriver(size_t object_size, CreateSpaceFn create_space) {
580   if (object_size < SizeOfZeroLengthByteArray()) {
581     // Too small for the object layout/model.
582     return;
583   }
584   size_t initial_size = 4 * MB;
585   size_t growth_limit = 8 * MB;
586   size_t capacity = 16 * MB;
587   MallocSpace* space(create_space("test", initial_size, growth_limit, capacity, nullptr));
588   ASSERT_TRUE(space != nullptr);
589 
590   // Basic sanity
591   EXPECT_EQ(space->Capacity(), growth_limit);
592   EXPECT_EQ(space->NonGrowthLimitCapacity(), capacity);
593 
594   // Make space findable to the heap, will also delete space when runtime is cleaned up
595   AddSpace(space);
596 
597   // In this round we don't allocate with growth and therefore can't grow past the initial size.
598   // This effectively makes the growth_limit the initial_size, so assert this.
599   SizeFootPrintGrowthLimitAndTrimBody(space, object_size, 1, initial_size);
600   SizeFootPrintGrowthLimitAndTrimBody(space, object_size, 2, growth_limit);
601   // Remove growth limit
602   space->ClearGrowthLimit();
603   EXPECT_EQ(space->Capacity(), capacity);
604   SizeFootPrintGrowthLimitAndTrimBody(space, object_size, 3, capacity);
605 }
606 
607 #define TEST_SizeFootPrintGrowthLimitAndTrimStatic(name, spaceName, spaceFn, size) \
608   TEST_F(spaceName##StaticTest, SizeFootPrintGrowthLimitAndTrim_AllocationsOf_##name) { \
609     SizeFootPrintGrowthLimitAndTrimDriver(size, spaceFn); \
610   }
611 
612 #define TEST_SizeFootPrintGrowthLimitAndTrimRandom(name, spaceName, spaceFn, size) \
613   TEST_F(spaceName##RandomTest, SizeFootPrintGrowthLimitAndTrim_RandomAllocationsWithMax_##name) { \
614     SizeFootPrintGrowthLimitAndTrimDriver(-size, spaceFn); \
615   }
616 
617 #define TEST_SPACE_CREATE_FN_BASE(spaceName, spaceFn) \
618   class spaceName##BaseTest : public SpaceTest { \
619   }; \
620   \
621   TEST_F(spaceName##BaseTest, Init) { \
622     InitTestBody(spaceFn); \
623   } \
624   TEST_F(spaceName##BaseTest, ZygoteSpace) { \
625     ZygoteSpaceTestBody(spaceFn); \
626   } \
627   TEST_F(spaceName##BaseTest, AllocAndFree) { \
628     AllocAndFreeTestBody(spaceFn); \
629   } \
630   TEST_F(spaceName##BaseTest, AllocAndFreeList) { \
631     AllocAndFreeListTestBody(spaceFn); \
632   }
633 
634 #define TEST_SPACE_CREATE_FN_STATIC(spaceName, spaceFn) \
635   class spaceName##StaticTest : public SpaceTest { \
636   }; \
637   \
638   TEST_SizeFootPrintGrowthLimitAndTrimStatic(12B, spaceName, spaceFn, 12) \
639   TEST_SizeFootPrintGrowthLimitAndTrimStatic(16B, spaceName, spaceFn, 16) \
640   TEST_SizeFootPrintGrowthLimitAndTrimStatic(24B, spaceName, spaceFn, 24) \
641   TEST_SizeFootPrintGrowthLimitAndTrimStatic(32B, spaceName, spaceFn, 32) \
642   TEST_SizeFootPrintGrowthLimitAndTrimStatic(64B, spaceName, spaceFn, 64) \
643   TEST_SizeFootPrintGrowthLimitAndTrimStatic(128B, spaceName, spaceFn, 128) \
644   TEST_SizeFootPrintGrowthLimitAndTrimStatic(1KB, spaceName, spaceFn, 1 * KB) \
645   TEST_SizeFootPrintGrowthLimitAndTrimStatic(4KB, spaceName, spaceFn, 4 * KB) \
646   TEST_SizeFootPrintGrowthLimitAndTrimStatic(1MB, spaceName, spaceFn, 1 * MB) \
647   TEST_SizeFootPrintGrowthLimitAndTrimStatic(4MB, spaceName, spaceFn, 4 * MB) \
648   TEST_SizeFootPrintGrowthLimitAndTrimStatic(8MB, spaceName, spaceFn, 8 * MB)
649 
650 #define TEST_SPACE_CREATE_FN_RANDOM(spaceName, spaceFn) \
651   class spaceName##RandomTest : public SpaceTest { \
652   }; \
653   \
654   TEST_SizeFootPrintGrowthLimitAndTrimRandom(16B, spaceName, spaceFn, 16) \
655   TEST_SizeFootPrintGrowthLimitAndTrimRandom(24B, spaceName, spaceFn, 24) \
656   TEST_SizeFootPrintGrowthLimitAndTrimRandom(32B, spaceName, spaceFn, 32) \
657   TEST_SizeFootPrintGrowthLimitAndTrimRandom(64B, spaceName, spaceFn, 64) \
658   TEST_SizeFootPrintGrowthLimitAndTrimRandom(128B, spaceName, spaceFn, 128) \
659   TEST_SizeFootPrintGrowthLimitAndTrimRandom(1KB, spaceName, spaceFn, 1 * KB) \
660   TEST_SizeFootPrintGrowthLimitAndTrimRandom(4KB, spaceName, spaceFn, 4 * KB) \
661   TEST_SizeFootPrintGrowthLimitAndTrimRandom(1MB, spaceName, spaceFn, 1 * MB) \
662   TEST_SizeFootPrintGrowthLimitAndTrimRandom(4MB, spaceName, spaceFn, 4 * MB) \
663   TEST_SizeFootPrintGrowthLimitAndTrimRandom(8MB, spaceName, spaceFn, 8 * MB)
664 
665 }  // namespace space
666 }  // namespace gc
667 }  // namespace art
668 
669 #endif  // ART_RUNTIME_GC_SPACE_SPACE_TEST_H_
670