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