| Index: Source/wtf/PartitionAllocTest.cpp
|
| diff --git a/Source/wtf/PartitionAllocTest.cpp b/Source/wtf/PartitionAllocTest.cpp
|
| index a9b29c7f1cbd617a776c5cd706507f0191db738b..07da35038811a8871fe0ce23844a30400ec89ca6 100644
|
| --- a/Source/wtf/PartitionAllocTest.cpp
|
| +++ b/Source/wtf/PartitionAllocTest.cpp
|
| @@ -119,6 +119,22 @@ static void FreeFullPage(WTF::PartitionPage* page)
|
| }
|
| }
|
|
|
| +static void CycleFreeCache(size_t size)
|
| +{
|
| + size_t realSize = size + kExtraAllocSize;
|
| + size_t bucketIdx = realSize >> WTF::kBucketShift;
|
| + WTF::PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx];
|
| + ASSERT(!bucket->activePagesHead->numAllocatedSlots);
|
| +
|
| + for (size_t i = 0; i < WTF::kMaxFreeableSpans; ++i) {
|
| + void* ptr = partitionAlloc(allocator.root(), size);
|
| + EXPECT_EQ(1, bucket->activePagesHead->numAllocatedSlots);
|
| + partitionFree(ptr);
|
| + EXPECT_EQ(0, bucket->activePagesHead->numAllocatedSlots);
|
| + EXPECT_TRUE(bucket->activePagesHead->freeCacheIndex);
|
| + }
|
| +}
|
| +
|
| // Check that the most basic of allocate / free pairs work.
|
| TEST(WTF_PartitionAlloc, Basic)
|
| {
|
| @@ -228,7 +244,7 @@ TEST(WTF_PartitionAlloc, MultiPages)
|
| EXPECT_EQ(0, page->numAllocatedSlots);
|
| EXPECT_EQ(0, page2->numAllocatedSlots);
|
| EXPECT_EQ(0, page2->numUnprovisionedSlots);
|
| - EXPECT_EQ(0, page2->freelistHead);
|
| + EXPECT_TRUE(page2->freeCacheIndex);
|
|
|
| TestShutdown();
|
| }
|
| @@ -313,7 +329,7 @@ TEST(WTF_PartitionAlloc, FreePageListPageTransitions)
|
| for (i = 0; i < numToFillFreeListPage; ++i)
|
| FreeFullPage(pages[i]);
|
| EXPECT_EQ(0, bucket->activePagesHead->numAllocatedSlots);
|
| - EXPECT_EQ(0, bucket->activePagesHead->nextPage->freelistHead);
|
| + EXPECT_TRUE(bucket->activePagesHead->nextPage->freeCacheIndex);
|
| EXPECT_EQ(0, bucket->activePagesHead->nextPage->numAllocatedSlots);
|
| EXPECT_EQ(0, bucket->activePagesHead->nextPage->numUnprovisionedSlots);
|
|
|
| @@ -343,7 +359,7 @@ TEST(WTF_PartitionAlloc, FreePageListPageTransitions)
|
| for (i = 0; i < numToFillFreeListPage; ++i)
|
| FreeFullPage(pages[i]);
|
| EXPECT_EQ(0, bucket->activePagesHead->numAllocatedSlots);
|
| - EXPECT_EQ(0, bucket->activePagesHead->nextPage->freelistHead);
|
| + EXPECT_TRUE(bucket->activePagesHead->nextPage->freeCacheIndex);
|
| EXPECT_EQ(0, bucket->activePagesHead->nextPage->numAllocatedSlots);
|
| EXPECT_EQ(0, bucket->activePagesHead->nextPage->numUnprovisionedSlots);
|
|
|
| @@ -491,11 +507,9 @@ TEST(WTF_PartitionAlloc, GenericAllocSizes)
|
| void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size);
|
| EXPECT_TRUE(ptr2);
|
| partitionFreeGeneric(genericAllocator.root(), ptr);
|
| - // Should have freelisted at this point.
|
| + // Should be freeable at this point.
|
| WTF::PartitionPage* page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr));
|
| -#if 0 // Temporarily disabled, see crbug.com/332282
|
| - EXPECT_TRUE(page->bucket->freePagesHead);
|
| -#endif
|
| + EXPECT_TRUE(page->freeCacheIndex);
|
| partitionFreeGeneric(genericAllocator.root(), ptr2);
|
|
|
| size = WTF::kGenericMaxBucketed - kExtraAllocSize;
|
| @@ -516,14 +530,14 @@ TEST(WTF_PartitionAlloc, GenericAllocSizes)
|
| partitionFreeGeneric(genericAllocator.root(), ptr);
|
| partitionFreeGeneric(genericAllocator.root(), ptr3);
|
| partitionFreeGeneric(genericAllocator.root(), ptr2);
|
| - // Should have been freed at this point.
|
| - EXPECT_FALSE(page->freelistHead);
|
| + // Should be freeable at this point.
|
| + EXPECT_TRUE(page->freeCacheIndex);
|
| EXPECT_EQ(0, page->numAllocatedSlots);
|
| EXPECT_EQ(0, page->numUnprovisionedSlots);
|
| void* newPtr = partitionAllocGeneric(genericAllocator.root(), size);
|
| EXPECT_EQ(ptr3, newPtr);
|
| newPtr = partitionAllocGeneric(genericAllocator.root(), size);
|
| - EXPECT_EQ(ptr, newPtr);
|
| + EXPECT_EQ(ptr2, newPtr);
|
| #if OS(LINUX) && defined(NDEBUG)
|
| // On Linux, we have a guarantee that freelisting a page should cause its
|
| // contents to be nulled out. We check for null here to detect an bug we
|
| @@ -599,8 +613,8 @@ TEST(WTF_PartitionAlloc, PartialPageFreelists)
|
| partitionFree(ptr4);
|
| partitionFree(ptr5);
|
| partitionFree(ptr6);
|
| - EXPECT_TRUE(bucket->freePagesHead);
|
| - EXPECT_EQ(page, bucket->freePagesHead);
|
| + EXPECT_TRUE(page->freeCacheIndex);
|
| + EXPECT_TRUE(page2->freeCacheIndex);
|
| EXPECT_TRUE(page2->freelistHead);
|
| EXPECT_EQ(0, page2->numAllocatedSlots);
|
|
|
| @@ -803,6 +817,50 @@ TEST(WTF_PartitionAlloc, MappingCollision)
|
| TestShutdown();
|
| }
|
|
|
| +// Tests that pages in the free page cache do get freed as appropriate.
|
| +TEST(WTF_PartitionAlloc, FreeCache)
|
| +{
|
| + TestSetup();
|
| +
|
| + size_t bigSize = allocator.root()->maxAllocation - kExtraAllocSize;
|
| + size_t bucketIdx = (bigSize + kExtraAllocSize) >> WTF::kBucketShift;
|
| + WTF::PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx];
|
| +
|
| + void* ptr = partitionAlloc(allocator.root(), bigSize);
|
| + EXPECT_TRUE(ptr);
|
| + WTF::PartitionPage* page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr));
|
| + EXPECT_EQ(0, bucket->freePagesHead);
|
| + EXPECT_EQ(1, page->numAllocatedSlots);
|
| + partitionFree(ptr);
|
| + EXPECT_EQ(0, page->numAllocatedSlots);
|
| + EXPECT_TRUE(page->freeCacheIndex);
|
| + EXPECT_TRUE(page->freelistHead);
|
| +
|
| + CycleFreeCache(kTestAllocSize);
|
| +
|
| + // Flushing the cache should have really freed the unused page.
|
| + EXPECT_FALSE(page->freelistHead);
|
| + EXPECT_FALSE(page->freeCacheIndex);
|
| + EXPECT_EQ(0, page->numAllocatedSlots);
|
| +
|
| + // Check that an allocation works ok whilst in this state (a free'd page
|
| + // as the active pages head).
|
| + ptr = partitionAlloc(allocator.root(), bigSize);
|
| + EXPECT_FALSE(bucket->freePagesHead);
|
| + partitionFree(ptr);
|
| +
|
| + // Also check that a page that is bouncing immediately between empty and
|
| + // used does not get freed.
|
| + for (size_t i = 0; i < WTF::kMaxFreeableSpans * 2; ++i) {
|
| + ptr = partitionAlloc(allocator.root(), bigSize);
|
| + EXPECT_TRUE(page->freelistHead);
|
| + partitionFree(ptr);
|
| + EXPECT_TRUE(page->freelistHead);
|
| + }
|
| +
|
| + TestShutdown();
|
| +}
|
| +
|
| // Make sure that malloc(-1) dies.
|
| // In the past, we had an integer overflow that would alias malloc(-1) to
|
| // malloc(0), which is not good.
|
|
|