/* * Copyright (C) 2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include #include #include #if OS(WINDOWS) #undef small #endif using namespace WTF; namespace TestWebKitAPI { class MetaAllocatorTest: public testing::Test { public: enum SanityCheckMode { RunSanityCheck, DontRunSanityCheck }; enum HeapGrowthMode { DontGrowHeap, ForTestDemandAllocCoalesce, ForTestDemandAllocDontCoalesce }; HeapGrowthMode currentHeapGrowthMode; size_t allowAllocatePages; size_t requestedNumPages; class SimpleTestAllocator: public MetaAllocator { public: SimpleTestAllocator(MetaAllocatorTest* parent) : MetaAllocator(32) , m_parent(parent) { addFreshFreeSpace(reinterpret_cast(basePage * pageSize()), defaultPagesInHeap * pageSize()); } virtual ~SimpleTestAllocator() { EXPECT_TRUE(!m_parent->allocatorDestroyed); m_parent->allocatorDestroyed = true; } virtual void* allocateNewSpace(size_t& numPages) { switch (m_parent->currentHeapGrowthMode) { case DontGrowHeap: return 0; case ForTestDemandAllocCoalesce: case ForTestDemandAllocDontCoalesce: { EXPECT_TRUE(m_parent->allowAllocatePages); EXPECT_TRUE(m_parent->allowAllocatePages >= numPages); m_parent->requestedNumPages = numPages; numPages = m_parent->allowAllocatePages; unsigned offset; if (m_parent->currentHeapGrowthMode == ForTestDemandAllocCoalesce) offset = 0; else offset = 1; void* result = reinterpret_cast((basePage + defaultPagesInHeap + offset) * pageSize()); m_parent->allowAllocatePages = 0; m_parent->currentHeapGrowthMode = DontGrowHeap; for (size_t counter = 0; counter < numPages + offset; ++counter) { m_parent->pageMap->append(false); for (unsigned byteCounter = 0; byteCounter < pageSize(); ++byteCounter) m_parent->memoryMap->append(false); } m_parent->additionalPagesInHeap += numPages; return result; } default: CRASH(); return 0; } } virtual void notifyNeedPage(void* page) { // the page should be both free and unmapped. EXPECT_TRUE(!m_parent->pageState(reinterpret_cast(page) / pageSize())); for (uintptr_t address = reinterpret_cast(page); address < reinterpret_cast(page) + pageSize(); ++address) EXPECT_TRUE(!m_parent->byteState(reinterpret_cast(address))); m_parent->pageState(reinterpret_cast(page) / pageSize()) = true; } virtual void notifyPageIsFree(void* page) { // the page should be free of objects at this point, but it should still // be mapped. EXPECT_TRUE(m_parent->pageState(reinterpret_cast(page) / pageSize())); for (uintptr_t address = reinterpret_cast(page); address < reinterpret_cast(page) + pageSize(); ++address) EXPECT_TRUE(!m_parent->byteState(reinterpret_cast(address))); m_parent->pageState(reinterpret_cast(page) / pageSize()) = false; } private: MetaAllocatorTest* m_parent; }; static const unsigned basePage = 1; static const unsigned defaultPagesInHeap = 100; unsigned additionalPagesInHeap; Vector* memoryMap; Vector* pageMap; bool allocatorDestroyed; SimpleTestAllocator* allocator; virtual void SetUp() { memoryMap = new Vector(); pageMap = new Vector(); for (unsigned page = basePage; page < basePage + defaultPagesInHeap; ++page) { pageMap->append(false); for (unsigned byteInPage = 0; byteInPage < pageSize(); ++byteInPage) memoryMap->append(false); } allocatorDestroyed = false; currentHeapGrowthMode = DontGrowHeap; allowAllocatePages = 0; additionalPagesInHeap = 0; requestedNumPages = 0; allocator = new SimpleTestAllocator(this); } virtual void TearDown() { EXPECT_TRUE(currentHeapGrowthMode == DontGrowHeap); EXPECT_EQ(allowAllocatePages, static_cast(0)); EXPECT_EQ(requestedNumPages, static_cast(0)); // memory should be free. for (unsigned page = basePage; page < basePage + defaultPagesInHeap; ++page) { EXPECT_TRUE(!pageState(page)); for (unsigned byteInPage = 0; byteInPage < pageSize(); ++byteInPage) EXPECT_TRUE(!byteState(page * pageSize() + byteInPage)); } // NOTE: this automatically tests that the allocator did not leak // memory, so long as these tests are running with !defined(NDEBUG). // See MetaAllocator::m_mallocBalance. delete allocator; EXPECT_TRUE(allocatorDestroyed); delete memoryMap; delete pageMap; } MetaAllocatorHandle* allocate(size_t sizeInBytes, SanityCheckMode sanityCheckMode = RunSanityCheck) { MetaAllocatorHandle* handle = allocator->allocate(sizeInBytes, 0).leakRef(); EXPECT_TRUE(handle); EXPECT_EQ(handle->sizeInBytes(), sizeInBytes); uintptr_t startByte = reinterpret_cast(handle->start()); uintptr_t endByte = startByte + sizeInBytes; for (uintptr_t currentByte = startByte; currentByte < endByte; ++currentByte) { EXPECT_TRUE(!byteState(currentByte)); byteState(currentByte) = true; EXPECT_TRUE(pageState(currentByte / pageSize())); } if (sanityCheckMode == RunSanityCheck) sanityCheck(); return handle; } void free(MetaAllocatorHandle* handle, SanityCheckMode sanityCheckMode = RunSanityCheck) { EXPECT_TRUE(handle); notifyFree(handle->start(), handle->sizeInBytes()); handle->deref(); if (sanityCheckMode == RunSanityCheck) sanityCheck(); } void notifyFree(void* start, size_t sizeInBytes) { uintptr_t startByte = reinterpret_cast(start); uintptr_t endByte = startByte + sizeInBytes; for (uintptr_t currentByte = startByte; currentByte < endByte; ++currentByte) { EXPECT_TRUE(byteState(currentByte)); byteState(currentByte) = false; } } void sanityCheck() { #ifndef NDEBUG EXPECT_EQ(allocator->bytesReserved() - allocator->bytesAllocated(), allocator->debugFreeSpaceSize()); #endif EXPECT_EQ(allocator->bytesReserved(), (defaultPagesInHeap + additionalPagesInHeap) * pageSize()); EXPECT_EQ(allocator->bytesAllocated(), bytesAllocated()); EXPECT_EQ(allocator->bytesCommitted(), bytesCommitted()); } void confirm(MetaAllocatorHandle* handle) { uintptr_t startByte = reinterpret_cast(handle->start()); confirm(startByte, startByte + handle->sizeInBytes(), true); } void confirmHighWatermark(MetaAllocatorHandle* handle) { confirm(reinterpret_cast(handle->end()), (basePage + defaultPagesInHeap) * pageSize(), false); } void confirm(uintptr_t startByte, uintptr_t endByte, bool value) { for (uintptr_t currentByte = startByte; currentByte < endByte; ++currentByte) { EXPECT_EQ(byteState(currentByte), value); if (value) EXPECT_TRUE(pageState(currentByte / pageSize())); } if (!value) { uintptr_t firstFreePage = (startByte + pageSize() - 1) / pageSize(); uintptr_t lastFreePage = (endByte - pageSize()) / pageSize(); for (uintptr_t currentPage = firstFreePage; currentPage <= lastFreePage; ++currentPage) EXPECT_TRUE(!pageState(currentPage)); } } size_t bytesAllocated() { size_t result = 0; for (unsigned index = 0; index < memoryMap->size(); ++index) { if (memoryMap->at(index)) result++; } return result; } size_t bytesCommitted() { size_t result = 0; for (unsigned index = 0; index < pageMap->size(); ++index) { if (pageMap->at(index)) result++; } return result * pageSize(); } bool& byteState(void* address) { return byteState(reinterpret_cast(address)); } bool& byteState(uintptr_t address) { uintptr_t byteIndex = address - basePage * pageSize(); return memoryMap->at(byteIndex); } bool& pageState(uintptr_t page) { uintptr_t pageIndex = page - basePage; return pageMap->at(pageIndex); } // Test helpers void testOneAlloc(size_t size) { // Tests the most basic behavior: allocate one thing and free it. Also // verifies that the state of pages is correct. MetaAllocatorHandle* handle = allocate(size); EXPECT_EQ(handle->start(), reinterpret_cast(basePage * pageSize())); EXPECT_EQ(handle->sizeInBytes(), size); EXPECT_TRUE(pageState(basePage)); confirm(handle); confirmHighWatermark(handle); free(handle); } void testRepeatAllocFree(size_t firstSize, ...) { // Tests right-coalescing by repeatedly allocating and freeing. The idea // is that if you allocate something and then free it, then the heap should // look identical to what it was before the allocation due to a right-coalesce // of the freed chunk and the already-free memory, and so subsequent // allocations should behave the same as the first one. MetaAllocatorHandle* handle = allocate(firstSize); EXPECT_EQ(handle->start(), reinterpret_cast(basePage * pageSize())); EXPECT_EQ(handle->sizeInBytes(), firstSize); confirm(handle); confirmHighWatermark(handle); free(handle); va_list argList; va_start(argList, firstSize); while (size_t sizeInBytes = va_arg(argList, int)) { handle = allocate(sizeInBytes); EXPECT_EQ(handle->start(), reinterpret_cast(basePage * pageSize())); EXPECT_EQ(handle->sizeInBytes(), sizeInBytes); confirm(handle); confirmHighWatermark(handle); free(handle); } va_end(argList); } void testSimpleFullCoalesce(size_t firstSize, size_t secondSize, size_t thirdSize) { // Allocates something of size firstSize, then something of size secondSize, and then // frees the first allocation, and then the second, and then attempts to allocate the // third, asserting that it allocated at the base address of the heap. // Note that this test may cause right-allocation, which will cause the test to fail. // Thus the correct way of running this test is to ensure that secondSize is // picked in such a way that it never straddles a page. MetaAllocatorHandle* firstHandle = allocate(firstSize); EXPECT_EQ(firstHandle->start(), reinterpret_cast(basePage * pageSize())); EXPECT_EQ(firstHandle->sizeInBytes(), firstSize); confirm(firstHandle); confirmHighWatermark(firstHandle); MetaAllocatorHandle* secondHandle = allocate(secondSize); EXPECT_EQ(secondHandle->start(), reinterpret_cast(basePage * pageSize() + firstSize)); EXPECT_EQ(secondHandle->sizeInBytes(), secondSize); confirm(firstHandle); confirm(secondHandle); confirmHighWatermark(secondHandle); free(firstHandle); confirm(secondHandle); confirmHighWatermark(secondHandle); free(secondHandle); confirm(basePage * pageSize(), (basePage + defaultPagesInHeap) * pageSize(), false); MetaAllocatorHandle* thirdHandle = allocate(thirdSize); EXPECT_EQ(thirdHandle->start(), reinterpret_cast(basePage * pageSize())); EXPECT_EQ(thirdHandle->sizeInBytes(), thirdSize); confirm(thirdHandle); confirmHighWatermark(thirdHandle); free(thirdHandle); } enum TestFIFOAllocMode { FillAtEnd, EagerFill }; void testFIFOAlloc(TestFIFOAllocMode mode, ...) { // This will test the simple case of no-coalesce (freeing the left-most // chunk in memory when the chunk to the right of it is allocated) and // fully exercise left-coalescing and full-coalescing. In EagerFill // mode, this also tests perfect-fit allocation and no-coalescing free. size_t totalSize = 0; Vector handles; va_list argList; va_start(argList, mode); while (size_t sizeInBytes = va_arg(argList, int)) { MetaAllocatorHandle* handle = allocate(sizeInBytes); EXPECT_EQ(handle->start(), reinterpret_cast(basePage * pageSize() + totalSize)); EXPECT_EQ(handle->sizeInBytes(), sizeInBytes); confirm(handle); confirmHighWatermark(handle); handles.append(handle); totalSize += sizeInBytes; } va_end(argList); for (unsigned index = 0; index < handles.size(); ++index) confirm(handles.at(index)); size_t sizeSoFar = 0; for (unsigned index = 0; index < handles.size(); ++index) { sizeSoFar += handles.at(index)->sizeInBytes(); free(handles.at(index)); if (mode == EagerFill) { MetaAllocatorHandle* handle = allocate(sizeSoFar); EXPECT_EQ(handle->start(), reinterpret_cast(basePage * pageSize())); EXPECT_EQ(handle->sizeInBytes(), sizeSoFar); confirm(basePage * pageSize(), basePage * pageSize() + totalSize, true); if (index < handles.size() - 1) confirmHighWatermark(handles.last()); else confirmHighWatermark(handle); free(handle); confirm(basePage * pageSize(), basePage * pageSize() + sizeSoFar, false); } } ASSERT(sizeSoFar == totalSize); confirm(basePage * pageSize(), (basePage + defaultPagesInHeap) * pageSize(), false); if (mode == FillAtEnd) { MetaAllocatorHandle* finalHandle = allocate(totalSize); EXPECT_EQ(finalHandle->start(), reinterpret_cast(basePage * pageSize())); EXPECT_EQ(finalHandle->sizeInBytes(), totalSize); confirm(finalHandle); confirmHighWatermark(finalHandle); free(finalHandle); } } void testFillHeap(size_t sizeInBytes, size_t numAllocations) { Vector handles; for (size_t index = 0; index < numAllocations; ++index) handles.append(allocate(sizeInBytes, DontRunSanityCheck)); sanityCheck(); EXPECT_TRUE(!allocator->allocate(sizeInBytes, 0)); for (size_t index = 0; index < numAllocations; ++index) free(handles.at(index), DontRunSanityCheck); sanityCheck(); } void testRightAllocation(size_t firstLeftSize, size_t firstRightSize, size_t secondLeftSize, size_t secondRightSize) { MetaAllocatorHandle* firstLeft = allocate(firstLeftSize); EXPECT_EQ(firstLeft->start(), reinterpret_cast(basePage * pageSize())); MetaAllocatorHandle* firstRight = allocate(firstRightSize); EXPECT_EQ(firstRight->end(), reinterpret_cast((basePage + defaultPagesInHeap) * pageSize())); MetaAllocatorHandle* secondLeft = allocate(secondLeftSize); EXPECT_EQ(secondLeft->start(), reinterpret_cast(basePage * pageSize() + firstLeft->sizeInBytes())); MetaAllocatorHandle* secondRight = allocate(secondRightSize); EXPECT_EQ(secondRight->end(), reinterpret_cast((basePage + defaultPagesInHeap) * pageSize() - firstRight->sizeInBytes())); free(firstLeft); free(firstRight); free(secondLeft); free(secondRight); MetaAllocatorHandle* final = allocate(defaultPagesInHeap * pageSize()); EXPECT_EQ(final->start(), reinterpret_cast(basePage * pageSize())); free(final); } void testBestFit(size_t firstSize, size_t step, unsigned numSlots, SanityCheckMode sanityCheckMode) { Vector handlesToFree; Vector handles; Vector locations; size_t size = firstSize; for (unsigned index = 0; index < numSlots; ++index) { MetaAllocatorHandle* toFree = allocate(size, sanityCheckMode); if (!handles.isEmpty()) { while (toFree->start() != handles.last()->end()) { handlesToFree.append(toFree); toFree = allocate(size, sanityCheckMode); } } MetaAllocatorHandle* fragger = allocate(32, sanityCheckMode); EXPECT_EQ(fragger->start(), toFree->end()); locations.append(toFree->start()); handlesToFree.append(toFree); handles.append(fragger); size += step; } ASSERT(locations.size() == numSlots); for (unsigned index = 0; index < handlesToFree.size(); ++index) free(handlesToFree.at(index), sanityCheckMode); size = firstSize; for (unsigned index = 0; index < numSlots; ++index) { MetaAllocatorHandle* bestFit = allocate(size - 32, sanityCheckMode); EXPECT_TRUE(bestFit->start() == locations.at(index) || bestFit->end() == reinterpret_cast(reinterpret_cast(locations.at(index)) + size)); MetaAllocatorHandle* small = allocate(32, sanityCheckMode); if (bestFit->start() == locations.at(index)) EXPECT_EQ(small->start(), bestFit->end()); else EXPECT_EQ(small->end(), bestFit->start()); free(bestFit, sanityCheckMode); free(small, sanityCheckMode); size += step; } for (unsigned index = 0; index < numSlots; ++index) free(handles.at(index), sanityCheckMode); MetaAllocatorHandle* final = allocate(defaultPagesInHeap * pageSize(), sanityCheckMode); EXPECT_EQ(final->start(), reinterpret_cast(basePage * pageSize())); free(final, sanityCheckMode); } void testShrink(size_t firstSize, size_t secondSize) { // Allocate the thing that will be shrunk MetaAllocatorHandle* handle = allocate(firstSize); // Shrink it, and make sure that our state reflects the shrinkage. notifyFree(reinterpret_cast(reinterpret_cast(handle->start()) + secondSize), firstSize - secondSize); handle->shrink(secondSize); EXPECT_EQ(handle->sizeInBytes(), secondSize); sanityCheck(); // Assert that the heap is not empty. EXPECT_TRUE(!allocator->allocate(defaultPagesInHeap * pageSize(), 0)); // Allocate the remainder of the heap. MetaAllocatorHandle* remainder = allocate(defaultPagesInHeap * pageSize() - secondSize); EXPECT_EQ(remainder->start(), handle->end()); free(remainder); free(handle); // Assert that the heap is empty and finish up. MetaAllocatorHandle* final = allocate(defaultPagesInHeap * pageSize()); EXPECT_EQ(final->start(), reinterpret_cast(basePage * pageSize())); free(final); } void testDemandAllocCoalesce(size_t firstSize, size_t numPages, size_t secondSize) { EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize(), 0)); MetaAllocatorHandle* firstHandle = allocate(firstSize); EXPECT_TRUE(!allocator->allocate(secondSize, 0)); EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize(), 0)); currentHeapGrowthMode = ForTestDemandAllocCoalesce; allowAllocatePages = numPages; MetaAllocatorHandle* secondHandle = allocate(secondSize); EXPECT_TRUE(currentHeapGrowthMode == DontGrowHeap); EXPECT_EQ(allowAllocatePages, static_cast(0)); EXPECT_EQ(requestedNumPages, (secondSize + pageSize() - 1) / pageSize()); EXPECT_EQ(secondHandle->start(), reinterpret_cast((basePage + defaultPagesInHeap) * pageSize())); requestedNumPages = 0; free(firstHandle); free(secondHandle); free(allocate((defaultPagesInHeap + numPages) * pageSize())); } void testDemandAllocDontCoalesce(size_t firstSize, size_t numPages, size_t secondSize) { free(allocate(firstSize)); free(allocate(defaultPagesInHeap * pageSize())); EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize(), 0)); MetaAllocatorHandle* firstHandle = allocate(firstSize); EXPECT_TRUE(!allocator->allocate(secondSize, 0)); EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize(), 0)); currentHeapGrowthMode = ForTestDemandAllocDontCoalesce; allowAllocatePages = numPages; MetaAllocatorHandle* secondHandle = allocate(secondSize); EXPECT_TRUE(currentHeapGrowthMode == DontGrowHeap); EXPECT_EQ(allowAllocatePages, static_cast(0)); EXPECT_EQ(requestedNumPages, (secondSize + pageSize() - 1) / pageSize()); EXPECT_EQ(secondHandle->start(), reinterpret_cast((basePage + defaultPagesInHeap + 1) * pageSize())); requestedNumPages = 0; EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize(), 0)); free(firstHandle); free(secondHandle); EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize(), 0)); firstHandle = allocate(firstSize); secondHandle = allocate(secondSize); EXPECT_EQ(firstHandle->start(), reinterpret_cast(basePage * pageSize())); EXPECT_EQ(secondHandle->start(), reinterpret_cast((basePage + defaultPagesInHeap + 1) * pageSize())); free(firstHandle); free(secondHandle); } }; TEST_F(MetaAllocatorTest, Empty) { // Tests that creating and destroying an allocator works. } TEST_F(MetaAllocatorTest, AllocZero) { // Tests that allocating a zero-length block returns 0 and // does not change anything in memory. ASSERT(!allocator->allocate(0, 0)); MetaAllocatorHandle* final = allocate(defaultPagesInHeap * pageSize()); EXPECT_EQ(final->start(), reinterpret_cast(basePage * pageSize())); free(final); } TEST_F(MetaAllocatorTest, OneAlloc32) { testOneAlloc(32); } TEST_F(MetaAllocatorTest, OneAlloc64) { testOneAlloc(64); } TEST_F(MetaAllocatorTest, OneAllocTwoPages) { testOneAlloc(pageSize() * 2); } TEST_F(MetaAllocatorTest, RepeatAllocFree32Twice) { testRepeatAllocFree(32, 32, 0); } TEST_F(MetaAllocatorTest, RepeatAllocFree32Then64) { testRepeatAllocFree(32, 64, 0); } TEST_F(MetaAllocatorTest, RepeatAllocFree64Then32) { testRepeatAllocFree(64, 32, 0); } TEST_F(MetaAllocatorTest, RepeatAllocFree32TwiceThen64) { testRepeatAllocFree(32, 32, 64, 0); } TEST_F(MetaAllocatorTest, RepeatAllocFree32Then64Twice) { testRepeatAllocFree(32, 64, 64, 0); } TEST_F(MetaAllocatorTest, RepeatAllocFree64Then32Then64) { testRepeatAllocFree(64, 32, 64, 0); } TEST_F(MetaAllocatorTest, RepeatAllocFree32Thrice) { testRepeatAllocFree(32, 32, 32, 0); } TEST_F(MetaAllocatorTest, RepeatAllocFree32Then64Then32) { testRepeatAllocFree(32, 32, 32, 0); } TEST_F(MetaAllocatorTest, RepeatAllocFree64Then32Twice) { testRepeatAllocFree(64, 32, 32, 0); } TEST_F(MetaAllocatorTest, RepeatAllocFreeTwoPagesThen32) { testRepeatAllocFree(static_cast(pageSize() * 2), 32, 0); } TEST_F(MetaAllocatorTest, RepeatAllocFree32ThenTwoPages) { testRepeatAllocFree(32, static_cast(pageSize() * 2), 0); } TEST_F(MetaAllocatorTest, RepeatAllocFreePageThenTwoPages) { testRepeatAllocFree(static_cast(pageSize()), static_cast(pageSize() * 2), 0); } TEST_F(MetaAllocatorTest, RepeatAllocFreeTwoPagesThenPage) { testRepeatAllocFree(static_cast(pageSize() * 2), static_cast(pageSize()), 0); } TEST_F(MetaAllocatorTest, SimpleFullCoalesce32Plus32Then128) { testSimpleFullCoalesce(32, 32, 128); } TEST_F(MetaAllocatorTest, SimpleFullCoalesce32Plus64Then128) { testSimpleFullCoalesce(32, 64, 128); } TEST_F(MetaAllocatorTest, SimpleFullCoalesce64Plus32Then128) { testSimpleFullCoalesce(64, 32, 128); } TEST_F(MetaAllocatorTest, SimpleFullCoalesce32PlusPageLess32ThenPage) { testSimpleFullCoalesce(32, pageSize() - 32, pageSize()); } TEST_F(MetaAllocatorTest, SimpleFullCoalesce32PlusPageLess32ThenTwoPages) { testSimpleFullCoalesce(32, pageSize() - 32, pageSize() * 2); } TEST_F(MetaAllocatorTest, SimpleFullCoalescePagePlus32ThenTwoPages) { testSimpleFullCoalesce(pageSize(), 32, pageSize() * 2); } TEST_F(MetaAllocatorTest, SimpleFullCoalescePagePlusPageThenTwoPages) { testSimpleFullCoalesce(pageSize(), pageSize(), pageSize() * 2); } TEST_F(MetaAllocatorTest, FIFOAllocFillAtEnd32Twice) { testFIFOAlloc(FillAtEnd, 32, 32, 0); } TEST_F(MetaAllocatorTest, FIFOAllocFillAtEnd32Thrice) { testFIFOAlloc(FillAtEnd, 32, 32, 32, 0); } TEST_F(MetaAllocatorTest, FIFOAllocFillAtEnd32FourTimes) { testFIFOAlloc(FillAtEnd, 32, 32, 32, 32, 0); } TEST_F(MetaAllocatorTest, FIFOAllocFillAtEndPageLess32Then32ThenPageLess64Then64) { testFIFOAlloc(FillAtEnd, static_cast(pageSize() - 32), 32, static_cast(pageSize() - 64), 64, 0); } TEST_F(MetaAllocatorTest, FIFOAllocEagerFill32Twice) { testFIFOAlloc(EagerFill, 32, 32, 0); } TEST_F(MetaAllocatorTest, FIFOAllocEagerFill32Thrice) { testFIFOAlloc(EagerFill, 32, 32, 32, 0); } TEST_F(MetaAllocatorTest, FIFOAllocEagerFill32FourTimes) { testFIFOAlloc(EagerFill, 32, 32, 32, 32, 0); } TEST_F(MetaAllocatorTest, FIFOAllocEagerFillPageLess32Then32ThenPageLess64Then64) { testFIFOAlloc(EagerFill, static_cast(pageSize() - 32), 32, static_cast(pageSize() - 64), 64, 0); } TEST_F(MetaAllocatorTest, FillHeap32) { testFillHeap(32, defaultPagesInHeap * pageSize() / 32); } TEST_F(MetaAllocatorTest, FillHeapPage) { testFillHeap(pageSize(), defaultPagesInHeap); } TEST_F(MetaAllocatorTest, FillHeapTwoPages) { testFillHeap(pageSize() * 2, defaultPagesInHeap / 2); } TEST_F(MetaAllocatorTest, RightAllocation32ThenPageThen32ThenPage) { testRightAllocation(32, pageSize(), 32, pageSize()); } TEST_F(MetaAllocatorTest, RightAllocationQuarterPageThenPageThenQuarterPageThenPage) { testRightAllocation(pageSize() / 4, pageSize(), pageSize() / 4, pageSize()); } TEST_F(MetaAllocatorTest, BestFit64Plus64Thrice) { testBestFit(64, 64, 3, RunSanityCheck); } TEST_F(MetaAllocatorTest, BestFit64Plus64TenTimes) { testBestFit(64, 64, 10, DontRunSanityCheck); } TEST_F(MetaAllocatorTest, BestFit64Plus64HundredTimes) { testBestFit(64, 64, 100, DontRunSanityCheck); } TEST_F(MetaAllocatorTest, BestFit96Plus64Thrice) { testBestFit(96, 64, 3, RunSanityCheck); } TEST_F(MetaAllocatorTest, BestFit96Plus64TenTimes) { testBestFit(96, 64, 10, DontRunSanityCheck); } TEST_F(MetaAllocatorTest, BestFit96Plus64HundredTimes) { testBestFit(96, 64, 100, DontRunSanityCheck); } TEST_F(MetaAllocatorTest, BestFit96Plus96Thrice) { testBestFit(96, 96, 3, RunSanityCheck); } TEST_F(MetaAllocatorTest, BestFit96Plus96TenTimes) { testBestFit(96, 96, 10, DontRunSanityCheck); } TEST_F(MetaAllocatorTest, BestFit96Plus96EightyTimes) { testBestFit(96, 96, 80, DontRunSanityCheck); } TEST_F(MetaAllocatorTest, Shrink64To32) { testShrink(64, 32); } TEST_F(MetaAllocatorTest, ShrinkPageTo32) { testShrink(pageSize(), 32); } TEST_F(MetaAllocatorTest, ShrinkPageToPageLess32) { testShrink(pageSize(), pageSize() - 32); } TEST_F(MetaAllocatorTest, ShrinkTwoPagesTo32) { testShrink(pageSize() * 2, 32); } TEST_F(MetaAllocatorTest, ShrinkTwoPagesToPagePlus32) { testShrink(pageSize() * 2, pageSize() + 32); } TEST_F(MetaAllocatorTest, ShrinkTwoPagesToPage) { testShrink(pageSize() * 2, pageSize()); } TEST_F(MetaAllocatorTest, ShrinkTwoPagesToPageLess32) { testShrink(pageSize() * 2, pageSize() - 32); } TEST_F(MetaAllocatorTest, ShrinkTwoPagesToTwoPagesLess32) { testShrink(pageSize() * 2, pageSize() * 2 - 32); } TEST_F(MetaAllocatorTest, DemandAllocCoalescePageThenDoubleHeap) { testDemandAllocCoalesce(pageSize(), defaultPagesInHeap, defaultPagesInHeap * pageSize()); } TEST_F(MetaAllocatorTest, DemandAllocCoalescePageThenTripleHeap) { testDemandAllocCoalesce(pageSize(), defaultPagesInHeap * 2, defaultPagesInHeap * pageSize()); } TEST_F(MetaAllocatorTest, DemandAllocDontCoalescePageThenDoubleHeap) { testDemandAllocDontCoalesce(pageSize(), defaultPagesInHeap, defaultPagesInHeap * pageSize()); } } // namespace TestWebKitAPI