1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2011 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_RUNTIME_GC_SPACE_SPACE_TEST_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_GC_SPACE_SPACE_TEST_H_
19*795d594fSAndroid Build Coastguard Worker
20*795d594fSAndroid Build Coastguard Worker #include <stdint.h>
21*795d594fSAndroid Build Coastguard Worker #include <memory>
22*795d594fSAndroid Build Coastguard Worker
23*795d594fSAndroid Build Coastguard Worker #include "common_runtime_test.h"
24*795d594fSAndroid Build Coastguard Worker #include "handle_scope-inl.h"
25*795d594fSAndroid Build Coastguard Worker #include "mirror/array-inl.h"
26*795d594fSAndroid Build Coastguard Worker #include "mirror/class-inl.h"
27*795d594fSAndroid Build Coastguard Worker #include "mirror/class_loader.h"
28*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
29*795d594fSAndroid Build Coastguard Worker #include "runtime_globals.h"
30*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
31*795d594fSAndroid Build Coastguard Worker #include "thread_list.h"
32*795d594fSAndroid Build Coastguard Worker #include "zygote_space.h"
33*795d594fSAndroid Build Coastguard Worker
34*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
35*795d594fSAndroid Build Coastguard Worker namespace gc {
36*795d594fSAndroid Build Coastguard Worker namespace space {
37*795d594fSAndroid Build Coastguard Worker
38*795d594fSAndroid Build Coastguard Worker template <class Super>
39*795d594fSAndroid Build Coastguard Worker class SpaceTest : public Super {
40*795d594fSAndroid Build Coastguard Worker public:
41*795d594fSAndroid Build Coastguard Worker jobject byte_array_class_ = nullptr;
42*795d594fSAndroid Build Coastguard Worker
43*795d594fSAndroid Build Coastguard Worker void AddSpace(ContinuousSpace* space, bool revoke = true) {
44*795d594fSAndroid Build Coastguard Worker Heap* heap = Runtime::Current()->GetHeap();
45*795d594fSAndroid Build Coastguard Worker if (revoke) {
46*795d594fSAndroid Build Coastguard Worker heap->RevokeAllThreadLocalBuffers();
47*795d594fSAndroid Build Coastguard Worker }
48*795d594fSAndroid Build Coastguard Worker {
49*795d594fSAndroid Build Coastguard Worker ScopedThreadStateChange sts(Thread::Current(), ThreadState::kSuspended);
50*795d594fSAndroid Build Coastguard Worker ScopedSuspendAll ssa("Add image space");
51*795d594fSAndroid Build Coastguard Worker heap->AddSpace(space);
52*795d594fSAndroid Build Coastguard Worker }
53*795d594fSAndroid Build Coastguard Worker heap->SetSpaceAsDefault(space);
54*795d594fSAndroid Build Coastguard Worker }
55*795d594fSAndroid Build Coastguard Worker
GetByteArrayClass(Thread * self)56*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> GetByteArrayClass(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) {
57*795d594fSAndroid Build Coastguard Worker if (byte_array_class_ == nullptr) {
58*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Class> byte_array_class =
59*795d594fSAndroid Build Coastguard Worker Runtime::Current()->GetClassLinker()->FindSystemClass(self, "[B");
60*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(byte_array_class != nullptr);
61*795d594fSAndroid Build Coastguard Worker byte_array_class_ = self->GetJniEnv()->NewLocalRef(byte_array_class.Ptr());
62*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(byte_array_class_ != nullptr);
63*795d594fSAndroid Build Coastguard Worker }
64*795d594fSAndroid Build Coastguard Worker return self->DecodeJObject(byte_array_class_)->AsClass();
65*795d594fSAndroid Build Coastguard Worker }
66*795d594fSAndroid Build Coastguard Worker
Alloc(space::MallocSpace * alloc_space,Thread * self,size_t bytes,size_t * bytes_allocated,size_t * usable_size,size_t * bytes_tl_bulk_allocated)67*795d594fSAndroid Build Coastguard Worker mirror::Object* Alloc(space::MallocSpace* alloc_space,
68*795d594fSAndroid Build Coastguard Worker Thread* self,
69*795d594fSAndroid Build Coastguard Worker size_t bytes,
70*795d594fSAndroid Build Coastguard Worker size_t* bytes_allocated,
71*795d594fSAndroid Build Coastguard Worker size_t* usable_size,
72*795d594fSAndroid Build Coastguard Worker size_t* bytes_tl_bulk_allocated)
73*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
74*795d594fSAndroid Build Coastguard Worker StackHandleScope<1> hs(self);
75*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> byte_array_class(hs.NewHandle(GetByteArrayClass(self)));
76*795d594fSAndroid Build Coastguard Worker mirror::Object* obj = alloc_space->Alloc(self,
77*795d594fSAndroid Build Coastguard Worker bytes,
78*795d594fSAndroid Build Coastguard Worker bytes_allocated,
79*795d594fSAndroid Build Coastguard Worker usable_size,
80*795d594fSAndroid Build Coastguard Worker bytes_tl_bulk_allocated);
81*795d594fSAndroid Build Coastguard Worker if (obj != nullptr) {
82*795d594fSAndroid Build Coastguard Worker InstallClass(obj, byte_array_class.Get(), bytes);
83*795d594fSAndroid Build Coastguard Worker }
84*795d594fSAndroid Build Coastguard Worker return obj;
85*795d594fSAndroid Build Coastguard Worker }
86*795d594fSAndroid Build Coastguard Worker
AllocWithGrowth(space::MallocSpace * alloc_space,Thread * self,size_t bytes,size_t * bytes_allocated,size_t * usable_size,size_t * bytes_tl_bulk_allocated)87*795d594fSAndroid Build Coastguard Worker mirror::Object* AllocWithGrowth(space::MallocSpace* alloc_space,
88*795d594fSAndroid Build Coastguard Worker Thread* self,
89*795d594fSAndroid Build Coastguard Worker size_t bytes,
90*795d594fSAndroid Build Coastguard Worker size_t* bytes_allocated,
91*795d594fSAndroid Build Coastguard Worker size_t* usable_size,
92*795d594fSAndroid Build Coastguard Worker size_t* bytes_tl_bulk_allocated)
93*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
94*795d594fSAndroid Build Coastguard Worker StackHandleScope<1> hs(self);
95*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> byte_array_class(hs.NewHandle(GetByteArrayClass(self)));
96*795d594fSAndroid Build Coastguard Worker mirror::Object* obj = alloc_space->AllocWithGrowth(self, bytes, bytes_allocated, usable_size,
97*795d594fSAndroid Build Coastguard Worker bytes_tl_bulk_allocated);
98*795d594fSAndroid Build Coastguard Worker if (obj != nullptr) {
99*795d594fSAndroid Build Coastguard Worker InstallClass(obj, byte_array_class.Get(), bytes);
100*795d594fSAndroid Build Coastguard Worker }
101*795d594fSAndroid Build Coastguard Worker return obj;
102*795d594fSAndroid Build Coastguard Worker }
103*795d594fSAndroid Build Coastguard Worker
InstallClass(mirror::Object * o,mirror::Class * byte_array_class,size_t size)104*795d594fSAndroid Build Coastguard Worker void InstallClass(mirror::Object* o, mirror::Class* byte_array_class, size_t size)
105*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
106*795d594fSAndroid Build Coastguard Worker // Note the minimum size, which is the size of a zero-length byte array.
107*795d594fSAndroid Build Coastguard Worker EXPECT_GE(size, SizeOfZeroLengthByteArray());
108*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(byte_array_class != nullptr);
109*795d594fSAndroid Build Coastguard Worker o->SetClass(byte_array_class);
110*795d594fSAndroid Build Coastguard Worker if (kUseBakerReadBarrier) {
111*795d594fSAndroid Build Coastguard Worker // Like the proper heap object allocation, install and verify
112*795d594fSAndroid Build Coastguard Worker // the correct read barrier state.
113*795d594fSAndroid Build Coastguard Worker o->AssertReadBarrierState();
114*795d594fSAndroid Build Coastguard Worker }
115*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::Array> arr = o->AsArray<kVerifyNone>();
116*795d594fSAndroid Build Coastguard Worker size_t header_size = SizeOfZeroLengthByteArray();
117*795d594fSAndroid Build Coastguard Worker int32_t length = size - header_size;
118*795d594fSAndroid Build Coastguard Worker arr->SetLength(length);
119*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(arr->SizeOf<kVerifyNone>(), size);
120*795d594fSAndroid Build Coastguard Worker }
121*795d594fSAndroid Build Coastguard Worker
SizeOfZeroLengthByteArray()122*795d594fSAndroid Build Coastguard Worker static size_t SizeOfZeroLengthByteArray() {
123*795d594fSAndroid Build Coastguard Worker return mirror::Array::DataOffset(Primitive::ComponentSize(Primitive::kPrimByte)).Uint32Value();
124*795d594fSAndroid Build Coastguard Worker }
125*795d594fSAndroid Build Coastguard Worker
126*795d594fSAndroid Build Coastguard Worker typedef MallocSpace* (*CreateSpaceFn)(const std::string& name,
127*795d594fSAndroid Build Coastguard Worker size_t initial_size,
128*795d594fSAndroid Build Coastguard Worker size_t growth_limit,
129*795d594fSAndroid Build Coastguard Worker size_t capacity);
130*795d594fSAndroid Build Coastguard Worker
131*795d594fSAndroid Build Coastguard Worker void SizeFootPrintGrowthLimitAndTrimBody(MallocSpace* space, intptr_t object_size,
132*795d594fSAndroid Build Coastguard Worker int round, size_t growth_limit);
133*795d594fSAndroid Build Coastguard Worker void SizeFootPrintGrowthLimitAndTrimDriver(size_t object_size, CreateSpaceFn create_space);
134*795d594fSAndroid Build Coastguard Worker };
135*795d594fSAndroid Build Coastguard Worker
test_rand(size_t * seed)136*795d594fSAndroid Build Coastguard Worker static inline size_t test_rand(size_t* seed) {
137*795d594fSAndroid Build Coastguard Worker *seed = *seed * 1103515245 + 12345;
138*795d594fSAndroid Build Coastguard Worker return *seed;
139*795d594fSAndroid Build Coastguard Worker }
140*795d594fSAndroid Build Coastguard Worker
141*795d594fSAndroid Build Coastguard Worker template <class Super>
SizeFootPrintGrowthLimitAndTrimBody(MallocSpace * space,intptr_t object_size,int round,size_t growth_limit)142*795d594fSAndroid Build Coastguard Worker void SpaceTest<Super>::SizeFootPrintGrowthLimitAndTrimBody(MallocSpace* space,
143*795d594fSAndroid Build Coastguard Worker intptr_t object_size,
144*795d594fSAndroid Build Coastguard Worker int round,
145*795d594fSAndroid Build Coastguard Worker size_t growth_limit) {
146*795d594fSAndroid Build Coastguard Worker if (((object_size > 0 && object_size >= static_cast<intptr_t>(growth_limit))) ||
147*795d594fSAndroid Build Coastguard Worker ((object_size < 0 && -object_size >= static_cast<intptr_t>(growth_limit)))) {
148*795d594fSAndroid Build Coastguard Worker // No allocation can succeed
149*795d594fSAndroid Build Coastguard Worker return;
150*795d594fSAndroid Build Coastguard Worker }
151*795d594fSAndroid Build Coastguard Worker
152*795d594fSAndroid Build Coastguard Worker // The space's footprint equals amount of resources requested from system
153*795d594fSAndroid Build Coastguard Worker size_t footprint = space->GetFootprint();
154*795d594fSAndroid Build Coastguard Worker
155*795d594fSAndroid Build Coastguard Worker // The space must at least have its book keeping allocated
156*795d594fSAndroid Build Coastguard Worker EXPECT_GT(footprint, 0u);
157*795d594fSAndroid Build Coastguard Worker
158*795d594fSAndroid Build Coastguard Worker // But it shouldn't exceed the initial size
159*795d594fSAndroid Build Coastguard Worker EXPECT_LE(footprint, growth_limit);
160*795d594fSAndroid Build Coastguard Worker
161*795d594fSAndroid Build Coastguard Worker // space's size shouldn't exceed the initial size
162*795d594fSAndroid Build Coastguard Worker EXPECT_LE(space->Size(), growth_limit);
163*795d594fSAndroid Build Coastguard Worker
164*795d594fSAndroid Build Coastguard Worker // this invariant should always hold or else the space has grown to be larger than what the
165*795d594fSAndroid Build Coastguard Worker // space believes its size is (which will break invariants)
166*795d594fSAndroid Build Coastguard Worker EXPECT_GE(space->Size(), footprint);
167*795d594fSAndroid Build Coastguard Worker
168*795d594fSAndroid Build Coastguard Worker // Fill the space with lots of small objects up to the growth limit
169*795d594fSAndroid Build Coastguard Worker size_t max_objects = (growth_limit / (object_size > 0 ? object_size : 8)) + 1;
170*795d594fSAndroid Build Coastguard Worker std::unique_ptr<mirror::Object*[]> lots_of_objects(new mirror::Object*[max_objects]);
171*795d594fSAndroid Build Coastguard Worker size_t last_object = 0; // last object for which allocation succeeded
172*795d594fSAndroid Build Coastguard Worker size_t amount_allocated = 0; // amount of space allocated
173*795d594fSAndroid Build Coastguard Worker Thread* self = Thread::Current();
174*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(self);
175*795d594fSAndroid Build Coastguard Worker size_t rand_seed = 123456789;
176*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < max_objects; i++) {
177*795d594fSAndroid Build Coastguard Worker size_t alloc_fails = 0; // number of failed allocations
178*795d594fSAndroid Build Coastguard Worker size_t max_fails = 30; // number of times we fail allocation before giving up
179*795d594fSAndroid Build Coastguard Worker for (; alloc_fails < max_fails; alloc_fails++) {
180*795d594fSAndroid Build Coastguard Worker size_t alloc_size;
181*795d594fSAndroid Build Coastguard Worker if (object_size > 0) {
182*795d594fSAndroid Build Coastguard Worker alloc_size = object_size;
183*795d594fSAndroid Build Coastguard Worker } else {
184*795d594fSAndroid Build Coastguard Worker alloc_size = test_rand(&rand_seed) % static_cast<size_t>(-object_size);
185*795d594fSAndroid Build Coastguard Worker // Note the minimum size, which is the size of a zero-length byte array.
186*795d594fSAndroid Build Coastguard Worker size_t size_of_zero_length_byte_array = SizeOfZeroLengthByteArray();
187*795d594fSAndroid Build Coastguard Worker if (alloc_size < size_of_zero_length_byte_array) {
188*795d594fSAndroid Build Coastguard Worker alloc_size = size_of_zero_length_byte_array;
189*795d594fSAndroid Build Coastguard Worker }
190*795d594fSAndroid Build Coastguard Worker }
191*795d594fSAndroid Build Coastguard Worker StackHandleScope<1> hs(soa.Self());
192*795d594fSAndroid Build Coastguard Worker auto object(hs.NewHandle<mirror::Object>(nullptr));
193*795d594fSAndroid Build Coastguard Worker size_t bytes_allocated = 0;
194*795d594fSAndroid Build Coastguard Worker size_t bytes_tl_bulk_allocated;
195*795d594fSAndroid Build Coastguard Worker if (round <= 1) {
196*795d594fSAndroid Build Coastguard Worker object.Assign(Alloc(space, self, alloc_size, &bytes_allocated, nullptr,
197*795d594fSAndroid Build Coastguard Worker &bytes_tl_bulk_allocated));
198*795d594fSAndroid Build Coastguard Worker } else {
199*795d594fSAndroid Build Coastguard Worker object.Assign(AllocWithGrowth(space, self, alloc_size, &bytes_allocated, nullptr,
200*795d594fSAndroid Build Coastguard Worker &bytes_tl_bulk_allocated));
201*795d594fSAndroid Build Coastguard Worker }
202*795d594fSAndroid Build Coastguard Worker footprint = space->GetFootprint();
203*795d594fSAndroid Build Coastguard Worker EXPECT_GE(space->Size(), footprint); // invariant
204*795d594fSAndroid Build Coastguard Worker if (object != nullptr) { // allocation succeeded
205*795d594fSAndroid Build Coastguard Worker lots_of_objects[i] = object.Get();
206*795d594fSAndroid Build Coastguard Worker size_t allocation_size = space->AllocationSize(object.Get(), nullptr);
207*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(bytes_allocated, allocation_size);
208*795d594fSAndroid Build Coastguard Worker if (object_size > 0) {
209*795d594fSAndroid Build Coastguard Worker EXPECT_GE(allocation_size, static_cast<size_t>(object_size));
210*795d594fSAndroid Build Coastguard Worker } else {
211*795d594fSAndroid Build Coastguard Worker EXPECT_GE(allocation_size, 8u);
212*795d594fSAndroid Build Coastguard Worker }
213*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(bytes_tl_bulk_allocated == 0 ||
214*795d594fSAndroid Build Coastguard Worker bytes_tl_bulk_allocated >= allocation_size);
215*795d594fSAndroid Build Coastguard Worker amount_allocated += allocation_size;
216*795d594fSAndroid Build Coastguard Worker break;
217*795d594fSAndroid Build Coastguard Worker }
218*795d594fSAndroid Build Coastguard Worker }
219*795d594fSAndroid Build Coastguard Worker if (alloc_fails == max_fails) {
220*795d594fSAndroid Build Coastguard Worker last_object = i;
221*795d594fSAndroid Build Coastguard Worker break;
222*795d594fSAndroid Build Coastguard Worker }
223*795d594fSAndroid Build Coastguard Worker }
224*795d594fSAndroid Build Coastguard Worker CHECK_NE(last_object, 0u); // we should have filled the space
225*795d594fSAndroid Build Coastguard Worker EXPECT_GT(amount_allocated, 0u);
226*795d594fSAndroid Build Coastguard Worker
227*795d594fSAndroid Build Coastguard Worker // We shouldn't have gone past the growth_limit
228*795d594fSAndroid Build Coastguard Worker EXPECT_LE(amount_allocated, growth_limit);
229*795d594fSAndroid Build Coastguard Worker EXPECT_LE(footprint, growth_limit);
230*795d594fSAndroid Build Coastguard Worker EXPECT_LE(space->Size(), growth_limit);
231*795d594fSAndroid Build Coastguard Worker
232*795d594fSAndroid Build Coastguard Worker // footprint and size should agree with amount allocated
233*795d594fSAndroid Build Coastguard Worker EXPECT_GE(footprint, amount_allocated);
234*795d594fSAndroid Build Coastguard Worker EXPECT_GE(space->Size(), amount_allocated);
235*795d594fSAndroid Build Coastguard Worker
236*795d594fSAndroid Build Coastguard Worker // Release storage in a semi-adhoc manner
237*795d594fSAndroid Build Coastguard Worker size_t free_increment = 96;
238*795d594fSAndroid Build Coastguard Worker while (true) {
239*795d594fSAndroid Build Coastguard Worker {
240*795d594fSAndroid Build Coastguard Worker ScopedThreadStateChange tsc(self, ThreadState::kNative);
241*795d594fSAndroid Build Coastguard Worker // Give the space a haircut.
242*795d594fSAndroid Build Coastguard Worker space->Trim();
243*795d594fSAndroid Build Coastguard Worker }
244*795d594fSAndroid Build Coastguard Worker
245*795d594fSAndroid Build Coastguard Worker // Bounds consistency check.
246*795d594fSAndroid Build Coastguard Worker footprint = space->GetFootprint();
247*795d594fSAndroid Build Coastguard Worker EXPECT_LE(amount_allocated, growth_limit);
248*795d594fSAndroid Build Coastguard Worker EXPECT_GE(footprint, amount_allocated);
249*795d594fSAndroid Build Coastguard Worker EXPECT_LE(footprint, growth_limit);
250*795d594fSAndroid Build Coastguard Worker EXPECT_GE(space->Size(), amount_allocated);
251*795d594fSAndroid Build Coastguard Worker EXPECT_LE(space->Size(), growth_limit);
252*795d594fSAndroid Build Coastguard Worker
253*795d594fSAndroid Build Coastguard Worker if (free_increment == 0) {
254*795d594fSAndroid Build Coastguard Worker break;
255*795d594fSAndroid Build Coastguard Worker }
256*795d594fSAndroid Build Coastguard Worker
257*795d594fSAndroid Build Coastguard Worker // Free some objects
258*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < last_object; i += free_increment) {
259*795d594fSAndroid Build Coastguard Worker mirror::Object* object = lots_of_objects.get()[i];
260*795d594fSAndroid Build Coastguard Worker if (object == nullptr) {
261*795d594fSAndroid Build Coastguard Worker continue;
262*795d594fSAndroid Build Coastguard Worker }
263*795d594fSAndroid Build Coastguard Worker size_t allocation_size = space->AllocationSize(object, nullptr);
264*795d594fSAndroid Build Coastguard Worker if (object_size > 0) {
265*795d594fSAndroid Build Coastguard Worker EXPECT_GE(allocation_size, static_cast<size_t>(object_size));
266*795d594fSAndroid Build Coastguard Worker } else {
267*795d594fSAndroid Build Coastguard Worker EXPECT_GE(allocation_size, 8u);
268*795d594fSAndroid Build Coastguard Worker }
269*795d594fSAndroid Build Coastguard Worker space->Free(self, object);
270*795d594fSAndroid Build Coastguard Worker lots_of_objects.get()[i] = nullptr;
271*795d594fSAndroid Build Coastguard Worker amount_allocated -= allocation_size;
272*795d594fSAndroid Build Coastguard Worker footprint = space->GetFootprint();
273*795d594fSAndroid Build Coastguard Worker EXPECT_GE(space->Size(), footprint); // invariant
274*795d594fSAndroid Build Coastguard Worker }
275*795d594fSAndroid Build Coastguard Worker
276*795d594fSAndroid Build Coastguard Worker free_increment >>= 1;
277*795d594fSAndroid Build Coastguard Worker }
278*795d594fSAndroid Build Coastguard Worker
279*795d594fSAndroid Build Coastguard Worker // The space has become empty here before allocating a large object
280*795d594fSAndroid Build Coastguard Worker // below. For RosAlloc, revoke thread-local runs, which are kept
281*795d594fSAndroid Build Coastguard Worker // even when empty for a performance reason, so that they won't
282*795d594fSAndroid Build Coastguard Worker // cause the following large object allocation to fail due to
283*795d594fSAndroid Build Coastguard Worker // potential fragmentation. Note they are normally revoked at each
284*795d594fSAndroid Build Coastguard Worker // GC (but no GC here.)
285*795d594fSAndroid Build Coastguard Worker space->RevokeAllThreadLocalBuffers();
286*795d594fSAndroid Build Coastguard Worker
287*795d594fSAndroid Build Coastguard Worker // All memory was released, try a large allocation to check freed memory is being coalesced
288*795d594fSAndroid Build Coastguard Worker StackHandleScope<1> hs(soa.Self());
289*795d594fSAndroid Build Coastguard Worker auto large_object(hs.NewHandle<mirror::Object>(nullptr));
290*795d594fSAndroid Build Coastguard Worker size_t three_quarters_space = (growth_limit / 2) + (growth_limit / 4);
291*795d594fSAndroid Build Coastguard Worker size_t bytes_allocated = 0;
292*795d594fSAndroid Build Coastguard Worker size_t bytes_tl_bulk_allocated;
293*795d594fSAndroid Build Coastguard Worker if (round <= 1) {
294*795d594fSAndroid Build Coastguard Worker large_object.Assign(Alloc(space, self, three_quarters_space, &bytes_allocated, nullptr,
295*795d594fSAndroid Build Coastguard Worker &bytes_tl_bulk_allocated));
296*795d594fSAndroid Build Coastguard Worker } else {
297*795d594fSAndroid Build Coastguard Worker large_object.Assign(AllocWithGrowth(space, self, three_quarters_space, &bytes_allocated,
298*795d594fSAndroid Build Coastguard Worker nullptr, &bytes_tl_bulk_allocated));
299*795d594fSAndroid Build Coastguard Worker }
300*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(large_object != nullptr);
301*795d594fSAndroid Build Coastguard Worker
302*795d594fSAndroid Build Coastguard Worker // Consistency check of the footprint.
303*795d594fSAndroid Build Coastguard Worker footprint = space->GetFootprint();
304*795d594fSAndroid Build Coastguard Worker EXPECT_LE(footprint, growth_limit);
305*795d594fSAndroid Build Coastguard Worker EXPECT_GE(space->Size(), footprint);
306*795d594fSAndroid Build Coastguard Worker EXPECT_LE(space->Size(), growth_limit);
307*795d594fSAndroid Build Coastguard Worker
308*795d594fSAndroid Build Coastguard Worker // Clean up.
309*795d594fSAndroid Build Coastguard Worker space->Free(self, large_object.Assign(nullptr));
310*795d594fSAndroid Build Coastguard Worker
311*795d594fSAndroid Build Coastguard Worker // Consistency check of the footprint.
312*795d594fSAndroid Build Coastguard Worker footprint = space->GetFootprint();
313*795d594fSAndroid Build Coastguard Worker EXPECT_LE(footprint, growth_limit);
314*795d594fSAndroid Build Coastguard Worker EXPECT_GE(space->Size(), footprint);
315*795d594fSAndroid Build Coastguard Worker EXPECT_LE(space->Size(), growth_limit);
316*795d594fSAndroid Build Coastguard Worker }
317*795d594fSAndroid Build Coastguard Worker
318*795d594fSAndroid Build Coastguard Worker template <class Super>
SizeFootPrintGrowthLimitAndTrimDriver(size_t object_size,CreateSpaceFn create_space)319*795d594fSAndroid Build Coastguard Worker void SpaceTest<Super>::SizeFootPrintGrowthLimitAndTrimDriver(size_t object_size,
320*795d594fSAndroid Build Coastguard Worker CreateSpaceFn create_space) {
321*795d594fSAndroid Build Coastguard Worker if (object_size < SizeOfZeroLengthByteArray()) {
322*795d594fSAndroid Build Coastguard Worker // Too small for the object layout/model.
323*795d594fSAndroid Build Coastguard Worker return;
324*795d594fSAndroid Build Coastguard Worker }
325*795d594fSAndroid Build Coastguard Worker size_t initial_size = 4 * MB;
326*795d594fSAndroid Build Coastguard Worker size_t growth_limit = 8 * MB;
327*795d594fSAndroid Build Coastguard Worker size_t capacity = 16 * MB;
328*795d594fSAndroid Build Coastguard Worker MallocSpace* space(create_space("test", initial_size, growth_limit, capacity));
329*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(space != nullptr);
330*795d594fSAndroid Build Coastguard Worker
331*795d594fSAndroid Build Coastguard Worker // Basic consistency check.
332*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(space->Capacity(), growth_limit);
333*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(space->NonGrowthLimitCapacity(), capacity);
334*795d594fSAndroid Build Coastguard Worker
335*795d594fSAndroid Build Coastguard Worker // Make space findable to the heap, will also delete space when runtime is cleaned up
336*795d594fSAndroid Build Coastguard Worker AddSpace(space);
337*795d594fSAndroid Build Coastguard Worker
338*795d594fSAndroid Build Coastguard Worker // In this round we don't allocate with growth and therefore can't grow past the initial size.
339*795d594fSAndroid Build Coastguard Worker // This effectively makes the growth_limit the initial_size, so assert this.
340*795d594fSAndroid Build Coastguard Worker SizeFootPrintGrowthLimitAndTrimBody(space, object_size, 1, initial_size);
341*795d594fSAndroid Build Coastguard Worker SizeFootPrintGrowthLimitAndTrimBody(space, object_size, 2, growth_limit);
342*795d594fSAndroid Build Coastguard Worker // Remove growth limit
343*795d594fSAndroid Build Coastguard Worker space->ClearGrowthLimit();
344*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(space->Capacity(), capacity);
345*795d594fSAndroid Build Coastguard Worker SizeFootPrintGrowthLimitAndTrimBody(space, object_size, 3, capacity);
346*795d594fSAndroid Build Coastguard Worker }
347*795d594fSAndroid Build Coastguard Worker
348*795d594fSAndroid Build Coastguard Worker #define TEST_SizeFootPrintGrowthLimitAndTrimStatic(name, spaceName, spaceFn, size) \
349*795d594fSAndroid Build Coastguard Worker TEST_F(spaceName##StaticTest, SizeFootPrintGrowthLimitAndTrim_AllocationsOf_##name) { \
350*795d594fSAndroid Build Coastguard Worker SizeFootPrintGrowthLimitAndTrimDriver(size, spaceFn); \
351*795d594fSAndroid Build Coastguard Worker }
352*795d594fSAndroid Build Coastguard Worker
353*795d594fSAndroid Build Coastguard Worker #define TEST_SizeFootPrintGrowthLimitAndTrimRandom(name, spaceName, spaceFn, size) \
354*795d594fSAndroid Build Coastguard Worker TEST_F(spaceName##RandomTest, SizeFootPrintGrowthLimitAndTrim_RandomAllocationsWithMax_##name) { \
355*795d594fSAndroid Build Coastguard Worker SizeFootPrintGrowthLimitAndTrimDriver(-(size), spaceFn); \
356*795d594fSAndroid Build Coastguard Worker }
357*795d594fSAndroid Build Coastguard Worker
358*795d594fSAndroid Build Coastguard Worker #define TEST_SPACE_CREATE_FN_STATIC(spaceName, spaceFn) \
359*795d594fSAndroid Build Coastguard Worker class spaceName##StaticTest : public SpaceTest<CommonRuntimeTest> { \
360*795d594fSAndroid Build Coastguard Worker }; \
361*795d594fSAndroid Build Coastguard Worker \
362*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimStatic(12B, spaceName, spaceFn, 12) \
363*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimStatic(16B, spaceName, spaceFn, 16) \
364*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimStatic(24B, spaceName, spaceFn, 24) \
365*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimStatic(32B, spaceName, spaceFn, 32) \
366*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimStatic(64B, spaceName, spaceFn, 64) \
367*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimStatic(128B, spaceName, spaceFn, 128) \
368*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimStatic(1KB, spaceName, spaceFn, 1 * KB) \
369*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimStatic(4KB, spaceName, spaceFn, 4 * KB) \
370*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimStatic(1MB, spaceName, spaceFn, 1 * MB) \
371*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimStatic(4MB, spaceName, spaceFn, 4 * MB) \
372*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimStatic(8MB, spaceName, spaceFn, 8 * MB)
373*795d594fSAndroid Build Coastguard Worker
374*795d594fSAndroid Build Coastguard Worker #define TEST_SPACE_CREATE_FN_RANDOM(spaceName, spaceFn) \
375*795d594fSAndroid Build Coastguard Worker class spaceName##RandomTest : public SpaceTest<CommonRuntimeTest> { \
376*795d594fSAndroid Build Coastguard Worker }; \
377*795d594fSAndroid Build Coastguard Worker \
378*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimRandom(16B, spaceName, spaceFn, 16) \
379*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimRandom(24B, spaceName, spaceFn, 24) \
380*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimRandom(32B, spaceName, spaceFn, 32) \
381*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimRandom(64B, spaceName, spaceFn, 64) \
382*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimRandom(128B, spaceName, spaceFn, 128) \
383*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimRandom(1KB, spaceName, spaceFn, 1 * KB) \
384*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimRandom(4KB, spaceName, spaceFn, 4 * KB) \
385*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimRandom(1MB, spaceName, spaceFn, 1 * MB) \
386*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimRandom(4MB, spaceName, spaceFn, 4 * MB) \
387*795d594fSAndroid Build Coastguard Worker TEST_SizeFootPrintGrowthLimitAndTrimRandom(8MB, spaceName, spaceFn, 8 * MB)
388*795d594fSAndroid Build Coastguard Worker
389*795d594fSAndroid Build Coastguard Worker } // namespace space
390*795d594fSAndroid Build Coastguard Worker } // namespace gc
391*795d594fSAndroid Build Coastguard Worker } // namespace art
392*795d594fSAndroid Build Coastguard Worker
393*795d594fSAndroid Build Coastguard Worker #endif // ART_RUNTIME_GC_SPACE_SPACE_TEST_H_
394