MarkedBlocks that are "full enough" shouldn't be swept after EdenCollections
https://bugs.webkit.org/show_bug.cgi?id=129920
Reviewed by Geoffrey Garen.
This patch introduces the notion of "retiring" MarkedBlocks. We retire a MarkedBlock
when the amount of free space in a MarkedBlock drops below a certain threshold.
Retired blocks are not considered for sweeping.
This is profitable because it reduces churn during sweeping. To build a free list,
we have to scan through each cell in a block. After a collection, all objects that
are live in the block will remain live until the next FullCollection, at which time
we un-retire all previously retired blocks. Thus, a small number of objects in a block
that die during each EdenCollection could cause us to do a disproportiante amount of
sweeping for how much free memory we get back.
This patch looks like a consistent ~2% progression on boyer and is neutral everywhere else.
* heap/Heap.h:
(JSC::Heap::didRetireBlockWithFreeListSize):
* heap/MarkedAllocator.cpp:
(JSC::MarkedAllocator::tryAllocateHelper):
(JSC::MarkedAllocator::removeBlock):
(JSC::MarkedAllocator::reset):
* heap/MarkedAllocator.h:
(JSC::MarkedAllocator::MarkedAllocator):
(JSC::MarkedAllocator::forEachBlock):
* heap/MarkedBlock.cpp:
(JSC::MarkedBlock::sweepHelper):
(JSC::MarkedBlock::clearMarksWithCollectionType):
(JSC::MarkedBlock::didRetireBlock):
* heap/MarkedBlock.h:
(JSC::MarkedBlock::willRemoveBlock):
(JSC::MarkedBlock::isLive):
* heap/MarkedSpace.cpp:
(JSC::MarkedSpace::clearNewlyAllocated):
(JSC::MarkedSpace::clearMarks):
* runtime/Options.h:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@165458 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/heap/MarkedAllocator.cpp b/Source/JavaScriptCore/heap/MarkedAllocator.cpp
index 1ed6add..c4f216b 100644
--- a/Source/JavaScriptCore/heap/MarkedAllocator.cpp
+++ b/Source/JavaScriptCore/heap/MarkedAllocator.cpp
@@ -79,12 +79,12 @@
MarkedBlock::FreeList freeList = block->sweep(MarkedBlock::SweepToFreeList);
- if (!freeList.head) {
- block->didConsumeEmptyFreeList();
+ double utilization = ((double)MarkedBlock::blockSize - (double)freeList.bytes) / (double)MarkedBlock::blockSize;
+ if (utilization >= Options::minMarkedBlockUtilization()) {
+ ASSERT(freeList.bytes || !freeList.head);
m_blockList.remove(block);
- m_blockList.push(block);
- if (!m_lastFullBlock)
- m_lastFullBlock = block;
+ m_retiredBlocks.push(block);
+ block->didRetireBlock(freeList);
continue;
}
@@ -211,9 +211,7 @@
if (m_nextBlockToSweep == block)
m_nextBlockToSweep = m_nextBlockToSweep->next();
- if (block == m_lastFullBlock)
- m_lastFullBlock = m_lastFullBlock->prev();
-
+ block->willRemoveBlock();
m_blockList.remove(block);
}
@@ -223,12 +221,9 @@
m_currentBlock = 0;
m_freeList = MarkedBlock::FreeList();
if (m_heap->operationInProgress() == FullCollection)
- m_lastFullBlock = 0;
+ m_blockList.append(m_retiredBlocks);
- if (m_lastFullBlock)
- m_nextBlockToSweep = m_lastFullBlock->next() ? m_lastFullBlock->next() : m_lastFullBlock;
- else
- m_nextBlockToSweep = m_blockList.head();
+ m_nextBlockToSweep = m_blockList.head();
}
} // namespace JSC