1/*
2 * Copyright (C) 2015 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#include "space_test.h"
18
19#include "dlmalloc_space.h"
20#include "rosalloc_space.h"
21#include "scoped_thread_state_change.h"
22
23namespace art {
24namespace gc {
25namespace space {
26
27enum MallocSpaceType {
28  kMallocSpaceDlMalloc,
29  kMallocSpaceRosAlloc,
30};
31
32class SpaceCreateTest : public SpaceTest<CommonRuntimeTestWithParam<MallocSpaceType>> {
33 public:
34  MallocSpace* CreateSpace(const std::string& name,
35                           size_t initial_size,
36                           size_t growth_limit,
37                           size_t capacity,
38                           uint8_t* requested_begin) {
39    const MallocSpaceType type = GetParam();
40    if (type == kMallocSpaceDlMalloc) {
41      return DlMallocSpace::Create(name,
42                                   initial_size,
43                                   growth_limit,
44                                   capacity,
45                                   requested_begin,
46                                   false);
47    }
48    DCHECK_EQ(static_cast<uint32_t>(type), static_cast<uint32_t>(kMallocSpaceRosAlloc));
49    return RosAllocSpace::Create(name,
50                                 initial_size,
51                                 growth_limit,
52                                 capacity,
53                                 requested_begin,
54                                 Runtime::Current()->GetHeap()->IsLowMemoryMode(),
55                                 false);
56  }
57};
58
59TEST_P(SpaceCreateTest, InitTestBody) {
60  // This will lead to error messages in the log.
61  ScopedLogSeverity sls(LogSeverity::FATAL);
62
63  {
64    // Init < max == growth
65    std::unique_ptr<Space> space(CreateSpace("test", 16 * MB, 32 * MB, 32 * MB, nullptr));
66    EXPECT_TRUE(space != nullptr);
67    // Init == max == growth
68    space.reset(CreateSpace("test", 16 * MB, 16 * MB, 16 * MB, nullptr));
69    EXPECT_TRUE(space != nullptr);
70    // Init > max == growth
71    space.reset(CreateSpace("test", 32 * MB, 16 * MB, 16 * MB, nullptr));
72    EXPECT_TRUE(space == nullptr);
73    // Growth == init < max
74    space.reset(CreateSpace("test", 16 * MB, 16 * MB, 32 * MB, nullptr));
75    EXPECT_TRUE(space != nullptr);
76    // Growth < init < max
77    space.reset(CreateSpace("test", 16 * MB, 8 * MB, 32 * MB, nullptr));
78    EXPECT_TRUE(space == nullptr);
79    // Init < growth < max
80    space.reset(CreateSpace("test", 8 * MB, 16 * MB, 32 * MB, nullptr));
81    EXPECT_TRUE(space != nullptr);
82    // Init < max < growth
83    space.reset(CreateSpace("test", 8 * MB, 32 * MB, 16 * MB, nullptr));
84    EXPECT_TRUE(space == nullptr);
85  }
86}
87
88// TODO: This test is not very good, we should improve it.
89// The test should do more allocations before the creation of the ZygoteSpace, and then do
90// allocations after the ZygoteSpace is created. The test should also do some GCs to ensure that
91// the GC works with the ZygoteSpace.
92TEST_P(SpaceCreateTest, ZygoteSpaceTestBody) {
93  size_t dummy;
94  MallocSpace* space(CreateSpace("test", 4 * MB, 16 * MB, 16 * MB, nullptr));
95  ASSERT_TRUE(space != nullptr);
96
97  // Make space findable to the heap, will also delete space when runtime is cleaned up
98  AddSpace(space);
99  Thread* self = Thread::Current();
100  ScopedObjectAccess soa(self);
101
102  // Succeeds, fits without adjusting the footprint limit.
103  size_t ptr1_bytes_allocated, ptr1_usable_size, ptr1_bytes_tl_bulk_allocated;
104  StackHandleScope<3> hs(soa.Self());
105  MutableHandle<mirror::Object> ptr1(hs.NewHandle(Alloc(space,
106                                                        self,
107                                                        1 * MB,
108                                                        &ptr1_bytes_allocated,
109                                                        &ptr1_usable_size,
110                                                        &ptr1_bytes_tl_bulk_allocated)));
111  EXPECT_TRUE(ptr1.Get() != nullptr);
112  EXPECT_LE(1U * MB, ptr1_bytes_allocated);
113  EXPECT_LE(1U * MB, ptr1_usable_size);
114  EXPECT_LE(ptr1_usable_size, ptr1_bytes_allocated);
115  EXPECT_EQ(ptr1_bytes_tl_bulk_allocated, ptr1_bytes_allocated);
116
117  // Fails, requires a higher footprint limit.
118  mirror::Object* ptr2 = Alloc(space, self, 8 * MB, &dummy, nullptr, &dummy);
119  EXPECT_TRUE(ptr2 == nullptr);
120
121  // Succeeds, adjusts the footprint.
122  size_t ptr3_bytes_allocated, ptr3_usable_size, ptr3_bytes_tl_bulk_allocated;
123  MutableHandle<mirror::Object> ptr3(hs.NewHandle(AllocWithGrowth(space,
124                                                                  self,
125                                                                  8 * MB,
126                                                                  &ptr3_bytes_allocated,
127                                                                  &ptr3_usable_size,
128                                                                  &ptr3_bytes_tl_bulk_allocated)));
129  EXPECT_TRUE(ptr3.Get() != nullptr);
130  EXPECT_LE(8U * MB, ptr3_bytes_allocated);
131  EXPECT_LE(8U * MB, ptr3_usable_size);
132  EXPECT_LE(ptr3_usable_size, ptr3_bytes_allocated);
133  EXPECT_EQ(ptr3_bytes_tl_bulk_allocated, ptr3_bytes_allocated);
134
135  // Fails, requires a higher footprint limit.
136  mirror::Object* ptr4 = space->Alloc(self, 8 * MB, &dummy, nullptr, &dummy);
137  EXPECT_TRUE(ptr4 == nullptr);
138
139  // Also fails, requires a higher allowed footprint.
140  mirror::Object* ptr5 = space->AllocWithGrowth(self, 8 * MB, &dummy, nullptr, &dummy);
141  EXPECT_TRUE(ptr5 == nullptr);
142
143  // Release some memory.
144  size_t free3 = space->AllocationSize(ptr3.Get(), nullptr);
145  EXPECT_EQ(free3, ptr3_bytes_allocated);
146  EXPECT_EQ(free3, space->Free(self, ptr3.Assign(nullptr)));
147  EXPECT_LE(8U * MB, free3);
148
149  // Succeeds, now that memory has been freed.
150  size_t ptr6_bytes_allocated, ptr6_usable_size, ptr6_bytes_tl_bulk_allocated;
151  Handle<mirror::Object> ptr6(hs.NewHandle(AllocWithGrowth(space,
152                                                           self,
153                                                           9 * MB,
154                                                           &ptr6_bytes_allocated,
155                                                           &ptr6_usable_size,
156                                                           &ptr6_bytes_tl_bulk_allocated)));
157  EXPECT_TRUE(ptr6.Get() != nullptr);
158  EXPECT_LE(9U * MB, ptr6_bytes_allocated);
159  EXPECT_LE(9U * MB, ptr6_usable_size);
160  EXPECT_LE(ptr6_usable_size, ptr6_bytes_allocated);
161  EXPECT_EQ(ptr6_bytes_tl_bulk_allocated, ptr6_bytes_allocated);
162
163  // Final clean up.
164  size_t free1 = space->AllocationSize(ptr1.Get(), nullptr);
165  space->Free(self, ptr1.Assign(nullptr));
166  EXPECT_LE(1U * MB, free1);
167
168  // Make sure that the zygote space isn't directly at the start of the space.
169  EXPECT_TRUE(space->Alloc(self, 1U * MB, &dummy, nullptr, &dummy) != nullptr);
170
171  gc::Heap* heap = Runtime::Current()->GetHeap();
172  space::Space* old_space = space;
173  {
174    ScopedThreadSuspension sts(self, kSuspended);
175    ScopedSuspendAll ssa("Add image space");
176    heap->RemoveSpace(old_space);
177  }
178  heap->RevokeAllThreadLocalBuffers();
179  space::ZygoteSpace* zygote_space = space->CreateZygoteSpace("alloc space",
180                                                              heap->IsLowMemoryMode(),
181                                                              &space);
182  delete old_space;
183  // Add the zygote space.
184  AddSpace(zygote_space, false);
185
186  // Make space findable to the heap, will also delete space when runtime is cleaned up
187  AddSpace(space, false);
188
189  // Succeeds, fits without adjusting the footprint limit.
190  ptr1.Assign(Alloc(space,
191                    self,
192                    1 * MB,
193                    &ptr1_bytes_allocated,
194                    &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  ptr2 = Alloc(space, self, 8 * MB, &dummy, nullptr, &dummy);
204  EXPECT_TRUE(ptr2 == nullptr);
205
206  // Succeeds, adjusts the footprint.
207  ptr3.Assign(AllocWithGrowth(space,
208                              self,
209                              2 * MB,
210                              &ptr3_bytes_allocated,
211                              &ptr3_usable_size,
212                              &ptr3_bytes_tl_bulk_allocated));
213  EXPECT_TRUE(ptr3.Get() != nullptr);
214  EXPECT_LE(2U * MB, ptr3_bytes_allocated);
215  EXPECT_LE(2U * MB, ptr3_usable_size);
216  EXPECT_LE(ptr3_usable_size, ptr3_bytes_allocated);
217  EXPECT_EQ(ptr3_bytes_tl_bulk_allocated, ptr3_bytes_allocated);
218  space->Free(self, ptr3.Assign(nullptr));
219
220  // Final clean up.
221  free1 = space->AllocationSize(ptr1.Get(), nullptr);
222  space->Free(self, ptr1.Assign(nullptr));
223  EXPECT_LE(1U * MB, free1);
224}
225
226TEST_P(SpaceCreateTest, AllocAndFreeTestBody) {
227  size_t dummy = 0;
228  MallocSpace* space(CreateSpace("test", 4 * MB, 16 * MB, 16 * MB, nullptr));
229  ASSERT_TRUE(space != nullptr);
230  Thread* self = Thread::Current();
231  ScopedObjectAccess soa(self);
232
233  // Make space findable to the heap, will also delete space when runtime is cleaned up
234  AddSpace(space);
235
236  // Succeeds, fits without adjusting the footprint limit.
237  size_t ptr1_bytes_allocated, ptr1_usable_size, ptr1_bytes_tl_bulk_allocated;
238  StackHandleScope<3> hs(soa.Self());
239  MutableHandle<mirror::Object> ptr1(hs.NewHandle(Alloc(space,
240                                                        self,
241                                                        1 * MB,
242                                                        &ptr1_bytes_allocated,
243                                                        &ptr1_usable_size,
244                                                        &ptr1_bytes_tl_bulk_allocated)));
245  EXPECT_TRUE(ptr1.Get() != nullptr);
246  EXPECT_LE(1U * MB, ptr1_bytes_allocated);
247  EXPECT_LE(1U * MB, ptr1_usable_size);
248  EXPECT_LE(ptr1_usable_size, ptr1_bytes_allocated);
249  EXPECT_EQ(ptr1_bytes_tl_bulk_allocated, ptr1_bytes_allocated);
250
251  // Fails, requires a higher footprint limit.
252  mirror::Object* ptr2 = Alloc(space, self, 8 * MB, &dummy, nullptr, &dummy);
253  EXPECT_TRUE(ptr2 == nullptr);
254
255  // Succeeds, adjusts the footprint.
256  size_t ptr3_bytes_allocated, ptr3_usable_size, ptr3_bytes_tl_bulk_allocated;
257  MutableHandle<mirror::Object> ptr3(hs.NewHandle(AllocWithGrowth(space,
258                                                                  self,
259                                                                  8 * MB,
260                                                                  &ptr3_bytes_allocated,
261                                                                  &ptr3_usable_size,
262                                                                  &ptr3_bytes_tl_bulk_allocated)));
263  EXPECT_TRUE(ptr3.Get() != nullptr);
264  EXPECT_LE(8U * MB, ptr3_bytes_allocated);
265  EXPECT_LE(8U * MB, ptr3_usable_size);
266  EXPECT_LE(ptr3_usable_size, ptr3_bytes_allocated);
267  EXPECT_EQ(ptr3_bytes_tl_bulk_allocated, ptr3_bytes_allocated);
268
269  // Fails, requires a higher footprint limit.
270  mirror::Object* ptr4 = Alloc(space, self, 8 * MB, &dummy, nullptr, &dummy);
271  EXPECT_TRUE(ptr4 == nullptr);
272
273  // Also fails, requires a higher allowed footprint.
274  mirror::Object* ptr5 = AllocWithGrowth(space, self, 8 * MB, &dummy, nullptr, &dummy);
275  EXPECT_TRUE(ptr5 == nullptr);
276
277  // Release some memory.
278  size_t free3 = space->AllocationSize(ptr3.Get(), nullptr);
279  EXPECT_EQ(free3, ptr3_bytes_allocated);
280  space->Free(self, ptr3.Assign(nullptr));
281  EXPECT_LE(8U * MB, free3);
282
283  // Succeeds, now that memory has been freed.
284  size_t ptr6_bytes_allocated, ptr6_usable_size, ptr6_bytes_tl_bulk_allocated;
285  Handle<mirror::Object> ptr6(hs.NewHandle(AllocWithGrowth(space,
286                                                           self,
287                                                           9 * MB,
288                                                           &ptr6_bytes_allocated,
289                                                           &ptr6_usable_size,
290                                                           &ptr6_bytes_tl_bulk_allocated)));
291  EXPECT_TRUE(ptr6.Get() != nullptr);
292  EXPECT_LE(9U * MB, ptr6_bytes_allocated);
293  EXPECT_LE(9U * MB, ptr6_usable_size);
294  EXPECT_LE(ptr6_usable_size, ptr6_bytes_allocated);
295  EXPECT_EQ(ptr6_bytes_tl_bulk_allocated, ptr6_bytes_allocated);
296
297  // Final clean up.
298  size_t free1 = space->AllocationSize(ptr1.Get(), nullptr);
299  space->Free(self, ptr1.Assign(nullptr));
300  EXPECT_LE(1U * MB, free1);
301}
302
303TEST_P(SpaceCreateTest, AllocAndFreeListTestBody) {
304  MallocSpace* space(CreateSpace("test", 4 * MB, 16 * MB, 16 * MB, nullptr));
305  ASSERT_TRUE(space != nullptr);
306
307  // Make space findable to the heap, will also delete space when runtime is cleaned up
308  AddSpace(space);
309  Thread* self = Thread::Current();
310  ScopedObjectAccess soa(self);
311
312  // Succeeds, fits without adjusting the max allowed footprint.
313  mirror::Object* lots_of_objects[1024];
314  for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
315    size_t allocation_size, usable_size, bytes_tl_bulk_allocated;
316    size_t size_of_zero_length_byte_array = SizeOfZeroLengthByteArray();
317    lots_of_objects[i] = Alloc(space,
318                               self,
319                               size_of_zero_length_byte_array,
320                               &allocation_size,
321                               &usable_size,
322                               &bytes_tl_bulk_allocated);
323    EXPECT_TRUE(lots_of_objects[i] != nullptr);
324    size_t computed_usable_size;
325    EXPECT_EQ(allocation_size, space->AllocationSize(lots_of_objects[i], &computed_usable_size));
326    EXPECT_EQ(usable_size, computed_usable_size);
327    EXPECT_TRUE(bytes_tl_bulk_allocated == 0 ||
328                bytes_tl_bulk_allocated >= allocation_size);
329  }
330
331  // Release memory.
332  space->FreeList(self, arraysize(lots_of_objects), lots_of_objects);
333
334  // Succeeds, fits by adjusting the max allowed footprint.
335  for (size_t i = 0; i < arraysize(lots_of_objects); i++) {
336    size_t allocation_size, usable_size, bytes_tl_bulk_allocated;
337    lots_of_objects[i] = AllocWithGrowth(space,
338                                         self,
339                                         1024,
340                                         &allocation_size,
341                                         &usable_size,
342                                         &bytes_tl_bulk_allocated);
343    EXPECT_TRUE(lots_of_objects[i] != nullptr);
344    size_t computed_usable_size;
345    EXPECT_EQ(allocation_size, space->AllocationSize(lots_of_objects[i], &computed_usable_size));
346    EXPECT_EQ(usable_size, computed_usable_size);
347    EXPECT_TRUE(bytes_tl_bulk_allocated == 0 ||
348                bytes_tl_bulk_allocated >= allocation_size);
349  }
350
351  // Release memory.
352  space->FreeList(self, arraysize(lots_of_objects), lots_of_objects);
353}
354
355INSTANTIATE_TEST_CASE_P(CreateRosAllocSpace,
356                        SpaceCreateTest,
357                        testing::Values(kMallocSpaceRosAlloc));
358INSTANTIATE_TEST_CASE_P(CreateDlMallocSpace,
359                        SpaceCreateTest,
360                        testing::Values(kMallocSpaceDlMalloc));
361
362}  // namespace space
363}  // namespace gc
364}  // namespace art
365