blob: 2ceadaacb99b341238b7b2a81962c592fd90bc92 [file] [log] [blame]
fpizlo@apple.comb426f862014-02-10 02:51:13 +00001/*
fpizlo@apple.comaeddff92016-07-18 21:33:45 +00002 * Copyright (C) 2012, 2013, 2016 Apple Inc. All rights reserved.
fpizlo@apple.comb426f862014-02-10 02:51:13 +00003 *
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 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +000026#include "config.h"
27#include "MarkedAllocator.h"
28
fpizlo@apple.comea379af2016-10-21 02:17:35 +000029#include "AllocatingScope.h"
mhahnenberg@apple.com2b64eec02012-04-18 16:18:32 +000030#include "GCActivityCallback.h"
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +000031#include "Heap.h"
mhahnenberg@apple.com59c64f12012-07-31 23:05:12 +000032#include "IncrementalSweeper.h"
fpizlo@apple.comfb7eff22014-02-11 01:45:50 +000033#include "JSCInlines.h"
fpizlo@apple.com96352992016-09-20 18:12:18 +000034#include "MarkedBlockInlines.h"
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000035#include "SuperSampler.h"
ggaren@apple.com9a9a4b52013-04-18 19:32:17 +000036#include "VM.h"
mhahnenberg@apple.com2e132e42012-05-03 00:14:05 +000037#include <wtf/CurrentTime.h>
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +000038
39namespace JSC {
40
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000041MarkedAllocator::MarkedAllocator(Heap* heap, MarkedSpace* markedSpace, size_t cellSize, const AllocatorAttributes& attributes)
42 : m_currentBlock(0)
43 , m_lastActiveBlock(0)
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000044 , m_cellSize(static_cast<unsigned>(cellSize))
45 , m_attributes(attributes)
46 , m_heap(heap)
47 , m_markedSpace(markedSpace)
48{
49}
50
51bool MarkedAllocator::isPagedOut(double deadline)
mhahnenberg@apple.com2e132e42012-05-03 00:14:05 +000052{
53 unsigned itersSinceLastTimeCheck = 0;
fpizlo@apple.com96352992016-09-20 18:12:18 +000054 for (size_t index = 0; index < m_blocks.size(); ++index) {
55 MarkedBlock::Handle* block = m_blocks[index];
fpizlo@apple.com7b231642016-10-11 23:52:02 +000056 if (block)
57 block->block().updateNeedsDestruction();
mhahnenberg@apple.com2e132e42012-05-03 00:14:05 +000058 ++itersSinceLastTimeCheck;
59 if (itersSinceLastTimeCheck >= Heap::s_timeCheckResolution) {
60 double currentTime = WTF::monotonicallyIncreasingTime();
61 if (currentTime > deadline)
62 return true;
63 itersSinceLastTimeCheck = 0;
64 }
65 }
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +000066 return false;
67}
mhahnenberg@apple.com2e132e42012-05-03 00:14:05 +000068
fpizlo@apple.com96352992016-09-20 18:12:18 +000069bool MarkedAllocator::shouldStealEmptyBlocksFromOtherAllocators() const
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +000070{
fpizlo@apple.com96352992016-09-20 18:12:18 +000071 return !needsDestruction();
ggaren@apple.com7535d922016-06-21 23:06:08 +000072}
73
fpizlo@apple.com96352992016-09-20 18:12:18 +000074MarkedBlock::Handle* MarkedAllocator::findEmptyBlockToSteal()
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +000075{
fpizlo@apple.com96352992016-09-20 18:12:18 +000076 // Don't allow others to steal from us, if we wouldn't steal from others.
77 if (!shouldStealEmptyBlocksFromOtherAllocators())
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000078 return nullptr;
fpizlo@apple.com96352992016-09-20 18:12:18 +000079
80 m_emptyCursor = m_empty.findBit(m_emptyCursor, true);
81 if (m_emptyCursor >= m_blocks.size())
82 return nullptr;
83 return m_blocks[m_emptyCursor];
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000084}
85
fpizlo@apple.com96352992016-09-20 18:12:18 +000086void MarkedAllocator::didConsumeFreeList()
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000087{
fpizlo@apple.com96352992016-09-20 18:12:18 +000088 if (m_currentBlock)
89 m_currentBlock->didConsumeFreeList();
90
91 setFreeList(FreeList());
92 m_currentBlock = nullptr;
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000093}
94
fpizlo@apple.com96352992016-09-20 18:12:18 +000095void* MarkedAllocator::tryAllocateWithoutCollecting()
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +000096{
97 SuperSamplerScope superSamplerScope(false);
98
fpizlo@apple.com96352992016-09-20 18:12:18 +000099 ASSERT(!m_currentBlock);
100 ASSERT(!m_freeList);
101
102 for (;;) {
103 m_allocationCursor = (m_canAllocateButNotEmpty | m_empty).findBit(m_allocationCursor, true);
104 if (m_allocationCursor >= m_blocks.size())
105 break;
106
107 setIsCanAllocateButNotEmpty(m_allocationCursor, false);
108
109 if (void* result = tryAllocateIn(m_blocks[m_allocationCursor]))
110 return result;
msaboff@apple.com84946d42015-02-06 01:12:00 +0000111 }
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000112
fpizlo@apple.com96352992016-09-20 18:12:18 +0000113 if (Options::stealEmptyBlocksFromOtherAllocators()
114 && shouldStealEmptyBlocksFromOtherAllocators()) {
115 if (MarkedBlock::Handle* block = m_markedSpace->findEmptyBlockToSteal()) {
116 block->sweep();
117
118 // It's good that this clears canAllocateButNotEmpty as well as all other bits,
119 // because there is a remote chance that a block may have both canAllocateButNotEmpty
120 // and empty set at the same time.
121 block->removeFromAllocator();
122 addBlock(block);
123 return allocateIn(block);
msaboff@apple.com84946d42015-02-06 01:12:00 +0000124 }
msaboff@apple.com84946d42015-02-06 01:12:00 +0000125 }
126
fpizlo@apple.com96352992016-09-20 18:12:18 +0000127 return nullptr;
128}
mhahnenberg@apple.com3f62e722013-12-19 04:30:02 +0000129
fpizlo@apple.com96352992016-09-20 18:12:18 +0000130void* MarkedAllocator::allocateIn(MarkedBlock::Handle* block)
131{
132 void* result = tryAllocateIn(block);
133 RELEASE_ASSERT(result);
134 return result;
135}
136
137void* MarkedAllocator::tryAllocateIn(MarkedBlock::Handle* block)
138{
139 ASSERT(block);
140 ASSERT(!block->hasAnyNewlyAllocated());
141 ASSERT(!block->isFreeListed());
142
143 FreeList freeList = block->sweep(MarkedBlock::Handle::SweepToFreeList);
144
145 // It's possible to stumble on a completely full block. Marking tries to retire these, but
146 // that algorithm is racy and may forget to do it sometimes.
147 if (freeList.allocationWillFail()) {
148 ASSERT(block->isFreeListed());
149 block->unsweepWithNoNewlyAllocated();
150 ASSERT(!block->isFreeListed());
151 ASSERT(!isEmpty(block));
152 ASSERT(!isCanAllocateButNotEmpty(block));
153 return nullptr;
154 }
155
156 m_currentBlock = block;
157 setFreeList(freeList);
158
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000159 void* result;
160 if (m_freeList.remaining) {
161 unsigned cellSize = m_cellSize;
162 m_freeList.remaining -= cellSize;
163 result = m_freeList.payloadEnd - m_freeList.remaining - cellSize;
164 } else {
165 FreeCell* head = m_freeList.head;
166 m_freeList.head = head->next;
167 result = head;
168 }
169 RELEASE_ASSERT(result);
fpizlo@apple.com96352992016-09-20 18:12:18 +0000170 setIsEden(m_currentBlock, true);
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +0000171 m_markedSpace->didAllocateInBlock(m_currentBlock);
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000172 return result;
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +0000173}
mhahnenberg@apple.comfa811df2014-02-13 04:24:41 +0000174
fpizlo@apple.com9a175952016-09-28 21:55:53 +0000175ALWAYS_INLINE void MarkedAllocator::doTestCollectionsIfNeeded(GCDeferralContext* deferralContext)
mark.lam@apple.coma2a9f662014-04-24 21:12:56 +0000176{
177 if (!Options::slowPathAllocsBetweenGCs())
178 return;
179
180 static unsigned allocationCount = 0;
181 if (!allocationCount) {
fpizlo@apple.com9a175952016-09-28 21:55:53 +0000182 if (!m_heap->isDeferred()) {
183 if (deferralContext)
184 deferralContext->m_shouldGC = true;
185 else
186 m_heap->collectAllGarbage();
187 }
mark.lam@apple.coma2a9f662014-04-24 21:12:56 +0000188 }
189 if (++allocationCount >= Options::slowPathAllocsBetweenGCs())
190 allocationCount = 0;
191}
192
fpizlo@apple.com9a175952016-09-28 21:55:53 +0000193void* MarkedAllocator::allocateSlowCase(GCDeferralContext* deferralContext)
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +0000194{
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000195 bool crashOnFailure = true;
fpizlo@apple.com9a175952016-09-28 21:55:53 +0000196 return allocateSlowCaseImpl(deferralContext, crashOnFailure);
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000197}
198
fpizlo@apple.com9a175952016-09-28 21:55:53 +0000199void* MarkedAllocator::tryAllocateSlowCase(GCDeferralContext* deferralContext)
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000200{
201 bool crashOnFailure = false;
fpizlo@apple.com9a175952016-09-28 21:55:53 +0000202 return allocateSlowCaseImpl(deferralContext, crashOnFailure);
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000203}
204
fpizlo@apple.com9a175952016-09-28 21:55:53 +0000205void* MarkedAllocator::allocateSlowCaseImpl(GCDeferralContext* deferralContext, bool crashOnFailure)
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000206{
207 SuperSamplerScope superSamplerScope(false);
andersca@apple.comb987aae2013-07-26 00:13:13 +0000208 ASSERT(m_heap->vm()->currentThreadIsHoldingAPILock());
fpizlo@apple.com9a175952016-09-28 21:55:53 +0000209 doTestCollectionsIfNeeded(deferralContext);
mark.lam@apple.coma2a9f662014-04-24 21:12:56 +0000210
mhahnenberg@apple.combee96a32013-09-16 19:48:48 +0000211 ASSERT(!m_markedSpace->isIterating());
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000212 m_heap->didAllocate(m_freeList.originalSize);
mhahnenberg@apple.com2b64eec02012-04-18 16:18:32 +0000213
fpizlo@apple.com96352992016-09-20 18:12:18 +0000214 didConsumeFreeList();
215
fpizlo@apple.comea379af2016-10-21 02:17:35 +0000216 AllocatingScope healpingHeap(*m_heap);
217
fpizlo@apple.com9a175952016-09-28 21:55:53 +0000218 m_heap->collectIfNecessaryOrDefer(deferralContext);
fpizlo@apple.com96352992016-09-20 18:12:18 +0000219
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000220 void* result = tryAllocateWithoutCollecting();
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +0000221
222 if (LIKELY(result != 0))
223 return result;
224
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000225 MarkedBlock::Handle* block = tryAllocateBlock();
226 if (!block) {
227 if (crashOnFailure)
228 RELEASE_ASSERT_NOT_REACHED();
229 else
230 return nullptr;
231 }
mhahnenberg@apple.com3e7e4e02012-05-09 02:44:39 +0000232 addBlock(block);
fpizlo@apple.com96352992016-09-20 18:12:18 +0000233 result = allocateIn(block);
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +0000234 ASSERT(result);
235 return result;
236}
ggaren@apple.coma68a6502012-05-22 23:59:51 +0000237
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000238static size_t blockHeaderSize()
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +0000239{
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000240 return WTF::roundUpToMultipleOf<MarkedBlock::atomSize>(sizeof(MarkedBlock));
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +0000241}
242
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000243size_t MarkedAllocator::blockSizeForBytes(size_t bytes)
244{
245 size_t minBlockSize = MarkedBlock::blockSize;
246 size_t minAllocationSize = blockHeaderSize() + WTF::roundUpToMultipleOf<MarkedBlock::atomSize>(bytes);
247 minAllocationSize = WTF::roundUpToMultipleOf(WTF::pageSize(), minAllocationSize);
248 return std::max(minBlockSize, minAllocationSize);
249}
250
251MarkedBlock::Handle* MarkedAllocator::tryAllocateBlock()
252{
253 SuperSamplerScope superSamplerScope(false);
fpizlo@apple.com96352992016-09-20 18:12:18 +0000254
255 MarkedBlock::Handle* handle = MarkedBlock::tryCreate(*m_heap);
256 if (!handle)
257 return nullptr;
258
259 m_markedSpace->didAddBlock(handle);
260
261 return handle;
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000262}
263
264void MarkedAllocator::addBlock(MarkedBlock::Handle* block)
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +0000265{
fpizlo@apple.com96352992016-09-20 18:12:18 +0000266 size_t index;
267 if (m_freeBlockIndices.isEmpty()) {
268 index = m_blocks.size();
269
270 size_t oldCapacity = m_blocks.capacity();
271 m_blocks.append(block);
272 if (m_blocks.capacity() != oldCapacity) {
273 forEachBitVector(
274 [&] (FastBitVector& vector) {
275 ASSERT_UNUSED(vector, vector.numBits() == oldCapacity);
276 });
277
278 ASSERT(m_blocks.capacity() > oldCapacity);
279
280 forEachBitVector(
281 [&] (FastBitVector& vector) {
282 vector.resize(m_blocks.capacity());
283 });
284 }
285 } else {
286 index = m_freeBlockIndices.takeLast();
287 ASSERT(!m_blocks[index]);
288 m_blocks[index] = block;
289 }
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +0000290
fpizlo@apple.com96352992016-09-20 18:12:18 +0000291 forEachBitVector(
292 [&] (FastBitVector& vector) {
293 ASSERT_UNUSED(vector, !vector[index]);
294 });
295
296 // This is the point at which the block learns of its cellSize() and attributes().
297 block->didAddToAllocator(this, index);
298
299 setIsLive(index, true);
300 setIsEmpty(index, true);
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +0000301}
302
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000303void MarkedAllocator::removeBlock(MarkedBlock::Handle* block)
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +0000304{
fpizlo@apple.com96352992016-09-20 18:12:18 +0000305 ASSERT(block->allocator() == this);
306 ASSERT(m_blocks[block->index()] == block);
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +0000307
fpizlo@apple.com96352992016-09-20 18:12:18 +0000308 m_blocks[block->index()] = nullptr;
309 m_freeBlockIndices.append(block->index());
310
311 forEachBitVector(
312 [&] (FastBitVector& vector) {
313 vector[block->index()] = false;
314 });
315
316 block->didRemoveFromAllocator();
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +0000317}
318
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000319void MarkedAllocator::stopAllocating()
320{
fpizlo@apple.com96352992016-09-20 18:12:18 +0000321 if (false)
322 dataLog(RawPointer(this), ": MarkedAllocator::stopAllocating!\n");
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000323 ASSERT(!m_lastActiveBlock);
324 if (!m_currentBlock) {
325 ASSERT(!m_freeList);
326 return;
327 }
328
329 m_currentBlock->stopAllocating(m_freeList);
330 m_lastActiveBlock = m_currentBlock;
331 m_currentBlock = 0;
332 m_freeList = FreeList();
333}
334
fpizlo@apple.com96352992016-09-20 18:12:18 +0000335void MarkedAllocator::prepareForAllocation()
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +0000336{
fpizlo@apple.com96352992016-09-20 18:12:18 +0000337 m_lastActiveBlock = nullptr;
338 m_currentBlock = nullptr;
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000339 setFreeList(FreeList());
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +0000340
fpizlo@apple.com96352992016-09-20 18:12:18 +0000341 m_allocationCursor = 0;
342 m_emptyCursor = 0;
343 m_unsweptCursor = 0;
344
345 m_eden.clearAll();
ggaren@apple.com7535d922016-06-21 23:06:08 +0000346
347 if (UNLIKELY(Options::useImmortalObjects())) {
fpizlo@apple.com96352992016-09-20 18:12:18 +0000348 // FIXME: Make this work again.
349 // https://bugs.webkit.org/show_bug.cgi?id=162296
350 RELEASE_ASSERT_NOT_REACHED();
ggaren@apple.com7535d922016-06-21 23:06:08 +0000351 }
mhahnenberg@apple.com3ddd7ac2014-01-10 02:28:27 +0000352}
353
mhahnenberg@apple.com96b8cd12014-03-12 18:17:43 +0000354void MarkedAllocator::lastChanceToFinalize()
355{
fpizlo@apple.comaeddff92016-07-18 21:33:45 +0000356 forEachBlock(
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000357 [&] (MarkedBlock::Handle* block) {
fpizlo@apple.comaeddff92016-07-18 21:33:45 +0000358 block->lastChanceToFinalize();
359 });
mhahnenberg@apple.com96b8cd12014-03-12 18:17:43 +0000360}
361
fpizlo@apple.combc16ddb2016-09-06 01:02:22 +0000362void MarkedAllocator::setFreeList(const FreeList& freeList)
363{
364 m_freeList = freeList;
365}
366
fpizlo@apple.com96352992016-09-20 18:12:18 +0000367void MarkedAllocator::resumeAllocating()
368{
369 if (!m_lastActiveBlock)
370 return;
371
372 m_freeList = m_lastActiveBlock->resumeAllocating();
373 m_currentBlock = m_lastActiveBlock;
374 m_lastActiveBlock = nullptr;
375}
376
377void MarkedAllocator::beginMarkingForFullCollection()
378{
379 // Mark bits are sticky and so is our summary of mark bits. We only clear these during full
380 // collections, so if you survived the last collection you will survive the next one so long
381 // as the next one is eden.
382 m_markingNotEmpty.clearAll();
383 m_markingRetired.clearAll();
384}
385
386void MarkedAllocator::endMarking()
387{
388 m_allocated.clearAll();
389
390 // It's surprising and frustrating to comprehend, but the end-of-marking flip does not need to
391 // know what kind of collection it is. That knowledge is already encoded in the m_markingXYZ
392 // vectors.
393
394 if (needsDestruction()) {
395 // If blocks need destruction then nothing is empty! This is a correct assertion but may
396 // become wrong once we go full concurrent: when we create a new block, it will flicker
397 // into the empty set for a tiny moment. On the other hand, this code is likely to be run
398 // in stopTheWorld.
399 ASSERT(m_empty.isEmpty());
400 m_canAllocateButNotEmpty = m_live & ~m_markingRetired;
401 return;
402 }
403
404 m_empty = m_live & ~m_markingNotEmpty;
405 m_canAllocateButNotEmpty = m_live & m_markingNotEmpty & ~m_markingRetired;
406
407 if (false) {
408 dataLog("Bits for ", m_cellSize, ", ", m_attributes, " after endMarking:\n");
409 dumpBits(WTF::dataFile());
410 }
411}
412
413void MarkedAllocator::snapshotUnsweptForEdenCollection()
414{
415 m_unswept |= m_eden;
416}
417
418void MarkedAllocator::snapshotUnsweptForFullCollection()
419{
420 m_unswept = m_live;
421}
422
423MarkedBlock::Handle* MarkedAllocator::findBlockToSweep()
424{
425 m_unsweptCursor = m_unswept.findBit(m_unsweptCursor, true);
426 if (m_unsweptCursor >= m_blocks.size())
427 return nullptr;
428 return m_blocks[m_unsweptCursor];
429}
430
431void MarkedAllocator::sweep()
432{
433 m_unswept.forEachSetBit(
434 [&] (size_t index) {
fpizlo@apple.com7b231642016-10-11 23:52:02 +0000435 MarkedBlock::Handle* block = m_blocks[index];
436 block->sweep();
fpizlo@apple.com96352992016-09-20 18:12:18 +0000437 });
438}
439
440void MarkedAllocator::shrink()
441{
442 m_empty.forEachSetBit(
443 [&] (size_t index) {
444 m_markedSpace->freeBlock(m_blocks[index]);
445 });
446}
447
448void MarkedAllocator::assertNoUnswept()
449{
450 if (ASSERT_DISABLED)
451 return;
452
453 if (m_unswept.isEmpty())
454 return;
455
456 dataLog("Assertion failed: unswept not empty in ", *this, ".\n");
457 dumpBits();
458 ASSERT_NOT_REACHED();
459}
460
461void MarkedAllocator::dump(PrintStream& out) const
462{
463 out.print(RawPointer(this), ":", m_cellSize, "/", m_attributes);
464}
465
466void MarkedAllocator::dumpBits(PrintStream& out)
467{
468 unsigned maxNameLength = 0;
469 forEachBitVectorWithName(
470 [&] (FastBitVector&, const char* name) {
471 unsigned length = strlen(name);
472 maxNameLength = std::max(maxNameLength, length);
473 });
474
475 forEachBitVectorWithName(
476 [&] (FastBitVector& vector, const char* name) {
477 out.print(" ", name, ": ");
478 for (unsigned i = maxNameLength - strlen(name); i--;)
479 out.print(" ");
480 out.print(vector, "\n");
481 });
482}
483
mhahnenberg@apple.comce85b932012-02-03 19:27:57 +0000484} // namespace JSC
fpizlo@apple.com96352992016-09-20 18:12:18 +0000485