Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: c2fa19276047500b65b8a582c68b0e6b1c928974
      
https://github.com/WebKit/WebKit/commit/c2fa19276047500b65b8a582c68b0e6b1c928974
  Author: Dan Hecht <[email protected]>
  Date:   2026-09-24 (Thu, 24 Sep 2026)

  Changed paths:
    M Source/JavaScriptCore/CMakeLists.txt
    M Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
    M Source/JavaScriptCore/SaferCPPExpectations/ForwardDeclCheckerExpectations
    M 
Source/JavaScriptCore/SaferCPPExpectations/NoUncountedMemberCheckerExpectations
    M Source/JavaScriptCore/heap/AbstractSlotVisitor.h
    M Source/JavaScriptCore/heap/AbstractSlotVisitorInlines.h
    A Source/JavaScriptCore/heap/Collector.h
    M Source/JavaScriptCore/heap/GCRequest.h
    M Source/JavaScriptCore/heap/Heap.cpp
    M Source/JavaScriptCore/heap/Heap.h
    M Source/JavaScriptCore/heap/HeapInlines.h
    M Source/JavaScriptCore/heap/MarkStackMergingConstraint.cpp
    M Source/JavaScriptCore/heap/MarkingConstraintSolver.cpp
    M Source/JavaScriptCore/heap/SlotVisitor.cpp
    M Source/JavaScriptCore/heap/SlotVisitor.h
    M Source/JavaScriptCore/heap/VerifierSlotVisitor.cpp
    M Source/JavaScriptCore/heap/VerifierSlotVisitor.h

  Log Message:
  -----------
  [JSC] Split the GC's collection-cycle state and machinery into a Collector 
class
https://bugs.webkit.org/show_bug.cgi?id=325056
rdar://188225105

Reviewed by Yusuke Suzuki.

Heap holds two kinds of state: state that describes a heap, and state that 
describes a
collection cycle. This separates the second kind into a new Collector class. 
Currently,
there is one Collector per Heap so this is a factoring with no change in 
behavior.

This commit just draws the rough line between classes and only does some light 
refactoring.
The code stays where it was located whenever possible to make the diff easier 
to review. A follow
on commit will move the Collector methods into CollectorInlines.h and 
Collector.cpp, and later
commits will make the boundary cleaner with more intrusive changes.

The motivation is to eventually allow the Collector to drive a collection across
multiple heaps in a single cycle.

Collector gets:
 * Marking machinery: the visitor pool, the shared and race mark stacks,
   the opaque roots, the marking mutex and its condition variables, the 
parallel marker counts
 * Phase machine (runCurrentPhase and the six run*Phase methods, changePhase,
   finishChangingPhase)
 * Its own thread as Collector::CollectorThread, which it starts itself, 
together with
   collectInCollectorThread and shouldCollectInCollectorThread
 * Request queue and its ticket counters
 * Compiler thread suspend and resume
 * The timestamps that exist only to compute the cycle's own intervals

Details on places where some minor refactoring has been done:

stopThePeriphery reorders some work: suspendCompilerThreads moves to
the front, and the visitor update after stopAllocating. Both are safe because
updateMutatorIsStopped() recomputes from the current stopped state rather than 
being told it,
so its only ordering requirement is to follow the write of that state, which it 
still does.
Updating later is also the harmless direction: mutatorIsStopped() gates one 
fast path in
JSObject::visitChildren, and false is the conservative answer.

didFinishCollection splits on the duration: the Collector takes m_afterGC and 
hands Heap the
interval m_beforeGC and m_afterGC bound, since the lengths derived from it are 
Heap's. The Heap
half keeps its statements in their existing order, including clearing the 
collection scope before
notifying the observers. And the scope precondition that sat immediately ahead 
of the call to
willStartCollection moves inside it, next to the write it guards.

Heap also stops comparing the request queue's ticket counters itself. 
hasOutstandingRequest and
hasServedTicket answer for it, because the counters are the mutator and 
collector's protocol
rather than state either side owns. The collect-continuously thread moves to 
the Collector with
its lock and condition, start and stop together.

prepareWasmCalleeCleanup and finalizeWasmCalleeCleanup move into 
Heap::beginMarking and
Heap::endMarking. They are the mark and sweep for a type that carries no mark 
bit: the first
snapshots the candidates and resets the Bloom filter that ConservativeRoots 
consults, the
second destroys whatever the conservative stack scan did not find.

Collector's members are grouped by access pattern rather than by where they 
used to sit: the
fields the marking threads mutate occupy the first two cache lines, the visitor 
pool the next,
then the phase machine, the collector thread and the request queue, and finally 
the cycle's
timestamps and the cold collect-continuously state. That keeps the mutator's 
read of
m_scheduler off lines the marking threads dirty.

SlotVisitor gets a Collector&, which required replacing its manual padding with 
alignas so that
sizeof stays a whole number of cache lines even as members are added.

Ticket becomes GCRequest::Ticket, beside the request it identifies, so that 
Collector can name
the type of the counters it now owns.

