Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: 7f5ab158824beeb9a5da5dd8b80086b23bbe5186
https://github.com/WebKit/WebKit/commit/7f5ab158824beeb9a5da5dd8b80086b23bbe5186
Author: Yusuke Suzuki <[email protected]>
Date: 2026-09-17 (Thu, 17 Sep 2026)
Changed paths:
A JSTests/stress/weak-block-recycling.js
M JSTests/stress/weakblock-trigger-gc.js
M Source/JavaScriptCore/heap/BlockDirectory.cpp
M Source/JavaScriptCore/heap/Heap.cpp
M Source/JavaScriptCore/heap/Heap.h
M Source/JavaScriptCore/heap/IncrementalSweeper.cpp
M Source/JavaScriptCore/heap/LocalAllocator.cpp
M Source/JavaScriptCore/heap/MarkedBlock.h
M Source/JavaScriptCore/heap/MarkedSpaceInlines.h
M Source/JavaScriptCore/heap/WeakBlock.cpp
M Source/JavaScriptCore/heap/WeakBlock.h
M Source/JavaScriptCore/heap/WeakImpl.h
M Source/JavaScriptCore/heap/WeakInlinesLight.h
M Source/JavaScriptCore/heap/WeakSet.cpp
M Source/JavaScriptCore/heap/WeakSet.h
M Source/JavaScriptCore/heap/WeakSetInlines.h
M Source/JavaScriptCore/runtime/OptionsList.h
M Source/JavaScriptCore/tools/Integrity.cpp
M Source/JavaScriptCore/tools/JSDollarVM.cpp
M Source/WTF/wtf/DebugHeap.h
M Source/WTF/wtf/FastMalloc.h
Log Message:
-----------
[JSC] Redesign WeakBlock
https://bugs.webkit.org/show_bug.cgi?id=324140
rdar://187358319
Reviewed by Keith Miller.
This patch redesigns WeakBlock implementation. Previously deallocation
of Weak<> just marking WeakImpl as Deallocated. This is not desiable
since we end up scanning WeakBlock repeatedly to detect it becomes empty.
WeakBlock with non-dead WeakImpls with all dead JSValues are called
logically-empty WeakBlocks. Heap is managing them, and each WeakBlock
allocation is having a piggy-backed job which scans logically-empty
WeakBlocks to detect whether it is empty now. But this touches
completely unrelated memory and super costly. And this is the reason why
we excluded MarkedBlock with WeakBlock from the block-stealing target.
But the mechanism should be dramatically simpler since WeakImpl
deallocation is synchronous and not GC-managed thing. Thus we can take
similar design to StrongBlock. WeakBlock should track # of Live, # of
Dead, # of allocated WeakImpls, and WeakImpl deallocation updates these
numbers. And when we reach to 0 allocation state, WeakBlock is empty. So
no longer need to have random logically-empty WeakBlock scanning.
Also, WeakSet should not pool empty WeakBlocks and instead Heap should pool
them. It does not make sense to have a pool of empty WeakBlocks for each
MarkedBlock. While partially released WeakBlock should be tied to this
MarkedBlock since all of WeakImpl's stored cells need to be tied to this
MarkedBlock, once it becomes completely empty, it is freely usable from
any MarkedBlocks.
One of the most carefully handled place is `WeakSet::sweep` function.
The reason is that this `sweep`'s finalize call can allocate and
deallocate WeakImpl, thus and now empty WeakBlock is synchronously
detected and destroyed while iterating WeakBlocks. We are marking the
currently iterated WeakBlock and defer empty / logically-empty chaining
of this WeakBlock. And after all sweep, we iterate again to detect the
newly empty / logically-empty blocks and chain them again.
These improvements allow us to always steal MarkedBlocks since now empty
MarkedBlocks never have WeakBlocks.
Test: JSTests/stress/weak-block-recycling.js
* JSTests/stress/weak-block-recycling.js: Added.
(churnOpaqueRoots):
(churnRegExps):
(churnArrayBuffers):
(churnSizeClasses):
* JSTests/stress/weakblock-trigger-gc.js:
(vm.gc.let.start.vm.totalGCTime): Deleted.
* Source/JavaScriptCore/heap/BlockDirectory.cpp:
(JSC::BlockDirectory::findEmptyBlockToSteal):
* Source/JavaScriptCore/heap/Heap.cpp:
(JSC::Heap::~Heap):
(JSC::Heap::lastChanceToFinalize):
(JSC::Heap::clearConcurrentRetainedDataIfPossible):
* Source/JavaScriptCore/heap/Heap.h:
(JSC::Heap::weakBlockCount const):
* Source/JavaScriptCore/heap/IncrementalSweeper.cpp:
(JSC::IncrementalSweeper::sweepNextBlock):
* Source/JavaScriptCore/heap/LocalAllocator.cpp:
(JSC::LocalAllocator::tryAllocateWithoutCollecting):
* Source/JavaScriptCore/heap/MarkedBlock.h:
* Source/JavaScriptCore/heap/MarkedSpaceInlines.h:
(JSC::MarkedSpace::forEachWeakInParallel):
* Source/JavaScriptCore/heap/WeakBlock.cpp:
(JSC::WeakBlock::create):
(JSC::WeakBlock::destroy):
(JSC::WeakBlock::WeakBlock):
(JSC::WeakBlock::didBecomeEmpty):
(JSC::WeakBlock::lastChanceToFinalize):
(JSC::WeakBlock::sweep):
(JSC::WeakBlock::specializedVisit):
(JSC::WeakBlock::visitImpl):
(JSC::WeakBlock::reap):
* Source/JavaScriptCore/heap/WeakBlock.h:
(JSC::WeakBlock::IterationScope::IterationScope):
(JSC::WeakBlock::IterationScope::~IterationScope):
(JSC::WeakBlock::heap const):
(JSC::WeakBlock::isEmpty const):
(JSC::WeakBlock::hasLiveHandles const):
(JSC::WeakBlock::hasOnlyFinalizedHandles const):
(JSC::WeakBlock::hasFreeCell const):
(JSC::WeakBlock::asFreeCell):
(JSC::WeakBlock::blockContaining):
(JSC::WeakBlock::weakImplCount):
(JSC::WeakBlock::blockFor):
(JSC::WeakBlock::takeFreeCell):
(JSC::WeakBlock::pushFreeCell):
(JSC::WeakBlock::deallocate):
(JSC::WeakBlock::reattach):
(JSC::WeakBlock::setDetached):
(JSC::WeakBlock::setPooled):
(JSC::WeakBlock::assertFreeListIsConsistent):
(JSC::WeakImpl::clear):
(JSC::WeakBlock::disconnectContainer): Deleted.
(JSC::WeakBlock::SweepResult::isNull const): Deleted.
(JSC::WeakBlock::takeSweepResult): Deleted.
(JSC::WeakBlock::addToFreeList): Deleted.
(JSC::WeakBlock::isEmpty): Deleted.
(JSC::WeakBlock::isLogicallyEmptyButNotFree const): Deleted.
* Source/JavaScriptCore/heap/WeakImpl.h:
(JSC::WeakImpl::clear): Deleted.
* Source/JavaScriptCore/heap/WeakInlinesLight.h:
* Source/JavaScriptCore/heap/WeakSet.cpp:
(JSC::WeakSet::~WeakSet):
(JSC::WeakSet::lastChanceToFinalize):
(JSC::WeakSet::didBecomeEmpty):
(JSC::WeakSet::tryReleaseBlock):
(JSC::WeakSet::sweep):
(JSC::WeakSet::shrink):
(JSC::WeakSet::findAllocator):
(JSC::WeakSet::tryFindAllocator):
(JSC::WeakSet::addAllocator):
(JSC::WeakSet::removeAllocator): Deleted.
* Source/JavaScriptCore/heap/WeakSet.h:
(JSC::WeakSet::detachAllocator):
(JSC::WeakSet::resetAllocator):
* Source/JavaScriptCore/heap/WeakSetInlines.h:
(JSC::WeakSet::allocate):
(JSC::WeakBlock::finalize):
* Source/JavaScriptCore/runtime/OptionsList.h:
* Source/JavaScriptCore/tools/Integrity.cpp:
(JSC::Integrity::Analyzer::analyzeCell):
* Source/JavaScriptCore/tools/JSDollarVM.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::JSDollarVM::finishCreation):
* Source/WTF/wtf/DebugHeap.h:
* Source/WTF/wtf/FastMalloc.h:
(WTF::FastMalloc::alignedMalloc):
(WTF::FastMalloc::tryAlignedMalloc):
(WTF::FastCompactMalloc::alignedMalloc):
(WTF::FastCompactMalloc::tryAlignedMalloc):
Canonical link: https://commits.webkit.org/321344@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications