| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 #if !ENABLE(ASSERT) | 63 #if !ENABLE(ASSERT) |
| 64 const size_t kPointerOffset = 0; | 64 const size_t kPointerOffset = 0; |
| 65 const size_t kExtraAllocSize = 0; | 65 const size_t kExtraAllocSize = 0; |
| 66 #else | 66 #else |
| 67 const size_t kPointerOffset = WTF::kCookieSize; | 67 const size_t kPointerOffset = WTF::kCookieSize; |
| 68 const size_t kExtraAllocSize = WTF::kCookieSize * 2; | 68 const size_t kExtraAllocSize = WTF::kCookieSize * 2; |
| 69 #endif | 69 #endif |
| 70 const size_t kRealAllocSize = kTestAllocSize + kExtraAllocSize; | 70 const size_t kRealAllocSize = kTestAllocSize + kExtraAllocSize; |
| 71 const size_t kTestBucketIndex = kRealAllocSize >> WTF::kBucketShift; | 71 const size_t kTestBucketIndex = kRealAllocSize >> WTF::kBucketShift; |
| 72 | 72 |
| 73 const char* kTypeName = nullptr; | 73 const char* typeName = nullptr; |
| 74 | 74 |
| 75 void TestSetup() | 75 void TestSetup() |
| 76 { | 76 { |
| 77 allocator.init(); | 77 allocator.init(); |
| 78 genericAllocator.init(); | 78 genericAllocator.init(); |
| 79 } | 79 } |
| 80 | 80 |
| 81 void TestShutdown() | 81 void TestShutdown() |
| 82 { | 82 { |
| 83 // We expect no leaks in the general case. We have a test for leak | 83 // We expect no leaks in the general case. We have a test for leak |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 PartitionPage* GetFullPage(size_t size) | 131 PartitionPage* GetFullPage(size_t size) |
| 132 { | 132 { |
| 133 size_t realSize = size + kExtraAllocSize; | 133 size_t realSize = size + kExtraAllocSize; |
| 134 size_t bucketIdx = realSize >> kBucketShift; | 134 size_t bucketIdx = realSize >> kBucketShift; |
| 135 PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx]; | 135 PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx]; |
| 136 size_t numSlots = (bucket->numSystemPagesPerSlotSpan * kSystemPageSize) / re
alSize; | 136 size_t numSlots = (bucket->numSystemPagesPerSlotSpan * kSystemPageSize) / re
alSize; |
| 137 void* first = 0; | 137 void* first = 0; |
| 138 void* last = 0; | 138 void* last = 0; |
| 139 size_t i; | 139 size_t i; |
| 140 for (i = 0; i < numSlots; ++i) { | 140 for (i = 0; i < numSlots; ++i) { |
| 141 void* ptr = partitionAlloc(allocator.root(), size, kTypeName); | 141 void* ptr = partitionAlloc(allocator.root(), size, typeName); |
| 142 EXPECT_TRUE(ptr); | 142 EXPECT_TRUE(ptr); |
| 143 if (!i) | 143 if (!i) |
| 144 first = partitionCookieFreePointerAdjust(ptr); | 144 first = partitionCookieFreePointerAdjust(ptr); |
| 145 else if (i == numSlots - 1) | 145 else if (i == numSlots - 1) |
| 146 last = partitionCookieFreePointerAdjust(ptr); | 146 last = partitionCookieFreePointerAdjust(ptr); |
| 147 } | 147 } |
| 148 EXPECT_EQ(partitionPointerToPage(first), partitionPointerToPage(last)); | 148 EXPECT_EQ(partitionPointerToPage(first), partitionPointerToPage(last)); |
| 149 if (bucket->numSystemPagesPerSlotSpan == kNumSystemPagesPerPartitionPage) | 149 if (bucket->numSystemPagesPerSlotSpan == kNumSystemPagesPerPartitionPage) |
| 150 EXPECT_EQ(reinterpret_cast<size_t>(first) & kPartitionPageBaseMask, rein
terpret_cast<size_t>(last) & kPartitionPageBaseMask); | 150 EXPECT_EQ(reinterpret_cast<size_t>(first) & kPartitionPageBaseMask, rein
terpret_cast<size_t>(last) & kPartitionPageBaseMask); |
| 151 EXPECT_EQ(numSlots, static_cast<size_t>(bucket->activePagesHead->numAllocate
dSlots)); | 151 EXPECT_EQ(numSlots, static_cast<size_t>(bucket->activePagesHead->numAllocate
dSlots)); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 169 } | 169 } |
| 170 | 170 |
| 171 void CycleFreeCache(size_t size) | 171 void CycleFreeCache(size_t size) |
| 172 { | 172 { |
| 173 size_t realSize = size + kExtraAllocSize; | 173 size_t realSize = size + kExtraAllocSize; |
| 174 size_t bucketIdx = realSize >> kBucketShift; | 174 size_t bucketIdx = realSize >> kBucketShift; |
| 175 PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx]; | 175 PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx]; |
| 176 ASSERT(!bucket->activePagesHead->numAllocatedSlots); | 176 ASSERT(!bucket->activePagesHead->numAllocatedSlots); |
| 177 | 177 |
| 178 for (size_t i = 0; i < kMaxFreeableSpans; ++i) { | 178 for (size_t i = 0; i < kMaxFreeableSpans; ++i) { |
| 179 void* ptr = partitionAlloc(allocator.root(), size, kTypeName); | 179 void* ptr = partitionAlloc(allocator.root(), size, typeName); |
| 180 EXPECT_EQ(1, bucket->activePagesHead->numAllocatedSlots); | 180 EXPECT_EQ(1, bucket->activePagesHead->numAllocatedSlots); |
| 181 partitionFree(ptr); | 181 partitionFree(ptr); |
| 182 EXPECT_EQ(0, bucket->activePagesHead->numAllocatedSlots); | 182 EXPECT_EQ(0, bucket->activePagesHead->numAllocatedSlots); |
| 183 EXPECT_NE(-1, bucket->activePagesHead->emptyCacheIndex); | 183 EXPECT_NE(-1, bucket->activePagesHead->emptyCacheIndex); |
| 184 } | 184 } |
| 185 } | 185 } |
| 186 | 186 |
| 187 void CycleGenericFreeCache(size_t size) | 187 void CycleGenericFreeCache(size_t size) |
| 188 { | 188 { |
| 189 for (size_t i = 0; i < kMaxFreeableSpans; ++i) { | 189 for (size_t i = 0; i < kMaxFreeableSpans; ++i) { |
| 190 void* ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeNa
me); | 190 void* ptr = partitionAllocGeneric(genericAllocator.root(), size, typeNam
e); |
| 191 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerA
djust(ptr)); | 191 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerA
djust(ptr)); |
| 192 PartitionBucket* bucket = page->bucket; | 192 PartitionBucket* bucket = page->bucket; |
| 193 EXPECT_EQ(1, bucket->activePagesHead->numAllocatedSlots); | 193 EXPECT_EQ(1, bucket->activePagesHead->numAllocatedSlots); |
| 194 partitionFreeGeneric(genericAllocator.root(), ptr); | 194 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 195 EXPECT_EQ(0, bucket->activePagesHead->numAllocatedSlots); | 195 EXPECT_EQ(0, bucket->activePagesHead->numAllocatedSlots); |
| 196 EXPECT_NE(-1, bucket->activePagesHead->emptyCacheIndex); | 196 EXPECT_NE(-1, bucket->activePagesHead->emptyCacheIndex); |
| 197 } | 197 } |
| 198 } | 198 } |
| 199 | 199 |
| 200 void CheckPageInCore(void* ptr, bool inCore) | 200 void CheckPageInCore(void* ptr, bool inCore) |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 { | 265 { |
| 266 TestSetup(); | 266 TestSetup(); |
| 267 PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex]; | 267 PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex]; |
| 268 PartitionPage* seedPage = &PartitionRootGeneric::gSeedPage; | 268 PartitionPage* seedPage = &PartitionRootGeneric::gSeedPage; |
| 269 | 269 |
| 270 EXPECT_FALSE(bucket->emptyPagesHead); | 270 EXPECT_FALSE(bucket->emptyPagesHead); |
| 271 EXPECT_FALSE(bucket->decommittedPagesHead); | 271 EXPECT_FALSE(bucket->decommittedPagesHead); |
| 272 EXPECT_EQ(seedPage, bucket->activePagesHead); | 272 EXPECT_EQ(seedPage, bucket->activePagesHead); |
| 273 EXPECT_EQ(0, bucket->activePagesHead->nextPage); | 273 EXPECT_EQ(0, bucket->activePagesHead->nextPage); |
| 274 | 274 |
| 275 void* ptr = partitionAlloc(allocator.root(), kTestAllocSize, kTypeName); | 275 void* ptr = partitionAlloc(allocator.root(), kTestAllocSize, typeName); |
| 276 EXPECT_TRUE(ptr); | 276 EXPECT_TRUE(ptr); |
| 277 EXPECT_EQ(kPointerOffset, reinterpret_cast<size_t>(ptr) & kPartitionPageOffs
etMask); | 277 EXPECT_EQ(kPointerOffset, reinterpret_cast<size_t>(ptr) & kPartitionPageOffs
etMask); |
| 278 // Check that the offset appears to include a guard page. | 278 // Check that the offset appears to include a guard page. |
| 279 EXPECT_EQ(kPartitionPageSize + kPointerOffset, reinterpret_cast<size_t>(ptr)
& kSuperPageOffsetMask); | 279 EXPECT_EQ(kPartitionPageSize + kPointerOffset, reinterpret_cast<size_t>(ptr)
& kSuperPageOffsetMask); |
| 280 | 280 |
| 281 partitionFree(ptr); | 281 partitionFree(ptr); |
| 282 // Expect that the last active page gets noticed as empty but doesn't get | 282 // Expect that the last active page gets noticed as empty but doesn't get |
| 283 // decommitted. | 283 // decommitted. |
| 284 EXPECT_TRUE(bucket->emptyPagesHead); | 284 EXPECT_TRUE(bucket->emptyPagesHead); |
| 285 EXPECT_FALSE(bucket->decommittedPagesHead); | 285 EXPECT_FALSE(bucket->decommittedPagesHead); |
| 286 | 286 |
| 287 TestShutdown(); | 287 TestShutdown(); |
| 288 } | 288 } |
| 289 | 289 |
| 290 // Check that we can detect a memory leak. | 290 // Check that we can detect a memory leak. |
| 291 TEST(PartitionAllocTest, SimpleLeak) | 291 TEST(PartitionAllocTest, SimpleLeak) |
| 292 { | 292 { |
| 293 TestSetup(); | 293 TestSetup(); |
| 294 void* leakedPtr = partitionAlloc(allocator.root(), kTestAllocSize, kTypeName
); | 294 void* leakedPtr = partitionAlloc(allocator.root(), kTestAllocSize, typeName)
; |
| 295 (void)leakedPtr; | 295 (void)leakedPtr; |
| 296 void* leakedPtr2 = partitionAllocGeneric(genericAllocator.root(), kTestAlloc
Size, kTypeName); | 296 void* leakedPtr2 = partitionAllocGeneric(genericAllocator.root(), kTestAlloc
Size, typeName); |
| 297 (void)leakedPtr2; | 297 (void)leakedPtr2; |
| 298 EXPECT_FALSE(allocator.shutdown()); | 298 EXPECT_FALSE(allocator.shutdown()); |
| 299 EXPECT_FALSE(genericAllocator.shutdown()); | 299 EXPECT_FALSE(genericAllocator.shutdown()); |
| 300 } | 300 } |
| 301 | 301 |
| 302 // Test multiple allocations, and freelist handling. | 302 // Test multiple allocations, and freelist handling. |
| 303 TEST(PartitionAllocTest, MultiAlloc) | 303 TEST(PartitionAllocTest, MultiAlloc) |
| 304 { | 304 { |
| 305 TestSetup(); | 305 TestSetup(); |
| 306 | 306 |
| 307 char* ptr1 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestA
llocSize, kTypeName)); | 307 char* ptr1 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestA
llocSize, typeName)); |
| 308 char* ptr2 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestA
llocSize, kTypeName)); | 308 char* ptr2 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestA
llocSize, typeName)); |
| 309 EXPECT_TRUE(ptr1); | 309 EXPECT_TRUE(ptr1); |
| 310 EXPECT_TRUE(ptr2); | 310 EXPECT_TRUE(ptr2); |
| 311 ptrdiff_t diff = ptr2 - ptr1; | 311 ptrdiff_t diff = ptr2 - ptr1; |
| 312 EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize), diff); | 312 EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize), diff); |
| 313 | 313 |
| 314 // Check that we re-use the just-freed slot. | 314 // Check that we re-use the just-freed slot. |
| 315 partitionFree(ptr2); | 315 partitionFree(ptr2); |
| 316 ptr2 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSi
ze, kTypeName)); | 316 ptr2 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSi
ze, typeName)); |
| 317 EXPECT_TRUE(ptr2); | 317 EXPECT_TRUE(ptr2); |
| 318 diff = ptr2 - ptr1; | 318 diff = ptr2 - ptr1; |
| 319 EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize), diff); | 319 EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize), diff); |
| 320 partitionFree(ptr1); | 320 partitionFree(ptr1); |
| 321 ptr1 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSi
ze, kTypeName)); | 321 ptr1 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSi
ze, typeName)); |
| 322 EXPECT_TRUE(ptr1); | 322 EXPECT_TRUE(ptr1); |
| 323 diff = ptr2 - ptr1; | 323 diff = ptr2 - ptr1; |
| 324 EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize), diff); | 324 EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize), diff); |
| 325 | 325 |
| 326 char* ptr3 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestA
llocSize, kTypeName)); | 326 char* ptr3 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestA
llocSize, typeName)); |
| 327 EXPECT_TRUE(ptr3); | 327 EXPECT_TRUE(ptr3); |
| 328 diff = ptr3 - ptr1; | 328 diff = ptr3 - ptr1; |
| 329 EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize * 2), diff); | 329 EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize * 2), diff); |
| 330 | 330 |
| 331 partitionFree(ptr1); | 331 partitionFree(ptr1); |
| 332 partitionFree(ptr2); | 332 partitionFree(ptr2); |
| 333 partitionFree(ptr3); | 333 partitionFree(ptr3); |
| 334 | 334 |
| 335 TestShutdown(); | 335 TestShutdown(); |
| 336 } | 336 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 EXPECT_EQ(page1, bucket->activePagesHead); | 387 EXPECT_EQ(page1, bucket->activePagesHead); |
| 388 EXPECT_EQ(0, page1->nextPage); | 388 EXPECT_EQ(0, page1->nextPage); |
| 389 PartitionPage* page2 = GetFullPage(kTestAllocSize); | 389 PartitionPage* page2 = GetFullPage(kTestAllocSize); |
| 390 EXPECT_EQ(page2, bucket->activePagesHead); | 390 EXPECT_EQ(page2, bucket->activePagesHead); |
| 391 EXPECT_EQ(0, page2->nextPage); | 391 EXPECT_EQ(0, page2->nextPage); |
| 392 | 392 |
| 393 // Bounce page1 back into the non-full list then fill it up again. | 393 // Bounce page1 back into the non-full list then fill it up again. |
| 394 char* ptr = reinterpret_cast<char*>(partitionPageToPointer(page1)) + kPointe
rOffset; | 394 char* ptr = reinterpret_cast<char*>(partitionPageToPointer(page1)) + kPointe
rOffset; |
| 395 partitionFree(ptr); | 395 partitionFree(ptr); |
| 396 EXPECT_EQ(page1, bucket->activePagesHead); | 396 EXPECT_EQ(page1, bucket->activePagesHead); |
| 397 (void)partitionAlloc(allocator.root(), kTestAllocSize, kTypeName); | 397 (void)partitionAlloc(allocator.root(), kTestAllocSize, typeName); |
| 398 EXPECT_EQ(page1, bucket->activePagesHead); | 398 EXPECT_EQ(page1, bucket->activePagesHead); |
| 399 EXPECT_EQ(page2, bucket->activePagesHead->nextPage); | 399 EXPECT_EQ(page2, bucket->activePagesHead->nextPage); |
| 400 | 400 |
| 401 // Allocating another page at this point should cause us to scan over page1 | 401 // Allocating another page at this point should cause us to scan over page1 |
| 402 // (which is both full and NOT our current page), and evict it from the | 402 // (which is both full and NOT our current page), and evict it from the |
| 403 // freelist. Older code had a O(n^2) condition due to failure to do this. | 403 // freelist. Older code had a O(n^2) condition due to failure to do this. |
| 404 PartitionPage* page3 = GetFullPage(kTestAllocSize); | 404 PartitionPage* page3 = GetFullPage(kTestAllocSize); |
| 405 EXPECT_EQ(page3, bucket->activePagesHead); | 405 EXPECT_EQ(page3, bucket->activePagesHead); |
| 406 EXPECT_EQ(0, page3->nextPage); | 406 EXPECT_EQ(0, page3->nextPage); |
| 407 | 407 |
| 408 // Work out a pointer into page2 and free it. | 408 // Work out a pointer into page2 and free it. |
| 409 ptr = reinterpret_cast<char*>(partitionPageToPointer(page2)) + kPointerOffse
t; | 409 ptr = reinterpret_cast<char*>(partitionPageToPointer(page2)) + kPointerOffse
t; |
| 410 partitionFree(ptr); | 410 partitionFree(ptr); |
| 411 // Trying to allocate at this time should cause us to cycle around to page2 | 411 // Trying to allocate at this time should cause us to cycle around to page2 |
| 412 // and find the recently freed slot. | 412 // and find the recently freed slot. |
| 413 char* newPtr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTes
tAllocSize, kTypeName)); | 413 char* newPtr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTes
tAllocSize, typeName)); |
| 414 EXPECT_EQ(ptr, newPtr); | 414 EXPECT_EQ(ptr, newPtr); |
| 415 EXPECT_EQ(page2, bucket->activePagesHead); | 415 EXPECT_EQ(page2, bucket->activePagesHead); |
| 416 EXPECT_EQ(page3, page2->nextPage); | 416 EXPECT_EQ(page3, page2->nextPage); |
| 417 | 417 |
| 418 // Work out a pointer into page1 and free it. This should pull the page | 418 // Work out a pointer into page1 and free it. This should pull the page |
| 419 // back into the list of available pages. | 419 // back into the list of available pages. |
| 420 ptr = reinterpret_cast<char*>(partitionPageToPointer(page1)) + kPointerOffse
t; | 420 ptr = reinterpret_cast<char*>(partitionPageToPointer(page1)) + kPointerOffse
t; |
| 421 partitionFree(ptr); | 421 partitionFree(ptr); |
| 422 // This allocation should be satisfied by page1. | 422 // This allocation should be satisfied by page1. |
| 423 newPtr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAlloc
Size, kTypeName)); | 423 newPtr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAlloc
Size, typeName)); |
| 424 EXPECT_EQ(ptr, newPtr); | 424 EXPECT_EQ(ptr, newPtr); |
| 425 EXPECT_EQ(page1, bucket->activePagesHead); | 425 EXPECT_EQ(page1, bucket->activePagesHead); |
| 426 EXPECT_EQ(page2, page1->nextPage); | 426 EXPECT_EQ(page2, page1->nextPage); |
| 427 | 427 |
| 428 FreeFullPage(page3); | 428 FreeFullPage(page3); |
| 429 FreeFullPage(page2); | 429 FreeFullPage(page2); |
| 430 FreeFullPage(page1); | 430 FreeFullPage(page1); |
| 431 | 431 |
| 432 // Allocating whilst in this state exposed a bug, so keep the test. | 432 // Allocating whilst in this state exposed a bug, so keep the test. |
| 433 ptr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSiz
e, kTypeName)); | 433 ptr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSiz
e, typeName)); |
| 434 partitionFree(ptr); | 434 partitionFree(ptr); |
| 435 | 435 |
| 436 TestShutdown(); | 436 TestShutdown(); |
| 437 } | 437 } |
| 438 | 438 |
| 439 // Test some corner cases relating to page transitions in the internal | 439 // Test some corner cases relating to page transitions in the internal |
| 440 // free page list metadata bucket. | 440 // free page list metadata bucket. |
| 441 TEST(PartitionAllocTest, FreePageListPageTransitions) | 441 TEST(PartitionAllocTest, FreePageListPageTransitions) |
| 442 { | 442 { |
| 443 TestSetup(); | 443 TestSetup(); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 | 515 |
| 516 TestShutdown(); | 516 TestShutdown(); |
| 517 } | 517 } |
| 518 | 518 |
| 519 // Test the generic allocation functions that can handle arbitrary sizes and | 519 // Test the generic allocation functions that can handle arbitrary sizes and |
| 520 // reallocing etc. | 520 // reallocing etc. |
| 521 TEST(PartitionAllocTest, GenericAlloc) | 521 TEST(PartitionAllocTest, GenericAlloc) |
| 522 { | 522 { |
| 523 TestSetup(); | 523 TestSetup(); |
| 524 | 524 |
| 525 void* ptr = partitionAllocGeneric(genericAllocator.root(), 1, kTypeName); | 525 void* ptr = partitionAllocGeneric(genericAllocator.root(), 1, typeName); |
| 526 EXPECT_TRUE(ptr); | 526 EXPECT_TRUE(ptr); |
| 527 partitionFreeGeneric(genericAllocator.root(), ptr); | 527 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 528 ptr = partitionAllocGeneric(genericAllocator.root(), kGenericMaxBucketed + 1
, kTypeName); | 528 ptr = partitionAllocGeneric(genericAllocator.root(), kGenericMaxBucketed + 1
, typeName); |
| 529 EXPECT_TRUE(ptr); | 529 EXPECT_TRUE(ptr); |
| 530 partitionFreeGeneric(genericAllocator.root(), ptr); | 530 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 531 | 531 |
| 532 ptr = partitionAllocGeneric(genericAllocator.root(), 1, kTypeName); | 532 ptr = partitionAllocGeneric(genericAllocator.root(), 1, typeName); |
| 533 EXPECT_TRUE(ptr); | 533 EXPECT_TRUE(ptr); |
| 534 void* origPtr = ptr; | 534 void* origPtr = ptr; |
| 535 char* charPtr = static_cast<char*>(ptr); | 535 char* charPtr = static_cast<char*>(ptr); |
| 536 *charPtr = 'A'; | 536 *charPtr = 'A'; |
| 537 | 537 |
| 538 // Change the size of the realloc, remaining inside the same bucket. | 538 // Change the size of the realloc, remaining inside the same bucket. |
| 539 void* newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 2, kTyp
eName); | 539 void* newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 2, type
Name); |
| 540 EXPECT_EQ(ptr, newPtr); | 540 EXPECT_EQ(ptr, newPtr); |
| 541 newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 1, kTypeName)
; | 541 newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 1, typeName); |
| 542 EXPECT_EQ(ptr, newPtr); | 542 EXPECT_EQ(ptr, newPtr); |
| 543 newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericSmall
estBucket, kTypeName); | 543 newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericSmall
estBucket, typeName); |
| 544 EXPECT_EQ(ptr, newPtr); | 544 EXPECT_EQ(ptr, newPtr); |
| 545 | 545 |
| 546 // Change the size of the realloc, switching buckets. | 546 // Change the size of the realloc, switching buckets. |
| 547 newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericSmall
estBucket + 1, kTypeName); | 547 newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericSmall
estBucket + 1, typeName); |
| 548 EXPECT_NE(newPtr, ptr); | 548 EXPECT_NE(newPtr, ptr); |
| 549 // Check that the realloc copied correctly. | 549 // Check that the realloc copied correctly. |
| 550 char* newCharPtr = static_cast<char*>(newPtr); | 550 char* newCharPtr = static_cast<char*>(newPtr); |
| 551 EXPECT_EQ(*newCharPtr, 'A'); | 551 EXPECT_EQ(*newCharPtr, 'A'); |
| 552 #if ENABLE(ASSERT) | 552 #if ENABLE(ASSERT) |
| 553 // Subtle: this checks for an old bug where we copied too much from the | 553 // Subtle: this checks for an old bug where we copied too much from the |
| 554 // source of the realloc. The condition can be detected by a trashing of | 554 // source of the realloc. The condition can be detected by a trashing of |
| 555 // the uninitialized value in the space of the upsized allocation. | 555 // the uninitialized value in the space of the upsized allocation. |
| 556 EXPECT_EQ(kUninitializedByte, static_cast<unsigned char>(*(newCharPtr + kGen
ericSmallestBucket))); | 556 EXPECT_EQ(kUninitializedByte, static_cast<unsigned char>(*(newCharPtr + kGen
ericSmallestBucket))); |
| 557 #endif | 557 #endif |
| 558 *newCharPtr = 'B'; | 558 *newCharPtr = 'B'; |
| 559 // The realloc moved. To check that the old allocation was freed, we can | 559 // The realloc moved. To check that the old allocation was freed, we can |
| 560 // do an alloc of the old allocation size and check that the old allocation | 560 // do an alloc of the old allocation size and check that the old allocation |
| 561 // address is at the head of the freelist and reused. | 561 // address is at the head of the freelist and reused. |
| 562 void* reusedPtr = partitionAllocGeneric(genericAllocator.root(), 1, kTypeNam
e); | 562 void* reusedPtr = partitionAllocGeneric(genericAllocator.root(), 1, typeName
); |
| 563 EXPECT_EQ(reusedPtr, origPtr); | 563 EXPECT_EQ(reusedPtr, origPtr); |
| 564 partitionFreeGeneric(genericAllocator.root(), reusedPtr); | 564 partitionFreeGeneric(genericAllocator.root(), reusedPtr); |
| 565 | 565 |
| 566 // Downsize the realloc. | 566 // Downsize the realloc. |
| 567 ptr = newPtr; | 567 ptr = newPtr; |
| 568 newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 1, kTypeName)
; | 568 newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 1, typeName); |
| 569 EXPECT_EQ(newPtr, origPtr); | 569 EXPECT_EQ(newPtr, origPtr); |
| 570 newCharPtr = static_cast<char*>(newPtr); | 570 newCharPtr = static_cast<char*>(newPtr); |
| 571 EXPECT_EQ(*newCharPtr, 'B'); | 571 EXPECT_EQ(*newCharPtr, 'B'); |
| 572 *newCharPtr = 'C'; | 572 *newCharPtr = 'C'; |
| 573 | 573 |
| 574 // Upsize the realloc to outside the partition. | 574 // Upsize the realloc to outside the partition. |
| 575 ptr = newPtr; | 575 ptr = newPtr; |
| 576 newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericMaxBu
cketed + 1, kTypeName); | 576 newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericMaxBu
cketed + 1, typeName); |
| 577 EXPECT_NE(newPtr, ptr); | 577 EXPECT_NE(newPtr, ptr); |
| 578 newCharPtr = static_cast<char*>(newPtr); | 578 newCharPtr = static_cast<char*>(newPtr); |
| 579 EXPECT_EQ(*newCharPtr, 'C'); | 579 EXPECT_EQ(*newCharPtr, 'C'); |
| 580 *newCharPtr = 'D'; | 580 *newCharPtr = 'D'; |
| 581 | 581 |
| 582 // Upsize and downsize the realloc, remaining outside the partition. | 582 // Upsize and downsize the realloc, remaining outside the partition. |
| 583 ptr = newPtr; | 583 ptr = newPtr; |
| 584 newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericMaxBu
cketed * 10, kTypeName); | 584 newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericMaxBu
cketed * 10, typeName); |
| 585 newCharPtr = static_cast<char*>(newPtr); | 585 newCharPtr = static_cast<char*>(newPtr); |
| 586 EXPECT_EQ(*newCharPtr, 'D'); | 586 EXPECT_EQ(*newCharPtr, 'D'); |
| 587 *newCharPtr = 'E'; | 587 *newCharPtr = 'E'; |
| 588 ptr = newPtr; | 588 ptr = newPtr; |
| 589 newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericMaxBu
cketed * 2, kTypeName); | 589 newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericMaxBu
cketed * 2, typeName); |
| 590 newCharPtr = static_cast<char*>(newPtr); | 590 newCharPtr = static_cast<char*>(newPtr); |
| 591 EXPECT_EQ(*newCharPtr, 'E'); | 591 EXPECT_EQ(*newCharPtr, 'E'); |
| 592 *newCharPtr = 'F'; | 592 *newCharPtr = 'F'; |
| 593 | 593 |
| 594 // Downsize the realloc to inside the partition. | 594 // Downsize the realloc to inside the partition. |
| 595 ptr = newPtr; | 595 ptr = newPtr; |
| 596 newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 1, kTypeName)
; | 596 newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 1, typeName); |
| 597 EXPECT_NE(newPtr, ptr); | 597 EXPECT_NE(newPtr, ptr); |
| 598 EXPECT_EQ(newPtr, origPtr); | 598 EXPECT_EQ(newPtr, origPtr); |
| 599 newCharPtr = static_cast<char*>(newPtr); | 599 newCharPtr = static_cast<char*>(newPtr); |
| 600 EXPECT_EQ(*newCharPtr, 'F'); | 600 EXPECT_EQ(*newCharPtr, 'F'); |
| 601 | 601 |
| 602 partitionFreeGeneric(genericAllocator.root(), newPtr); | 602 partitionFreeGeneric(genericAllocator.root(), newPtr); |
| 603 TestShutdown(); | 603 TestShutdown(); |
| 604 } | 604 } |
| 605 | 605 |
| 606 // Test the generic allocation functions can handle some specific sizes of | 606 // Test the generic allocation functions can handle some specific sizes of |
| 607 // interest. | 607 // interest. |
| 608 TEST(PartitionAllocTest, GenericAllocSizes) | 608 TEST(PartitionAllocTest, GenericAllocSizes) |
| 609 { | 609 { |
| 610 TestSetup(); | 610 TestSetup(); |
| 611 | 611 |
| 612 void* ptr = partitionAllocGeneric(genericAllocator.root(), 0, kTypeName); | 612 void* ptr = partitionAllocGeneric(genericAllocator.root(), 0, typeName); |
| 613 EXPECT_TRUE(ptr); | 613 EXPECT_TRUE(ptr); |
| 614 partitionFreeGeneric(genericAllocator.root(), ptr); | 614 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 615 | 615 |
| 616 // kPartitionPageSize is interesting because it results in just one | 616 // kPartitionPageSize is interesting because it results in just one |
| 617 // allocation per page, which tripped up some corner cases. | 617 // allocation per page, which tripped up some corner cases. |
| 618 size_t size = kPartitionPageSize - kExtraAllocSize; | 618 size_t size = kPartitionPageSize - kExtraAllocSize; |
| 619 ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName); | 619 ptr = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 620 EXPECT_TRUE(ptr); | 620 EXPECT_TRUE(ptr); |
| 621 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName)
; | 621 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 622 EXPECT_TRUE(ptr2); | 622 EXPECT_TRUE(ptr2); |
| 623 partitionFreeGeneric(genericAllocator.root(), ptr); | 623 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 624 // Should be freeable at this point. | 624 // Should be freeable at this point. |
| 625 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjus
t(ptr)); | 625 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjus
t(ptr)); |
| 626 EXPECT_NE(-1, page->emptyCacheIndex); | 626 EXPECT_NE(-1, page->emptyCacheIndex); |
| 627 partitionFreeGeneric(genericAllocator.root(), ptr2); | 627 partitionFreeGeneric(genericAllocator.root(), ptr2); |
| 628 | 628 |
| 629 size = (((kPartitionPageSize * kMaxPartitionPagesPerSlotSpan) - kSystemPageS
ize) / 2) - kExtraAllocSize; | 629 size = (((kPartitionPageSize * kMaxPartitionPagesPerSlotSpan) - kSystemPageS
ize) / 2) - kExtraAllocSize; |
| 630 ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName); | 630 ptr = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 631 EXPECT_TRUE(ptr); | 631 EXPECT_TRUE(ptr); |
| 632 memset(ptr, 'A', size); | 632 memset(ptr, 'A', size); |
| 633 ptr2 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName); | 633 ptr2 = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 634 EXPECT_TRUE(ptr2); | 634 EXPECT_TRUE(ptr2); |
| 635 void* ptr3 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName)
; | 635 void* ptr3 = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 636 EXPECT_TRUE(ptr3); | 636 EXPECT_TRUE(ptr3); |
| 637 void* ptr4 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName)
; | 637 void* ptr4 = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 638 EXPECT_TRUE(ptr4); | 638 EXPECT_TRUE(ptr4); |
| 639 | 639 |
| 640 page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr)); | 640 page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr)); |
| 641 PartitionPage* page2 = partitionPointerToPage(partitionCookieFreePointerAdju
st(ptr3)); | 641 PartitionPage* page2 = partitionPointerToPage(partitionCookieFreePointerAdju
st(ptr3)); |
| 642 EXPECT_NE(page, page2); | 642 EXPECT_NE(page, page2); |
| 643 | 643 |
| 644 partitionFreeGeneric(genericAllocator.root(), ptr); | 644 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 645 partitionFreeGeneric(genericAllocator.root(), ptr3); | 645 partitionFreeGeneric(genericAllocator.root(), ptr3); |
| 646 partitionFreeGeneric(genericAllocator.root(), ptr2); | 646 partitionFreeGeneric(genericAllocator.root(), ptr2); |
| 647 // Should be freeable at this point. | 647 // Should be freeable at this point. |
| 648 EXPECT_NE(-1, page->emptyCacheIndex); | 648 EXPECT_NE(-1, page->emptyCacheIndex); |
| 649 EXPECT_EQ(0, page->numAllocatedSlots); | 649 EXPECT_EQ(0, page->numAllocatedSlots); |
| 650 EXPECT_EQ(0, page->numUnprovisionedSlots); | 650 EXPECT_EQ(0, page->numUnprovisionedSlots); |
| 651 void* newPtr = partitionAllocGeneric(genericAllocator.root(), size, kTypeNam
e); | 651 void* newPtr = partitionAllocGeneric(genericAllocator.root(), size, typeName
); |
| 652 EXPECT_EQ(ptr3, newPtr); | 652 EXPECT_EQ(ptr3, newPtr); |
| 653 newPtr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName); | 653 newPtr = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 654 EXPECT_EQ(ptr2, newPtr); | 654 EXPECT_EQ(ptr2, newPtr); |
| 655 #if OS(LINUX) && !ENABLE(ASSERT) | 655 #if OS(LINUX) && !ENABLE(ASSERT) |
| 656 // On Linux, we have a guarantee that freelisting a page should cause its | 656 // On Linux, we have a guarantee that freelisting a page should cause its |
| 657 // contents to be nulled out. We check for null here to detect an bug we | 657 // contents to be nulled out. We check for null here to detect an bug we |
| 658 // had where a large slot size was causing us to not properly free all | 658 // had where a large slot size was causing us to not properly free all |
| 659 // resources back to the system. | 659 // resources back to the system. |
| 660 // We only run the check when asserts are disabled because when they are | 660 // We only run the check when asserts are disabled because when they are |
| 661 // enabled, the allocated area is overwritten with an "uninitialized" | 661 // enabled, the allocated area is overwritten with an "uninitialized" |
| 662 // byte pattern. | 662 // byte pattern. |
| 663 EXPECT_EQ(0, *(reinterpret_cast<char*>(newPtr) + (size - 1))); | 663 EXPECT_EQ(0, *(reinterpret_cast<char*>(newPtr) + (size - 1))); |
| 664 #endif | 664 #endif |
| 665 partitionFreeGeneric(genericAllocator.root(), newPtr); | 665 partitionFreeGeneric(genericAllocator.root(), newPtr); |
| 666 partitionFreeGeneric(genericAllocator.root(), ptr3); | 666 partitionFreeGeneric(genericAllocator.root(), ptr3); |
| 667 partitionFreeGeneric(genericAllocator.root(), ptr4); | 667 partitionFreeGeneric(genericAllocator.root(), ptr4); |
| 668 | 668 |
| 669 // Can we allocate a massive (512MB) size? | 669 // Can we allocate a massive (512MB) size? |
| 670 // Allocate 512MB, but +1, to test for cookie writing alignment issues. | 670 // Allocate 512MB, but +1, to test for cookie writing alignment issues. |
| 671 ptr = partitionAllocGeneric(genericAllocator.root(), 512 * 1024 * 1024 + 1,
kTypeName); | 671 ptr = partitionAllocGeneric(genericAllocator.root(), 512 * 1024 * 1024 + 1,
typeName); |
| 672 partitionFreeGeneric(genericAllocator.root(), ptr); | 672 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 673 | 673 |
| 674 // Check a more reasonable, but still direct mapped, size. | 674 // Check a more reasonable, but still direct mapped, size. |
| 675 // Chop a system page and a byte off to test for rounding errors. | 675 // Chop a system page and a byte off to test for rounding errors. |
| 676 size = 20 * 1024 * 1024; | 676 size = 20 * 1024 * 1024; |
| 677 size -= kSystemPageSize; | 677 size -= kSystemPageSize; |
| 678 size -= 1; | 678 size -= 1; |
| 679 ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName); | 679 ptr = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 680 char* charPtr = reinterpret_cast<char*>(ptr); | 680 char* charPtr = reinterpret_cast<char*>(ptr); |
| 681 *(charPtr + (size - 1)) = 'A'; | 681 *(charPtr + (size - 1)) = 'A'; |
| 682 partitionFreeGeneric(genericAllocator.root(), ptr); | 682 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 683 | 683 |
| 684 // Can we free null? | 684 // Can we free null? |
| 685 partitionFreeGeneric(genericAllocator.root(), 0); | 685 partitionFreeGeneric(genericAllocator.root(), 0); |
| 686 | 686 |
| 687 // Do we correctly get a null for a failed allocation? | 687 // Do we correctly get a null for a failed allocation? |
| 688 EXPECT_EQ(0, partitionAllocGenericFlags(genericAllocator.root(), PartitionAl
locReturnNull, 3u * 1024 * 1024 * 1024, kTypeName)); | 688 EXPECT_EQ(0, partitionAllocGenericFlags(genericAllocator.root(), PartitionAl
locReturnNull, 3u * 1024 * 1024 * 1024, typeName)); |
| 689 | 689 |
| 690 TestShutdown(); | 690 TestShutdown(); |
| 691 } | 691 } |
| 692 | 692 |
| 693 // Test that we can fetch the real allocated size after an allocation. | 693 // Test that we can fetch the real allocated size after an allocation. |
| 694 TEST(PartitionAllocTest, GenericAllocGetSize) | 694 TEST(PartitionAllocTest, GenericAllocGetSize) |
| 695 { | 695 { |
| 696 TestSetup(); | 696 TestSetup(); |
| 697 | 697 |
| 698 void* ptr; | 698 void* ptr; |
| 699 size_t requestedSize, actualSize, predictedSize; | 699 size_t requestedSize, actualSize, predictedSize; |
| 700 | 700 |
| 701 EXPECT_TRUE(partitionAllocSupportsGetSize()); | 701 EXPECT_TRUE(partitionAllocSupportsGetSize()); |
| 702 | 702 |
| 703 // Allocate something small. | 703 // Allocate something small. |
| 704 requestedSize = 511 - kExtraAllocSize; | 704 requestedSize = 511 - kExtraAllocSize; |
| 705 predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedS
ize); | 705 predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedS
ize); |
| 706 ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize, kTypeNam
e); | 706 ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize, typeName
); |
| 707 EXPECT_TRUE(ptr); | 707 EXPECT_TRUE(ptr); |
| 708 actualSize = partitionAllocGetSize(ptr); | 708 actualSize = partitionAllocGetSize(ptr); |
| 709 EXPECT_EQ(predictedSize, actualSize); | 709 EXPECT_EQ(predictedSize, actualSize); |
| 710 EXPECT_LT(requestedSize, actualSize); | 710 EXPECT_LT(requestedSize, actualSize); |
| 711 partitionFreeGeneric(genericAllocator.root(), ptr); | 711 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 712 | 712 |
| 713 // Allocate a size that should be a perfect match for a bucket, because it | 713 // Allocate a size that should be a perfect match for a bucket, because it |
| 714 // is an exact power of 2. | 714 // is an exact power of 2. |
| 715 requestedSize = (256 * 1024) - kExtraAllocSize; | 715 requestedSize = (256 * 1024) - kExtraAllocSize; |
| 716 predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedS
ize); | 716 predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedS
ize); |
| 717 ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize, kTypeNam
e); | 717 ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize, typeName
); |
| 718 EXPECT_TRUE(ptr); | 718 EXPECT_TRUE(ptr); |
| 719 actualSize = partitionAllocGetSize(ptr); | 719 actualSize = partitionAllocGetSize(ptr); |
| 720 EXPECT_EQ(predictedSize, actualSize); | 720 EXPECT_EQ(predictedSize, actualSize); |
| 721 EXPECT_EQ(requestedSize, actualSize); | 721 EXPECT_EQ(requestedSize, actualSize); |
| 722 partitionFreeGeneric(genericAllocator.root(), ptr); | 722 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 723 | 723 |
| 724 // Allocate a size that is a system page smaller than a bucket. GetSize() | 724 // Allocate a size that is a system page smaller than a bucket. GetSize() |
| 725 // should return a larger size than we asked for now. | 725 // should return a larger size than we asked for now. |
| 726 requestedSize = (256 * 1024) - kSystemPageSize - kExtraAllocSize; | 726 requestedSize = (256 * 1024) - kSystemPageSize - kExtraAllocSize; |
| 727 predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedS
ize); | 727 predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedS
ize); |
| 728 ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize, kTypeNam
e); | 728 ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize, typeName
); |
| 729 EXPECT_TRUE(ptr); | 729 EXPECT_TRUE(ptr); |
| 730 actualSize = partitionAllocGetSize(ptr); | 730 actualSize = partitionAllocGetSize(ptr); |
| 731 EXPECT_EQ(predictedSize, actualSize); | 731 EXPECT_EQ(predictedSize, actualSize); |
| 732 EXPECT_EQ(requestedSize + kSystemPageSize, actualSize); | 732 EXPECT_EQ(requestedSize + kSystemPageSize, actualSize); |
| 733 // Check that we can write at the end of the reported size too. | 733 // Check that we can write at the end of the reported size too. |
| 734 char* charPtr = reinterpret_cast<char*>(ptr); | 734 char* charPtr = reinterpret_cast<char*>(ptr); |
| 735 *(charPtr + (actualSize - 1)) = 'A'; | 735 *(charPtr + (actualSize - 1)) = 'A'; |
| 736 partitionFreeGeneric(genericAllocator.root(), ptr); | 736 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 737 | 737 |
| 738 // Allocate something very large, and uneven. | 738 // Allocate something very large, and uneven. |
| 739 requestedSize = 512 * 1024 * 1024 - 1; | 739 requestedSize = 512 * 1024 * 1024 - 1; |
| 740 predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedS
ize); | 740 predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedS
ize); |
| 741 ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize, kTypeNam
e); | 741 ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize, typeName
); |
| 742 EXPECT_TRUE(ptr); | 742 EXPECT_TRUE(ptr); |
| 743 actualSize = partitionAllocGetSize(ptr); | 743 actualSize = partitionAllocGetSize(ptr); |
| 744 EXPECT_EQ(predictedSize, actualSize); | 744 EXPECT_EQ(predictedSize, actualSize); |
| 745 EXPECT_LT(requestedSize, actualSize); | 745 EXPECT_LT(requestedSize, actualSize); |
| 746 partitionFreeGeneric(genericAllocator.root(), ptr); | 746 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 747 | 747 |
| 748 // Too large allocation. | 748 // Too large allocation. |
| 749 requestedSize = INT_MAX; | 749 requestedSize = INT_MAX; |
| 750 predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedS
ize); | 750 predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedS
ize); |
| 751 EXPECT_EQ(requestedSize, predictedSize); | 751 EXPECT_EQ(requestedSize, predictedSize); |
| 752 | 752 |
| 753 TestShutdown(); | 753 TestShutdown(); |
| 754 } | 754 } |
| 755 | 755 |
| 756 // Test the realloc() contract. | 756 // Test the realloc() contract. |
| 757 TEST(PartitionAllocTest, Realloc) | 757 TEST(PartitionAllocTest, Realloc) |
| 758 { | 758 { |
| 759 TestSetup(); | 759 TestSetup(); |
| 760 | 760 |
| 761 // realloc(0, size) should be equivalent to malloc(). | 761 // realloc(0, size) should be equivalent to malloc(). |
| 762 void* ptr = partitionReallocGeneric(genericAllocator.root(), 0, kTestAllocSi
ze, kTypeName); | 762 void* ptr = partitionReallocGeneric(genericAllocator.root(), 0, kTestAllocSi
ze, typeName); |
| 763 memset(ptr, 'A', kTestAllocSize); | 763 memset(ptr, 'A', kTestAllocSize); |
| 764 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjus
t(ptr)); | 764 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjus
t(ptr)); |
| 765 // realloc(ptr, 0) should be equivalent to free(). | 765 // realloc(ptr, 0) should be equivalent to free(). |
| 766 void* ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, 0, kTypeN
ame); | 766 void* ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, 0, typeNa
me); |
| 767 EXPECT_EQ(0, ptr2); | 767 EXPECT_EQ(0, ptr2); |
| 768 EXPECT_EQ(partitionCookieFreePointerAdjust(ptr), page->freelistHead); | 768 EXPECT_EQ(partitionCookieFreePointerAdjust(ptr), page->freelistHead); |
| 769 | 769 |
| 770 // Test that growing an allocation with realloc() copies everything from the | 770 // Test that growing an allocation with realloc() copies everything from the |
| 771 // old allocation. | 771 // old allocation. |
| 772 size_t size = kSystemPageSize - kExtraAllocSize; | 772 size_t size = kSystemPageSize - kExtraAllocSize; |
| 773 EXPECT_EQ(size, partitionAllocActualSize(genericAllocator.root(), size)); | 773 EXPECT_EQ(size, partitionAllocActualSize(genericAllocator.root(), size)); |
| 774 ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName); | 774 ptr = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 775 memset(ptr, 'A', size); | 775 memset(ptr, 'A', size); |
| 776 ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, size + 1, kType
Name); | 776 ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, size + 1, typeN
ame); |
| 777 EXPECT_NE(ptr, ptr2); | 777 EXPECT_NE(ptr, ptr2); |
| 778 char* charPtr2 = static_cast<char*>(ptr2); | 778 char* charPtr2 = static_cast<char*>(ptr2); |
| 779 EXPECT_EQ('A', charPtr2[0]); | 779 EXPECT_EQ('A', charPtr2[0]); |
| 780 EXPECT_EQ('A', charPtr2[size - 1]); | 780 EXPECT_EQ('A', charPtr2[size - 1]); |
| 781 #if ENABLE(ASSERT) | 781 #if ENABLE(ASSERT) |
| 782 EXPECT_EQ(kUninitializedByte, static_cast<unsigned char>(charPtr2[size])); | 782 EXPECT_EQ(kUninitializedByte, static_cast<unsigned char>(charPtr2[size])); |
| 783 #endif | 783 #endif |
| 784 | 784 |
| 785 // Test that shrinking an allocation with realloc() also copies everything | 785 // Test that shrinking an allocation with realloc() also copies everything |
| 786 // from the old allocation. | 786 // from the old allocation. |
| 787 ptr = partitionReallocGeneric(genericAllocator.root(), ptr2, size - 1, kType
Name); | 787 ptr = partitionReallocGeneric(genericAllocator.root(), ptr2, size - 1, typeN
ame); |
| 788 EXPECT_NE(ptr2, ptr); | 788 EXPECT_NE(ptr2, ptr); |
| 789 char* charPtr = static_cast<char*>(ptr); | 789 char* charPtr = static_cast<char*>(ptr); |
| 790 EXPECT_EQ('A', charPtr[0]); | 790 EXPECT_EQ('A', charPtr[0]); |
| 791 EXPECT_EQ('A', charPtr[size - 2]); | 791 EXPECT_EQ('A', charPtr[size - 2]); |
| 792 #if ENABLE(ASSERT) | 792 #if ENABLE(ASSERT) |
| 793 EXPECT_EQ(kUninitializedByte, static_cast<unsigned char>(charPtr[size - 1]))
; | 793 EXPECT_EQ(kUninitializedByte, static_cast<unsigned char>(charPtr[size - 1]))
; |
| 794 #endif | 794 #endif |
| 795 | 795 |
| 796 partitionFreeGeneric(genericAllocator.root(), ptr); | 796 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 797 | 797 |
| 798 // Test that shrinking a direct mapped allocation happens in-place. | 798 // Test that shrinking a direct mapped allocation happens in-place. |
| 799 size = kGenericMaxBucketed + 16 * kSystemPageSize; | 799 size = kGenericMaxBucketed + 16 * kSystemPageSize; |
| 800 ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName); | 800 ptr = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 801 size_t actualSize = partitionAllocGetSize(ptr); | 801 size_t actualSize = partitionAllocGetSize(ptr); |
| 802 ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericMaxBuck
eted + 8 * kSystemPageSize, kTypeName); | 802 ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, kGenericMaxBuck
eted + 8 * kSystemPageSize, typeName); |
| 803 EXPECT_EQ(ptr, ptr2); | 803 EXPECT_EQ(ptr, ptr2); |
| 804 EXPECT_EQ(actualSize - 8 * kSystemPageSize, partitionAllocGetSize(ptr2)); | 804 EXPECT_EQ(actualSize - 8 * kSystemPageSize, partitionAllocGetSize(ptr2)); |
| 805 | 805 |
| 806 // Test that a previously in-place shrunk direct mapped allocation can be | 806 // Test that a previously in-place shrunk direct mapped allocation can be |
| 807 // expanded up again within its original size. | 807 // expanded up again within its original size. |
| 808 ptr = partitionReallocGeneric(genericAllocator.root(), ptr2, size - kSystemP
ageSize, kTypeName); | 808 ptr = partitionReallocGeneric(genericAllocator.root(), ptr2, size - kSystemP
ageSize, typeName); |
| 809 EXPECT_EQ(ptr2, ptr); | 809 EXPECT_EQ(ptr2, ptr); |
| 810 EXPECT_EQ(actualSize - kSystemPageSize, partitionAllocGetSize(ptr)); | 810 EXPECT_EQ(actualSize - kSystemPageSize, partitionAllocGetSize(ptr)); |
| 811 | 811 |
| 812 // Test that a direct mapped allocation is performed not in-place when the | 812 // Test that a direct mapped allocation is performed not in-place when the |
| 813 // new size is small enough. | 813 // new size is small enough. |
| 814 ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, kSystemPageSize
, kTypeName); | 814 ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, kSystemPageSize
, typeName); |
| 815 EXPECT_NE(ptr, ptr2); | 815 EXPECT_NE(ptr, ptr2); |
| 816 | 816 |
| 817 partitionFreeGeneric(genericAllocator.root(), ptr2); | 817 partitionFreeGeneric(genericAllocator.root(), ptr2); |
| 818 | 818 |
| 819 TestShutdown(); | 819 TestShutdown(); |
| 820 } | 820 } |
| 821 | 821 |
| 822 // Tests the handing out of freelists for partial pages. | 822 // Tests the handing out of freelists for partial pages. |
| 823 TEST(PartitionAllocTest, PartialPageFreelists) | 823 TEST(PartitionAllocTest, PartialPageFreelists) |
| 824 { | 824 { |
| 825 TestSetup(); | 825 TestSetup(); |
| 826 | 826 |
| 827 size_t bigSize = allocator.root()->maxAllocation - kExtraAllocSize; | 827 size_t bigSize = allocator.root()->maxAllocation - kExtraAllocSize; |
| 828 EXPECT_EQ(kSystemPageSize - kAllocationGranularity, bigSize + kExtraAllocSiz
e); | 828 EXPECT_EQ(kSystemPageSize - kAllocationGranularity, bigSize + kExtraAllocSiz
e); |
| 829 size_t bucketIdx = (bigSize + kExtraAllocSize) >> kBucketShift; | 829 size_t bucketIdx = (bigSize + kExtraAllocSize) >> kBucketShift; |
| 830 PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx]; | 830 PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx]; |
| 831 EXPECT_EQ(0, bucket->emptyPagesHead); | 831 EXPECT_EQ(0, bucket->emptyPagesHead); |
| 832 | 832 |
| 833 void* ptr = partitionAlloc(allocator.root(), bigSize, kTypeName); | 833 void* ptr = partitionAlloc(allocator.root(), bigSize, typeName); |
| 834 EXPECT_TRUE(ptr); | 834 EXPECT_TRUE(ptr); |
| 835 | 835 |
| 836 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjus
t(ptr)); | 836 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjus
t(ptr)); |
| 837 size_t totalSlots = (page->bucket->numSystemPagesPerSlotSpan * kSystemPageSi
ze) / (bigSize + kExtraAllocSize); | 837 size_t totalSlots = (page->bucket->numSystemPagesPerSlotSpan * kSystemPageSi
ze) / (bigSize + kExtraAllocSize); |
| 838 EXPECT_EQ(4u, totalSlots); | 838 EXPECT_EQ(4u, totalSlots); |
| 839 // The freelist should have one entry, because we were able to exactly fit | 839 // The freelist should have one entry, because we were able to exactly fit |
| 840 // one object slot and one freelist pointer (the null that the head points | 840 // one object slot and one freelist pointer (the null that the head points |
| 841 // to) into a system page. | 841 // to) into a system page. |
| 842 EXPECT_TRUE(page->freelistHead); | 842 EXPECT_TRUE(page->freelistHead); |
| 843 EXPECT_EQ(1, page->numAllocatedSlots); | 843 EXPECT_EQ(1, page->numAllocatedSlots); |
| 844 EXPECT_EQ(2, page->numUnprovisionedSlots); | 844 EXPECT_EQ(2, page->numUnprovisionedSlots); |
| 845 | 845 |
| 846 void* ptr2 = partitionAlloc(allocator.root(), bigSize, kTypeName); | 846 void* ptr2 = partitionAlloc(allocator.root(), bigSize, typeName); |
| 847 EXPECT_TRUE(ptr2); | 847 EXPECT_TRUE(ptr2); |
| 848 EXPECT_FALSE(page->freelistHead); | 848 EXPECT_FALSE(page->freelistHead); |
| 849 EXPECT_EQ(2, page->numAllocatedSlots); | 849 EXPECT_EQ(2, page->numAllocatedSlots); |
| 850 EXPECT_EQ(2, page->numUnprovisionedSlots); | 850 EXPECT_EQ(2, page->numUnprovisionedSlots); |
| 851 | 851 |
| 852 void* ptr3 = partitionAlloc(allocator.root(), bigSize, kTypeName); | 852 void* ptr3 = partitionAlloc(allocator.root(), bigSize, typeName); |
| 853 EXPECT_TRUE(ptr3); | 853 EXPECT_TRUE(ptr3); |
| 854 EXPECT_TRUE(page->freelistHead); | 854 EXPECT_TRUE(page->freelistHead); |
| 855 EXPECT_EQ(3, page->numAllocatedSlots); | 855 EXPECT_EQ(3, page->numAllocatedSlots); |
| 856 EXPECT_EQ(0, page->numUnprovisionedSlots); | 856 EXPECT_EQ(0, page->numUnprovisionedSlots); |
| 857 | 857 |
| 858 void* ptr4 = partitionAlloc(allocator.root(), bigSize, kTypeName); | 858 void* ptr4 = partitionAlloc(allocator.root(), bigSize, typeName); |
| 859 EXPECT_TRUE(ptr4); | 859 EXPECT_TRUE(ptr4); |
| 860 EXPECT_FALSE(page->freelistHead); | 860 EXPECT_FALSE(page->freelistHead); |
| 861 EXPECT_EQ(4, page->numAllocatedSlots); | 861 EXPECT_EQ(4, page->numAllocatedSlots); |
| 862 EXPECT_EQ(0, page->numUnprovisionedSlots); | 862 EXPECT_EQ(0, page->numUnprovisionedSlots); |
| 863 | 863 |
| 864 void* ptr5 = partitionAlloc(allocator.root(), bigSize, kTypeName); | 864 void* ptr5 = partitionAlloc(allocator.root(), bigSize, typeName); |
| 865 EXPECT_TRUE(ptr5); | 865 EXPECT_TRUE(ptr5); |
| 866 | 866 |
| 867 PartitionPage* page2 = partitionPointerToPage(partitionCookieFreePointerAdju
st(ptr5)); | 867 PartitionPage* page2 = partitionPointerToPage(partitionCookieFreePointerAdju
st(ptr5)); |
| 868 EXPECT_EQ(1, page2->numAllocatedSlots); | 868 EXPECT_EQ(1, page2->numAllocatedSlots); |
| 869 | 869 |
| 870 // Churn things a little whilst there's a partial page freelist. | 870 // Churn things a little whilst there's a partial page freelist. |
| 871 partitionFree(ptr); | 871 partitionFree(ptr); |
| 872 ptr = partitionAlloc(allocator.root(), bigSize, kTypeName); | 872 ptr = partitionAlloc(allocator.root(), bigSize, typeName); |
| 873 void* ptr6 = partitionAlloc(allocator.root(), bigSize, kTypeName); | 873 void* ptr6 = partitionAlloc(allocator.root(), bigSize, typeName); |
| 874 | 874 |
| 875 partitionFree(ptr); | 875 partitionFree(ptr); |
| 876 partitionFree(ptr2); | 876 partitionFree(ptr2); |
| 877 partitionFree(ptr3); | 877 partitionFree(ptr3); |
| 878 partitionFree(ptr4); | 878 partitionFree(ptr4); |
| 879 partitionFree(ptr5); | 879 partitionFree(ptr5); |
| 880 partitionFree(ptr6); | 880 partitionFree(ptr6); |
| 881 EXPECT_NE(-1, page->emptyCacheIndex); | 881 EXPECT_NE(-1, page->emptyCacheIndex); |
| 882 EXPECT_NE(-1, page2->emptyCacheIndex); | 882 EXPECT_NE(-1, page2->emptyCacheIndex); |
| 883 EXPECT_TRUE(page2->freelistHead); | 883 EXPECT_TRUE(page2->freelistHead); |
| 884 EXPECT_EQ(0, page2->numAllocatedSlots); | 884 EXPECT_EQ(0, page2->numAllocatedSlots); |
| 885 | 885 |
| 886 // And test a couple of sizes that do not cross kSystemPageSize with a singl
e allocation. | 886 // And test a couple of sizes that do not cross kSystemPageSize with a singl
e allocation. |
| 887 size_t mediumSize = (kSystemPageSize / 2) - kExtraAllocSize; | 887 size_t mediumSize = (kSystemPageSize / 2) - kExtraAllocSize; |
| 888 bucketIdx = (mediumSize + kExtraAllocSize) >> kBucketShift; | 888 bucketIdx = (mediumSize + kExtraAllocSize) >> kBucketShift; |
| 889 bucket = &allocator.root()->buckets()[bucketIdx]; | 889 bucket = &allocator.root()->buckets()[bucketIdx]; |
| 890 EXPECT_EQ(0, bucket->emptyPagesHead); | 890 EXPECT_EQ(0, bucket->emptyPagesHead); |
| 891 | 891 |
| 892 ptr = partitionAlloc(allocator.root(), mediumSize, kTypeName); | 892 ptr = partitionAlloc(allocator.root(), mediumSize, typeName); |
| 893 EXPECT_TRUE(ptr); | 893 EXPECT_TRUE(ptr); |
| 894 page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr)); | 894 page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr)); |
| 895 EXPECT_EQ(1, page->numAllocatedSlots); | 895 EXPECT_EQ(1, page->numAllocatedSlots); |
| 896 totalSlots = (page->bucket->numSystemPagesPerSlotSpan * kSystemPageSize) / (
mediumSize + kExtraAllocSize); | 896 totalSlots = (page->bucket->numSystemPagesPerSlotSpan * kSystemPageSize) / (
mediumSize + kExtraAllocSize); |
| 897 size_t firstPageSlots = kSystemPageSize / (mediumSize + kExtraAllocSize); | 897 size_t firstPageSlots = kSystemPageSize / (mediumSize + kExtraAllocSize); |
| 898 EXPECT_EQ(2u, firstPageSlots); | 898 EXPECT_EQ(2u, firstPageSlots); |
| 899 EXPECT_EQ(totalSlots - firstPageSlots, page->numUnprovisionedSlots); | 899 EXPECT_EQ(totalSlots - firstPageSlots, page->numUnprovisionedSlots); |
| 900 | 900 |
| 901 partitionFree(ptr); | 901 partitionFree(ptr); |
| 902 | 902 |
| 903 size_t smallSize = (kSystemPageSize / 4) - kExtraAllocSize; | 903 size_t smallSize = (kSystemPageSize / 4) - kExtraAllocSize; |
| 904 bucketIdx = (smallSize + kExtraAllocSize) >> kBucketShift; | 904 bucketIdx = (smallSize + kExtraAllocSize) >> kBucketShift; |
| 905 bucket = &allocator.root()->buckets()[bucketIdx]; | 905 bucket = &allocator.root()->buckets()[bucketIdx]; |
| 906 EXPECT_EQ(0, bucket->emptyPagesHead); | 906 EXPECT_EQ(0, bucket->emptyPagesHead); |
| 907 | 907 |
| 908 ptr = partitionAlloc(allocator.root(), smallSize, kTypeName); | 908 ptr = partitionAlloc(allocator.root(), smallSize, typeName); |
| 909 EXPECT_TRUE(ptr); | 909 EXPECT_TRUE(ptr); |
| 910 page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr)); | 910 page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr)); |
| 911 EXPECT_EQ(1, page->numAllocatedSlots); | 911 EXPECT_EQ(1, page->numAllocatedSlots); |
| 912 totalSlots = (page->bucket->numSystemPagesPerSlotSpan * kSystemPageSize) / (
smallSize + kExtraAllocSize); | 912 totalSlots = (page->bucket->numSystemPagesPerSlotSpan * kSystemPageSize) / (
smallSize + kExtraAllocSize); |
| 913 firstPageSlots = kSystemPageSize / (smallSize + kExtraAllocSize); | 913 firstPageSlots = kSystemPageSize / (smallSize + kExtraAllocSize); |
| 914 EXPECT_EQ(totalSlots - firstPageSlots, page->numUnprovisionedSlots); | 914 EXPECT_EQ(totalSlots - firstPageSlots, page->numUnprovisionedSlots); |
| 915 | 915 |
| 916 partitionFree(ptr); | 916 partitionFree(ptr); |
| 917 EXPECT_TRUE(page->freelistHead); | 917 EXPECT_TRUE(page->freelistHead); |
| 918 EXPECT_EQ(0, page->numAllocatedSlots); | 918 EXPECT_EQ(0, page->numAllocatedSlots); |
| 919 | 919 |
| 920 size_t verySmallSize = 32 - kExtraAllocSize; | 920 size_t verySmallSize = 32 - kExtraAllocSize; |
| 921 bucketIdx = (verySmallSize + kExtraAllocSize) >> kBucketShift; | 921 bucketIdx = (verySmallSize + kExtraAllocSize) >> kBucketShift; |
| 922 bucket = &allocator.root()->buckets()[bucketIdx]; | 922 bucket = &allocator.root()->buckets()[bucketIdx]; |
| 923 EXPECT_EQ(0, bucket->emptyPagesHead); | 923 EXPECT_EQ(0, bucket->emptyPagesHead); |
| 924 | 924 |
| 925 ptr = partitionAlloc(allocator.root(), verySmallSize, kTypeName); | 925 ptr = partitionAlloc(allocator.root(), verySmallSize, typeName); |
| 926 EXPECT_TRUE(ptr); | 926 EXPECT_TRUE(ptr); |
| 927 page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr)); | 927 page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr)); |
| 928 EXPECT_EQ(1, page->numAllocatedSlots); | 928 EXPECT_EQ(1, page->numAllocatedSlots); |
| 929 totalSlots = (page->bucket->numSystemPagesPerSlotSpan * kSystemPageSize) / (
verySmallSize + kExtraAllocSize); | 929 totalSlots = (page->bucket->numSystemPagesPerSlotSpan * kSystemPageSize) / (
verySmallSize + kExtraAllocSize); |
| 930 firstPageSlots = kSystemPageSize / (verySmallSize + kExtraAllocSize); | 930 firstPageSlots = kSystemPageSize / (verySmallSize + kExtraAllocSize); |
| 931 EXPECT_EQ(totalSlots - firstPageSlots, page->numUnprovisionedSlots); | 931 EXPECT_EQ(totalSlots - firstPageSlots, page->numUnprovisionedSlots); |
| 932 | 932 |
| 933 partitionFree(ptr); | 933 partitionFree(ptr); |
| 934 EXPECT_TRUE(page->freelistHead); | 934 EXPECT_TRUE(page->freelistHead); |
| 935 EXPECT_EQ(0, page->numAllocatedSlots); | 935 EXPECT_EQ(0, page->numAllocatedSlots); |
| 936 | 936 |
| 937 // And try an allocation size (against the generic allocator) that is | 937 // And try an allocation size (against the generic allocator) that is |
| 938 // larger than a system page. | 938 // larger than a system page. |
| 939 size_t pageAndAHalfSize = (kSystemPageSize + (kSystemPageSize / 2)) - kExtra
AllocSize; | 939 size_t pageAndAHalfSize = (kSystemPageSize + (kSystemPageSize / 2)) - kExtra
AllocSize; |
| 940 ptr = partitionAllocGeneric(genericAllocator.root(), pageAndAHalfSize, kType
Name); | 940 ptr = partitionAllocGeneric(genericAllocator.root(), pageAndAHalfSize, typeN
ame); |
| 941 EXPECT_TRUE(ptr); | 941 EXPECT_TRUE(ptr); |
| 942 page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr)); | 942 page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr)); |
| 943 EXPECT_EQ(1, page->numAllocatedSlots); | 943 EXPECT_EQ(1, page->numAllocatedSlots); |
| 944 EXPECT_TRUE(page->freelistHead); | 944 EXPECT_TRUE(page->freelistHead); |
| 945 totalSlots = (page->bucket->numSystemPagesPerSlotSpan * kSystemPageSize) / (
pageAndAHalfSize + kExtraAllocSize); | 945 totalSlots = (page->bucket->numSystemPagesPerSlotSpan * kSystemPageSize) / (
pageAndAHalfSize + kExtraAllocSize); |
| 946 EXPECT_EQ(totalSlots - 2, page->numUnprovisionedSlots); | 946 EXPECT_EQ(totalSlots - 2, page->numUnprovisionedSlots); |
| 947 partitionFreeGeneric(genericAllocator.root(), ptr); | 947 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 948 | 948 |
| 949 // And then make sure than exactly the page size only faults one page. | 949 // And then make sure than exactly the page size only faults one page. |
| 950 size_t pageSize = kSystemPageSize - kExtraAllocSize; | 950 size_t pageSize = kSystemPageSize - kExtraAllocSize; |
| 951 ptr = partitionAllocGeneric(genericAllocator.root(), pageSize, kTypeName); | 951 ptr = partitionAllocGeneric(genericAllocator.root(), pageSize, typeName); |
| 952 EXPECT_TRUE(ptr); | 952 EXPECT_TRUE(ptr); |
| 953 page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr)); | 953 page = partitionPointerToPage(partitionCookieFreePointerAdjust(ptr)); |
| 954 EXPECT_EQ(1, page->numAllocatedSlots); | 954 EXPECT_EQ(1, page->numAllocatedSlots); |
| 955 EXPECT_FALSE(page->freelistHead); | 955 EXPECT_FALSE(page->freelistHead); |
| 956 totalSlots = (page->bucket->numSystemPagesPerSlotSpan * kSystemPageSize) / (
pageSize + kExtraAllocSize); | 956 totalSlots = (page->bucket->numSystemPagesPerSlotSpan * kSystemPageSize) / (
pageSize + kExtraAllocSize); |
| 957 EXPECT_EQ(totalSlots - 1, page->numUnprovisionedSlots); | 957 EXPECT_EQ(totalSlots - 1, page->numUnprovisionedSlots); |
| 958 partitionFreeGeneric(genericAllocator.root(), ptr); | 958 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 959 | 959 |
| 960 TestShutdown(); | 960 TestShutdown(); |
| 961 } | 961 } |
| 962 | 962 |
| 963 // Test some of the fragmentation-resistant properties of the allocator. | 963 // Test some of the fragmentation-resistant properties of the allocator. |
| 964 TEST(PartitionAllocTest, PageRefilling) | 964 TEST(PartitionAllocTest, PageRefilling) |
| 965 { | 965 { |
| 966 TestSetup(); | 966 TestSetup(); |
| 967 PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex]; | 967 PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex]; |
| 968 | 968 |
| 969 // Grab two full pages and a non-full page. | 969 // Grab two full pages and a non-full page. |
| 970 PartitionPage* page1 = GetFullPage(kTestAllocSize); | 970 PartitionPage* page1 = GetFullPage(kTestAllocSize); |
| 971 PartitionPage* page2 = GetFullPage(kTestAllocSize); | 971 PartitionPage* page2 = GetFullPage(kTestAllocSize); |
| 972 void* ptr = partitionAlloc(allocator.root(), kTestAllocSize, kTypeName); | 972 void* ptr = partitionAlloc(allocator.root(), kTestAllocSize, typeName); |
| 973 EXPECT_TRUE(ptr); | 973 EXPECT_TRUE(ptr); |
| 974 EXPECT_NE(page1, bucket->activePagesHead); | 974 EXPECT_NE(page1, bucket->activePagesHead); |
| 975 EXPECT_NE(page2, bucket->activePagesHead); | 975 EXPECT_NE(page2, bucket->activePagesHead); |
| 976 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjus
t(ptr)); | 976 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjus
t(ptr)); |
| 977 EXPECT_EQ(1, page->numAllocatedSlots); | 977 EXPECT_EQ(1, page->numAllocatedSlots); |
| 978 | 978 |
| 979 // Work out a pointer into page2 and free it; and then page1 and free it. | 979 // Work out a pointer into page2 and free it; and then page1 and free it. |
| 980 char* ptr2 = reinterpret_cast<char*>(partitionPageToPointer(page1)) + kPoint
erOffset; | 980 char* ptr2 = reinterpret_cast<char*>(partitionPageToPointer(page1)) + kPoint
erOffset; |
| 981 partitionFree(ptr2); | 981 partitionFree(ptr2); |
| 982 ptr2 = reinterpret_cast<char*>(partitionPageToPointer(page2)) + kPointerOffs
et; | 982 ptr2 = reinterpret_cast<char*>(partitionPageToPointer(page2)) + kPointerOffs
et; |
| 983 partitionFree(ptr2); | 983 partitionFree(ptr2); |
| 984 | 984 |
| 985 // If we perform two allocations from the same bucket now, we expect to | 985 // If we perform two allocations from the same bucket now, we expect to |
| 986 // refill both the nearly full pages. | 986 // refill both the nearly full pages. |
| 987 (void)partitionAlloc(allocator.root(), kTestAllocSize, kTypeName); | 987 (void)partitionAlloc(allocator.root(), kTestAllocSize, typeName); |
| 988 (void)partitionAlloc(allocator.root(), kTestAllocSize, kTypeName); | 988 (void)partitionAlloc(allocator.root(), kTestAllocSize, typeName); |
| 989 EXPECT_EQ(1, page->numAllocatedSlots); | 989 EXPECT_EQ(1, page->numAllocatedSlots); |
| 990 | 990 |
| 991 FreeFullPage(page2); | 991 FreeFullPage(page2); |
| 992 FreeFullPage(page1); | 992 FreeFullPage(page1); |
| 993 partitionFree(ptr); | 993 partitionFree(ptr); |
| 994 | 994 |
| 995 TestShutdown(); | 995 TestShutdown(); |
| 996 } | 996 } |
| 997 | 997 |
| 998 // Basic tests to ensure that allocations work for partial page buckets. | 998 // Basic tests to ensure that allocations work for partial page buckets. |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1084 TEST(PartitionAllocTest, FreeCache) | 1084 TEST(PartitionAllocTest, FreeCache) |
| 1085 { | 1085 { |
| 1086 TestSetup(); | 1086 TestSetup(); |
| 1087 | 1087 |
| 1088 EXPECT_EQ(0U, allocator.root()->totalSizeOfCommittedPages); | 1088 EXPECT_EQ(0U, allocator.root()->totalSizeOfCommittedPages); |
| 1089 | 1089 |
| 1090 size_t bigSize = allocator.root()->maxAllocation - kExtraAllocSize; | 1090 size_t bigSize = allocator.root()->maxAllocation - kExtraAllocSize; |
| 1091 size_t bucketIdx = (bigSize + kExtraAllocSize) >> kBucketShift; | 1091 size_t bucketIdx = (bigSize + kExtraAllocSize) >> kBucketShift; |
| 1092 PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx]; | 1092 PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx]; |
| 1093 | 1093 |
| 1094 void* ptr = partitionAlloc(allocator.root(), bigSize, kTypeName); | 1094 void* ptr = partitionAlloc(allocator.root(), bigSize, typeName); |
| 1095 EXPECT_TRUE(ptr); | 1095 EXPECT_TRUE(ptr); |
| 1096 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjus
t(ptr)); | 1096 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjus
t(ptr)); |
| 1097 EXPECT_EQ(0, bucket->emptyPagesHead); | 1097 EXPECT_EQ(0, bucket->emptyPagesHead); |
| 1098 EXPECT_EQ(1, page->numAllocatedSlots); | 1098 EXPECT_EQ(1, page->numAllocatedSlots); |
| 1099 EXPECT_EQ(kPartitionPageSize, allocator.root()->totalSizeOfCommittedPages); | 1099 EXPECT_EQ(kPartitionPageSize, allocator.root()->totalSizeOfCommittedPages); |
| 1100 partitionFree(ptr); | 1100 partitionFree(ptr); |
| 1101 EXPECT_EQ(0, page->numAllocatedSlots); | 1101 EXPECT_EQ(0, page->numAllocatedSlots); |
| 1102 EXPECT_NE(-1, page->emptyCacheIndex); | 1102 EXPECT_NE(-1, page->emptyCacheIndex); |
| 1103 EXPECT_TRUE(page->freelistHead); | 1103 EXPECT_TRUE(page->freelistHead); |
| 1104 | 1104 |
| 1105 CycleFreeCache(kTestAllocSize); | 1105 CycleFreeCache(kTestAllocSize); |
| 1106 | 1106 |
| 1107 // Flushing the cache should have really freed the unused page. | 1107 // Flushing the cache should have really freed the unused page. |
| 1108 EXPECT_FALSE(page->freelistHead); | 1108 EXPECT_FALSE(page->freelistHead); |
| 1109 EXPECT_EQ(-1, page->emptyCacheIndex); | 1109 EXPECT_EQ(-1, page->emptyCacheIndex); |
| 1110 EXPECT_EQ(0, page->numAllocatedSlots); | 1110 EXPECT_EQ(0, page->numAllocatedSlots); |
| 1111 PartitionBucket* cycleFreeCacheBucket = &allocator.root()->buckets()[kTestBu
cketIndex]; | 1111 PartitionBucket* cycleFreeCacheBucket = &allocator.root()->buckets()[kTestBu
cketIndex]; |
| 1112 EXPECT_EQ(cycleFreeCacheBucket->numSystemPagesPerSlotSpan * kSystemPageSize,
allocator.root()->totalSizeOfCommittedPages); | 1112 EXPECT_EQ(cycleFreeCacheBucket->numSystemPagesPerSlotSpan * kSystemPageSize,
allocator.root()->totalSizeOfCommittedPages); |
| 1113 | 1113 |
| 1114 // Check that an allocation works ok whilst in this state (a free'd page | 1114 // Check that an allocation works ok whilst in this state (a free'd page |
| 1115 // as the active pages head). | 1115 // as the active pages head). |
| 1116 ptr = partitionAlloc(allocator.root(), bigSize, kTypeName); | 1116 ptr = partitionAlloc(allocator.root(), bigSize, typeName); |
| 1117 EXPECT_FALSE(bucket->emptyPagesHead); | 1117 EXPECT_FALSE(bucket->emptyPagesHead); |
| 1118 partitionFree(ptr); | 1118 partitionFree(ptr); |
| 1119 | 1119 |
| 1120 // Also check that a page that is bouncing immediately between empty and | 1120 // Also check that a page that is bouncing immediately between empty and |
| 1121 // used does not get freed. | 1121 // used does not get freed. |
| 1122 for (size_t i = 0; i < kMaxFreeableSpans * 2; ++i) { | 1122 for (size_t i = 0; i < kMaxFreeableSpans * 2; ++i) { |
| 1123 ptr = partitionAlloc(allocator.root(), bigSize, kTypeName); | 1123 ptr = partitionAlloc(allocator.root(), bigSize, typeName); |
| 1124 EXPECT_TRUE(page->freelistHead); | 1124 EXPECT_TRUE(page->freelistHead); |
| 1125 partitionFree(ptr); | 1125 partitionFree(ptr); |
| 1126 EXPECT_TRUE(page->freelistHead); | 1126 EXPECT_TRUE(page->freelistHead); |
| 1127 } | 1127 } |
| 1128 EXPECT_EQ(kPartitionPageSize, allocator.root()->totalSizeOfCommittedPages); | 1128 EXPECT_EQ(kPartitionPageSize, allocator.root()->totalSizeOfCommittedPages); |
| 1129 TestShutdown(); | 1129 TestShutdown(); |
| 1130 } | 1130 } |
| 1131 | 1131 |
| 1132 // Tests for a bug we had with losing references to free pages. | 1132 // Tests for a bug we had with losing references to free pages. |
| 1133 TEST(PartitionAllocTest, LostFreePagesBug) | 1133 TEST(PartitionAllocTest, LostFreePagesBug) |
| 1134 { | 1134 { |
| 1135 TestSetup(); | 1135 TestSetup(); |
| 1136 | 1136 |
| 1137 size_t size = kPartitionPageSize - kExtraAllocSize; | 1137 size_t size = kPartitionPageSize - kExtraAllocSize; |
| 1138 | 1138 |
| 1139 void* ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName); | 1139 void* ptr = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 1140 EXPECT_TRUE(ptr); | 1140 EXPECT_TRUE(ptr); |
| 1141 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName)
; | 1141 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 1142 EXPECT_TRUE(ptr2); | 1142 EXPECT_TRUE(ptr2); |
| 1143 | 1143 |
| 1144 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjus
t(ptr)); | 1144 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerAdjus
t(ptr)); |
| 1145 PartitionPage* page2 = partitionPointerToPage(partitionCookieFreePointerAdju
st(ptr2)); | 1145 PartitionPage* page2 = partitionPointerToPage(partitionCookieFreePointerAdju
st(ptr2)); |
| 1146 PartitionBucket* bucket = page->bucket; | 1146 PartitionBucket* bucket = page->bucket; |
| 1147 | 1147 |
| 1148 EXPECT_EQ(0, bucket->emptyPagesHead); | 1148 EXPECT_EQ(0, bucket->emptyPagesHead); |
| 1149 EXPECT_EQ(-1, page->numAllocatedSlots); | 1149 EXPECT_EQ(-1, page->numAllocatedSlots); |
| 1150 EXPECT_EQ(1, page2->numAllocatedSlots); | 1150 EXPECT_EQ(1, page2->numAllocatedSlots); |
| 1151 | 1151 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1162 CycleGenericFreeCache(kTestAllocSize); | 1162 CycleGenericFreeCache(kTestAllocSize); |
| 1163 | 1163 |
| 1164 EXPECT_FALSE(page->freelistHead); | 1164 EXPECT_FALSE(page->freelistHead); |
| 1165 EXPECT_FALSE(page2->freelistHead); | 1165 EXPECT_FALSE(page2->freelistHead); |
| 1166 | 1166 |
| 1167 EXPECT_TRUE(bucket->emptyPagesHead); | 1167 EXPECT_TRUE(bucket->emptyPagesHead); |
| 1168 EXPECT_TRUE(bucket->emptyPagesHead->nextPage); | 1168 EXPECT_TRUE(bucket->emptyPagesHead->nextPage); |
| 1169 EXPECT_EQ(&PartitionRootGeneric::gSeedPage, bucket->activePagesHead); | 1169 EXPECT_EQ(&PartitionRootGeneric::gSeedPage, bucket->activePagesHead); |
| 1170 | 1170 |
| 1171 // At this moment, we have two decommitted pages, on the empty list. | 1171 // At this moment, we have two decommitted pages, on the empty list. |
| 1172 ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName); | 1172 ptr = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 1173 EXPECT_TRUE(ptr); | 1173 EXPECT_TRUE(ptr); |
| 1174 partitionFreeGeneric(genericAllocator.root(), ptr); | 1174 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 1175 | 1175 |
| 1176 EXPECT_EQ(&PartitionRootGeneric::gSeedPage, bucket->activePagesHead); | 1176 EXPECT_EQ(&PartitionRootGeneric::gSeedPage, bucket->activePagesHead); |
| 1177 EXPECT_TRUE(bucket->emptyPagesHead); | 1177 EXPECT_TRUE(bucket->emptyPagesHead); |
| 1178 EXPECT_TRUE(bucket->decommittedPagesHead); | 1178 EXPECT_TRUE(bucket->decommittedPagesHead); |
| 1179 | 1179 |
| 1180 CycleGenericFreeCache(kTestAllocSize); | 1180 CycleGenericFreeCache(kTestAllocSize); |
| 1181 | 1181 |
| 1182 // We're now set up to trigger a historical bug by scanning over the active | 1182 // We're now set up to trigger a historical bug by scanning over the active |
| 1183 // pages list. The current code gets into a different state, but we'll keep | 1183 // pages list. The current code gets into a different state, but we'll keep |
| 1184 // the test as being an interesting corner case. | 1184 // the test as being an interesting corner case. |
| 1185 ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName); | 1185 ptr = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 1186 EXPECT_TRUE(ptr); | 1186 EXPECT_TRUE(ptr); |
| 1187 partitionFreeGeneric(genericAllocator.root(), ptr); | 1187 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 1188 | 1188 |
| 1189 EXPECT_TRUE(bucket->activePagesHead); | 1189 EXPECT_TRUE(bucket->activePagesHead); |
| 1190 EXPECT_TRUE(bucket->emptyPagesHead); | 1190 EXPECT_TRUE(bucket->emptyPagesHead); |
| 1191 EXPECT_TRUE(bucket->decommittedPagesHead); | 1191 EXPECT_TRUE(bucket->decommittedPagesHead); |
| 1192 | 1192 |
| 1193 TestShutdown(); | 1193 TestShutdown(); |
| 1194 } | 1194 } |
| 1195 | 1195 |
| 1196 #if !CPU(64BIT) || OS(POSIX) | 1196 #if !CPU(64BIT) || OS(POSIX) |
| 1197 | 1197 |
| 1198 static void DoReturnNullTest(size_t allocSize) | 1198 static void DoReturnNullTest(size_t allocSize) |
| 1199 { | 1199 { |
| 1200 TestSetup(); | 1200 TestSetup(); |
| 1201 | 1201 |
| 1202 EXPECT_TRUE(SetAddressSpaceLimit()); | 1202 EXPECT_TRUE(SetAddressSpaceLimit()); |
| 1203 | 1203 |
| 1204 // Work out the number of allocations for 6 GB of memory. | 1204 // Work out the number of allocations for 6 GB of memory. |
| 1205 const int numAllocations = (6 * 1024 * 1024) / (allocSize / 1024); | 1205 const int numAllocations = (6 * 1024 * 1024) / (allocSize / 1024); |
| 1206 | 1206 |
| 1207 void** ptrs = reinterpret_cast<void**>(partitionAllocGeneric(genericAllocato
r.root(), numAllocations * sizeof(void*), kTypeName)); | 1207 void** ptrs = reinterpret_cast<void**>(partitionAllocGeneric(genericAllocato
r.root(), numAllocations * sizeof(void*), typeName)); |
| 1208 int i; | 1208 int i; |
| 1209 | 1209 |
| 1210 for (i = 0; i < numAllocations; ++i) { | 1210 for (i = 0; i < numAllocations; ++i) { |
| 1211 ptrs[i] = partitionAllocGenericFlags(genericAllocator.root(), PartitionA
llocReturnNull, allocSize, kTypeName); | 1211 ptrs[i] = partitionAllocGenericFlags(genericAllocator.root(), PartitionA
llocReturnNull, allocSize, typeName); |
| 1212 if (!i) | 1212 if (!i) |
| 1213 EXPECT_TRUE(ptrs[0]); | 1213 EXPECT_TRUE(ptrs[0]); |
| 1214 if (!ptrs[i]) { | 1214 if (!ptrs[i]) { |
| 1215 ptrs[i] = partitionAllocGenericFlags(genericAllocator.root(), Partit
ionAllocReturnNull, allocSize, kTypeName); | 1215 ptrs[i] = partitionAllocGenericFlags(genericAllocator.root(), Partit
ionAllocReturnNull, allocSize, typeName); |
| 1216 EXPECT_FALSE(ptrs[i]); | 1216 EXPECT_FALSE(ptrs[i]); |
| 1217 break; | 1217 break; |
| 1218 } | 1218 } |
| 1219 } | 1219 } |
| 1220 | 1220 |
| 1221 // We shouldn't succeed in allocating all 6 GB of memory. If we do, then | 1221 // We shouldn't succeed in allocating all 6 GB of memory. If we do, then |
| 1222 // we're not actually testing anything here. | 1222 // we're not actually testing anything here. |
| 1223 EXPECT_LT(i, numAllocations); | 1223 EXPECT_LT(i, numAllocations); |
| 1224 | 1224 |
| 1225 // Free, reallocate and free again each block we allocated. We do this to | 1225 // Free, reallocate and free again each block we allocated. We do this to |
| 1226 // check that freeing memory also works correctly after a failed allocation. | 1226 // check that freeing memory also works correctly after a failed allocation. |
| 1227 for (--i; i >= 0; --i) { | 1227 for (--i; i >= 0; --i) { |
| 1228 partitionFreeGeneric(genericAllocator.root(), ptrs[i]); | 1228 partitionFreeGeneric(genericAllocator.root(), ptrs[i]); |
| 1229 ptrs[i] = partitionAllocGenericFlags(genericAllocator.root(), PartitionA
llocReturnNull, allocSize, kTypeName); | 1229 ptrs[i] = partitionAllocGenericFlags(genericAllocator.root(), PartitionA
llocReturnNull, allocSize, typeName); |
| 1230 EXPECT_TRUE(ptrs[i]); | 1230 EXPECT_TRUE(ptrs[i]); |
| 1231 partitionFreeGeneric(genericAllocator.root(), ptrs[i]); | 1231 partitionFreeGeneric(genericAllocator.root(), ptrs[i]); |
| 1232 } | 1232 } |
| 1233 | 1233 |
| 1234 partitionFreeGeneric(genericAllocator.root(), ptrs); | 1234 partitionFreeGeneric(genericAllocator.root(), ptrs); |
| 1235 | 1235 |
| 1236 EXPECT_TRUE(ClearAddressSpaceLimit()); | 1236 EXPECT_TRUE(ClearAddressSpaceLimit()); |
| 1237 | 1237 |
| 1238 TestShutdown(); | 1238 TestShutdown(); |
| 1239 } | 1239 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1269 | 1269 |
| 1270 #if !OS(ANDROID) | 1270 #if !OS(ANDROID) |
| 1271 | 1271 |
| 1272 // Make sure that malloc(-1) dies. | 1272 // Make sure that malloc(-1) dies. |
| 1273 // In the past, we had an integer overflow that would alias malloc(-1) to | 1273 // In the past, we had an integer overflow that would alias malloc(-1) to |
| 1274 // malloc(0), which is not good. | 1274 // malloc(0), which is not good. |
| 1275 TEST(PartitionAllocDeathTest, LargeAllocs) | 1275 TEST(PartitionAllocDeathTest, LargeAllocs) |
| 1276 { | 1276 { |
| 1277 TestSetup(); | 1277 TestSetup(); |
| 1278 // Largest alloc. | 1278 // Largest alloc. |
| 1279 EXPECT_DEATH(partitionAllocGeneric(genericAllocator.root(), static_cast<size
_t>(-1), kTypeName), ""); | 1279 EXPECT_DEATH(partitionAllocGeneric(genericAllocator.root(), static_cast<size
_t>(-1), typeName), ""); |
| 1280 // And the smallest allocation we expect to die. | 1280 // And the smallest allocation we expect to die. |
| 1281 EXPECT_DEATH(partitionAllocGeneric(genericAllocator.root(), static_cast<size
_t>(INT_MAX) + 1, kTypeName), ""); | 1281 EXPECT_DEATH(partitionAllocGeneric(genericAllocator.root(), static_cast<size
_t>(INT_MAX) + 1, typeName), ""); |
| 1282 | 1282 |
| 1283 TestShutdown(); | 1283 TestShutdown(); |
| 1284 } | 1284 } |
| 1285 | 1285 |
| 1286 // Check that our immediate double-free detection works. | 1286 // Check that our immediate double-free detection works. |
| 1287 TEST(PartitionAllocDeathTest, ImmediateDoubleFree) | 1287 TEST(PartitionAllocDeathTest, ImmediateDoubleFree) |
| 1288 { | 1288 { |
| 1289 TestSetup(); | 1289 TestSetup(); |
| 1290 | 1290 |
| 1291 void* ptr = partitionAllocGeneric(genericAllocator.root(), kTestAllocSize, k
TypeName); | 1291 void* ptr = partitionAllocGeneric(genericAllocator.root(), kTestAllocSize, t
ypeName); |
| 1292 EXPECT_TRUE(ptr); | 1292 EXPECT_TRUE(ptr); |
| 1293 partitionFreeGeneric(genericAllocator.root(), ptr); | 1293 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 1294 | 1294 |
| 1295 EXPECT_DEATH(partitionFreeGeneric(genericAllocator.root(), ptr), ""); | 1295 EXPECT_DEATH(partitionFreeGeneric(genericAllocator.root(), ptr), ""); |
| 1296 | 1296 |
| 1297 TestShutdown(); | 1297 TestShutdown(); |
| 1298 } | 1298 } |
| 1299 | 1299 |
| 1300 // Check that our refcount-based double-free detection works. | 1300 // Check that our refcount-based double-free detection works. |
| 1301 TEST(PartitionAllocDeathTest, RefcountDoubleFree) | 1301 TEST(PartitionAllocDeathTest, RefcountDoubleFree) |
| 1302 { | 1302 { |
| 1303 TestSetup(); | 1303 TestSetup(); |
| 1304 | 1304 |
| 1305 void* ptr = partitionAllocGeneric(genericAllocator.root(), kTestAllocSize, k
TypeName); | 1305 void* ptr = partitionAllocGeneric(genericAllocator.root(), kTestAllocSize, t
ypeName); |
| 1306 EXPECT_TRUE(ptr); | 1306 EXPECT_TRUE(ptr); |
| 1307 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), kTestAllocSize,
kTypeName); | 1307 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), kTestAllocSize,
typeName); |
| 1308 EXPECT_TRUE(ptr2); | 1308 EXPECT_TRUE(ptr2); |
| 1309 partitionFreeGeneric(genericAllocator.root(), ptr); | 1309 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 1310 partitionFreeGeneric(genericAllocator.root(), ptr2); | 1310 partitionFreeGeneric(genericAllocator.root(), ptr2); |
| 1311 // This is not an immediate double-free so our immediate detection won't | 1311 // This is not an immediate double-free so our immediate detection won't |
| 1312 // fire. However, it does take the "refcount" of the partition page to -1, | 1312 // fire. However, it does take the "refcount" of the partition page to -1, |
| 1313 // which is illegal and should be trapped. | 1313 // which is illegal and should be trapped. |
| 1314 EXPECT_DEATH(partitionFreeGeneric(genericAllocator.root(), ptr), ""); | 1314 EXPECT_DEATH(partitionFreeGeneric(genericAllocator.root(), ptr), ""); |
| 1315 | 1315 |
| 1316 TestShutdown(); | 1316 TestShutdown(); |
| 1317 } | 1317 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1331 // (On 32-bit, partitionAlloc adds another kSystemPageSize to the | 1331 // (On 32-bit, partitionAlloc adds another kSystemPageSize to the |
| 1332 // allocation size before rounding, but there it marks the memory right | 1332 // allocation size before rounding, but there it marks the memory right |
| 1333 // after size as inaccessible, so it's fine to write 1 past the size we | 1333 // after size as inaccessible, so it's fine to write 1 past the size we |
| 1334 // hand to partitionAlloc and we don't need to worry about allocation | 1334 // hand to partitionAlloc and we don't need to worry about allocation |
| 1335 // granularities.) | 1335 // granularities.) |
| 1336 #define ALIGN(N, A) (((N) + (A) - 1) / (A) * (A)) | 1336 #define ALIGN(N, A) (((N) + (A) - 1) / (A) * (A)) |
| 1337 const int kSize = ALIGN(kGenericMaxBucketed + 1 + kPartitionPageSize, kPageA
llocationGranularity) - kPartitionPageSize; | 1337 const int kSize = ALIGN(kGenericMaxBucketed + 1 + kPartitionPageSize, kPageA
llocationGranularity) - kPartitionPageSize; |
| 1338 #undef ALIGN | 1338 #undef ALIGN |
| 1339 static_assert(kSize > kGenericMaxBucketed, "allocation not large enough for
direct allocation"); | 1339 static_assert(kSize > kGenericMaxBucketed, "allocation not large enough for
direct allocation"); |
| 1340 size_t size = kSize - kExtraAllocSize; | 1340 size_t size = kSize - kExtraAllocSize; |
| 1341 void* ptr = partitionAllocGeneric(genericAllocator.root(), size, kTypeName); | 1341 void* ptr = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 1342 | 1342 |
| 1343 EXPECT_TRUE(ptr); | 1343 EXPECT_TRUE(ptr); |
| 1344 char* charPtr = reinterpret_cast<char*>(ptr) - kPointerOffset; | 1344 char* charPtr = reinterpret_cast<char*>(ptr) - kPointerOffset; |
| 1345 | 1345 |
| 1346 EXPECT_DEATH(*(charPtr - 1) = 'A', ""); | 1346 EXPECT_DEATH(*(charPtr - 1) = 'A', ""); |
| 1347 EXPECT_DEATH(*(charPtr + size + kExtraAllocSize) = 'A', ""); | 1347 EXPECT_DEATH(*(charPtr + size + kExtraAllocSize) = 'A', ""); |
| 1348 | 1348 |
| 1349 partitionFreeGeneric(genericAllocator.root(), ptr); | 1349 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 1350 | 1350 |
| 1351 TestShutdown(); | 1351 TestShutdown(); |
| 1352 } | 1352 } |
| 1353 | 1353 |
| 1354 // Check that a bad free() is caught where the free() refers to an unused | 1354 // Check that a bad free() is caught where the free() refers to an unused |
| 1355 // partition page of a large allocation. | 1355 // partition page of a large allocation. |
| 1356 TEST(PartitionAllocDeathTest, FreeWrongPartitionPage) | 1356 TEST(PartitionAllocDeathTest, FreeWrongPartitionPage) |
| 1357 { | 1357 { |
| 1358 TestSetup(); | 1358 TestSetup(); |
| 1359 | 1359 |
| 1360 // This large size will result in a direct mapped allocation with guard | 1360 // This large size will result in a direct mapped allocation with guard |
| 1361 // pages at either end. | 1361 // pages at either end. |
| 1362 void* ptr = partitionAllocGeneric(genericAllocator.root(), kPartitionPageSiz
e * 2, kTypeName); | 1362 void* ptr = partitionAllocGeneric(genericAllocator.root(), kPartitionPageSiz
e * 2, typeName); |
| 1363 EXPECT_TRUE(ptr); | 1363 EXPECT_TRUE(ptr); |
| 1364 char* badPtr = reinterpret_cast<char*>(ptr) + kPartitionPageSize; | 1364 char* badPtr = reinterpret_cast<char*>(ptr) + kPartitionPageSize; |
| 1365 | 1365 |
| 1366 EXPECT_DEATH(partitionFreeGeneric(genericAllocator.root(), badPtr), ""); | 1366 EXPECT_DEATH(partitionFreeGeneric(genericAllocator.root(), badPtr), ""); |
| 1367 | 1367 |
| 1368 partitionFreeGeneric(genericAllocator.root(), ptr); | 1368 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 1369 | 1369 |
| 1370 TestShutdown(); | 1370 TestShutdown(); |
| 1371 } | 1371 } |
| 1372 | 1372 |
| 1373 #endif // !OS(ANDROID) | 1373 #endif // !OS(ANDROID) |
| 1374 | 1374 |
| 1375 // Tests that partitionDumpStatsGeneric and partitionDumpStats runs without | 1375 // Tests that partitionDumpStatsGeneric and partitionDumpStats runs without |
| 1376 // crashing and returns non zero values when memory is allocated. | 1376 // crashing and returns non zero values when memory is allocated. |
| 1377 TEST(PartitionAllocTest, DumpMemoryStats) | 1377 TEST(PartitionAllocTest, DumpMemoryStats) |
| 1378 { | 1378 { |
| 1379 TestSetup(); | 1379 TestSetup(); |
| 1380 { | 1380 { |
| 1381 void* ptr = partitionAlloc(allocator.root(), kTestAllocSize, kTypeName); | 1381 void* ptr = partitionAlloc(allocator.root(), kTestAllocSize, typeName); |
| 1382 MockPartitionStatsDumper mockStatsDumper; | 1382 MockPartitionStatsDumper mockStatsDumper; |
| 1383 partitionDumpStats(allocator.root(), "mock_allocator", false /* detailed
dump */, &mockStatsDumper); | 1383 partitionDumpStats(allocator.root(), "mock_allocator", false /* detailed
dump */, &mockStatsDumper); |
| 1384 EXPECT_TRUE(mockStatsDumper.IsMemoryAllocationRecorded()); | 1384 EXPECT_TRUE(mockStatsDumper.IsMemoryAllocationRecorded()); |
| 1385 | 1385 |
| 1386 partitionFree(ptr); | 1386 partitionFree(ptr); |
| 1387 } | 1387 } |
| 1388 | 1388 |
| 1389 // This series of tests checks the active -> empty -> decommitted states. | 1389 // This series of tests checks the active -> empty -> decommitted states. |
| 1390 { | 1390 { |
| 1391 void* genericPtr = partitionAllocGeneric(genericAllocator.root(), 2048 -
kExtraAllocSize, kTypeName); | 1391 void* genericPtr = partitionAllocGeneric(genericAllocator.root(), 2048 -
kExtraAllocSize, typeName); |
| 1392 { | 1392 { |
| 1393 MockPartitionStatsDumper mockStatsDumperGeneric; | 1393 MockPartitionStatsDumper mockStatsDumperGeneric; |
| 1394 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_all
ocator", false /* detailed dump */, &mockStatsDumperGeneric); | 1394 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_all
ocator", false /* detailed dump */, &mockStatsDumperGeneric); |
| 1395 EXPECT_TRUE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); | 1395 EXPECT_TRUE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); |
| 1396 | 1396 |
| 1397 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.Get
BucketStats(2048); | 1397 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.Get
BucketStats(2048); |
| 1398 EXPECT_TRUE(stats); | 1398 EXPECT_TRUE(stats); |
| 1399 EXPECT_TRUE(stats->isValid); | 1399 EXPECT_TRUE(stats->isValid); |
| 1400 EXPECT_EQ(2048u, stats->bucketSlotSize); | 1400 EXPECT_EQ(2048u, stats->bucketSlotSize); |
| 1401 EXPECT_EQ(2048u, stats->activeBytes); | 1401 EXPECT_EQ(2048u, stats->activeBytes); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1447 EXPECT_EQ(0u, stats->numFullPages); | 1447 EXPECT_EQ(0u, stats->numFullPages); |
| 1448 EXPECT_EQ(0u, stats->numActivePages); | 1448 EXPECT_EQ(0u, stats->numActivePages); |
| 1449 EXPECT_EQ(0u, stats->numEmptyPages); | 1449 EXPECT_EQ(0u, stats->numEmptyPages); |
| 1450 EXPECT_EQ(1u, stats->numDecommittedPages); | 1450 EXPECT_EQ(1u, stats->numDecommittedPages); |
| 1451 } | 1451 } |
| 1452 } | 1452 } |
| 1453 | 1453 |
| 1454 // This test checks for correct empty page list accounting. | 1454 // This test checks for correct empty page list accounting. |
| 1455 { | 1455 { |
| 1456 size_t size = kPartitionPageSize - kExtraAllocSize; | 1456 size_t size = kPartitionPageSize - kExtraAllocSize; |
| 1457 void* ptr1 = partitionAllocGeneric(genericAllocator.root(), size, kTypeN
ame); | 1457 void* ptr1 = partitionAllocGeneric(genericAllocator.root(), size, typeNa
me); |
| 1458 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size, kTypeN
ame); | 1458 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size, typeNa
me); |
| 1459 partitionFreeGeneric(genericAllocator.root(), ptr1); | 1459 partitionFreeGeneric(genericAllocator.root(), ptr1); |
| 1460 partitionFreeGeneric(genericAllocator.root(), ptr2); | 1460 partitionFreeGeneric(genericAllocator.root(), ptr2); |
| 1461 | 1461 |
| 1462 CycleGenericFreeCache(kTestAllocSize); | 1462 CycleGenericFreeCache(kTestAllocSize); |
| 1463 | 1463 |
| 1464 ptr1 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName); | 1464 ptr1 = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 1465 | 1465 |
| 1466 { | 1466 { |
| 1467 MockPartitionStatsDumper mockStatsDumperGeneric; | 1467 MockPartitionStatsDumper mockStatsDumperGeneric; |
| 1468 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_all
ocator", false /* detailed dump */, &mockStatsDumperGeneric); | 1468 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_all
ocator", false /* detailed dump */, &mockStatsDumperGeneric); |
| 1469 EXPECT_TRUE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); | 1469 EXPECT_TRUE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); |
| 1470 | 1470 |
| 1471 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.Get
BucketStats(kPartitionPageSize); | 1471 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.Get
BucketStats(kPartitionPageSize); |
| 1472 EXPECT_TRUE(stats); | 1472 EXPECT_TRUE(stats); |
| 1473 EXPECT_TRUE(stats->isValid); | 1473 EXPECT_TRUE(stats->isValid); |
| 1474 EXPECT_EQ(kPartitionPageSize, stats->bucketSlotSize); | 1474 EXPECT_EQ(kPartitionPageSize, stats->bucketSlotSize); |
| 1475 EXPECT_EQ(kPartitionPageSize, stats->activeBytes); | 1475 EXPECT_EQ(kPartitionPageSize, stats->activeBytes); |
| 1476 EXPECT_EQ(kPartitionPageSize, stats->residentBytes); | 1476 EXPECT_EQ(kPartitionPageSize, stats->residentBytes); |
| 1477 EXPECT_EQ(0u, stats->decommittableBytes); | 1477 EXPECT_EQ(0u, stats->decommittableBytes); |
| 1478 EXPECT_EQ(0u, stats->discardableBytes); | 1478 EXPECT_EQ(0u, stats->discardableBytes); |
| 1479 EXPECT_EQ(1u, stats->numFullPages); | 1479 EXPECT_EQ(1u, stats->numFullPages); |
| 1480 EXPECT_EQ(0u, stats->numActivePages); | 1480 EXPECT_EQ(0u, stats->numActivePages); |
| 1481 EXPECT_EQ(0u, stats->numEmptyPages); | 1481 EXPECT_EQ(0u, stats->numEmptyPages); |
| 1482 EXPECT_EQ(1u, stats->numDecommittedPages); | 1482 EXPECT_EQ(1u, stats->numDecommittedPages); |
| 1483 } | 1483 } |
| 1484 partitionFreeGeneric(genericAllocator.root(), ptr1); | 1484 partitionFreeGeneric(genericAllocator.root(), ptr1); |
| 1485 } | 1485 } |
| 1486 | 1486 |
| 1487 // This test checks for correct direct mapped accounting. | 1487 // This test checks for correct direct mapped accounting. |
| 1488 { | 1488 { |
| 1489 size_t sizeSmaller = kGenericMaxBucketed + 1; | 1489 size_t sizeSmaller = kGenericMaxBucketed + 1; |
| 1490 size_t sizeBigger = (kGenericMaxBucketed * 2) + 1; | 1490 size_t sizeBigger = (kGenericMaxBucketed * 2) + 1; |
| 1491 size_t realSizeSmaller = (sizeSmaller + kSystemPageOffsetMask) & kSystem
PageBaseMask; | 1491 size_t realSizeSmaller = (sizeSmaller + kSystemPageOffsetMask) & kSystem
PageBaseMask; |
| 1492 size_t realSizeBigger = (sizeBigger + kSystemPageOffsetMask) & kSystemPa
geBaseMask; | 1492 size_t realSizeBigger = (sizeBigger + kSystemPageOffsetMask) & kSystemPa
geBaseMask; |
| 1493 void* ptr = partitionAllocGeneric(genericAllocator.root(), sizeSmaller,
kTypeName); | 1493 void* ptr = partitionAllocGeneric(genericAllocator.root(), sizeSmaller,
typeName); |
| 1494 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), sizeBigger,
kTypeName); | 1494 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), sizeBigger,
typeName); |
| 1495 | 1495 |
| 1496 { | 1496 { |
| 1497 MockPartitionStatsDumper mockStatsDumperGeneric; | 1497 MockPartitionStatsDumper mockStatsDumperGeneric; |
| 1498 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_all
ocator", false /* detailed dump */, &mockStatsDumperGeneric); | 1498 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_all
ocator", false /* detailed dump */, &mockStatsDumperGeneric); |
| 1499 EXPECT_TRUE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); | 1499 EXPECT_TRUE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); |
| 1500 | 1500 |
| 1501 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.Get
BucketStats(realSizeSmaller); | 1501 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.Get
BucketStats(realSizeSmaller); |
| 1502 EXPECT_TRUE(stats); | 1502 EXPECT_TRUE(stats); |
| 1503 EXPECT_TRUE(stats->isValid); | 1503 EXPECT_TRUE(stats->isValid); |
| 1504 EXPECT_TRUE(stats->isDirectMap); | 1504 EXPECT_TRUE(stats->isDirectMap); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1525 EXPECT_EQ(0u, stats->numActivePages); | 1525 EXPECT_EQ(0u, stats->numActivePages); |
| 1526 EXPECT_EQ(0u, stats->numEmptyPages); | 1526 EXPECT_EQ(0u, stats->numEmptyPages); |
| 1527 EXPECT_EQ(0u, stats->numDecommittedPages); | 1527 EXPECT_EQ(0u, stats->numDecommittedPages); |
| 1528 } | 1528 } |
| 1529 | 1529 |
| 1530 partitionFreeGeneric(genericAllocator.root(), ptr2); | 1530 partitionFreeGeneric(genericAllocator.root(), ptr2); |
| 1531 partitionFreeGeneric(genericAllocator.root(), ptr); | 1531 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 1532 | 1532 |
| 1533 // Whilst we're here, allocate again and free with different ordering | 1533 // Whilst we're here, allocate again and free with different ordering |
| 1534 // to give a workout to our linked list code. | 1534 // to give a workout to our linked list code. |
| 1535 ptr = partitionAllocGeneric(genericAllocator.root(), sizeSmaller, kTypeN
ame); | 1535 ptr = partitionAllocGeneric(genericAllocator.root(), sizeSmaller, typeNa
me); |
| 1536 ptr2 = partitionAllocGeneric(genericAllocator.root(), sizeBigger, kTypeN
ame); | 1536 ptr2 = partitionAllocGeneric(genericAllocator.root(), sizeBigger, typeNa
me); |
| 1537 partitionFreeGeneric(genericAllocator.root(), ptr); | 1537 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 1538 partitionFreeGeneric(genericAllocator.root(), ptr2); | 1538 partitionFreeGeneric(genericAllocator.root(), ptr2); |
| 1539 } | 1539 } |
| 1540 | 1540 |
| 1541 // This test checks large-but-not-quite-direct allocations. | 1541 // This test checks large-but-not-quite-direct allocations. |
| 1542 { | 1542 { |
| 1543 void* ptr = partitionAllocGeneric(genericAllocator.root(), 65536 + 1, kT
ypeName); | 1543 void* ptr = partitionAllocGeneric(genericAllocator.root(), 65536 + 1, ty
peName); |
| 1544 | 1544 |
| 1545 { | 1545 { |
| 1546 MockPartitionStatsDumper mockStatsDumperGeneric; | 1546 MockPartitionStatsDumper mockStatsDumperGeneric; |
| 1547 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_all
ocator", false /* detailed dump */, &mockStatsDumperGeneric); | 1547 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_all
ocator", false /* detailed dump */, &mockStatsDumperGeneric); |
| 1548 EXPECT_TRUE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); | 1548 EXPECT_TRUE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); |
| 1549 | 1549 |
| 1550 size_t slotSize = 65536 + (65536 / kGenericNumBucketsPerOrder); | 1550 size_t slotSize = 65536 + (65536 / kGenericNumBucketsPerOrder); |
| 1551 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.Get
BucketStats(slotSize); | 1551 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.Get
BucketStats(slotSize); |
| 1552 EXPECT_TRUE(stats); | 1552 EXPECT_TRUE(stats); |
| 1553 EXPECT_TRUE(stats->isValid); | 1553 EXPECT_TRUE(stats->isValid); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1578 EXPECT_EQ(slotSize, stats->bucketSlotSize); | 1578 EXPECT_EQ(slotSize, stats->bucketSlotSize); |
| 1579 EXPECT_EQ(0u, stats->activeBytes); | 1579 EXPECT_EQ(0u, stats->activeBytes); |
| 1580 EXPECT_EQ(slotSize, stats->residentBytes); | 1580 EXPECT_EQ(slotSize, stats->residentBytes); |
| 1581 EXPECT_EQ(slotSize, stats->decommittableBytes); | 1581 EXPECT_EQ(slotSize, stats->decommittableBytes); |
| 1582 EXPECT_EQ(0u, stats->numFullPages); | 1582 EXPECT_EQ(0u, stats->numFullPages); |
| 1583 EXPECT_EQ(0u, stats->numActivePages); | 1583 EXPECT_EQ(0u, stats->numActivePages); |
| 1584 EXPECT_EQ(1u, stats->numEmptyPages); | 1584 EXPECT_EQ(1u, stats->numEmptyPages); |
| 1585 EXPECT_EQ(0u, stats->numDecommittedPages); | 1585 EXPECT_EQ(0u, stats->numDecommittedPages); |
| 1586 } | 1586 } |
| 1587 | 1587 |
| 1588 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), 65536 + kSys
temPageSize + 1, kTypeName); | 1588 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), 65536 + kSys
temPageSize + 1, typeName); |
| 1589 EXPECT_EQ(ptr, ptr2); | 1589 EXPECT_EQ(ptr, ptr2); |
| 1590 | 1590 |
| 1591 { | 1591 { |
| 1592 MockPartitionStatsDumper mockStatsDumperGeneric; | 1592 MockPartitionStatsDumper mockStatsDumperGeneric; |
| 1593 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_all
ocator", false /* detailed dump */, &mockStatsDumperGeneric); | 1593 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_all
ocator", false /* detailed dump */, &mockStatsDumperGeneric); |
| 1594 EXPECT_TRUE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); | 1594 EXPECT_TRUE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); |
| 1595 | 1595 |
| 1596 size_t slotSize = 65536 + (65536 / kGenericNumBucketsPerOrder); | 1596 size_t slotSize = 65536 + (65536 / kGenericNumBucketsPerOrder); |
| 1597 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.Get
BucketStats(slotSize); | 1597 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.Get
BucketStats(slotSize); |
| 1598 EXPECT_TRUE(stats); | 1598 EXPECT_TRUE(stats); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1613 } | 1613 } |
| 1614 | 1614 |
| 1615 TestShutdown(); | 1615 TestShutdown(); |
| 1616 } | 1616 } |
| 1617 | 1617 |
| 1618 // Tests the API to purge freeable memory. | 1618 // Tests the API to purge freeable memory. |
| 1619 TEST(PartitionAllocTest, Purge) | 1619 TEST(PartitionAllocTest, Purge) |
| 1620 { | 1620 { |
| 1621 TestSetup(); | 1621 TestSetup(); |
| 1622 | 1622 |
| 1623 char* ptr = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.r
oot(), 2048 - kExtraAllocSize, kTypeName)); | 1623 char* ptr = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.r
oot(), 2048 - kExtraAllocSize, typeName)); |
| 1624 partitionFreeGeneric(genericAllocator.root(), ptr); | 1624 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 1625 { | 1625 { |
| 1626 MockPartitionStatsDumper mockStatsDumperGeneric; | 1626 MockPartitionStatsDumper mockStatsDumperGeneric; |
| 1627 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_allocat
or", false /* detailed dump */, &mockStatsDumperGeneric); | 1627 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_allocat
or", false /* detailed dump */, &mockStatsDumperGeneric); |
| 1628 EXPECT_FALSE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); | 1628 EXPECT_FALSE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); |
| 1629 | 1629 |
| 1630 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.GetBuck
etStats(2048); | 1630 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.GetBuck
etStats(2048); |
| 1631 EXPECT_TRUE(stats); | 1631 EXPECT_TRUE(stats); |
| 1632 EXPECT_TRUE(stats->isValid); | 1632 EXPECT_TRUE(stats->isValid); |
| 1633 EXPECT_EQ(kSystemPageSize, stats->decommittableBytes); | 1633 EXPECT_EQ(kSystemPageSize, stats->decommittableBytes); |
| 1634 EXPECT_EQ(kSystemPageSize, stats->residentBytes); | 1634 EXPECT_EQ(kSystemPageSize, stats->residentBytes); |
| 1635 } | 1635 } |
| 1636 partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDecommitE
mptyPages); | 1636 partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDecommitE
mptyPages); |
| 1637 { | 1637 { |
| 1638 MockPartitionStatsDumper mockStatsDumperGeneric; | 1638 MockPartitionStatsDumper mockStatsDumperGeneric; |
| 1639 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_allocat
or", false /* detailed dump */, &mockStatsDumperGeneric); | 1639 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_allocat
or", false /* detailed dump */, &mockStatsDumperGeneric); |
| 1640 EXPECT_FALSE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); | 1640 EXPECT_FALSE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); |
| 1641 | 1641 |
| 1642 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.GetBuck
etStats(2048); | 1642 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.GetBuck
etStats(2048); |
| 1643 EXPECT_TRUE(stats); | 1643 EXPECT_TRUE(stats); |
| 1644 EXPECT_TRUE(stats->isValid); | 1644 EXPECT_TRUE(stats->isValid); |
| 1645 EXPECT_EQ(0u, stats->decommittableBytes); | 1645 EXPECT_EQ(0u, stats->decommittableBytes); |
| 1646 EXPECT_EQ(0u, stats->residentBytes); | 1646 EXPECT_EQ(0u, stats->residentBytes); |
| 1647 } | 1647 } |
| 1648 // Calling purge again here is a good way of testing we didn't mess up the | 1648 // Calling purge again here is a good way of testing we didn't mess up the |
| 1649 // state of the free cache ring. | 1649 // state of the free cache ring. |
| 1650 partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDecommitE
mptyPages); | 1650 partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDecommitE
mptyPages); |
| 1651 | 1651 |
| 1652 char* bigPtr = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocato
r.root(), 256 * 1024, kTypeName)); | 1652 char* bigPtr = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocato
r.root(), 256 * 1024, typeName)); |
| 1653 partitionFreeGeneric(genericAllocator.root(), bigPtr); | 1653 partitionFreeGeneric(genericAllocator.root(), bigPtr); |
| 1654 partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDecommitE
mptyPages); | 1654 partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDecommitE
mptyPages); |
| 1655 | 1655 |
| 1656 CheckPageInCore(ptr - kPointerOffset, false); | 1656 CheckPageInCore(ptr - kPointerOffset, false); |
| 1657 CheckPageInCore(bigPtr - kPointerOffset, false); | 1657 CheckPageInCore(bigPtr - kPointerOffset, false); |
| 1658 | 1658 |
| 1659 TestShutdown(); | 1659 TestShutdown(); |
| 1660 } | 1660 } |
| 1661 | 1661 |
| 1662 // Tests that we prefer to allocate into a non-empty partition page over an | 1662 // Tests that we prefer to allocate into a non-empty partition page over an |
| 1663 // empty one. This is an important aspect of minimizing memory usage for some | 1663 // empty one. This is an important aspect of minimizing memory usage for some |
| 1664 // allocation sizes, particularly larger ones. | 1664 // allocation sizes, particularly larger ones. |
| 1665 TEST(PartitionAllocTest, PreferActiveOverEmpty) | 1665 TEST(PartitionAllocTest, PreferActiveOverEmpty) |
| 1666 { | 1666 { |
| 1667 TestSetup(); | 1667 TestSetup(); |
| 1668 | 1668 |
| 1669 size_t size = (kSystemPageSize * 2) - kExtraAllocSize; | 1669 size_t size = (kSystemPageSize * 2) - kExtraAllocSize; |
| 1670 // Allocate 3 full slot spans worth of 8192-byte allocations. | 1670 // Allocate 3 full slot spans worth of 8192-byte allocations. |
| 1671 // Each slot span for this size is 16384 bytes, or 1 partition page and 2 | 1671 // Each slot span for this size is 16384 bytes, or 1 partition page and 2 |
| 1672 // slots. | 1672 // slots. |
| 1673 void* ptr1 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName)
; | 1673 void* ptr1 = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 1674 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName)
; | 1674 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 1675 void* ptr3 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName)
; | 1675 void* ptr3 = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 1676 void* ptr4 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName)
; | 1676 void* ptr4 = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 1677 void* ptr5 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName)
; | 1677 void* ptr5 = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 1678 void* ptr6 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName)
; | 1678 void* ptr6 = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 1679 | 1679 |
| 1680 PartitionPage* page1 = partitionPointerToPage(partitionCookieFreePointerAdju
st(ptr1)); | 1680 PartitionPage* page1 = partitionPointerToPage(partitionCookieFreePointerAdju
st(ptr1)); |
| 1681 PartitionPage* page2 = partitionPointerToPage(partitionCookieFreePointerAdju
st(ptr3)); | 1681 PartitionPage* page2 = partitionPointerToPage(partitionCookieFreePointerAdju
st(ptr3)); |
| 1682 PartitionPage* page3 = partitionPointerToPage(partitionCookieFreePointerAdju
st(ptr6)); | 1682 PartitionPage* page3 = partitionPointerToPage(partitionCookieFreePointerAdju
st(ptr6)); |
| 1683 EXPECT_NE(page1, page2); | 1683 EXPECT_NE(page1, page2); |
| 1684 EXPECT_NE(page2, page3); | 1684 EXPECT_NE(page2, page3); |
| 1685 PartitionBucket* bucket = page1->bucket; | 1685 PartitionBucket* bucket = page1->bucket; |
| 1686 EXPECT_EQ(page3, bucket->activePagesHead); | 1686 EXPECT_EQ(page3, bucket->activePagesHead); |
| 1687 | 1687 |
| 1688 // Free up the 2nd slot in each slot span. | 1688 // Free up the 2nd slot in each slot span. |
| 1689 // This leaves the active list containing 3 pages, each with 1 used and 1 | 1689 // This leaves the active list containing 3 pages, each with 1 used and 1 |
| 1690 // free slot. The active page will be the one containing ptr1. | 1690 // free slot. The active page will be the one containing ptr1. |
| 1691 partitionFreeGeneric(genericAllocator.root(), ptr6); | 1691 partitionFreeGeneric(genericAllocator.root(), ptr6); |
| 1692 partitionFreeGeneric(genericAllocator.root(), ptr4); | 1692 partitionFreeGeneric(genericAllocator.root(), ptr4); |
| 1693 partitionFreeGeneric(genericAllocator.root(), ptr2); | 1693 partitionFreeGeneric(genericAllocator.root(), ptr2); |
| 1694 EXPECT_EQ(page1, bucket->activePagesHead); | 1694 EXPECT_EQ(page1, bucket->activePagesHead); |
| 1695 | 1695 |
| 1696 // Empty the middle page in the active list. | 1696 // Empty the middle page in the active list. |
| 1697 partitionFreeGeneric(genericAllocator.root(), ptr3); | 1697 partitionFreeGeneric(genericAllocator.root(), ptr3); |
| 1698 EXPECT_EQ(page1, bucket->activePagesHead); | 1698 EXPECT_EQ(page1, bucket->activePagesHead); |
| 1699 | 1699 |
| 1700 // Empty the the first page in the active list -- also the current page. | 1700 // Empty the the first page in the active list -- also the current page. |
| 1701 partitionFreeGeneric(genericAllocator.root(), ptr1); | 1701 partitionFreeGeneric(genericAllocator.root(), ptr1); |
| 1702 | 1702 |
| 1703 // A good choice here is to re-fill the third page since the first two are | 1703 // A good choice here is to re-fill the third page since the first two are |
| 1704 // empty. We used to fail that. | 1704 // empty. We used to fail that. |
| 1705 void* ptr7 = partitionAllocGeneric(genericAllocator.root(), size, kTypeName)
; | 1705 void* ptr7 = partitionAllocGeneric(genericAllocator.root(), size, typeName); |
| 1706 EXPECT_EQ(ptr6, ptr7); | 1706 EXPECT_EQ(ptr6, ptr7); |
| 1707 EXPECT_EQ(page3, bucket->activePagesHead); | 1707 EXPECT_EQ(page3, bucket->activePagesHead); |
| 1708 | 1708 |
| 1709 partitionFreeGeneric(genericAllocator.root(), ptr5); | 1709 partitionFreeGeneric(genericAllocator.root(), ptr5); |
| 1710 partitionFreeGeneric(genericAllocator.root(), ptr7); | 1710 partitionFreeGeneric(genericAllocator.root(), ptr7); |
| 1711 | 1711 |
| 1712 TestShutdown(); | 1712 TestShutdown(); |
| 1713 } | 1713 } |
| 1714 | 1714 |
| 1715 // Tests the API to purge discardable memory. | 1715 // Tests the API to purge discardable memory. |
| 1716 TEST(PartitionAllocTest, PurgeDiscardable) | 1716 TEST(PartitionAllocTest, PurgeDiscardable) |
| 1717 { | 1717 { |
| 1718 TestSetup(); | 1718 TestSetup(); |
| 1719 | 1719 |
| 1720 // Free the second of two 4096 byte allocations and then purge. | 1720 // Free the second of two 4096 byte allocations and then purge. |
| 1721 { | 1721 { |
| 1722 void* ptr1 = partitionAllocGeneric(genericAllocator.root(), kSystemPageS
ize - kExtraAllocSize, kTypeName); | 1722 void* ptr1 = partitionAllocGeneric(genericAllocator.root(), kSystemPageS
ize - kExtraAllocSize, typeName); |
| 1723 char* ptr2 = reinterpret_cast<char*>(partitionAllocGeneric(genericAlloca
tor.root(), kSystemPageSize - kExtraAllocSize, kTypeName)); | 1723 char* ptr2 = reinterpret_cast<char*>(partitionAllocGeneric(genericAlloca
tor.root(), kSystemPageSize - kExtraAllocSize, typeName)); |
| 1724 partitionFreeGeneric(genericAllocator.root(), ptr2); | 1724 partitionFreeGeneric(genericAllocator.root(), ptr2); |
| 1725 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerA
djust(ptr1)); | 1725 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerA
djust(ptr1)); |
| 1726 EXPECT_EQ(2u, page->numUnprovisionedSlots); | 1726 EXPECT_EQ(2u, page->numUnprovisionedSlots); |
| 1727 { | 1727 { |
| 1728 MockPartitionStatsDumper mockStatsDumperGeneric; | 1728 MockPartitionStatsDumper mockStatsDumperGeneric; |
| 1729 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_all
ocator", false /* detailed dump */, &mockStatsDumperGeneric); | 1729 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_all
ocator", false /* detailed dump */, &mockStatsDumperGeneric); |
| 1730 EXPECT_TRUE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); | 1730 EXPECT_TRUE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); |
| 1731 | 1731 |
| 1732 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.Get
BucketStats(kSystemPageSize); | 1732 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.Get
BucketStats(kSystemPageSize); |
| 1733 EXPECT_TRUE(stats); | 1733 EXPECT_TRUE(stats); |
| 1734 EXPECT_TRUE(stats->isValid); | 1734 EXPECT_TRUE(stats->isValid); |
| 1735 EXPECT_EQ(0u, stats->decommittableBytes); | 1735 EXPECT_EQ(0u, stats->decommittableBytes); |
| 1736 EXPECT_EQ(kSystemPageSize, stats->discardableBytes); | 1736 EXPECT_EQ(kSystemPageSize, stats->discardableBytes); |
| 1737 EXPECT_EQ(kSystemPageSize, stats->activeBytes); | 1737 EXPECT_EQ(kSystemPageSize, stats->activeBytes); |
| 1738 EXPECT_EQ(2 * kSystemPageSize, stats->residentBytes); | 1738 EXPECT_EQ(2 * kSystemPageSize, stats->residentBytes); |
| 1739 } | 1739 } |
| 1740 CheckPageInCore(ptr2 - kPointerOffset, true); | 1740 CheckPageInCore(ptr2 - kPointerOffset, true); |
| 1741 partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDisca
rdUnusedSystemPages); | 1741 partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDisca
rdUnusedSystemPages); |
| 1742 CheckPageInCore(ptr2 - kPointerOffset, false); | 1742 CheckPageInCore(ptr2 - kPointerOffset, false); |
| 1743 EXPECT_EQ(3u, page->numUnprovisionedSlots); | 1743 EXPECT_EQ(3u, page->numUnprovisionedSlots); |
| 1744 | 1744 |
| 1745 partitionFreeGeneric(genericAllocator.root(), ptr1); | 1745 partitionFreeGeneric(genericAllocator.root(), ptr1); |
| 1746 } | 1746 } |
| 1747 // Free the first of two 4096 byte allocations and then purge. | 1747 // Free the first of two 4096 byte allocations and then purge. |
| 1748 { | 1748 { |
| 1749 char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAlloca
tor.root(), kSystemPageSize - kExtraAllocSize, kTypeName)); | 1749 char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAlloca
tor.root(), kSystemPageSize - kExtraAllocSize, typeName)); |
| 1750 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), kSystemPageS
ize - kExtraAllocSize, kTypeName); | 1750 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), kSystemPageS
ize - kExtraAllocSize, typeName); |
| 1751 partitionFreeGeneric(genericAllocator.root(), ptr1); | 1751 partitionFreeGeneric(genericAllocator.root(), ptr1); |
| 1752 { | 1752 { |
| 1753 MockPartitionStatsDumper mockStatsDumperGeneric; | 1753 MockPartitionStatsDumper mockStatsDumperGeneric; |
| 1754 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_all
ocator", false /* detailed dump */, &mockStatsDumperGeneric); | 1754 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_all
ocator", false /* detailed dump */, &mockStatsDumperGeneric); |
| 1755 EXPECT_TRUE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); | 1755 EXPECT_TRUE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); |
| 1756 | 1756 |
| 1757 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.Get
BucketStats(kSystemPageSize); | 1757 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.Get
BucketStats(kSystemPageSize); |
| 1758 EXPECT_TRUE(stats); | 1758 EXPECT_TRUE(stats); |
| 1759 EXPECT_TRUE(stats->isValid); | 1759 EXPECT_TRUE(stats->isValid); |
| 1760 EXPECT_EQ(0u, stats->decommittableBytes); | 1760 EXPECT_EQ(0u, stats->decommittableBytes); |
| 1761 EXPECT_EQ(kSystemPageSize, stats->discardableBytes); | 1761 EXPECT_EQ(kSystemPageSize, stats->discardableBytes); |
| 1762 EXPECT_EQ(kSystemPageSize, stats->activeBytes); | 1762 EXPECT_EQ(kSystemPageSize, stats->activeBytes); |
| 1763 EXPECT_EQ(2 * kSystemPageSize, stats->residentBytes); | 1763 EXPECT_EQ(2 * kSystemPageSize, stats->residentBytes); |
| 1764 } | 1764 } |
| 1765 CheckPageInCore(ptr1 - kPointerOffset, true); | 1765 CheckPageInCore(ptr1 - kPointerOffset, true); |
| 1766 partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDisca
rdUnusedSystemPages); | 1766 partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDisca
rdUnusedSystemPages); |
| 1767 CheckPageInCore(ptr1 - kPointerOffset, false); | 1767 CheckPageInCore(ptr1 - kPointerOffset, false); |
| 1768 | 1768 |
| 1769 partitionFreeGeneric(genericAllocator.root(), ptr2); | 1769 partitionFreeGeneric(genericAllocator.root(), ptr2); |
| 1770 } | 1770 } |
| 1771 { | 1771 { |
| 1772 char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAlloca
tor.root(), 9216 - kExtraAllocSize, kTypeName)); | 1772 char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAlloca
tor.root(), 9216 - kExtraAllocSize, typeName)); |
| 1773 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), 9216 - kExtr
aAllocSize, kTypeName); | 1773 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), 9216 - kExtr
aAllocSize, typeName); |
| 1774 void* ptr3 = partitionAllocGeneric(genericAllocator.root(), 9216 - kExtr
aAllocSize, kTypeName); | 1774 void* ptr3 = partitionAllocGeneric(genericAllocator.root(), 9216 - kExtr
aAllocSize, typeName); |
| 1775 void* ptr4 = partitionAllocGeneric(genericAllocator.root(), 9216 - kExtr
aAllocSize, kTypeName); | 1775 void* ptr4 = partitionAllocGeneric(genericAllocator.root(), 9216 - kExtr
aAllocSize, typeName); |
| 1776 memset(ptr1, 'A', 9216 - kExtraAllocSize); | 1776 memset(ptr1, 'A', 9216 - kExtraAllocSize); |
| 1777 memset(ptr2, 'A', 9216 - kExtraAllocSize); | 1777 memset(ptr2, 'A', 9216 - kExtraAllocSize); |
| 1778 partitionFreeGeneric(genericAllocator.root(), ptr2); | 1778 partitionFreeGeneric(genericAllocator.root(), ptr2); |
| 1779 partitionFreeGeneric(genericAllocator.root(), ptr1); | 1779 partitionFreeGeneric(genericAllocator.root(), ptr1); |
| 1780 { | 1780 { |
| 1781 MockPartitionStatsDumper mockStatsDumperGeneric; | 1781 MockPartitionStatsDumper mockStatsDumperGeneric; |
| 1782 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_all
ocator", false /* detailed dump */, &mockStatsDumperGeneric); | 1782 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_all
ocator", false /* detailed dump */, &mockStatsDumperGeneric); |
| 1783 EXPECT_TRUE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); | 1783 EXPECT_TRUE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); |
| 1784 | 1784 |
| 1785 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.Get
BucketStats(9216); | 1785 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.Get
BucketStats(9216); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1799 CheckPageInCore(ptr1 - kPointerOffset, true); | 1799 CheckPageInCore(ptr1 - kPointerOffset, true); |
| 1800 CheckPageInCore(ptr1 - kPointerOffset + kSystemPageSize, false); | 1800 CheckPageInCore(ptr1 - kPointerOffset + kSystemPageSize, false); |
| 1801 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 2), true); | 1801 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 2), true); |
| 1802 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 3), false); | 1802 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 3), false); |
| 1803 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 4), true); | 1803 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 4), true); |
| 1804 | 1804 |
| 1805 partitionFreeGeneric(genericAllocator.root(), ptr3); | 1805 partitionFreeGeneric(genericAllocator.root(), ptr3); |
| 1806 partitionFreeGeneric(genericAllocator.root(), ptr4); | 1806 partitionFreeGeneric(genericAllocator.root(), ptr4); |
| 1807 } | 1807 } |
| 1808 { | 1808 { |
| 1809 char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAlloca
tor.root(), (64 * kSystemPageSize) - kExtraAllocSize, kTypeName)); | 1809 char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAlloca
tor.root(), (64 * kSystemPageSize) - kExtraAllocSize, typeName)); |
| 1810 memset(ptr1, 'A', (64 * kSystemPageSize) - kExtraAllocSize); | 1810 memset(ptr1, 'A', (64 * kSystemPageSize) - kExtraAllocSize); |
| 1811 partitionFreeGeneric(genericAllocator.root(), ptr1); | 1811 partitionFreeGeneric(genericAllocator.root(), ptr1); |
| 1812 ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.ro
ot(), (61 * kSystemPageSize) - kExtraAllocSize, kTypeName)); | 1812 ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAllocator.ro
ot(), (61 * kSystemPageSize) - kExtraAllocSize, typeName)); |
| 1813 { | 1813 { |
| 1814 MockPartitionStatsDumper mockStatsDumperGeneric; | 1814 MockPartitionStatsDumper mockStatsDumperGeneric; |
| 1815 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_all
ocator", false /* detailed dump */, &mockStatsDumperGeneric); | 1815 partitionDumpStatsGeneric(genericAllocator.root(), "mock_generic_all
ocator", false /* detailed dump */, &mockStatsDumperGeneric); |
| 1816 EXPECT_TRUE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); | 1816 EXPECT_TRUE(mockStatsDumperGeneric.IsMemoryAllocationRecorded()); |
| 1817 | 1817 |
| 1818 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.Get
BucketStats(64 * kSystemPageSize); | 1818 const PartitionBucketMemoryStats* stats = mockStatsDumperGeneric.Get
BucketStats(64 * kSystemPageSize); |
| 1819 EXPECT_TRUE(stats); | 1819 EXPECT_TRUE(stats); |
| 1820 EXPECT_TRUE(stats->isValid); | 1820 EXPECT_TRUE(stats->isValid); |
| 1821 EXPECT_EQ(0u, stats->decommittableBytes); | 1821 EXPECT_EQ(0u, stats->decommittableBytes); |
| 1822 EXPECT_EQ(3 * kSystemPageSize, stats->discardableBytes); | 1822 EXPECT_EQ(3 * kSystemPageSize, stats->discardableBytes); |
| 1823 EXPECT_EQ(61 * kSystemPageSize, stats->activeBytes); | 1823 EXPECT_EQ(61 * kSystemPageSize, stats->activeBytes); |
| 1824 EXPECT_EQ(64 * kSystemPageSize, stats->residentBytes); | 1824 EXPECT_EQ(64 * kSystemPageSize, stats->residentBytes); |
| 1825 } | 1825 } |
| 1826 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 60), true); | 1826 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 60), true); |
| 1827 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 61), true); | 1827 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 61), true); |
| 1828 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 62), true); | 1828 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 62), true); |
| 1829 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 63), true); | 1829 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 63), true); |
| 1830 partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDisca
rdUnusedSystemPages); | 1830 partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDisca
rdUnusedSystemPages); |
| 1831 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 60), true); | 1831 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 60), true); |
| 1832 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 61), false); | 1832 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 61), false); |
| 1833 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 62), false); | 1833 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 62), false); |
| 1834 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 63), false); | 1834 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 63), false); |
| 1835 | 1835 |
| 1836 partitionFreeGeneric(genericAllocator.root(), ptr1); | 1836 partitionFreeGeneric(genericAllocator.root(), ptr1); |
| 1837 } | 1837 } |
| 1838 // This sub-test tests truncation of the provisioned slots in a trickier | 1838 // This sub-test tests truncation of the provisioned slots in a trickier |
| 1839 // case where the freelist is rewritten. | 1839 // case where the freelist is rewritten. |
| 1840 partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDecommitE
mptyPages); | 1840 partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDecommitE
mptyPages); |
| 1841 { | 1841 { |
| 1842 char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAlloca
tor.root(), kSystemPageSize - kExtraAllocSize, kTypeName)); | 1842 char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAlloca
tor.root(), kSystemPageSize - kExtraAllocSize, typeName)); |
| 1843 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), kSystemPageS
ize - kExtraAllocSize, kTypeName); | 1843 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), kSystemPageS
ize - kExtraAllocSize, typeName); |
| 1844 void* ptr3 = partitionAllocGeneric(genericAllocator.root(), kSystemPageS
ize - kExtraAllocSize, kTypeName); | 1844 void* ptr3 = partitionAllocGeneric(genericAllocator.root(), kSystemPageS
ize - kExtraAllocSize, typeName); |
| 1845 void* ptr4 = partitionAllocGeneric(genericAllocator.root(), kSystemPageS
ize - kExtraAllocSize, kTypeName); | 1845 void* ptr4 = partitionAllocGeneric(genericAllocator.root(), kSystemPageS
ize - kExtraAllocSize, typeName); |
| 1846 ptr1[0] = 'A'; | 1846 ptr1[0] = 'A'; |
| 1847 ptr1[kSystemPageSize] = 'A'; | 1847 ptr1[kSystemPageSize] = 'A'; |
| 1848 ptr1[kSystemPageSize * 2] = 'A'; | 1848 ptr1[kSystemPageSize * 2] = 'A'; |
| 1849 ptr1[kSystemPageSize * 3] = 'A'; | 1849 ptr1[kSystemPageSize * 3] = 'A'; |
| 1850 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerA
djust(ptr1)); | 1850 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerA
djust(ptr1)); |
| 1851 partitionFreeGeneric(genericAllocator.root(), ptr2); | 1851 partitionFreeGeneric(genericAllocator.root(), ptr2); |
| 1852 partitionFreeGeneric(genericAllocator.root(), ptr4); | 1852 partitionFreeGeneric(genericAllocator.root(), ptr4); |
| 1853 partitionFreeGeneric(genericAllocator.root(), ptr1); | 1853 partitionFreeGeneric(genericAllocator.root(), ptr1); |
| 1854 EXPECT_EQ(0u, page->numUnprovisionedSlots); | 1854 EXPECT_EQ(0u, page->numUnprovisionedSlots); |
| 1855 | 1855 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1871 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 2), true); | 1871 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 2), true); |
| 1872 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 3), true); | 1872 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 3), true); |
| 1873 partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDisca
rdUnusedSystemPages); | 1873 partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDisca
rdUnusedSystemPages); |
| 1874 EXPECT_EQ(1u, page->numUnprovisionedSlots); | 1874 EXPECT_EQ(1u, page->numUnprovisionedSlots); |
| 1875 CheckPageInCore(ptr1 - kPointerOffset, true); | 1875 CheckPageInCore(ptr1 - kPointerOffset, true); |
| 1876 CheckPageInCore(ptr1 - kPointerOffset + kSystemPageSize, false); | 1876 CheckPageInCore(ptr1 - kPointerOffset + kSystemPageSize, false); |
| 1877 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 2), true); | 1877 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 2), true); |
| 1878 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 3), false); | 1878 CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 3), false); |
| 1879 | 1879 |
| 1880 // Let's check we didn't brick the freelist. | 1880 // Let's check we didn't brick the freelist. |
| 1881 void* ptr1b = partitionAllocGeneric(genericAllocator.root(), kSystemPage
Size - kExtraAllocSize, kTypeName); | 1881 void* ptr1b = partitionAllocGeneric(genericAllocator.root(), kSystemPage
Size - kExtraAllocSize, typeName); |
| 1882 EXPECT_EQ(ptr1, ptr1b); | 1882 EXPECT_EQ(ptr1, ptr1b); |
| 1883 void* ptr2b = partitionAllocGeneric(genericAllocator.root(), kSystemPage
Size - kExtraAllocSize, kTypeName); | 1883 void* ptr2b = partitionAllocGeneric(genericAllocator.root(), kSystemPage
Size - kExtraAllocSize, typeName); |
| 1884 EXPECT_EQ(ptr2, ptr2b); | 1884 EXPECT_EQ(ptr2, ptr2b); |
| 1885 EXPECT_FALSE(page->freelistHead); | 1885 EXPECT_FALSE(page->freelistHead); |
| 1886 | 1886 |
| 1887 partitionFreeGeneric(genericAllocator.root(), ptr1); | 1887 partitionFreeGeneric(genericAllocator.root(), ptr1); |
| 1888 partitionFreeGeneric(genericAllocator.root(), ptr2); | 1888 partitionFreeGeneric(genericAllocator.root(), ptr2); |
| 1889 partitionFreeGeneric(genericAllocator.root(), ptr3); | 1889 partitionFreeGeneric(genericAllocator.root(), ptr3); |
| 1890 } | 1890 } |
| 1891 // This sub-test is similar, but tests a double-truncation. | 1891 // This sub-test is similar, but tests a double-truncation. |
| 1892 partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDecommitE
mptyPages); | 1892 partitionPurgeMemoryGeneric(genericAllocator.root(), PartitionPurgeDecommitE
mptyPages); |
| 1893 { | 1893 { |
| 1894 char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAlloca
tor.root(), kSystemPageSize - kExtraAllocSize, kTypeName)); | 1894 char* ptr1 = reinterpret_cast<char*>(partitionAllocGeneric(genericAlloca
tor.root(), kSystemPageSize - kExtraAllocSize, typeName)); |
| 1895 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), kSystemPageS
ize - kExtraAllocSize, kTypeName); | 1895 void* ptr2 = partitionAllocGeneric(genericAllocator.root(), kSystemPageS
ize - kExtraAllocSize, typeName); |
| 1896 void* ptr3 = partitionAllocGeneric(genericAllocator.root(), kSystemPageS
ize - kExtraAllocSize, kTypeName); | 1896 void* ptr3 = partitionAllocGeneric(genericAllocator.root(), kSystemPageS
ize - kExtraAllocSize, typeName); |
| 1897 void* ptr4 = partitionAllocGeneric(genericAllocator.root(), kSystemPageS
ize - kExtraAllocSize, kTypeName); | 1897 void* ptr4 = partitionAllocGeneric(genericAllocator.root(), kSystemPageS
ize - kExtraAllocSize, typeName); |
| 1898 ptr1[0] = 'A'; | 1898 ptr1[0] = 'A'; |
| 1899 ptr1[kSystemPageSize] = 'A'; | 1899 ptr1[kSystemPageSize] = 'A'; |
| 1900 ptr1[kSystemPageSize * 2] = 'A'; | 1900 ptr1[kSystemPageSize * 2] = 'A'; |
| 1901 ptr1[kSystemPageSize * 3] = 'A'; | 1901 ptr1[kSystemPageSize * 3] = 'A'; |
| 1902 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerA
djust(ptr1)); | 1902 PartitionPage* page = partitionPointerToPage(partitionCookieFreePointerA
djust(ptr1)); |
| 1903 partitionFreeGeneric(genericAllocator.root(), ptr4); | 1903 partitionFreeGeneric(genericAllocator.root(), ptr4); |
| 1904 partitionFreeGeneric(genericAllocator.root(), ptr3); | 1904 partitionFreeGeneric(genericAllocator.root(), ptr3); |
| 1905 EXPECT_EQ(0u, page->numUnprovisionedSlots); | 1905 EXPECT_EQ(0u, page->numUnprovisionedSlots); |
| 1906 | 1906 |
| 1907 { | 1907 { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1958 EXPECT_EQ(32u, countLeadingZerosSizet(0u)); | 1958 EXPECT_EQ(32u, countLeadingZerosSizet(0u)); |
| 1959 EXPECT_EQ(31u, countLeadingZerosSizet(1u)); | 1959 EXPECT_EQ(31u, countLeadingZerosSizet(1u)); |
| 1960 EXPECT_EQ(1u, countLeadingZerosSizet(1u << 30)); | 1960 EXPECT_EQ(1u, countLeadingZerosSizet(1u << 30)); |
| 1961 EXPECT_EQ(0u, countLeadingZerosSizet(1u << 31)); | 1961 EXPECT_EQ(0u, countLeadingZerosSizet(1u << 31)); |
| 1962 #endif | 1962 #endif |
| 1963 } | 1963 } |
| 1964 | 1964 |
| 1965 } // namespace WTF | 1965 } // namespace WTF |
| 1966 | 1966 |
| 1967 #endif // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) | 1967 #endif // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) |
| OLD | NEW |