123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954 |
- /*
- * 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 Computer, 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 <stdarg.h>
- #include <wtf/MetaAllocator.h>
- #include <wtf/Vector.h>
- 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<void*>(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<void*>((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<uintptr_t>(page) / pageSize()));
- for (uintptr_t address = reinterpret_cast<uintptr_t>(page); address < reinterpret_cast<uintptr_t>(page) + pageSize(); ++address)
- EXPECT_TRUE(!m_parent->byteState(reinterpret_cast<void*>(address)));
- m_parent->pageState(reinterpret_cast<uintptr_t>(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<uintptr_t>(page) / pageSize()));
- for (uintptr_t address = reinterpret_cast<uintptr_t>(page); address < reinterpret_cast<uintptr_t>(page) + pageSize(); ++address)
- EXPECT_TRUE(!m_parent->byteState(reinterpret_cast<void*>(address)));
- m_parent->pageState(reinterpret_cast<uintptr_t>(page) / pageSize()) = false;
- }
-
- private:
- MetaAllocatorTest* m_parent;
- };
- static const unsigned basePage = 1;
- static const unsigned defaultPagesInHeap = 100;
-
- unsigned additionalPagesInHeap;
-
- Vector<bool, 0>* memoryMap;
- Vector<bool, 0>* pageMap;
- bool allocatorDestroyed;
-
- SimpleTestAllocator* allocator;
-
- virtual void SetUp()
- {
- memoryMap = new Vector<bool, 0>();
- pageMap = new Vector<bool, 0>();
-
- 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<size_t>(0));
- EXPECT_EQ(requestedNumPages, static_cast<size_t>(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<uintptr_t>(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<uintptr_t>(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<uintptr_t>(handle->start());
- confirm(startByte, startByte + handle->sizeInBytes(), true);
- }
-
- void confirmHighWatermark(MetaAllocatorHandle* handle)
- {
- confirm(reinterpret_cast<uintptr_t>(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<uintptr_t>(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<void*>(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<void*>(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<void*>(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<void*>(basePage * pageSize()));
- EXPECT_EQ(firstHandle->sizeInBytes(), firstSize);
-
- confirm(firstHandle);
- confirmHighWatermark(firstHandle);
- MetaAllocatorHandle* secondHandle = allocate(secondSize);
- EXPECT_EQ(secondHandle->start(), reinterpret_cast<void*>(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<void*>(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<MetaAllocatorHandle*, 0> 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<void*>(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<void*>(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<void*>(basePage * pageSize()));
- EXPECT_EQ(finalHandle->sizeInBytes(), totalSize);
-
- confirm(finalHandle);
- confirmHighWatermark(finalHandle);
-
- free(finalHandle);
- }
- }
-
- void testFillHeap(size_t sizeInBytes, size_t numAllocations)
- {
- Vector<MetaAllocatorHandle*, 0> 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<void*>(basePage * pageSize()));
-
- MetaAllocatorHandle* firstRight = allocate(firstRightSize);
- EXPECT_EQ(firstRight->end(), reinterpret_cast<void*>((basePage + defaultPagesInHeap) * pageSize()));
-
- MetaAllocatorHandle* secondLeft = allocate(secondLeftSize);
- EXPECT_EQ(secondLeft->start(), reinterpret_cast<void*>(basePage * pageSize() + firstLeft->sizeInBytes()));
-
- MetaAllocatorHandle* secondRight = allocate(secondRightSize);
- EXPECT_EQ(secondRight->end(), reinterpret_cast<void*>((basePage + defaultPagesInHeap) * pageSize() - firstRight->sizeInBytes()));
-
- free(firstLeft);
- free(firstRight);
- free(secondLeft);
- free(secondRight);
-
- MetaAllocatorHandle* final = allocate(defaultPagesInHeap * pageSize());
- EXPECT_EQ(final->start(), reinterpret_cast<void*>(basePage * pageSize()));
-
- free(final);
- }
-
- void testBestFit(size_t firstSize, size_t step, unsigned numSlots, SanityCheckMode sanityCheckMode)
- {
- Vector<MetaAllocatorHandle*, 0> handlesToFree;
- Vector<MetaAllocatorHandle*, 0> handles;
- Vector<void*, 0> 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<void*>(reinterpret_cast<uintptr_t>(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<void*>(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<void*>(reinterpret_cast<uintptr_t>(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<void*>(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<size_t>(0));
- EXPECT_EQ(requestedNumPages, (secondSize + pageSize() - 1) / pageSize());
- EXPECT_EQ(secondHandle->start(), reinterpret_cast<void*>((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<size_t>(0));
- EXPECT_EQ(requestedNumPages, (secondSize + pageSize() - 1) / pageSize());
- EXPECT_EQ(secondHandle->start(), reinterpret_cast<void*>((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<void*>(basePage * pageSize()));
- EXPECT_EQ(secondHandle->start(), reinterpret_cast<void*>((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<void*>(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<int>(pageSize() * 2), 32, 0);
- }
- TEST_F(MetaAllocatorTest, RepeatAllocFree32ThenTwoPages)
- {
- testRepeatAllocFree(32, static_cast<int>(pageSize() * 2), 0);
- }
- TEST_F(MetaAllocatorTest, RepeatAllocFreePageThenTwoPages)
- {
- testRepeatAllocFree(static_cast<int>(pageSize()), static_cast<int>(pageSize() * 2), 0);
- }
- TEST_F(MetaAllocatorTest, RepeatAllocFreeTwoPagesThenPage)
- {
- testRepeatAllocFree(static_cast<int>(pageSize() * 2), static_cast<int>(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<int>(pageSize() - 32), 32, static_cast<int>(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<int>(pageSize() - 32), 32, static_cast<int>(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
|