MetaAllocator.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954
  1. /*
  2. * Copyright (C) 2011 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  14. * its contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  18. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  21. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #include "config.h"
  29. #include <stdarg.h>
  30. #include <wtf/MetaAllocator.h>
  31. #include <wtf/Vector.h>
  32. using namespace WTF;
  33. namespace TestWebKitAPI {
  34. class MetaAllocatorTest: public testing::Test {
  35. public:
  36. enum SanityCheckMode { RunSanityCheck, DontRunSanityCheck };
  37. enum HeapGrowthMode { DontGrowHeap, ForTestDemandAllocCoalesce, ForTestDemandAllocDontCoalesce };
  38. HeapGrowthMode currentHeapGrowthMode;
  39. size_t allowAllocatePages;
  40. size_t requestedNumPages;
  41. class SimpleTestAllocator: public MetaAllocator {
  42. public:
  43. SimpleTestAllocator(MetaAllocatorTest* parent)
  44. : MetaAllocator(32)
  45. , m_parent(parent)
  46. {
  47. addFreshFreeSpace(reinterpret_cast<void*>(basePage * pageSize()), defaultPagesInHeap * pageSize());
  48. }
  49. virtual ~SimpleTestAllocator()
  50. {
  51. EXPECT_TRUE(!m_parent->allocatorDestroyed);
  52. m_parent->allocatorDestroyed = true;
  53. }
  54. virtual void* allocateNewSpace(size_t& numPages)
  55. {
  56. switch (m_parent->currentHeapGrowthMode) {
  57. case DontGrowHeap:
  58. return 0;
  59. case ForTestDemandAllocCoalesce:
  60. case ForTestDemandAllocDontCoalesce: {
  61. EXPECT_TRUE(m_parent->allowAllocatePages);
  62. EXPECT_TRUE(m_parent->allowAllocatePages >= numPages);
  63. m_parent->requestedNumPages = numPages;
  64. numPages = m_parent->allowAllocatePages;
  65. unsigned offset;
  66. if (m_parent->currentHeapGrowthMode == ForTestDemandAllocCoalesce)
  67. offset = 0;
  68. else
  69. offset = 1;
  70. void* result = reinterpret_cast<void*>((basePage + defaultPagesInHeap + offset) * pageSize());
  71. m_parent->allowAllocatePages = 0;
  72. m_parent->currentHeapGrowthMode = DontGrowHeap;
  73. for (size_t counter = 0; counter < numPages + offset; ++counter) {
  74. m_parent->pageMap->append(false);
  75. for (unsigned byteCounter = 0; byteCounter < pageSize(); ++byteCounter)
  76. m_parent->memoryMap->append(false);
  77. }
  78. m_parent->additionalPagesInHeap += numPages;
  79. return result;
  80. }
  81. default:
  82. CRASH();
  83. return 0;
  84. }
  85. }
  86. virtual void notifyNeedPage(void* page)
  87. {
  88. // the page should be both free and unmapped.
  89. EXPECT_TRUE(!m_parent->pageState(reinterpret_cast<uintptr_t>(page) / pageSize()));
  90. for (uintptr_t address = reinterpret_cast<uintptr_t>(page); address < reinterpret_cast<uintptr_t>(page) + pageSize(); ++address)
  91. EXPECT_TRUE(!m_parent->byteState(reinterpret_cast<void*>(address)));
  92. m_parent->pageState(reinterpret_cast<uintptr_t>(page) / pageSize()) = true;
  93. }
  94. virtual void notifyPageIsFree(void* page)
  95. {
  96. // the page should be free of objects at this point, but it should still
  97. // be mapped.
  98. EXPECT_TRUE(m_parent->pageState(reinterpret_cast<uintptr_t>(page) / pageSize()));
  99. for (uintptr_t address = reinterpret_cast<uintptr_t>(page); address < reinterpret_cast<uintptr_t>(page) + pageSize(); ++address)
  100. EXPECT_TRUE(!m_parent->byteState(reinterpret_cast<void*>(address)));
  101. m_parent->pageState(reinterpret_cast<uintptr_t>(page) / pageSize()) = false;
  102. }
  103. private:
  104. MetaAllocatorTest* m_parent;
  105. };
  106. static const unsigned basePage = 1;
  107. static const unsigned defaultPagesInHeap = 100;
  108. unsigned additionalPagesInHeap;
  109. Vector<bool, 0>* memoryMap;
  110. Vector<bool, 0>* pageMap;
  111. bool allocatorDestroyed;
  112. SimpleTestAllocator* allocator;
  113. virtual void SetUp()
  114. {
  115. memoryMap = new Vector<bool, 0>();
  116. pageMap = new Vector<bool, 0>();
  117. for (unsigned page = basePage; page < basePage + defaultPagesInHeap; ++page) {
  118. pageMap->append(false);
  119. for (unsigned byteInPage = 0; byteInPage < pageSize(); ++byteInPage)
  120. memoryMap->append(false);
  121. }
  122. allocatorDestroyed = false;
  123. currentHeapGrowthMode = DontGrowHeap;
  124. allowAllocatePages = 0;
  125. additionalPagesInHeap = 0;
  126. requestedNumPages = 0;
  127. allocator = new SimpleTestAllocator(this);
  128. }
  129. virtual void TearDown()
  130. {
  131. EXPECT_TRUE(currentHeapGrowthMode == DontGrowHeap);
  132. EXPECT_EQ(allowAllocatePages, static_cast<size_t>(0));
  133. EXPECT_EQ(requestedNumPages, static_cast<size_t>(0));
  134. // memory should be free.
  135. for (unsigned page = basePage; page < basePage + defaultPagesInHeap; ++page) {
  136. EXPECT_TRUE(!pageState(page));
  137. for (unsigned byteInPage = 0; byteInPage < pageSize(); ++byteInPage)
  138. EXPECT_TRUE(!byteState(page * pageSize() + byteInPage));
  139. }
  140. // NOTE: this automatically tests that the allocator did not leak
  141. // memory, so long as these tests are running with !defined(NDEBUG).
  142. // See MetaAllocator::m_mallocBalance.
  143. delete allocator;
  144. EXPECT_TRUE(allocatorDestroyed);
  145. delete memoryMap;
  146. delete pageMap;
  147. }
  148. MetaAllocatorHandle* allocate(size_t sizeInBytes, SanityCheckMode sanityCheckMode = RunSanityCheck)
  149. {
  150. MetaAllocatorHandle* handle = allocator->allocate(sizeInBytes, 0).leakRef();
  151. EXPECT_TRUE(handle);
  152. EXPECT_EQ(handle->sizeInBytes(), sizeInBytes);
  153. uintptr_t startByte = reinterpret_cast<uintptr_t>(handle->start());
  154. uintptr_t endByte = startByte + sizeInBytes;
  155. for (uintptr_t currentByte = startByte; currentByte < endByte; ++currentByte) {
  156. EXPECT_TRUE(!byteState(currentByte));
  157. byteState(currentByte) = true;
  158. EXPECT_TRUE(pageState(currentByte / pageSize()));
  159. }
  160. if (sanityCheckMode == RunSanityCheck)
  161. sanityCheck();
  162. return handle;
  163. }
  164. void free(MetaAllocatorHandle* handle, SanityCheckMode sanityCheckMode = RunSanityCheck)
  165. {
  166. EXPECT_TRUE(handle);
  167. notifyFree(handle->start(), handle->sizeInBytes());
  168. handle->deref();
  169. if (sanityCheckMode == RunSanityCheck)
  170. sanityCheck();
  171. }
  172. void notifyFree(void* start, size_t sizeInBytes)
  173. {
  174. uintptr_t startByte = reinterpret_cast<uintptr_t>(start);
  175. uintptr_t endByte = startByte + sizeInBytes;
  176. for (uintptr_t currentByte = startByte; currentByte < endByte; ++currentByte) {
  177. EXPECT_TRUE(byteState(currentByte));
  178. byteState(currentByte) = false;
  179. }
  180. }
  181. void sanityCheck()
  182. {
  183. #ifndef NDEBUG
  184. EXPECT_EQ(allocator->bytesReserved() - allocator->bytesAllocated(), allocator->debugFreeSpaceSize());
  185. #endif
  186. EXPECT_EQ(allocator->bytesReserved(), (defaultPagesInHeap + additionalPagesInHeap) * pageSize());
  187. EXPECT_EQ(allocator->bytesAllocated(), bytesAllocated());
  188. EXPECT_EQ(allocator->bytesCommitted(), bytesCommitted());
  189. }
  190. void confirm(MetaAllocatorHandle* handle)
  191. {
  192. uintptr_t startByte = reinterpret_cast<uintptr_t>(handle->start());
  193. confirm(startByte, startByte + handle->sizeInBytes(), true);
  194. }
  195. void confirmHighWatermark(MetaAllocatorHandle* handle)
  196. {
  197. confirm(reinterpret_cast<uintptr_t>(handle->end()), (basePage + defaultPagesInHeap) * pageSize(), false);
  198. }
  199. void confirm(uintptr_t startByte, uintptr_t endByte, bool value)
  200. {
  201. for (uintptr_t currentByte = startByte; currentByte < endByte; ++currentByte) {
  202. EXPECT_EQ(byteState(currentByte), value);
  203. if (value)
  204. EXPECT_TRUE(pageState(currentByte / pageSize()));
  205. }
  206. if (!value) {
  207. uintptr_t firstFreePage = (startByte + pageSize() - 1) / pageSize();
  208. uintptr_t lastFreePage = (endByte - pageSize()) / pageSize();
  209. for (uintptr_t currentPage = firstFreePage; currentPage <= lastFreePage; ++currentPage)
  210. EXPECT_TRUE(!pageState(currentPage));
  211. }
  212. }
  213. size_t bytesAllocated()
  214. {
  215. size_t result = 0;
  216. for (unsigned index = 0; index < memoryMap->size(); ++index) {
  217. if (memoryMap->at(index))
  218. result++;
  219. }
  220. return result;
  221. }
  222. size_t bytesCommitted()
  223. {
  224. size_t result = 0;
  225. for (unsigned index = 0; index < pageMap->size(); ++index) {
  226. if (pageMap->at(index))
  227. result++;
  228. }
  229. return result * pageSize();
  230. }
  231. bool& byteState(void* address)
  232. {
  233. return byteState(reinterpret_cast<uintptr_t>(address));
  234. }
  235. bool& byteState(uintptr_t address)
  236. {
  237. uintptr_t byteIndex = address - basePage * pageSize();
  238. return memoryMap->at(byteIndex);
  239. }
  240. bool& pageState(uintptr_t page)
  241. {
  242. uintptr_t pageIndex = page - basePage;
  243. return pageMap->at(pageIndex);
  244. }
  245. // Test helpers
  246. void testOneAlloc(size_t size)
  247. {
  248. // Tests the most basic behavior: allocate one thing and free it. Also
  249. // verifies that the state of pages is correct.
  250. MetaAllocatorHandle* handle = allocate(size);
  251. EXPECT_EQ(handle->start(), reinterpret_cast<void*>(basePage * pageSize()));
  252. EXPECT_EQ(handle->sizeInBytes(), size);
  253. EXPECT_TRUE(pageState(basePage));
  254. confirm(handle);
  255. confirmHighWatermark(handle);
  256. free(handle);
  257. }
  258. void testRepeatAllocFree(size_t firstSize, ...)
  259. {
  260. // Tests right-coalescing by repeatedly allocating and freeing. The idea
  261. // is that if you allocate something and then free it, then the heap should
  262. // look identical to what it was before the allocation due to a right-coalesce
  263. // of the freed chunk and the already-free memory, and so subsequent
  264. // allocations should behave the same as the first one.
  265. MetaAllocatorHandle* handle = allocate(firstSize);
  266. EXPECT_EQ(handle->start(), reinterpret_cast<void*>(basePage * pageSize()));
  267. EXPECT_EQ(handle->sizeInBytes(), firstSize);
  268. confirm(handle);
  269. confirmHighWatermark(handle);
  270. free(handle);
  271. va_list argList;
  272. va_start(argList, firstSize);
  273. while (size_t sizeInBytes = va_arg(argList, int)) {
  274. handle = allocate(sizeInBytes);
  275. EXPECT_EQ(handle->start(), reinterpret_cast<void*>(basePage * pageSize()));
  276. EXPECT_EQ(handle->sizeInBytes(), sizeInBytes);
  277. confirm(handle);
  278. confirmHighWatermark(handle);
  279. free(handle);
  280. }
  281. va_end(argList);
  282. }
  283. void testSimpleFullCoalesce(size_t firstSize, size_t secondSize, size_t thirdSize)
  284. {
  285. // Allocates something of size firstSize, then something of size secondSize, and then
  286. // frees the first allocation, and then the second, and then attempts to allocate the
  287. // third, asserting that it allocated at the base address of the heap.
  288. // Note that this test may cause right-allocation, which will cause the test to fail.
  289. // Thus the correct way of running this test is to ensure that secondSize is
  290. // picked in such a way that it never straddles a page.
  291. MetaAllocatorHandle* firstHandle = allocate(firstSize);
  292. EXPECT_EQ(firstHandle->start(), reinterpret_cast<void*>(basePage * pageSize()));
  293. EXPECT_EQ(firstHandle->sizeInBytes(), firstSize);
  294. confirm(firstHandle);
  295. confirmHighWatermark(firstHandle);
  296. MetaAllocatorHandle* secondHandle = allocate(secondSize);
  297. EXPECT_EQ(secondHandle->start(), reinterpret_cast<void*>(basePage * pageSize() + firstSize));
  298. EXPECT_EQ(secondHandle->sizeInBytes(), secondSize);
  299. confirm(firstHandle);
  300. confirm(secondHandle);
  301. confirmHighWatermark(secondHandle);
  302. free(firstHandle);
  303. confirm(secondHandle);
  304. confirmHighWatermark(secondHandle);
  305. free(secondHandle);
  306. confirm(basePage * pageSize(), (basePage + defaultPagesInHeap) * pageSize(), false);
  307. MetaAllocatorHandle* thirdHandle = allocate(thirdSize);
  308. EXPECT_EQ(thirdHandle->start(), reinterpret_cast<void*>(basePage * pageSize()));
  309. EXPECT_EQ(thirdHandle->sizeInBytes(), thirdSize);
  310. confirm(thirdHandle);
  311. confirmHighWatermark(thirdHandle);
  312. free(thirdHandle);
  313. }
  314. enum TestFIFOAllocMode { FillAtEnd, EagerFill };
  315. void testFIFOAlloc(TestFIFOAllocMode mode, ...)
  316. {
  317. // This will test the simple case of no-coalesce (freeing the left-most
  318. // chunk in memory when the chunk to the right of it is allocated) and
  319. // fully exercise left-coalescing and full-coalescing. In EagerFill
  320. // mode, this also tests perfect-fit allocation and no-coalescing free.
  321. size_t totalSize = 0;
  322. Vector<MetaAllocatorHandle*, 0> handles;
  323. va_list argList;
  324. va_start(argList, mode);
  325. while (size_t sizeInBytes = va_arg(argList, int)) {
  326. MetaAllocatorHandle* handle = allocate(sizeInBytes);
  327. EXPECT_EQ(handle->start(), reinterpret_cast<void*>(basePage * pageSize() + totalSize));
  328. EXPECT_EQ(handle->sizeInBytes(), sizeInBytes);
  329. confirm(handle);
  330. confirmHighWatermark(handle);
  331. handles.append(handle);
  332. totalSize += sizeInBytes;
  333. }
  334. va_end(argList);
  335. for (unsigned index = 0; index < handles.size(); ++index)
  336. confirm(handles.at(index));
  337. size_t sizeSoFar = 0;
  338. for (unsigned index = 0; index < handles.size(); ++index) {
  339. sizeSoFar += handles.at(index)->sizeInBytes();
  340. free(handles.at(index));
  341. if (mode == EagerFill) {
  342. MetaAllocatorHandle* handle = allocate(sizeSoFar);
  343. EXPECT_EQ(handle->start(), reinterpret_cast<void*>(basePage * pageSize()));
  344. EXPECT_EQ(handle->sizeInBytes(), sizeSoFar);
  345. confirm(basePage * pageSize(), basePage * pageSize() + totalSize, true);
  346. if (index < handles.size() - 1)
  347. confirmHighWatermark(handles.last());
  348. else
  349. confirmHighWatermark(handle);
  350. free(handle);
  351. confirm(basePage * pageSize(), basePage * pageSize() + sizeSoFar, false);
  352. }
  353. }
  354. ASSERT(sizeSoFar == totalSize);
  355. confirm(basePage * pageSize(), (basePage + defaultPagesInHeap) * pageSize(), false);
  356. if (mode == FillAtEnd) {
  357. MetaAllocatorHandle* finalHandle = allocate(totalSize);
  358. EXPECT_EQ(finalHandle->start(), reinterpret_cast<void*>(basePage * pageSize()));
  359. EXPECT_EQ(finalHandle->sizeInBytes(), totalSize);
  360. confirm(finalHandle);
  361. confirmHighWatermark(finalHandle);
  362. free(finalHandle);
  363. }
  364. }
  365. void testFillHeap(size_t sizeInBytes, size_t numAllocations)
  366. {
  367. Vector<MetaAllocatorHandle*, 0> handles;
  368. for (size_t index = 0; index < numAllocations; ++index)
  369. handles.append(allocate(sizeInBytes, DontRunSanityCheck));
  370. sanityCheck();
  371. EXPECT_TRUE(!allocator->allocate(sizeInBytes, 0));
  372. for (size_t index = 0; index < numAllocations; ++index)
  373. free(handles.at(index), DontRunSanityCheck);
  374. sanityCheck();
  375. }
  376. void testRightAllocation(size_t firstLeftSize, size_t firstRightSize, size_t secondLeftSize, size_t secondRightSize)
  377. {
  378. MetaAllocatorHandle* firstLeft = allocate(firstLeftSize);
  379. EXPECT_EQ(firstLeft->start(), reinterpret_cast<void*>(basePage * pageSize()));
  380. MetaAllocatorHandle* firstRight = allocate(firstRightSize);
  381. EXPECT_EQ(firstRight->end(), reinterpret_cast<void*>((basePage + defaultPagesInHeap) * pageSize()));
  382. MetaAllocatorHandle* secondLeft = allocate(secondLeftSize);
  383. EXPECT_EQ(secondLeft->start(), reinterpret_cast<void*>(basePage * pageSize() + firstLeft->sizeInBytes()));
  384. MetaAllocatorHandle* secondRight = allocate(secondRightSize);
  385. EXPECT_EQ(secondRight->end(), reinterpret_cast<void*>((basePage + defaultPagesInHeap) * pageSize() - firstRight->sizeInBytes()));
  386. free(firstLeft);
  387. free(firstRight);
  388. free(secondLeft);
  389. free(secondRight);
  390. MetaAllocatorHandle* final = allocate(defaultPagesInHeap * pageSize());
  391. EXPECT_EQ(final->start(), reinterpret_cast<void*>(basePage * pageSize()));
  392. free(final);
  393. }
  394. void testBestFit(size_t firstSize, size_t step, unsigned numSlots, SanityCheckMode sanityCheckMode)
  395. {
  396. Vector<MetaAllocatorHandle*, 0> handlesToFree;
  397. Vector<MetaAllocatorHandle*, 0> handles;
  398. Vector<void*, 0> locations;
  399. size_t size = firstSize;
  400. for (unsigned index = 0; index < numSlots; ++index) {
  401. MetaAllocatorHandle* toFree = allocate(size, sanityCheckMode);
  402. if (!handles.isEmpty()) {
  403. while (toFree->start() != handles.last()->end()) {
  404. handlesToFree.append(toFree);
  405. toFree = allocate(size, sanityCheckMode);
  406. }
  407. }
  408. MetaAllocatorHandle* fragger = allocate(32, sanityCheckMode);
  409. EXPECT_EQ(fragger->start(), toFree->end());
  410. locations.append(toFree->start());
  411. handlesToFree.append(toFree);
  412. handles.append(fragger);
  413. size += step;
  414. }
  415. ASSERT(locations.size() == numSlots);
  416. for (unsigned index = 0; index < handlesToFree.size(); ++index)
  417. free(handlesToFree.at(index), sanityCheckMode);
  418. size = firstSize;
  419. for (unsigned index = 0; index < numSlots; ++index) {
  420. MetaAllocatorHandle* bestFit = allocate(size - 32, sanityCheckMode);
  421. EXPECT_TRUE(bestFit->start() == locations.at(index)
  422. || bestFit->end() == reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(locations.at(index)) + size));
  423. MetaAllocatorHandle* small = allocate(32, sanityCheckMode);
  424. if (bestFit->start() == locations.at(index))
  425. EXPECT_EQ(small->start(), bestFit->end());
  426. else
  427. EXPECT_EQ(small->end(), bestFit->start());
  428. free(bestFit, sanityCheckMode);
  429. free(small, sanityCheckMode);
  430. size += step;
  431. }
  432. for (unsigned index = 0; index < numSlots; ++index)
  433. free(handles.at(index), sanityCheckMode);
  434. MetaAllocatorHandle* final = allocate(defaultPagesInHeap * pageSize(), sanityCheckMode);
  435. EXPECT_EQ(final->start(), reinterpret_cast<void*>(basePage * pageSize()));
  436. free(final, sanityCheckMode);
  437. }
  438. void testShrink(size_t firstSize, size_t secondSize)
  439. {
  440. // Allocate the thing that will be shrunk
  441. MetaAllocatorHandle* handle = allocate(firstSize);
  442. // Shrink it, and make sure that our state reflects the shrinkage.
  443. notifyFree(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(handle->start()) + secondSize), firstSize - secondSize);
  444. handle->shrink(secondSize);
  445. EXPECT_EQ(handle->sizeInBytes(), secondSize);
  446. sanityCheck();
  447. // Assert that the heap is not empty.
  448. EXPECT_TRUE(!allocator->allocate(defaultPagesInHeap * pageSize(), 0));
  449. // Allocate the remainder of the heap.
  450. MetaAllocatorHandle* remainder = allocate(defaultPagesInHeap * pageSize() - secondSize);
  451. EXPECT_EQ(remainder->start(), handle->end());
  452. free(remainder);
  453. free(handle);
  454. // Assert that the heap is empty and finish up.
  455. MetaAllocatorHandle* final = allocate(defaultPagesInHeap * pageSize());
  456. EXPECT_EQ(final->start(), reinterpret_cast<void*>(basePage * pageSize()));
  457. free(final);
  458. }
  459. void testDemandAllocCoalesce(size_t firstSize, size_t numPages, size_t secondSize)
  460. {
  461. EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize(), 0));
  462. MetaAllocatorHandle* firstHandle = allocate(firstSize);
  463. EXPECT_TRUE(!allocator->allocate(secondSize, 0));
  464. EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize(), 0));
  465. currentHeapGrowthMode = ForTestDemandAllocCoalesce;
  466. allowAllocatePages = numPages;
  467. MetaAllocatorHandle* secondHandle = allocate(secondSize);
  468. EXPECT_TRUE(currentHeapGrowthMode == DontGrowHeap);
  469. EXPECT_EQ(allowAllocatePages, static_cast<size_t>(0));
  470. EXPECT_EQ(requestedNumPages, (secondSize + pageSize() - 1) / pageSize());
  471. EXPECT_EQ(secondHandle->start(), reinterpret_cast<void*>((basePage + defaultPagesInHeap) * pageSize()));
  472. requestedNumPages = 0;
  473. free(firstHandle);
  474. free(secondHandle);
  475. free(allocate((defaultPagesInHeap + numPages) * pageSize()));
  476. }
  477. void testDemandAllocDontCoalesce(size_t firstSize, size_t numPages, size_t secondSize)
  478. {
  479. free(allocate(firstSize));
  480. free(allocate(defaultPagesInHeap * pageSize()));
  481. EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize(), 0));
  482. MetaAllocatorHandle* firstHandle = allocate(firstSize);
  483. EXPECT_TRUE(!allocator->allocate(secondSize, 0));
  484. EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize(), 0));
  485. currentHeapGrowthMode = ForTestDemandAllocDontCoalesce;
  486. allowAllocatePages = numPages;
  487. MetaAllocatorHandle* secondHandle = allocate(secondSize);
  488. EXPECT_TRUE(currentHeapGrowthMode == DontGrowHeap);
  489. EXPECT_EQ(allowAllocatePages, static_cast<size_t>(0));
  490. EXPECT_EQ(requestedNumPages, (secondSize + pageSize() - 1) / pageSize());
  491. EXPECT_EQ(secondHandle->start(), reinterpret_cast<void*>((basePage + defaultPagesInHeap + 1) * pageSize()));
  492. requestedNumPages = 0;
  493. EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize(), 0));
  494. free(firstHandle);
  495. free(secondHandle);
  496. EXPECT_TRUE(!allocator->allocate((defaultPagesInHeap + numPages) * pageSize(), 0));
  497. firstHandle = allocate(firstSize);
  498. secondHandle = allocate(secondSize);
  499. EXPECT_EQ(firstHandle->start(), reinterpret_cast<void*>(basePage * pageSize()));
  500. EXPECT_EQ(secondHandle->start(), reinterpret_cast<void*>((basePage + defaultPagesInHeap + 1) * pageSize()));
  501. free(firstHandle);
  502. free(secondHandle);
  503. }
  504. };
  505. TEST_F(MetaAllocatorTest, Empty)
  506. {
  507. // Tests that creating and destroying an allocator works.
  508. }
  509. TEST_F(MetaAllocatorTest, AllocZero)
  510. {
  511. // Tests that allocating a zero-length block returns 0 and
  512. // does not change anything in memory.
  513. ASSERT(!allocator->allocate(0, 0));
  514. MetaAllocatorHandle* final = allocate(defaultPagesInHeap * pageSize());
  515. EXPECT_EQ(final->start(), reinterpret_cast<void*>(basePage * pageSize()));
  516. free(final);
  517. }
  518. TEST_F(MetaAllocatorTest, OneAlloc32)
  519. {
  520. testOneAlloc(32);
  521. }
  522. TEST_F(MetaAllocatorTest, OneAlloc64)
  523. {
  524. testOneAlloc(64);
  525. }
  526. TEST_F(MetaAllocatorTest, OneAllocTwoPages)
  527. {
  528. testOneAlloc(pageSize() * 2);
  529. }
  530. TEST_F(MetaAllocatorTest, RepeatAllocFree32Twice)
  531. {
  532. testRepeatAllocFree(32, 32, 0);
  533. }
  534. TEST_F(MetaAllocatorTest, RepeatAllocFree32Then64)
  535. {
  536. testRepeatAllocFree(32, 64, 0);
  537. }
  538. TEST_F(MetaAllocatorTest, RepeatAllocFree64Then32)
  539. {
  540. testRepeatAllocFree(64, 32, 0);
  541. }
  542. TEST_F(MetaAllocatorTest, RepeatAllocFree32TwiceThen64)
  543. {
  544. testRepeatAllocFree(32, 32, 64, 0);
  545. }
  546. TEST_F(MetaAllocatorTest, RepeatAllocFree32Then64Twice)
  547. {
  548. testRepeatAllocFree(32, 64, 64, 0);
  549. }
  550. TEST_F(MetaAllocatorTest, RepeatAllocFree64Then32Then64)
  551. {
  552. testRepeatAllocFree(64, 32, 64, 0);
  553. }
  554. TEST_F(MetaAllocatorTest, RepeatAllocFree32Thrice)
  555. {
  556. testRepeatAllocFree(32, 32, 32, 0);
  557. }
  558. TEST_F(MetaAllocatorTest, RepeatAllocFree32Then64Then32)
  559. {
  560. testRepeatAllocFree(32, 32, 32, 0);
  561. }
  562. TEST_F(MetaAllocatorTest, RepeatAllocFree64Then32Twice)
  563. {
  564. testRepeatAllocFree(64, 32, 32, 0);
  565. }
  566. TEST_F(MetaAllocatorTest, RepeatAllocFreeTwoPagesThen32)
  567. {
  568. testRepeatAllocFree(static_cast<int>(pageSize() * 2), 32, 0);
  569. }
  570. TEST_F(MetaAllocatorTest, RepeatAllocFree32ThenTwoPages)
  571. {
  572. testRepeatAllocFree(32, static_cast<int>(pageSize() * 2), 0);
  573. }
  574. TEST_F(MetaAllocatorTest, RepeatAllocFreePageThenTwoPages)
  575. {
  576. testRepeatAllocFree(static_cast<int>(pageSize()), static_cast<int>(pageSize() * 2), 0);
  577. }
  578. TEST_F(MetaAllocatorTest, RepeatAllocFreeTwoPagesThenPage)
  579. {
  580. testRepeatAllocFree(static_cast<int>(pageSize() * 2), static_cast<int>(pageSize()), 0);
  581. }
  582. TEST_F(MetaAllocatorTest, SimpleFullCoalesce32Plus32Then128)
  583. {
  584. testSimpleFullCoalesce(32, 32, 128);
  585. }
  586. TEST_F(MetaAllocatorTest, SimpleFullCoalesce32Plus64Then128)
  587. {
  588. testSimpleFullCoalesce(32, 64, 128);
  589. }
  590. TEST_F(MetaAllocatorTest, SimpleFullCoalesce64Plus32Then128)
  591. {
  592. testSimpleFullCoalesce(64, 32, 128);
  593. }
  594. TEST_F(MetaAllocatorTest, SimpleFullCoalesce32PlusPageLess32ThenPage)
  595. {
  596. testSimpleFullCoalesce(32, pageSize() - 32, pageSize());
  597. }
  598. TEST_F(MetaAllocatorTest, SimpleFullCoalesce32PlusPageLess32ThenTwoPages)
  599. {
  600. testSimpleFullCoalesce(32, pageSize() - 32, pageSize() * 2);
  601. }
  602. TEST_F(MetaAllocatorTest, SimpleFullCoalescePagePlus32ThenTwoPages)
  603. {
  604. testSimpleFullCoalesce(pageSize(), 32, pageSize() * 2);
  605. }
  606. TEST_F(MetaAllocatorTest, SimpleFullCoalescePagePlusPageThenTwoPages)
  607. {
  608. testSimpleFullCoalesce(pageSize(), pageSize(), pageSize() * 2);
  609. }
  610. TEST_F(MetaAllocatorTest, FIFOAllocFillAtEnd32Twice)
  611. {
  612. testFIFOAlloc(FillAtEnd, 32, 32, 0);
  613. }
  614. TEST_F(MetaAllocatorTest, FIFOAllocFillAtEnd32Thrice)
  615. {
  616. testFIFOAlloc(FillAtEnd, 32, 32, 32, 0);
  617. }
  618. TEST_F(MetaAllocatorTest, FIFOAllocFillAtEnd32FourTimes)
  619. {
  620. testFIFOAlloc(FillAtEnd, 32, 32, 32, 32, 0);
  621. }
  622. TEST_F(MetaAllocatorTest, FIFOAllocFillAtEndPageLess32Then32ThenPageLess64Then64)
  623. {
  624. testFIFOAlloc(FillAtEnd, static_cast<int>(pageSize() - 32), 32, static_cast<int>(pageSize() - 64), 64, 0);
  625. }
  626. TEST_F(MetaAllocatorTest, FIFOAllocEagerFill32Twice)
  627. {
  628. testFIFOAlloc(EagerFill, 32, 32, 0);
  629. }
  630. TEST_F(MetaAllocatorTest, FIFOAllocEagerFill32Thrice)
  631. {
  632. testFIFOAlloc(EagerFill, 32, 32, 32, 0);
  633. }
  634. TEST_F(MetaAllocatorTest, FIFOAllocEagerFill32FourTimes)
  635. {
  636. testFIFOAlloc(EagerFill, 32, 32, 32, 32, 0);
  637. }
  638. TEST_F(MetaAllocatorTest, FIFOAllocEagerFillPageLess32Then32ThenPageLess64Then64)
  639. {
  640. testFIFOAlloc(EagerFill, static_cast<int>(pageSize() - 32), 32, static_cast<int>(pageSize() - 64), 64, 0);
  641. }
  642. TEST_F(MetaAllocatorTest, FillHeap32)
  643. {
  644. testFillHeap(32, defaultPagesInHeap * pageSize() / 32);
  645. }
  646. TEST_F(MetaAllocatorTest, FillHeapPage)
  647. {
  648. testFillHeap(pageSize(), defaultPagesInHeap);
  649. }
  650. TEST_F(MetaAllocatorTest, FillHeapTwoPages)
  651. {
  652. testFillHeap(pageSize() * 2, defaultPagesInHeap / 2);
  653. }
  654. TEST_F(MetaAllocatorTest, RightAllocation32ThenPageThen32ThenPage)
  655. {
  656. testRightAllocation(32, pageSize(), 32, pageSize());
  657. }
  658. TEST_F(MetaAllocatorTest, RightAllocationQuarterPageThenPageThenQuarterPageThenPage)
  659. {
  660. testRightAllocation(pageSize() / 4, pageSize(), pageSize() / 4, pageSize());
  661. }
  662. TEST_F(MetaAllocatorTest, BestFit64Plus64Thrice)
  663. {
  664. testBestFit(64, 64, 3, RunSanityCheck);
  665. }
  666. TEST_F(MetaAllocatorTest, BestFit64Plus64TenTimes)
  667. {
  668. testBestFit(64, 64, 10, DontRunSanityCheck);
  669. }
  670. TEST_F(MetaAllocatorTest, BestFit64Plus64HundredTimes)
  671. {
  672. testBestFit(64, 64, 100, DontRunSanityCheck);
  673. }
  674. TEST_F(MetaAllocatorTest, BestFit96Plus64Thrice)
  675. {
  676. testBestFit(96, 64, 3, RunSanityCheck);
  677. }
  678. TEST_F(MetaAllocatorTest, BestFit96Plus64TenTimes)
  679. {
  680. testBestFit(96, 64, 10, DontRunSanityCheck);
  681. }
  682. TEST_F(MetaAllocatorTest, BestFit96Plus64HundredTimes)
  683. {
  684. testBestFit(96, 64, 100, DontRunSanityCheck);
  685. }
  686. TEST_F(MetaAllocatorTest, BestFit96Plus96Thrice)
  687. {
  688. testBestFit(96, 96, 3, RunSanityCheck);
  689. }
  690. TEST_F(MetaAllocatorTest, BestFit96Plus96TenTimes)
  691. {
  692. testBestFit(96, 96, 10, DontRunSanityCheck);
  693. }
  694. TEST_F(MetaAllocatorTest, BestFit96Plus96EightyTimes)
  695. {
  696. testBestFit(96, 96, 80, DontRunSanityCheck);
  697. }
  698. TEST_F(MetaAllocatorTest, Shrink64To32)
  699. {
  700. testShrink(64, 32);
  701. }
  702. TEST_F(MetaAllocatorTest, ShrinkPageTo32)
  703. {
  704. testShrink(pageSize(), 32);
  705. }
  706. TEST_F(MetaAllocatorTest, ShrinkPageToPageLess32)
  707. {
  708. testShrink(pageSize(), pageSize() - 32);
  709. }
  710. TEST_F(MetaAllocatorTest, ShrinkTwoPagesTo32)
  711. {
  712. testShrink(pageSize() * 2, 32);
  713. }
  714. TEST_F(MetaAllocatorTest, ShrinkTwoPagesToPagePlus32)
  715. {
  716. testShrink(pageSize() * 2, pageSize() + 32);
  717. }
  718. TEST_F(MetaAllocatorTest, ShrinkTwoPagesToPage)
  719. {
  720. testShrink(pageSize() * 2, pageSize());
  721. }
  722. TEST_F(MetaAllocatorTest, ShrinkTwoPagesToPageLess32)
  723. {
  724. testShrink(pageSize() * 2, pageSize() - 32);
  725. }
  726. TEST_F(MetaAllocatorTest, ShrinkTwoPagesToTwoPagesLess32)
  727. {
  728. testShrink(pageSize() * 2, pageSize() * 2 - 32);
  729. }
  730. TEST_F(MetaAllocatorTest, DemandAllocCoalescePageThenDoubleHeap)
  731. {
  732. testDemandAllocCoalesce(pageSize(), defaultPagesInHeap, defaultPagesInHeap * pageSize());
  733. }
  734. TEST_F(MetaAllocatorTest, DemandAllocCoalescePageThenTripleHeap)
  735. {
  736. testDemandAllocCoalesce(pageSize(), defaultPagesInHeap * 2, defaultPagesInHeap * pageSize());
  737. }
  738. TEST_F(MetaAllocatorTest, DemandAllocDontCoalescePageThenDoubleHeap)
  739. {
  740. testDemandAllocDontCoalesce(pageSize(), defaultPagesInHeap, defaultPagesInHeap * pageSize());
  741. }
  742. } // namespace TestWebKitAPI