m_currentThread and m_currentThreadState become m_conductorThread and 
m_conductingMutatorState.
Either the mutator or the collector thread conducts a phase, but only a 
conducting mutator supplies
the machine state the conservative scan needs, since it cannot suspend the 
thread it is scanning
for. The old names said neither, and left the two reading as the same fact.

Four unused members found on the way are removed: Collector::visitCount(),
Heap::phaseVersion(), Heap::increaseLastFullGCLength() and 
Heap::s_blockFragmentLength.

m_lastGCStartTime goes too, but for a different reason: it was read, just never 
for anything the
line below it did not already have. It held a copy of m_currentGCStartTime 
taken one line earlier,
so that m_totalGCTime += m_lastGCEndTime - m_lastGCStartTime could be written; 
that is now
m_totalGCTime += now - m_currentGCStartTime, the same arithmetic without the 
copy.

No change in behavior; covered by existing tests.

* Source/JavaScriptCore/CMakeLists.txt:
* Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj:
* Source/JavaScriptCore/heap/AbstractSlotVisitor.h:
* Source/JavaScriptCore/heap/AbstractSlotVisitorInlines.h:
(JSC::AbstractSlotVisitor::AbstractSlotVisitor):
(JSC::AbstractSlotVisitor::heap const):
(JSC::AbstractSlotVisitor::collector const):
* Source/JavaScriptCore/heap/GCRequest.h:
* Source/JavaScriptCore/heap/Heap.cpp:
(JSC::Heap::Heap):
(JSC::Heap::~Heap):
(JSC::Collector::Collector):
(JSC::Heap::lastChanceToFinalize):
(JSC::Collector::assertMarkStacksEmpty):
(JSC::Heap::gatherStackRoots):
(JSC::Heap::beginMarking):
(JSC::Heap::updateObjectCounts):
(JSC::Collector::endMarking):
(JSC::Heap::endMarking):
(JSC::Heap::clearConcurrentRetainedDataIfPossible):
(JSC::Heap::assertMarkStacksEmpty): Deleted.
* Source/JavaScriptCore/heap/Heap.h:
(JSC::Heap::lastEdenGCLength const):
(JSC::Heap::collectorSlotVisitor): Deleted.
(JSC::Heap::increaseLastFullGCLength): Deleted.
(JSC::Heap::phaseVersion const): Deleted.
(JSC::Heap::runFunctionInParallel): Deleted.
(JSC::Heap::isInPhase const): Deleted.
(JSC::Heap::WTF_GUARDED_BY_LOCK): Deleted.
* Source/JavaScriptCore/heap/HeapInlines.h:
(JSC::Heap::collectorSlotVisitor):
(JSC::Heap::isInPhase const):
(JSC::Collector::forEachSlotVisitor):
(JSC::Heap::forEachSlotVisitor): Deleted.
* Source/JavaScriptCore/heap/MarkStackMergingConstraint.cpp:
(JSC::MarkStackMergingConstraint::quickWorkEstimate):
(JSC::MarkStackMergingConstraint::prepareToExecuteImpl):
(JSC::MarkStackMergingConstraint::executeImplImpl):
* Source/JavaScriptCore/heap/MarkingConstraintSolver.cpp:
(JSC::MarkingConstraintSolver::MarkingConstraintSolver):
(JSC::MarkingConstraintSolver::execute):
* Source/JavaScriptCore/heap/SlotVisitor.cpp:
(JSC::SlotVisitor::SlotVisitor):
(JSC::SlotVisitor::donateKnownParallel):
(JSC::SlotVisitor::performIncrementOfDraining):
(JSC::SlotVisitor::didReachTermination):
(JSC::SlotVisitor::hasWork):
(JSC::SlotVisitor::drainFromShared):
(JSC::SlotVisitor::drainInParallelPassively):
(JSC::SlotVisitor::donateAll):
(JSC::SlotVisitor::didRace):
(JSC::SlotVisitor::correspondingGlobalStack):
* Source/JavaScriptCore/heap/SlotVisitor.h:
* Source/JavaScriptCore/heap/VerifierSlotVisitor.cpp:
(JSC::VerifierSlotVisitor::VerifierSlotVisitor):
(JSC::VerifierSlotVisitor::dumpMarkerData):
* Source/JavaScriptCore/heap/VerifierSlotVisitor.h:
* Source/JavaScriptCore/heap/Collector.h: Added.
(JSC::Collector::heap):
(JSC::Collector::runFunctionInParallel):
(JSC::Collector::hasOutstandingRequest const):
(JSC::Collector::hasServedTicket const):
(JSC::Collector::WTF_GUARDED_BY_LOCK):
* Source/JavaScriptCore/SaferCPPExpectations/ForwardDeclCheckerExpectations:
* 
Source/JavaScriptCore/SaferCPPExpectations/NoUncountedMemberCheckerExpectations:

Canonical link: https://commits.webkit.org/321791@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to