15267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)/* 25267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * Copyright (C) 2013 Google Inc. All rights reserved. 35267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * 45267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * modification, are permitted provided that the following conditions are 65267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * met: 75267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * 85267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * * Redistributions of source code must retain the above copyright 95267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * * Redistributions in binary form must reproduce the above 115267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer 125267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * in the documentation and/or other materials provided with the 135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * distribution. 145267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * * Neither the name of Google Inc. nor the names of its 155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * contributors may be used to endorse or promote products derived from 165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * this software without specific prior written permission. 175267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * 185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) */ 305267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 315267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "config.h" 325267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "wtf/PartitionAlloc.h" 335267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 34a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "wtf/BitwiseOperations.h" 351e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "wtf/OwnPtr.h" 361e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "wtf/PassOwnPtr.h" 375267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include <gtest/gtest.h> 385267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include <stdlib.h> 395267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include <string.h> 405267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 418abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)#if OS(POSIX) 42521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include <sys/mman.h> 43521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 44521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#ifndef MAP_ANONYMOUS 45521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#define MAP_ANONYMOUS MAP_ANON 46521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#endif 478abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)#endif // OS(POSIX) 48521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 49591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) 505267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 515267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)namespace { 525267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 53f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)static const size_t kTestMaxAllocation = 4096; 5409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)static SizeSpecificPartitionAllocator<kTestMaxAllocation> allocator; 5509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)static PartitionAllocatorGeneric genericAllocator; 56f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 5709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)static const size_t kTestAllocSize = 16; 58197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if !ENABLE(ASSERT) 59f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)static const size_t kPointerOffset = 0; 60f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)static const size_t kExtraAllocSize = 0; 61f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)#else 6209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)static const size_t kPointerOffset = WTF::kCookieSize; 6309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)static const size_t kExtraAllocSize = WTF::kCookieSize * 2; 64f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)#endif 65f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)static const size_t kRealAllocSize = kTestAllocSize + kExtraAllocSize; 66f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)static const size_t kTestBucketIndex = kRealAllocSize >> WTF::kBucketShift; 675267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 685267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)static void TestSetup() 695267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){ 708abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) allocator.init(); 7109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) genericAllocator.init(); 725267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)} 735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)static void TestShutdown() 755267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){ 76d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#ifndef NDEBUG 77d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) // Test that the partition statistic dumping code works. Previously, it 78d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) // bitrotted because no test calls it. 79d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) partitionDumpStats(*allocator.root()); 80d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#endif 81d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 82591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch // We expect no leaks in the general case. We have a test for leak 83591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch // detection. 848abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) EXPECT_TRUE(allocator.shutdown()); 8509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(genericAllocator.shutdown()); 865267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)} 875267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 88a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static WTF::PartitionPage* GetFullPage(size_t size) 895267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){ 90f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) size_t realSize = size + kExtraAllocSize; 91f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) size_t bucketIdx = realSize >> WTF::kBucketShift; 928abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) WTF::PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx]; 9309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t numSlots = (bucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize) / realSize; 945267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) void* first = 0; 955267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) void* last = 0; 965267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) size_t i; 975267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) for (i = 0; i < numSlots; ++i) { 988abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) void* ptr = partitionAlloc(allocator.root(), size); 995267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) EXPECT_TRUE(ptr); 1005267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) if (!i) 10109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) first = WTF::partitionCookieFreePointerAdjust(ptr); 1025267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) else if (i == numSlots - 1) 10309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) last = WTF::partitionCookieFreePointerAdjust(ptr); 1045267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) } 10509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(WTF::partitionPointerToPage(first), WTF::partitionPointerToPage(last)); 10609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (bucket->numSystemPagesPerSlotSpan == WTF::kNumSystemPagesPerPartitionPage) 10709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(reinterpret_cast<size_t>(first) & WTF::kPartitionPageBaseMask, reinterpret_cast<size_t>(last) & WTF::kPartitionPageBaseMask); 108a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(numSlots, static_cast<size_t>(bucket->activePagesHead->numAllocatedSlots)); 10909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, bucket->activePagesHead->freelistHead); 110a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_TRUE(bucket->activePagesHead); 11109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(bucket->activePagesHead != &WTF::PartitionRootGeneric::gSeedPage); 112a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) return bucket->activePagesHead; 1135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)} 1145267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 115a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)static void FreeFullPage(WTF::PartitionPage* page) 1165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){ 11709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t size = page->bucket->slotSize; 11809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t numSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize) / size; 1195267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) EXPECT_EQ(numSlots, static_cast<size_t>(abs(page->numAllocatedSlots))); 120a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) char* ptr = reinterpret_cast<char*>(partitionPageToPointer(page)); 1215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) size_t i; 1225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) for (i = 0; i < numSlots; ++i) { 123f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) partitionFree(ptr + kPointerOffset); 124521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) ptr += size; 1255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) } 1265267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)} 1275267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 12809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)static void CycleFreeCache(size_t size) 12909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 13009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t realSize = size + kExtraAllocSize; 13109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t bucketIdx = realSize >> WTF::kBucketShift; 13209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) WTF::PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx]; 13309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ASSERT(!bucket->activePagesHead->numAllocatedSlots); 13409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 13509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (size_t i = 0; i < WTF::kMaxFreeableSpans; ++i) { 13609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void* ptr = partitionAlloc(allocator.root(), size); 13709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(1, bucket->activePagesHead->numAllocatedSlots); 13809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFree(ptr); 13909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, bucket->activePagesHead->numAllocatedSlots); 14009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_NE(-1, bucket->activePagesHead->freeCacheIndex); 14109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 14209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 14309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 144d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)static void CycleGenericFreeCache(size_t size) 145d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){ 146d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) for (size_t i = 0; i < WTF::kMaxFreeableSpans; ++i) { 147d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) void* ptr = partitionAllocGeneric(genericAllocator.root(), size); 148d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) WTF::PartitionPage* page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr)); 149d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) WTF::PartitionBucket* bucket = page->bucket; 150d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(1, bucket->activePagesHead->numAllocatedSlots); 151d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 152d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(0, bucket->activePagesHead->numAllocatedSlots); 153d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_NE(-1, bucket->activePagesHead->freeCacheIndex); 154d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) } 155d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} 156d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1575267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)// Check that the most basic of allocate / free pairs work. 158f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocTest, Basic) 1595267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){ 1605267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) TestSetup(); 161f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) WTF::PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex]; 16209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) WTF::PartitionPage* seedPage = &WTF::PartitionRootGeneric::gSeedPage; 1635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 164a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_FALSE(bucket->freePagesHead); 16509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(seedPage, bucket->activePagesHead); 16609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, bucket->activePagesHead->nextPage); 1675267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 1688abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) void* ptr = partitionAlloc(allocator.root(), kTestAllocSize); 1695267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) EXPECT_TRUE(ptr); 170a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(kPointerOffset, reinterpret_cast<size_t>(ptr) & WTF::kPartitionPageOffsetMask); 171521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // Check that the offset appears to include a guard page. 172a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(WTF::kPartitionPageSize + kPointerOffset, reinterpret_cast<size_t>(ptr) & WTF::kSuperPageOffsetMask); 1735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 1745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) partitionFree(ptr); 175bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) // Expect that the last active page does not get tossed to the freelist. 176a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_FALSE(bucket->freePagesHead); 1775267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 1785267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) TestShutdown(); 1795267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)} 1805267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 181591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch// Check that we can detect a memory leak. 182f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocTest, SimpleLeak) 183591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{ 184591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch TestSetup(); 1858abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) void* leakedPtr = partitionAlloc(allocator.root(), kTestAllocSize); 186f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) (void)leakedPtr; 18709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void* leakedPtr2 = partitionAllocGeneric(genericAllocator.root(), kTestAllocSize); 18809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) (void)leakedPtr2; 1898abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) EXPECT_FALSE(allocator.shutdown()); 19009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_FALSE(genericAllocator.shutdown()); 191591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} 192591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch 1935267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)// Test multiple allocations, and freelist handling. 194f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocTest, MultiAlloc) 1955267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){ 1965267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) TestSetup(); 1975267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 1988abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) char* ptr1 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize)); 1998abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) char* ptr2 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize)); 2005267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) EXPECT_TRUE(ptr1); 2015267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) EXPECT_TRUE(ptr2); 2025267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) ptrdiff_t diff = ptr2 - ptr1; 203f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize), diff); 2045267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 2055267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) // Check that we re-use the just-freed slot. 2065267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) partitionFree(ptr2); 2078abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) ptr2 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize)); 2085267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) EXPECT_TRUE(ptr2); 2095267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) diff = ptr2 - ptr1; 210f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize), diff); 2115267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) partitionFree(ptr1); 2128abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) ptr1 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize)); 2135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) EXPECT_TRUE(ptr1); 2145267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) diff = ptr2 - ptr1; 215f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize), diff); 2165267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 2178abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) char* ptr3 = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize)); 2185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) EXPECT_TRUE(ptr3); 2195267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) diff = ptr3 - ptr1; 220f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize * 2), diff); 2215267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 2225267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) partitionFree(ptr1); 2235267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) partitionFree(ptr2); 2245267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) partitionFree(ptr3); 2255267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 2265267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) TestShutdown(); 2275267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)} 2285267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 2295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)// Test a bucket with multiple pages. 230f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocTest, MultiPages) 2315267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){ 2325267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) TestSetup(); 233f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) WTF::PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex]; 2345267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 235a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::PartitionPage* page = GetFullPage(kTestAllocSize); 236f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(page); 237a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_FALSE(bucket->freePagesHead); 238a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(page, bucket->activePagesHead); 23909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, page->nextPage); 240a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(0, page->numAllocatedSlots); 2415267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 242521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) page = GetFullPage(kTestAllocSize); 243a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::PartitionPage* page2 = GetFullPage(kTestAllocSize); 2445267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 245a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(page2, bucket->activePagesHead); 24609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, page2->nextPage); 247a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(reinterpret_cast<uintptr_t>(partitionPageToPointer(page)) & WTF::kSuperPageBaseMask, reinterpret_cast<uintptr_t>(partitionPageToPointer(page2)) & WTF::kSuperPageBaseMask); 2485267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 249a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) // Fully free the non-current page. It should not be freelisted because 25009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // there is no other immediately useable page. The other page is full. 251f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(page); 2525267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) EXPECT_EQ(0, page->numAllocatedSlots); 253a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_FALSE(bucket->freePagesHead); 254a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(page, bucket->activePagesHead); 2555267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 2565267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) // Allocate a new page, it should pull from the freelist. 257521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) page = GetFullPage(kTestAllocSize); 258a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_FALSE(bucket->freePagesHead); 259a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(page, bucket->activePagesHead); 2605267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 261f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(page); 262f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(page2); 2635267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) EXPECT_EQ(0, page->numAllocatedSlots); 26409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, page2->numAllocatedSlots); 26509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, page2->numUnprovisionedSlots); 26609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_NE(-1, page2->freeCacheIndex); 2675267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 2685267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) TestShutdown(); 2695267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)} 2705267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 2715267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)// Test some finer aspects of internal page transitions. 272f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocTest, PageTransitions) 2735267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles){ 2745267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) TestSetup(); 275f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) WTF::PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex]; 2765267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 277a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::PartitionPage* page1 = GetFullPage(kTestAllocSize); 278a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(page1, bucket->activePagesHead); 27909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, page1->nextPage); 280a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::PartitionPage* page2 = GetFullPage(kTestAllocSize); 281a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(page2, bucket->activePagesHead); 28209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, page2->nextPage); 2831e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 2841e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) // Bounce page1 back into the non-full list then fill it up again. 285a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) char* ptr = reinterpret_cast<char*>(partitionPageToPointer(page1)) + kPointerOffset; 2861e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) partitionFree(ptr); 287a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(page1, bucket->activePagesHead); 2881e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) (void) partitionAlloc(allocator.root(), kTestAllocSize); 289a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(page1, bucket->activePagesHead); 29009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(page2, bucket->activePagesHead->nextPage); 2911e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 2925267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) // Allocating another page at this point should cause us to scan over page1 2935267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) // (which is both full and NOT our current page), and evict it from the 2945267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) // freelist. Older code had a O(n^2) condition due to failure to do this. 295a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::PartitionPage* page3 = GetFullPage(kTestAllocSize); 296a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(page3, bucket->activePagesHead); 29709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, page3->nextPage); 2985267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 2995267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) // Work out a pointer into page2 and free it. 300a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) ptr = reinterpret_cast<char*>(partitionPageToPointer(page2)) + kPointerOffset; 3015267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) partitionFree(ptr); 3025267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) // Trying to allocate at this time should cause us to cycle around to page2 3035267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) // and find the recently freed slot. 3048abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) char* newPtr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize)); 3055267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) EXPECT_EQ(ptr, newPtr); 306a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(page2, bucket->activePagesHead); 30709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(page3, page2->nextPage); 3085267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 3095267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) // Work out a pointer into page1 and free it. This should pull the page 310a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) // back into the list of available pages. 311a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) ptr = reinterpret_cast<char*>(partitionPageToPointer(page1)) + kPointerOffset; 3125267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) partitionFree(ptr); 3135267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) // This allocation should be satisfied by page1. 3148abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) newPtr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize)); 3155267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) EXPECT_EQ(ptr, newPtr); 316a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(page1, bucket->activePagesHead); 31709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(page2, page1->nextPage); 3185267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 319f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(page3); 320f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(page2); 321f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(page1); 322521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 323a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) // Allocating whilst in this state exposed a bug, so keep the test. 324a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) ptr = reinterpret_cast<char*>(partitionAlloc(allocator.root(), kTestAllocSize)); 325a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) partitionFree(ptr); 326a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) 327521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) TestShutdown(); 328521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)} 329521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 330521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// Test some corner cases relating to page transitions in the internal 331521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// free page list metadata bucket. 332f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocTest, FreePageListPageTransitions) 333521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){ 334521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) TestSetup(); 335f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) WTF::PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex]; 336521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 337a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) size_t numToFillFreeListPage = WTF::kPartitionPageSize / (sizeof(WTF::PartitionPage) + kExtraAllocSize); 338bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) // The +1 is because we need to account for the fact that the current page 339bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) // never gets thrown on the freelist. 340bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) ++numToFillFreeListPage; 341a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) OwnPtr<WTF::PartitionPage*[]> pages = adoptArrayPtr(new WTF::PartitionPage*[numToFillFreeListPage]); 342bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) 343521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) size_t i; 3441e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) for (i = 0; i < numToFillFreeListPage; ++i) { 345521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) pages[i] = GetFullPage(kTestAllocSize); 346521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) } 347a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(pages[numToFillFreeListPage - 1], bucket->activePagesHead); 348f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) for (i = 0; i < numToFillFreeListPage; ++i) 349f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(pages[i]); 350a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(0, bucket->activePagesHead->numAllocatedSlots); 35109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_NE(-1, bucket->activePagesHead->nextPage->freeCacheIndex); 35209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, bucket->activePagesHead->nextPage->numAllocatedSlots); 35309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, bucket->activePagesHead->nextPage->numUnprovisionedSlots); 354521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 3551e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) // Allocate / free in a different bucket size so we get control of a 356bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) // different free page list. We need two pages because one will be the last 357bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) // active page and not get freed. 358a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::PartitionPage* page1 = GetFullPage(kTestAllocSize * 2); 359a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::PartitionPage* page2 = GetFullPage(kTestAllocSize * 2); 360f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(page1); 361f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(page2); 362521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 363521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // If we re-allocate all kTestAllocSize allocations, we'll pull all the 364521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // free pages and end up freeing the first page for free page objects. 365521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // It's getting a bit tricky but a nice re-entrancy is going on: 366521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // alloc(kTestAllocSize) -> pulls page from free page list -> 367521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // free(PartitionFreepagelistEntry) -> last entry in page freed -> 368521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // alloc(PartitionFreepagelistEntry). 3691e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) for (i = 0; i < numToFillFreeListPage; ++i) { 370521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) pages[i] = GetFullPage(kTestAllocSize); 371521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) } 372a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(pages[numToFillFreeListPage - 1], bucket->activePagesHead); 373521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 374521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // As part of the final free-up, we'll test another re-entrancy: 375521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // free(kTestAllocSize) -> last entry in page freed -> 376521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // alloc(PartitionFreepagelistEntry) -> pulls page from free page list -> 377521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // free(PartitionFreepagelistEntry) 378f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) for (i = 0; i < numToFillFreeListPage; ++i) 379f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(pages[i]); 380a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(0, bucket->activePagesHead->numAllocatedSlots); 38109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_NE(-1, bucket->activePagesHead->nextPage->freeCacheIndex); 38209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, bucket->activePagesHead->nextPage->numAllocatedSlots); 38309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, bucket->activePagesHead->nextPage->numUnprovisionedSlots); 3845267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 3855267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) TestShutdown(); 3865267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)} 3875267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 388521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// Test a large series of allocations that cross more than one underlying 389521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// 64KB super page allocation. 390f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocTest, MultiPageAllocs) 391521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){ 392521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) TestSetup(); 393521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // This is guaranteed to cross a super page boundary because the first 394521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // partition page "slot" will be taken up by a guard page. 395a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) size_t numPagesNeeded = WTF::kNumPartitionPagesPerSuperPage; 396a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) // The super page should begin and end in a guard so we one less page in 397a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) // order to allocate a single page in the new super page. 398a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) --numPagesNeeded; 399a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) 400521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) EXPECT_GT(numPagesNeeded, 1u); 401a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) OwnPtr<WTF::PartitionPage*[]> pages; 402a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) pages = adoptArrayPtr(new WTF::PartitionPage*[numPagesNeeded]); 403521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) uintptr_t firstSuperPageBase = 0; 404521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) size_t i; 405521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) for (i = 0; i < numPagesNeeded; ++i) { 406521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) pages[i] = GetFullPage(kTestAllocSize); 407a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) void* storagePtr = partitionPageToPointer(pages[i]); 408521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) if (!i) 409a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) firstSuperPageBase = reinterpret_cast<uintptr_t>(storagePtr) & WTF::kSuperPageBaseMask; 410521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) if (i == numPagesNeeded - 1) { 411a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) uintptr_t secondSuperPageBase = reinterpret_cast<uintptr_t>(storagePtr) & WTF::kSuperPageBaseMask; 412a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) uintptr_t secondSuperPageOffset = reinterpret_cast<uintptr_t>(storagePtr) & WTF::kSuperPageOffsetMask; 413521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) EXPECT_FALSE(secondSuperPageBase == firstSuperPageBase); 414a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) // Check that we allocated a guard page for the second page. 415a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(WTF::kPartitionPageSize, secondSuperPageOffset); 416521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) } 417521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) } 418f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) for (i = 0; i < numPagesNeeded; ++i) 419f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(pages[i]); 420521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 421521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) TestShutdown(); 422521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)} 423521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 4241fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch// Test the generic allocation functions that can handle arbitrary sizes and 4251fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch// reallocing etc. 426f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocTest, GenericAlloc) 4271fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch{ 4281fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch TestSetup(); 4291fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch 43009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void* ptr = partitionAllocGeneric(genericAllocator.root(), 1); 4311fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch EXPECT_TRUE(ptr); 43209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 43309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ptr = partitionAllocGeneric(genericAllocator.root(), WTF::kGenericMaxBucketed + 1); 4341fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch EXPECT_TRUE(ptr); 43509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 4361fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch 43709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ptr = partitionAllocGeneric(genericAllocator.root(), 1); 4381fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch EXPECT_TRUE(ptr); 4391fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch void* origPtr = ptr; 4401fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch char* charPtr = static_cast<char*>(ptr); 4411fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch *charPtr = 'A'; 4421fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch 4431fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch // Change the size of the realloc, remaining inside the same bucket. 44409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void* newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 2); 4451fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch EXPECT_EQ(ptr, newPtr); 44609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 1); 4471fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch EXPECT_EQ(ptr, newPtr); 44809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, WTF::kGenericSmallestBucket); 4493c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch EXPECT_EQ(ptr, newPtr); 4501fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch 4511fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch // Change the size of the realloc, switching buckets. 45209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, WTF::kGenericSmallestBucket + 1); 4533c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch EXPECT_NE(newPtr, ptr); 4541fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch // Check that the realloc copied correctly. 4551fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch char* newCharPtr = static_cast<char*>(newPtr); 4561fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch EXPECT_EQ(*newCharPtr, 'A'); 457197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT) 45819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) // Subtle: this checks for an old bug where we copied too much from the 45919cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) // source of the realloc. The condition can be detected by a trashing of 46019cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles) // the uninitialized value in the space of the upsized allocation. 46109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(WTF::kUninitializedByte, static_cast<unsigned char>(*(newCharPtr + WTF::kGenericSmallestBucket))); 46219cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)#endif 4631fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch *newCharPtr = 'B'; 4641fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch // The realloc moved. To check that the old allocation was freed, we can 4651fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch // do an alloc of the old allocation size and check that the old allocation 4661fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch // address is at the head of the freelist and reused. 46709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void* reusedPtr = partitionAllocGeneric(genericAllocator.root(), 1); 4681fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch EXPECT_EQ(reusedPtr, origPtr); 46909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), reusedPtr); 4701fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch 4711fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch // Downsize the realloc. 4721fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch ptr = newPtr; 47309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 1); 4741fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch EXPECT_EQ(newPtr, origPtr); 4751fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch newCharPtr = static_cast<char*>(newPtr); 4761fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch EXPECT_EQ(*newCharPtr, 'B'); 4771fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch *newCharPtr = 'C'; 4781fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch 4791fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch // Upsize the realloc to outside the partition. 4801fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch ptr = newPtr; 48109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, WTF::kGenericMaxBucketed + 1); 4823c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch EXPECT_NE(newPtr, ptr); 4831fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch newCharPtr = static_cast<char*>(newPtr); 4841fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch EXPECT_EQ(*newCharPtr, 'C'); 4851fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch *newCharPtr = 'D'; 4861fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch 4871fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch // Upsize and downsize the realloc, remaining outside the partition. 4881fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch ptr = newPtr; 48909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, WTF::kGenericMaxBucketed * 10); 4901fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch newCharPtr = static_cast<char*>(newPtr); 4911fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch EXPECT_EQ(*newCharPtr, 'D'); 4921fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch *newCharPtr = 'E'; 4931fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch ptr = newPtr; 49409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, WTF::kGenericMaxBucketed * 2); 4951fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch newCharPtr = static_cast<char*>(newPtr); 4961fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch EXPECT_EQ(*newCharPtr, 'E'); 4971fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch *newCharPtr = 'F'; 4981fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch 4991fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch // Downsize the realloc to inside the partition. 5001fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch ptr = newPtr; 50109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) newPtr = partitionReallocGeneric(genericAllocator.root(), ptr, 1); 5023c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch EXPECT_NE(newPtr, ptr); 5031fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch EXPECT_EQ(newPtr, origPtr); 5041fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch newCharPtr = static_cast<char*>(newPtr); 5051fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch EXPECT_EQ(*newCharPtr, 'F'); 5061fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch 50709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), newPtr); 50809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) TestShutdown(); 50909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 51009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 51109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Test the generic allocation functions can handle some specific sizes of 51209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// interest. 513f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocTest, GenericAllocSizes) 51409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 51509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) TestSetup(); 51609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 51709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void* ptr = partitionAllocGeneric(genericAllocator.root(), 0); 51809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(ptr); 51909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 52009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 52109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // kPartitionPageSize is interesting because it results in just one 52209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // allocation per page, which tripped up some corner cases. 52309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t size = WTF::kPartitionPageSize - kExtraAllocSize; 52409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ptr = partitionAllocGeneric(genericAllocator.root(), size); 52509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(ptr); 52609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size); 52709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(ptr2); 52809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 52909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Should be freeable at this point. 53009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) WTF::PartitionPage* page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr)); 53109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_NE(-1, page->freeCacheIndex); 53209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr2); 53309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 53409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size = (((WTF::kPartitionPageSize * WTF::kMaxPartitionPagesPerSlotSpan) - WTF::kSystemPageSize) / 2) - kExtraAllocSize; 53509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ptr = partitionAllocGeneric(genericAllocator.root(), size); 53609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(ptr); 53709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) memset(ptr, 'A', size); 53809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ptr2 = partitionAllocGeneric(genericAllocator.root(), size); 53909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(ptr2); 54009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void* ptr3 = partitionAllocGeneric(genericAllocator.root(), size); 54109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(ptr3); 54209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void* ptr4 = partitionAllocGeneric(genericAllocator.root(), size); 54309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(ptr4); 54409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 54509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr)); 54609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) WTF::PartitionPage* page2 = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr3)); 54709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_NE(page, page2); 54809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 54909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 55009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr3); 55109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr2); 55209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Should be freeable at this point. 55309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_NE(-1, page->freeCacheIndex); 55409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, page->numAllocatedSlots); 55509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, page->numUnprovisionedSlots); 55609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void* newPtr = partitionAllocGeneric(genericAllocator.root(), size); 55709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(ptr3, newPtr); 55809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) newPtr = partitionAllocGeneric(genericAllocator.root(), size); 55909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(ptr2, newPtr); 560197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if OS(LINUX) && !ENABLE(ASSERT) 56109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // On Linux, we have a guarantee that freelisting a page should cause its 56209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // contents to be nulled out. We check for null here to detect an bug we 56309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // had where a large slot size was causing us to not properly free all 56409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // resources back to the system. 565197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // We only run the check when asserts are disabled because when they are 566197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // enabled, the allocated area is overwritten with an "uninitialized" 567197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch // byte pattern. 56809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, *(reinterpret_cast<char*>(newPtr) + (size - 1))); 56909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif 57009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), newPtr); 57109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr3); 57209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr4); 57309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 57409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Can we allocate a massive (512MB) size? 57509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ptr = partitionAllocGeneric(genericAllocator.root(), 512 * 1024 * 1024); 57609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 57709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 57809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Check a more reasonable, but still direct mapped, size. 57909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Chop a system page and a byte off to test for rounding errors. 58009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size = 20 * 1024 * 1024; 58109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size -= WTF::kSystemPageSize; 58209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size -= 1; 58309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ptr = partitionAllocGeneric(genericAllocator.root(), size); 58409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) char* charPtr = reinterpret_cast<char*>(ptr); 58509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) *(charPtr + (size - 1)) = 'A'; 58609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 58709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 58809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Can we free null? 58909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), 0); 59009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 59109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Do we correctly get a null for a failed allocation? 59209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, partitionAllocGenericFlags(genericAllocator.root(), WTF::PartitionAllocReturnNull, 3u * 1024 * 1024 * 1024)); 59309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 59409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) TestShutdown(); 59509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 59609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 597d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// Test that we can fetch the real allocated size after an allocation. 598f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocTest, GenericAllocGetSize) 599d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){ 600d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) TestSetup(); 601d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 602d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) void* ptr; 603d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) size_t requestedSize, actualSize, predictedSize; 604d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 605d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_TRUE(partitionAllocSupportsGetSize()); 606d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 607d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // Allocate something small. 608d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) requestedSize = 511 - kExtraAllocSize; 609d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedSize); 610d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize); 611d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_TRUE(ptr); 612d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) actualSize = partitionAllocGetSize(ptr); 613d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(predictedSize, actualSize); 614d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_LT(requestedSize, actualSize); 615d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 616d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 617d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // Allocate a size that should be a perfect match for a bucket, because it 618d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // is an exact power of 2. 619d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) requestedSize = (256 * 1024) - kExtraAllocSize; 620d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedSize); 621d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize); 622d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_TRUE(ptr); 623d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) actualSize = partitionAllocGetSize(ptr); 624d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(predictedSize, actualSize); 625d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(requestedSize, actualSize); 626d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 627d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 628d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // Allocate a size that is a system page smaller than a bucket. GetSize() 629d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // should return a larger size than we asked for now. 630d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) requestedSize = (256 * 1024) - WTF::kSystemPageSize - kExtraAllocSize; 631d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedSize); 632d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize); 633d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_TRUE(ptr); 634d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) actualSize = partitionAllocGetSize(ptr); 635d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(predictedSize, actualSize); 636d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(requestedSize + WTF::kSystemPageSize, actualSize); 637d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // Check that we can write at the end of the reported size too. 638d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) char* charPtr = reinterpret_cast<char*>(ptr); 639d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) *(charPtr + (actualSize - 1)) = 'A'; 640d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 641d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 642d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // Allocate something very large, and uneven. 643d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) requestedSize = 512 * 1024 * 1024 - 1; 644d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedSize); 645d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ptr = partitionAllocGeneric(genericAllocator.root(), requestedSize); 646d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_TRUE(ptr); 647d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) actualSize = partitionAllocGetSize(ptr); 648d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(predictedSize, actualSize); 649d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_LT(requestedSize, actualSize); 650d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 651d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 652d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // Too large allocation. 653d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) requestedSize = INT_MAX; 654d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) predictedSize = partitionAllocActualSize(genericAllocator.root(), requestedSize); 655d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(requestedSize, predictedSize); 656d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 657d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) TestShutdown(); 658d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} 659d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 66009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Test the realloc() contract. 661f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocTest, Realloc) 66209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 66309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) TestSetup(); 66409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 66509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // realloc(0, size) should be equivalent to malloc(). 66609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void* ptr = partitionReallocGeneric(genericAllocator.root(), 0, kTestAllocSize); 66709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) memset(ptr, 'A', kTestAllocSize); 66809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) WTF::PartitionPage* page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr)); 66909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // realloc(ptr, 0) should be equivalent to free(). 67009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void* ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, 0); 67109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, ptr2); 67209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(WTF::partitionCookieFreePointerAdjust(ptr), page->freelistHead); 67309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 674d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // Test that growing an allocation with realloc() copies everything from the 675d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // old allocation. 676d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) size_t size = WTF::kSystemPageSize - kExtraAllocSize; 677d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(size, partitionAllocActualSize(genericAllocator.root(), size)); 678d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ptr = partitionAllocGeneric(genericAllocator.root(), size); 679d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) memset(ptr, 'A', size); 680d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, size + 1); 681d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_NE(ptr, ptr2); 682d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) char* charPtr2 = static_cast<char*>(ptr2); 683d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ('A', charPtr2[0]); 684d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ('A', charPtr2[size - 1]); 685197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT) 686d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(WTF::kUninitializedByte, static_cast<unsigned char>(charPtr2[size])); 687d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#endif 688d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 689d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // Test that shrinking an allocation with realloc() also copies everything 690d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // from the old allocation. 691d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ptr = partitionReallocGeneric(genericAllocator.root(), ptr2, size - 1); 692d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_NE(ptr2, ptr); 693d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) char* charPtr = static_cast<char*>(ptr); 694d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ('A', charPtr[0]); 695d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ('A', charPtr[size - 2]); 696197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT) 697d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(WTF::kUninitializedByte, static_cast<unsigned char>(charPtr[size - 1])); 698d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#endif 699d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 700d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 701d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 702f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // Test that shrinking a direct mapped allocation happens in-place. 703d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) size = WTF::kGenericMaxBucketed + 16 * WTF::kSystemPageSize; 704d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ptr = partitionAllocGeneric(genericAllocator.root(), size); 705d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) size_t actualSize = partitionAllocGetSize(ptr); 706f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, WTF::kGenericMaxBucketed + 8 * WTF::kSystemPageSize); 707d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(ptr, ptr2); 708f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu EXPECT_EQ(actualSize - 8 * WTF::kSystemPageSize, partitionAllocGetSize(ptr2)); 709d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 710d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // Test that a previously in-place shrunk direct mapped allocation can be 711d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // expanded up again within its original size. 712d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ptr = partitionReallocGeneric(genericAllocator.root(), ptr2, size - WTF::kSystemPageSize); 713d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(ptr2, ptr); 714d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(actualSize - WTF::kSystemPageSize, partitionAllocGetSize(ptr)); 715d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 716f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // Test that a direct mapped allocation is performed not in-place when the 717f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu // new size is small enough. 718f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu ptr2 = partitionReallocGeneric(genericAllocator.root(), ptr, WTF::kSystemPageSize); 719f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu EXPECT_NE(ptr, ptr2); 720f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu 721f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu partitionFreeGeneric(genericAllocator.root(), ptr2); 722d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 7231fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch TestShutdown(); 7241fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch} 7251fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch 72606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)// Tests the handing out of freelists for partial pages. 727f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocTest, PartialPageFreelists) 72806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles){ 72906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) TestSetup(); 73006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 731f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) size_t bigSize = allocator.root()->maxAllocation - kExtraAllocSize; 732a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(WTF::kSystemPageSize - WTF::kAllocationGranularity, bigSize + kExtraAllocSize); 733f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) size_t bucketIdx = (bigSize + kExtraAllocSize) >> WTF::kBucketShift; 73406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) WTF::PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx]; 735a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(0, bucket->freePagesHead); 73606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 73706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) void* ptr = partitionAlloc(allocator.root(), bigSize); 73806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) EXPECT_TRUE(ptr); 73906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 740a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::PartitionPage* page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr)); 74109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t totalSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize) / (bigSize + kExtraAllocSize); 74209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(4u, totalSlots); 74309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // The freelist should have one entry, because we were able to exactly fit 74409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // one object slot and one freelist pointer (the null that the head points 74509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // to) into a system page. 74609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(page->freelistHead); 74706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) EXPECT_EQ(1, page->numAllocatedSlots); 74809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(2, page->numUnprovisionedSlots); 74906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 75006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) void* ptr2 = partitionAlloc(allocator.root(), bigSize); 75106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) EXPECT_TRUE(ptr2); 75209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_FALSE(page->freelistHead); 75306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) EXPECT_EQ(2, page->numAllocatedSlots); 75409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(2, page->numUnprovisionedSlots); 75506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 75606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) void* ptr3 = partitionAlloc(allocator.root(), bigSize); 75706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) EXPECT_TRUE(ptr3); 75809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(page->freelistHead); 75906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) EXPECT_EQ(3, page->numAllocatedSlots); 76009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, page->numUnprovisionedSlots); 76106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 76206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) void* ptr4 = partitionAlloc(allocator.root(), bigSize); 76306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) EXPECT_TRUE(ptr4); 76409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_FALSE(page->freelistHead); 765a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(4, page->numAllocatedSlots); 76609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, page->numUnprovisionedSlots); 767a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) 768a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) void* ptr5 = partitionAlloc(allocator.root(), bigSize); 769a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_TRUE(ptr5); 770a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) 771a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::PartitionPage* page2 = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr5)); 77206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) EXPECT_EQ(1, page2->numAllocatedSlots); 77306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 7741e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) // Churn things a little whilst there's a partial page freelist. 7751e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) partitionFree(ptr); 7761e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) ptr = partitionAlloc(allocator.root(), bigSize); 777a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) void* ptr6 = partitionAlloc(allocator.root(), bigSize); 7781e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 77906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) partitionFree(ptr); 78006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) partitionFree(ptr2); 78106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) partitionFree(ptr3); 78206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) partitionFree(ptr4); 7831e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) partitionFree(ptr5); 784a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) partitionFree(ptr6); 78509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_NE(-1, page->freeCacheIndex); 78609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_NE(-1, page2->freeCacheIndex); 78709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(page2->freelistHead); 788bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) EXPECT_EQ(0, page2->numAllocatedSlots); 78906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 790a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) // And test a couple of sizes that do not cross kSystemPageSize with a single allocation. 79109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t mediumSize = (WTF::kSystemPageSize / 2) - kExtraAllocSize; 792f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) bucketIdx = (mediumSize + kExtraAllocSize) >> WTF::kBucketShift; 79306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) bucket = &allocator.root()->buckets()[bucketIdx]; 794a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(0, bucket->freePagesHead); 79506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 79606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) ptr = partitionAlloc(allocator.root(), mediumSize); 79706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) EXPECT_TRUE(ptr); 798a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr)); 79906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) EXPECT_EQ(1, page->numAllocatedSlots); 80009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) totalSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize) / (mediumSize + kExtraAllocSize); 801a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) size_t firstPageSlots = WTF::kSystemPageSize / (mediumSize + kExtraAllocSize); 80209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(2u, firstPageSlots); 803a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(totalSlots - firstPageSlots, page->numUnprovisionedSlots); 80406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 80506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) partitionFree(ptr); 80606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 80709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t smallSize = (WTF::kSystemPageSize / 4) - kExtraAllocSize; 808f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) bucketIdx = (smallSize + kExtraAllocSize) >> WTF::kBucketShift; 80906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) bucket = &allocator.root()->buckets()[bucketIdx]; 810a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(0, bucket->freePagesHead); 81106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 81206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) ptr = partitionAlloc(allocator.root(), smallSize); 81306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) EXPECT_TRUE(ptr); 814a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr)); 81506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) EXPECT_EQ(1, page->numAllocatedSlots); 81609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) totalSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize) / (smallSize + kExtraAllocSize); 817a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) firstPageSlots = WTF::kSystemPageSize / (smallSize + kExtraAllocSize); 81806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) EXPECT_EQ(totalSlots - firstPageSlots, page->numUnprovisionedSlots); 81906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 82006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) partitionFree(ptr); 82109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(page->freelistHead); 822bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) EXPECT_EQ(0, page->numAllocatedSlots); 82306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 82409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t verySmallSize = 32 - kExtraAllocSize; 825f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) bucketIdx = (verySmallSize + kExtraAllocSize) >> WTF::kBucketShift; 82606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) bucket = &allocator.root()->buckets()[bucketIdx]; 827a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(0, bucket->freePagesHead); 82806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 82906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) ptr = partitionAlloc(allocator.root(), verySmallSize); 83006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) EXPECT_TRUE(ptr); 831a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr)); 83206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) EXPECT_EQ(1, page->numAllocatedSlots); 83309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) totalSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize) / (verySmallSize + kExtraAllocSize); 834a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) firstPageSlots = WTF::kSystemPageSize / (verySmallSize + kExtraAllocSize); 83506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) EXPECT_EQ(totalSlots - firstPageSlots, page->numUnprovisionedSlots); 83606f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 83706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) partitionFree(ptr); 83809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(page->freelistHead); 839bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) EXPECT_EQ(0, page->numAllocatedSlots); 8401e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 84109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // And try an allocation size (against the generic allocator) that is 84209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // larger than a system page. 84309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t pageAndAHalfSize = (WTF::kSystemPageSize + (WTF::kSystemPageSize / 2)) - kExtraAllocSize; 84409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ptr = partitionAllocGeneric(genericAllocator.root(), pageAndAHalfSize); 84509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(ptr); 84609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr)); 84709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(1, page->numAllocatedSlots); 84809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(page->freelistHead); 84909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) totalSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize) / (pageAndAHalfSize + kExtraAllocSize); 85009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(totalSlots - 2, page->numUnprovisionedSlots); 85109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 85209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 85309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // And then make sure than exactly the page size only faults one page. 85409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t pageSize = WTF::kSystemPageSize - kExtraAllocSize; 85509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ptr = partitionAllocGeneric(genericAllocator.root(), pageSize); 85609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(ptr); 85709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr)); 85809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(1, page->numAllocatedSlots); 85909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_FALSE(page->freelistHead); 86009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) totalSlots = (page->bucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize) / (pageSize + kExtraAllocSize); 86109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(totalSlots - 1, page->numUnprovisionedSlots); 86209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 86309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 8641e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) TestShutdown(); 8651e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)} 8661e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 8671e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)// Test some of the fragmentation-resistant properties of the allocator. 868f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocTest, PageRefilling) 8691e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles){ 8701e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) TestSetup(); 871f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) WTF::PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex]; 8721e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 8731e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) // Grab two full pages and a non-full page. 874a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::PartitionPage* page1 = GetFullPage(kTestAllocSize); 875a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::PartitionPage* page2 = GetFullPage(kTestAllocSize); 8761e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) void* ptr = partitionAlloc(allocator.root(), kTestAllocSize); 8771e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) EXPECT_TRUE(ptr); 878a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_NE(page1, bucket->activePagesHead); 879a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_NE(page2, bucket->activePagesHead); 880a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::PartitionPage* page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr)); 8811e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) EXPECT_EQ(1, page->numAllocatedSlots); 8821e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 8831e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) // Work out a pointer into page2 and free it; and then page1 and free it. 884a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) char* ptr2 = reinterpret_cast<char*>(WTF::partitionPageToPointer(page1)) + kPointerOffset; 8851e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) partitionFree(ptr2); 886a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) ptr2 = reinterpret_cast<char*>(WTF::partitionPageToPointer(page2)) + kPointerOffset; 8871e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) partitionFree(ptr2); 8881e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 8891e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) // If we perform two allocations from the same bucket now, we expect to 8901e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) // refill both the nearly full pages. 8911e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) (void) partitionAlloc(allocator.root(), kTestAllocSize); 8921e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) (void) partitionAlloc(allocator.root(), kTestAllocSize); 8931e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) EXPECT_EQ(1, page->numAllocatedSlots); 8941e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 895f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(page2); 896f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(page1); 8971e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) partitionFree(ptr); 89806f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 89906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) TestShutdown(); 90006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)} 90106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) 902f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)// Basic tests to ensure that allocations work for partial page buckets. 903f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocTest, PartialPages) 904f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles){ 905f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) TestSetup(); 906f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 907f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) // Find a size that is backed by a partial partition page. 908f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) size_t size = sizeof(void*); 909f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) WTF::PartitionBucket* bucket = 0; 910f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) while (size < kTestMaxAllocation) { 911f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) bucket = &allocator.root()->buckets()[size >> WTF::kBucketShift]; 91209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) if (bucket->numSystemPagesPerSlotSpan % WTF::kNumSystemPagesPerPartitionPage) 913f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) break; 914f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) size += sizeof(void*); 915f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) } 916f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) EXPECT_LT(size, kTestMaxAllocation); 917f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 918a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::PartitionPage* page1 = GetFullPage(size); 919a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::PartitionPage* page2 = GetFullPage(size); 920f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(page2); 921f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(page1); 922f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 923f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) TestShutdown(); 924f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)} 925f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) 926521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)// Test correct handling if our mapping collides with another. 927f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocTest, MappingCollision) 928521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){ 929521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) TestSetup(); 930a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) // The -2 is because the first and last partition pages in a super page are 931a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) // guard pages. 932a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) size_t numPartitionPagesNeeded = WTF::kNumPartitionPagesPerSuperPage - 2; 933a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) OwnPtr<WTF::PartitionPage*[]> firstSuperPagePages = adoptArrayPtr(new WTF::PartitionPage*[numPartitionPagesNeeded]); 934a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) OwnPtr<WTF::PartitionPage*[]> secondSuperPagePages = adoptArrayPtr(new WTF::PartitionPage*[numPartitionPagesNeeded]); 935521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 9361e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) size_t i; 9371e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) for (i = 0; i < numPartitionPagesNeeded; ++i) 9381e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) firstSuperPagePages[i] = GetFullPage(kTestAllocSize); 9391e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 940a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) char* pageBase = reinterpret_cast<char*>(WTF::partitionPageToPointer(firstSuperPagePages[0])); 941a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(WTF::kPartitionPageSize, reinterpret_cast<uintptr_t>(pageBase) & WTF::kSuperPageOffsetMask); 942a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) pageBase -= WTF::kPartitionPageSize; 943521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // Map a single system page either side of the mapping for our allocations, 944521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) // with the goal of tripping up alignment of the next mapping. 945a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) void* map1 = WTF::allocPages(pageBase - WTF::kPageAllocationGranularity, WTF::kPageAllocationGranularity, WTF::kPageAllocationGranularity); 946a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_TRUE(map1); 947a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) void* map2 = WTF::allocPages(pageBase + WTF::kSuperPageSize, WTF::kPageAllocationGranularity, WTF::kPageAllocationGranularity); 948a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_TRUE(map2); 949a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::setSystemPagesInaccessible(map1, WTF::kPageAllocationGranularity); 950a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::setSystemPagesInaccessible(map2, WTF::kPageAllocationGranularity); 951521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 9521e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) for (i = 0; i < numPartitionPagesNeeded; ++i) 9531e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) secondSuperPagePages[i] = GetFullPage(kTestAllocSize); 954521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 955a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::freePages(map1, WTF::kPageAllocationGranularity); 956a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::freePages(map2, WTF::kPageAllocationGranularity); 957521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 958a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) pageBase = reinterpret_cast<char*>(partitionPageToPointer(secondSuperPagePages[0])); 959a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(WTF::kPartitionPageSize, reinterpret_cast<uintptr_t>(pageBase) & WTF::kSuperPageOffsetMask); 960a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) pageBase -= WTF::kPartitionPageSize; 9611e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) // Map a single system page either side of the mapping for our allocations, 9621e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) // with the goal of tripping up alignment of the next mapping. 963a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) map1 = WTF::allocPages(pageBase - WTF::kPageAllocationGranularity, WTF::kPageAllocationGranularity, WTF::kPageAllocationGranularity); 964a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_TRUE(map1); 965a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) map2 = WTF::allocPages(pageBase + WTF::kSuperPageSize, WTF::kPageAllocationGranularity, WTF::kPageAllocationGranularity); 966a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_TRUE(map2); 967a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::setSystemPagesInaccessible(map1, WTF::kPageAllocationGranularity); 968a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::setSystemPagesInaccessible(map2, WTF::kPageAllocationGranularity); 9691e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 970a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::PartitionPage* pageInThirdSuperPage = GetFullPage(kTestAllocSize); 971a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::freePages(map1, WTF::kPageAllocationGranularity); 972a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF::freePages(map2, WTF::kPageAllocationGranularity); 9731e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 974a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(partitionPageToPointer(pageInThirdSuperPage)) & WTF::kPartitionPageOffsetMask); 9751e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 9761e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) // And make sure we really did get a page in a new superpage. 977a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_NE(reinterpret_cast<uintptr_t>(partitionPageToPointer(firstSuperPagePages[0])) & WTF::kSuperPageBaseMask, reinterpret_cast<uintptr_t>(partitionPageToPointer(pageInThirdSuperPage)) & WTF::kSuperPageBaseMask); 978a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_NE(reinterpret_cast<uintptr_t>(partitionPageToPointer(secondSuperPagePages[0])) & WTF::kSuperPageBaseMask, reinterpret_cast<uintptr_t>(partitionPageToPointer(pageInThirdSuperPage)) & WTF::kSuperPageBaseMask); 9791e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 980f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(pageInThirdSuperPage); 9811e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) for (i = 0; i < numPartitionPagesNeeded; ++i) { 982f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(firstSuperPagePages[i]); 983f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) FreeFullPage(secondSuperPagePages[i]); 9841e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) } 9851e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) 986521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) TestShutdown(); 987521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)} 988521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 98909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Tests that pages in the free page cache do get freed as appropriate. 990f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocTest, FreeCache) 99109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 99209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) TestSetup(); 99309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 9945d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) EXPECT_EQ(0U, allocator.root()->totalSizeOfCommittedPages); 9955d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) 99609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t bigSize = allocator.root()->maxAllocation - kExtraAllocSize; 99709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t bucketIdx = (bigSize + kExtraAllocSize) >> WTF::kBucketShift; 99809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) WTF::PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx]; 99909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 100009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void* ptr = partitionAlloc(allocator.root(), bigSize); 100109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(ptr); 100209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) WTF::PartitionPage* page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr)); 100309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, bucket->freePagesHead); 100409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(1, page->numAllocatedSlots); 10055d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) EXPECT_EQ(WTF::kPartitionPageSize, allocator.root()->totalSizeOfCommittedPages); 100609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFree(ptr); 100709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, page->numAllocatedSlots); 100809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_NE(-1, page->freeCacheIndex); 100909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(page->freelistHead); 101009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 101109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) CycleFreeCache(kTestAllocSize); 101209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 101309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Flushing the cache should have really freed the unused page. 101409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_FALSE(page->freelistHead); 101509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(-1, page->freeCacheIndex); 101609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_EQ(0, page->numAllocatedSlots); 10175d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) WTF::PartitionBucket* cycleFreeCacheBucket = &allocator.root()->buckets()[kTestBucketIndex]; 10185d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) EXPECT_EQ(cycleFreeCacheBucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize, allocator.root()->totalSizeOfCommittedPages); 101909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 102009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Check that an allocation works ok whilst in this state (a free'd page 102109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // as the active pages head). 102209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ptr = partitionAlloc(allocator.root(), bigSize); 102309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_FALSE(bucket->freePagesHead); 102409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFree(ptr); 102509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 102609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Also check that a page that is bouncing immediately between empty and 102709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // used does not get freed. 102809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) for (size_t i = 0; i < WTF::kMaxFreeableSpans * 2; ++i) { 102909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) ptr = partitionAlloc(allocator.root(), bigSize); 103009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(page->freelistHead); 103109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFree(ptr); 103209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(page->freelistHead); 103309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } 10345d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) EXPECT_EQ(WTF::kPartitionPageSize, allocator.root()->totalSizeOfCommittedPages); 103509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) TestShutdown(); 103609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 103709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 1038d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)// Tests for a bug we had with losing references to free pages. 1039f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocTest, LostFreePagesBug) 1040d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){ 1041d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) TestSetup(); 1042d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1043d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) size_t size = WTF::kPartitionPageSize - kExtraAllocSize; 1044d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1045d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) void* ptr = partitionAllocGeneric(genericAllocator.root(), size); 1046d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_TRUE(ptr); 1047d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) void* ptr2 = partitionAllocGeneric(genericAllocator.root(), size); 1048d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_TRUE(ptr2); 1049d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1050d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) WTF::PartitionPage* page = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr)); 1051d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) WTF::PartitionPage* page2 = WTF::partitionPointerToPage(WTF::partitionCookieFreePointerAdjust(ptr2)); 1052d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) WTF::PartitionBucket* bucket = page->bucket; 1053d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1054d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(0, bucket->freePagesHead); 1055d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(-1, page->numAllocatedSlots); 1056d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(1, page2->numAllocatedSlots); 1057d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1058d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 1059d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr2); 1060d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1061d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(0, bucket->freePagesHead); 1062d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(0, page->numAllocatedSlots); 1063d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_EQ(0, page2->numAllocatedSlots); 1064d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_TRUE(page->freelistHead); 1065d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_TRUE(page2->freelistHead); 1066d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1067d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) CycleGenericFreeCache(kTestAllocSize); 1068d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1069d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_FALSE(page->freelistHead); 1070d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_FALSE(page2->freelistHead); 1071d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1072d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_FALSE(bucket->freePagesHead); 1073d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_TRUE(bucket->activePagesHead); 1074d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_TRUE(bucket->activePagesHead->nextPage); 1075d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1076d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // At this moment, we have two freed pages, on the freelist. 1077d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1078d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ptr = partitionAllocGeneric(genericAllocator.root(), size); 1079d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_TRUE(ptr); 1080d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 1081d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1082d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_TRUE(bucket->activePagesHead); 1083d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_TRUE(bucket->freePagesHead); 1084d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1085d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) CycleGenericFreeCache(kTestAllocSize); 1086d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1087d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // We're now set up to trigger the bug by scanning over the active pages 1088d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // list, where the current active page is freed, and there exists at least 1089d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // one freed page in the free pages list. 1090d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ptr = partitionAllocGeneric(genericAllocator.root(), size); 1091d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_TRUE(ptr); 1092d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 1093d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1094d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_TRUE(bucket->activePagesHead); 1095d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) EXPECT_TRUE(bucket->freePagesHead); 1096d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1097d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) TestShutdown(); 1098d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} 1099d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1100d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#if !OS(ANDROID) 1101d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 110209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Make sure that malloc(-1) dies. 110309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// In the past, we had an integer overflow that would alias malloc(-1) to 110409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// malloc(0), which is not good. 1105f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocDeathTest, LargeAllocs) 110609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 110709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) TestSetup(); 110809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // Largest alloc. 110909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_DEATH(partitionAllocGeneric(genericAllocator.root(), static_cast<size_t>(-1)), ""); 111009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // And the smallest allocation we expect to die. 111109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_DEATH(partitionAllocGeneric(genericAllocator.root(), static_cast<size_t>(INT_MAX) + 1), ""); 111209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 111309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) TestShutdown(); 111409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 111509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 111609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Check that our immediate double-free detection works. 1117f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocDeathTest, ImmediateDoubleFree) 111809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 111909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) TestSetup(); 112009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 112109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void* ptr = partitionAllocGeneric(genericAllocator.root(), kTestAllocSize); 112209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(ptr); 112309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 112409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 112509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_DEATH(partitionFreeGeneric(genericAllocator.root(), ptr), ""); 112609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 112709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) TestShutdown(); 112809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 112909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 113009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Check that our refcount-based double-free detection works. 1131f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocDeathTest, RefcountDoubleFree) 113209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 113309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) TestSetup(); 113409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 113509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void* ptr = partitionAllocGeneric(genericAllocator.root(), kTestAllocSize); 113609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(ptr); 113709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void* ptr2 = partitionAllocGeneric(genericAllocator.root(), kTestAllocSize); 113809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(ptr2); 113909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 114009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr2); 114109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // This is not an immediate double-free so our immediate detection won't 114209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // fire. However, it does take the "refcount" of the partition page to -1, 114309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // which is illegal and should be trapped. 114409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_DEATH(partitionFreeGeneric(genericAllocator.root(), ptr), ""); 114509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 114609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) TestShutdown(); 114709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 114809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 114909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)// Check that guard pages are present where expected. 1150f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocDeathTest, GuardPages) 115109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 115209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) TestSetup(); 115309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 115409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // This large size will result in a direct mapped allocation with guard 115509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) // pages at either end. 115609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) size_t size = (WTF::kGenericMaxBucketed + WTF::kSystemPageSize) - kExtraAllocSize; 115709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) void* ptr = partitionAllocGeneric(genericAllocator.root(), size); 115809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_TRUE(ptr); 115909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) char* charPtr = reinterpret_cast<char*>(ptr) - kPointerOffset; 116009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 116109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_DEATH(*(charPtr - 1) = 'A', ""); 116209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) EXPECT_DEATH(*(charPtr + size + kExtraAllocSize) = 'A', ""); 116309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 116409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) partitionFreeGeneric(genericAllocator.root(), ptr); 116509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 116609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) TestShutdown(); 116709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 116809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 1169d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#endif // !OS(ANDROID) 1170d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 1171a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)// Tests that the countLeadingZeros() functions work to our satisfaction. 1172a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)// It doesn't seem worth the overhead of a whole new file for these tests, so 1173a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)// we'll put them here since partitionAllocGeneric will depend heavily on these 1174a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)// functions working correctly. 1175f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo LiuTEST(PartitionAllocTest, CLZWorks) 1176a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles){ 1177197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_EQ(32u, WTF::countLeadingZeros32(0u)); 1178197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_EQ(31u, WTF::countLeadingZeros32(1u)); 1179197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_EQ(1u, WTF::countLeadingZeros32(1u << 30)); 1180197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_EQ(0u, WTF::countLeadingZeros32(1u << 31)); 1181a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) 1182a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#if CPU(64BIT) 1183a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(64u, WTF::countLeadingZerosSizet(0ull)); 1184a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(63u, WTF::countLeadingZerosSizet(1ull)); 1185a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(32u, WTF::countLeadingZerosSizet(1ull << 31)); 1186a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(1u, WTF::countLeadingZerosSizet(1ull << 62)); 1187a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) EXPECT_EQ(0u, WTF::countLeadingZerosSizet(1ull << 63)); 1188a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#else 1189197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_EQ(32u, WTF::countLeadingZerosSizet(0u)); 1190197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_EQ(31u, WTF::countLeadingZerosSizet(1u)); 1191197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_EQ(1u, WTF::countLeadingZerosSizet(1u << 30)); 1192197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch EXPECT_EQ(0u, WTF::countLeadingZerosSizet(1u << 31)); 1193a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#endif 1194a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)} 1195521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 11965267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)} // namespace 11975267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) 1198591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#endif // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) 1199