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