Shared-memory threads for JavaScriptCore (experimental, not working yet) by Jarred-Sumner · Pull Request #249 · oven-sh/WebKit

· GitHub

105 min read Original article ↗

added 21 commits

June 5, 2026 08:09
Design specs for shared-heap Thread support in JSC: heap server and
per-thread allocators, shared VM state, TID/SW-tagged and segmented
butterflies, JIT tiers under N mutators, and the Thread/Lock/Condition/
ThreadLocal API. Includes TSAN, race-amplifier, and bench-gate docs plus
the design overview in THREAD.md.
…harness

Thread/Lock/Condition/ThreadLocal and Atomics-on-properties behind
--useThreads, serialized by the VM's JSLock as a semantic oracle for the
upcoming shared-heap implementation. Includes a 39-test corpus, a TSAN
no-JIT build target (zero data races at idle, empty suppressions), a
randomized-yield race amplifier, and a serial-perf bench gate with a
recorded baseline. Also fixes ICU static-archive link order in WTF and
two pre-existing no-JIT build breaks.
…rent object model, JIT support, and Thread API

Multi-mutator heap with per-thread allocators and N-thread safepoints,
process-global sharded atom table and StructureID allocation locking,
per-thread VM-lite execution state, TID/shared-write tagged butterflies
with segmented fallback and TTL watchpoint elision, per-tier TID/SW
checks with handler ICs in FTL and epoch-based CodeBlock reclamation,
and real mutator threads behind the Thread/Lock/Condition/ThreadLocal
API with Atomics on object properties. All behind --useJSThreads with
the GIL retained as a --useThreadGIL fallback layer.
…ation, waiter lists

Six rounds of gate-driven fixes against the threads corpus: per-thread
CLoop stacks replacing the shared-stack frame clobber, LocalAllocator
and Heap shared-mode races, retired JIT artifact accounting, waiter
list and condition wakeup fixes, LLInt call path initialization for
spawned threads, butterfly regime dispatch in slow paths, and a
watchpoint disarm before the flag-on JITData leak in ~CodeBlock.
Corpus: 81/85 passing; adds per-test timeouts to the runner so hangs
report as failures.
… on spawned threads

trySpreadFast reached the flat-only butterfly() accessor on arrays
whose butterfly had segmented under a racing same-shape add storm; the
spread path now dispatches on the regime and falls back to the generic
slow path. Baseline-compiled callees invoked from spawned threads read
per-thread JIT state that only LLInt entry initialized; the thread
entry sequence now materializes it for all tiers. Threads corpus green.
…tion handout

SPEC-ungil.md: N-mutator execution model — JSLock GIL-off entered-token mode,
per-thread microtask/task queues with keepalive lifetime, stop-the-world
conductor protocol (seq_cst stop-bit/access Dekker pair), thread teardown
state machine (TEARDOWN/COLLECTED/DETACHED under the lite registry lock),
~VM completion fence via registry condition wait, haveABadTime class-4 stops,
lazy-init owner-reentry contract, termination model (VM-wide only).
Includes executed inventory audits (K4/N7), full revision history with
binding annexes, and the flattened 18-task implementation handout.

Workflow updates: ungil implementation runs DAG-scheduled parallel task waves
with disjoint file ownership and per-task adversarial review; verification
ladder covers GIL-on and flag-off regression arms; scanner/fuzz/CVE-audit
workflows harden id/path sanitization.

@Jarred-Sumner

@Jarred-Sumner

@Jarred-Sumner

@Jarred-Sumner

coderabbitai[bot]

@Jarred-Sumner

coderabbitai[bot]

coderabbitai[bot]

sosukesuzuki pushed a commit that referenced this pull request

Sep 14, 2026
…om table ordering

Fixes for the per-hunk review of #249 (review finding ids: 131-5, 151-1, 151-2, 152-1, 153-1, 153-2, 154-1, 154-2, 154-3).

- BitSet: gate relaxed-atomic zeroing constructor on TSAN_ENABLED, keep aggregate zero-init otherwise
- DeferrableRefCounted: gate the atomic refcount RMWs on a process-latched GIL-off Config byte
- StringImpl: keep the legacy load/modify/store in cost, setIsAtom and setHash when the shared atom table is off
- SymbolImpl: make the symbol hash counter atomic
- Thread: add WTF Thread::tryCreate and throw RangeError when the OS refuses a thread
- WTF Thread: reword dedicated-byte flag comments to name the real writer/reader race
- WTF: define SharedAtomStringTable::singleton and the latch in SharedAtomStringTable.cpp
- WTF: state the migrate-then-latch-then-clear order in enableSharedAtomStringTable without citing the spec

sosukesuzuki pushed a commit that referenced this pull request

Sep 14, 2026
…er, drop temporary diagnostics

Fixes for the per-hunk review of #249 (review finding ids: 033-1, 033-2, 033-3, 034-1, 034-2, 034-3, 034-5, 035-1, 035-2, 035-3, 036-1, 036-3, 036-4, 036-5, 036-6, 037-1, 037-2, 038-1, 038-2, 038-3, 039-1, 039-2, 039-3, 040-1, 041-1, 041-3, 042-1, 042-2, 042-3, 043-1, 043-2, 043-3, 043-4, 043-5, 044-1, 044-2, 045-1, 045-2, 045-3, 046-1, 046-2, 046-3, 046-4, 046-5, 046-6, 046-7, 047-2, 047-3, 047-4, 048-1, 048-2, 048-3, 048-4, 048-5, 049-1, 049-2, 050-1, 050-2, 051-3, 052-1, 052-2, 052-3, 052-4, 052-5, 053-1, 053-2, 053-3, 054-1, 054-2, 055-1, 055-2, 056-1, 056-2, 116-6, 135-3).

- BlockDirectory: assert the lock-free m_bits witness is this thread's exclusive MSPL or own stripe
- BlockDirectory: make assertSweeperIsSuspended a world-stopped/exclusive-owner assertion; drop sweeper-disabled claims
- BlockDirectory: remove findOwnEmptyBlockForRefill, whose target population cannot exist
- BlockDirectory: step the steal cursor past weak-bearing empties instead of declining them
- CompleteSubspace::allocate: test the server allocator before the useSharedGCHeap branch
- CompleteSubspace::allocate: trust the per-thread TLC snapshot only when vm is gilOff
- Drop the dead null-client disjunct from the TLC hit ASSERT and restate its invariant
- GCIncomingRefCountedSet: take the incoming-reference lock only under gilOffProcess
- GCIncomingRefCountedSet: walk the set unlocked in sweep/lastChanceToFinalize (world stopped)
- GCThreadLocalCache: remove uncalled allocatorFor(BlockDirectory&), stopAllocating, prepareForAllocation, server
- GCThreadLocalCache: replace unreachable growTable realloc leg with a fixed-capacity RELEASE_ASSERT
- HandleSet: fold the Strong leaf lock into the class, drop the process-global side table
- HandleSet: lock the live protected-cell walk; route the NODELETE counter through m_strongLock
- HandleSet: make m_strongLock a real member and rewrite the seam comments as invariants
- HandleSet: take m_strongLock in forEachStrongHandle under gilOff
- Heap: correct the F28 successor-open comments to the drain the code performs
- Heap: correct the Wlr comment: Auxiliary witnesses are marked, not traced
- Heap: count drainFromShared entrants for the marker pause; restore flag-off steal denominator
- Heap: create sibling-assist visitors in runBeginPhase, decline assists when the pool is empty
- Heap: delete dead allocationClientForJITCodegen and the duplicate free resolver
- Heap: delete the dead namespace-scope allocationClientForCurrentThread and its stale note
- Heap: delete the never-constructed SharedGCWindowOpen::TicketDrainSuccessor arm
- Heap: delete the unreferenced allocationClientForJITCodegen resolver
- Heap: describe the STW-forbidden scope depth as a release-mode per-thread counter
- Heap: document that a LambdaFinalizer may receive a null JSCell* under GIL-off
- Heap: document that shared-mode hooks/reclaim/rebias run once per drained ticket batch
- Heap: document the GIL-off LambdaFinalizer contract (null cell, runs after the world resumes)
- Heap: drain GCSafepointEpoch retired items in lastChanceToFinalize, before blocks are freed
- Heap: drain an orphaned needFinalizeBit inside the ISS flip before storing ISS
- Heap: drop dead sharedGCWindowedStagesEnabled(); Heap.cpp keeps the one stage-flag list
- Heap: drop stale NOTE claiming worldIsStopped() still does a plain read
- Heap: drop the untimed JSThreadsStopScope ctor; harness uses the watchdog ctor
- Heap: drop the unused 1-byte layout pad and state what the trailer guards check
- Heap: drop unused GCClient::CompleteSubspaceView, its members and bind hook
- Heap: exempt the PreventCollectionScope holder from the shared conduct-tenure gate
- Heap: fix comments still claiming the IncrementalSweeper is disabled when shared
- Heap: gate DeferGC slot routing on useSharedGCHeap and resolve both slots once
- Heap: gate allocationClientForCurrentThread on gilOffWithProcessGate, drop stale rationale
- Heap: gate the freelisted-block walk in stopThePeriphery on Options::verifyGC()
- Heap: gate the possibly-accessed-strings append lock on gilOff
- Heap: gate the shared-GC root-snapshot/endMarking/freelisted-block checks behind Options::verifyGC()
- Heap: make barrierThreshold()/mutatorShouldBeFenced() plain server-master reads
- Heap: make sharedGCMaxSiblingMarkingAssists=0 mean disabled and drop the dead auto branch
- Heap: read the server master barrier pair in mutatorShouldBeFenced/barrierThreshold
- Heap: register the epochReclaim safepoint hook per heap, make hook registry idempotent
- Heap: remove the unconsumed CompleteSubspaceView wrappers and bind hook
- Heap: route server-level acquire/release/hasAccess to the calling thread's client GIL-off
- Heap: run TID-rebias fires as the GC conductor and retire the stale tripwire banner
- Heap: run the conservative-scan constraint on the conductor when sibling assists are admissible
- Heap: run verifyStickySharedServerDesignation before HeapClientSet::add's sticky trigger
- Heap: scan and grant the shared collectAsync ticket under one m_threadLock hold
- Heap: serialize the server mutator mark stack with a Heap lock, not a MarkStackArray flag
- Heap: state the pin-lock-then-codeBlockSet-lock order at pinRetiredCallLinkRecordCodeBlock
- Heap: state the shared-mode no-runloop-push rule and log access-barrier stalls
- Heap: strip the TEMPORARY ring-liveness diagnostics from the shared-heap harness
- Heap: take m_possiblyAccessedStringsFromConcurrentThreadsLock only under gilOff
- Heap: take m_protectedValuesLock in protect/unprotect and statistics walks under gilOff
- Heap: test useSharedGCHeap before isSharedServer in the per-client slot dispatchers
- HeapClientSet: run the sticky-server designation check before the second-client ISS flip
- IsoSubspace: inline GCClient::IsoSubspace::tlcSlot, drop false out-of-line rationale
- IsoSubspace: remove unused GCClient::IsoSubspace::allocateForClient
- Key the TLC snapshot hit on vm.gilOff() so nested foreign-VM entry cannot allocate from the wrong heap
- MarkedBlock: correct the isMarkedRaw comment to name its callers' protocols
- MarkedBlock: drop the unreachable allocBit leg and last-era skip from the window snapshot
- MarkedBlock: state the real stale-true argument for the destructible hint; keep it in lockstep for false
- MarkedBlock: take the heapRandom lock in specializedSweep only when sweeps can run concurrently
- MarkedSpace: bound TLC slot reservation by numCompleteSubspaces * numSizeClasses
- MarkedSpace: say isPagedOut's only caller skips it when shared, not that it never fires
- MarkingConstraint: delete dead m_lock member and the comment deferring its removal
- SharedHeapTestHarness: remove the ring-liveness diagnostics and the Heap.cpp audit seam
- SlotVisitor: arm the per-batch helper pause checkpoint in the gilOff single-handoff shape
- Threads: relinquish a spawned thread's allocators while its lite is Live, not from the client dtor
- TinyBloomFilter: replace relaxed fetch_or in add() with relaxed load+store
- VMManager.h: declare the thread-granular conductor predicates once; drop seven hand copies

sosukesuzuki pushed a commit that referenced this pull request

Sep 14, 2026
…hared butterfly protocol

Fixes for the per-hunk review of #249 (review finding ids: 021-2, 036-2, 061-3, 061-4, 072-1, 072-2, 072-3, 072-4, 073-1, 073-2, 073-5, 075-1, 075-2, 075-3, 076-1, 076-2, 076-3, 077-1, 077-2, 078-1, 078-2, 078-3, 079-1, 079-2, 080-2, 080-3, 080-4, 083-1, 084-1, 084-2, 084-4, 086-1, 086-2, 086-3, 086-4, 086-5, 087-1, 087-2, 087-3, 087-4, 087-5, 088-1, 088-2, 089-3, 089-4, 090-2, 090-4, 090-5, 090-6, 091-3, 099-1, 099-2, 099-3, 100-1, 100-2, 100-3, 100-4, 100-5, 101-1, 101-2, 102-2, 102-3, 102-4, 102-6, 103-1, 103-2, 103-4, 104-2, 104-3, 104-4, 105-1, 105-2, 105-3, 106-5, 108-4, 110-2, 111-1, 112-1, 112-2, 113-1, 113-2, 113-3, 116-2, 116-3, 116-4, 117-1, 118-1, 118-2, 119-1, 119-2, 119-3, 120-2, 121-1, 121-2, 121-4, 122-1, 122-2, 123-1, 123-2, 123-3, 124-1, 124-4, 132-1, 149-1).

- ArrayPrototype: derive join/indexOf/concat fast paths from one tagged butterfly word snapshot
- ArrayPrototype: re-read indexing types after the concat result allocation flag-on
- ArrayPrototype: reverse fast path flips SW for foreign writers and uses one butterfly snapshot
- ButterflyInlines: keep optimalContiguousVectorLength within MAX_STORAGE_VECTOR_LENGTH
- ClonedArguments: copyToArguments reads one butterfly-word snapshot, bails on segmented/null
- ClonedArguments: serialize GIL-off materializeSpecials under a park-capable lock
- ConcurrentButterfly.h: document the gilOff StayFlatShared transition in the regime contract
- ConcurrentButterfly.h: read the verify/stress options directly instead of SFINAE probes
- ConcurrentButterfly: StayFlat copy-grow copies no element payload for typed-array views
- ConcurrentButterfly: assert non-null fragments under verifyConcurrentButterfly in the GC visit
- ConcurrentButterfly: bail out of the ensureLength/shrink drivers when an AS conversion lands
- ConcurrentButterfly: delete the uncalled segmentedTransition/structureOnlyTransition drivers
- ConcurrentButterfly: drop the process-global stub world-stopped witness
- ConcurrentButterfly: make butterflyWorldIsStopped the JSThreadsSafepoint predicate alone
- ConcurrentButterfly: name the useSharedGCHeap gate in the mode (b) rarity comments
- ConcurrentButterfly: register the quarantine epoch hook on every Heap, not per address
- ConcurrentButterfly: remove the uncalled spineOutOfLineFragment/spineIndexedFragment exports
- ConcurrentButterfly: route far-beyond-vector indexed stores to the sparse-map path flag-on
- ConcurrentButterfly: size typed-array view conversions from a zero indexed payload
- ConcurrentButterfly: state the GC visit bound as the spine's vectorLength in code comments
- ConcurrentButterflyOperations: drop __has_include scaffolding and the TID-0 shim
- ConcurrentButterflyOperations: remove the seven unreachable JIT operation shims
- DFG operationCreateThis: validate the allocation profile snapshot under gilOff like slow_path_create_this
- DirectArguments: serialize overrideThings puts and bitmap publication under gilOff
- FunctionRareData: GIL-off .prototype store is followed by a clear that waits for the initializer
- GetterSetter: restore WriteBarrier::set() in ctor, drop stale hand-expansion and comment
- JSArray AS shift/unshift concurrent: re-check the caller's range under the cell lock and bail
- JSArray/JSObject: replace GIL-only sparse-map iterators on flag-on paths with keyed locked access
- JSArray::appendMemcpy: re-read both indexing types after ensureLength before the memcpy
- JSArray::copyToArguments: clamp the flat scan to the caller's length as well as the snapshot
- JSArray::fastFill: bail when the flag-on relabel left indexingType != nextType
- JSArray::fastFlat: bail flag-on when pass 2 copied a different count than pass 1
- JSArray::fastFlat: bail when the source shape changed across the result allocation
- JSArray::fastSlice: hold one GCDeferralContext across butterfly allocation, copy and cell allocation
- JSArray::fastToReversed/fastWith/fastToSpliced: re-read indexingType after the result allocation
- JSArray::pop: return undefined when a racing shrink emptied the array before the generic tail
- JSArray::setLength/pop/fastShift: restart on a null word paired with an indexed mode
- JSArray::unshiftCountSlowCase: drop unreachable flag-on branches
- JSBigInt: throw OutOfMemoryError from createFromDigit instead of RELEASE_ASSERT
- JSCJSValue: make the 64-bit JSValue slot accessors relaxed atomics only under TSAN
- JSCell: drop no-op decontaminate() in structure(); state the nuke-bit contract
- JSCellInlines: delete orphaned comment describing the withdrawn H-CALLSITE-LASTSIZE-LA mechanism
- JSCellInlines: make tlcSlotForSubspace fail closed for non-CompleteSubspace kinds
- JSCellLock: maintain GCCellLockDepth in lock/tryLock/unlock so the no-park asserts are live
- JSFunction: CAS-publish FunctionRareData under gilOff so racing installs adopt one cell
- JSObject.h: drop the stale i03-i37 FIXME in tryMakeWritableInt32
- JSObject.h: remove uncalled butterflyRegime() and isSharedArrayStorage()
- JSObject: RESTART stop-published indexing transitions when a dictionary table was edited in place
- JSObject: always CAS-max publicLength after flag-on dense stores and ensureLength
- JSObject: barrier the owner after the AS-COPY growth publication
- JSObject: butterfly() contract drops the guard-then-reload witness; snapshot JSCellButterfly::createFromArray
- JSObject: check the ThrowScope when putInlineSlow's thread-restrict gate throws
- JSObject: check the ThrowScope when threadRestrictCheck fails in getNonIndexPropertySlot
- JSObject: correct the flatten re-check comment about renumberPropertyOffsets' edit stamp
- JSObject: dispatch flag-on indexed delete on one loaded word, never the flat switch
- JSObject: fence mode-then-word loads in indexed names walk and beyond-vector put
- JSObject: install a fresh sparse map under the cell lock only if none is installed (flag-on)
- JSObject: load mode before the fenced word in setIndexQuicklyConcurrent; putDirectIndex uses the try variant
- JSObject: publish dictionary attribute changes under the cell lock with a table-stamp re-check
- JSObject: putDirectIndex AS grow arm re-checks the vector bound under the lock before storing
- JSObject: re-check i < vectorLength under the lock after increaseVectorLength before storing
- JSObject: re-check vectorLength on the fresh word in setIndexQuicklyConcurrent and route putDirectIndex via try
- JSObject: re-dispatch putDirectIndex after createArrayStorage instead of indexing the returned vector
- JSObject: re-validate structureID after the word load in createInitialIndexedStorageConcurrent
- JSObject: recount m_numValuesInVector under the lock in sparse-map consolidation
- JSObject: return the settled ArrayStorage from convertToArrayStorageConcurrent when a racer converted first
- JSObject: route null-word foreign-keyed indexed first installs to the shared stop leg
- JSObject: run the F1 SW flip before cell-locked ArrayStorage stores in putByIndex and the AS funnels
- JSObjectWithButterfly: delete the uncalled getDirectConcurrent/putDirectConcurrent
- JSPropertyNameEnumerator: drop stale NOTE, state the relaxed store/load invariant
- LazyProperty: drop unreachable initializer-abandonment restore in callFunc
- MegamorphicCache: restore plain epoch bump; make bumpEpoch a no-op under useJSThreads
- ObjectConstructor: clone fast paths copy from one tagged-word snapshot paired with the structure
- PropertyTable: document that inline deleted offsets are quarantined too
- PropertyTable: fold deleted-offset bookkeeping into one side struct (cell 80 -> 48 bytes)
- PropertyTable: say seal()/freeze() edit a still-private table; keep the seqlock bracket
- PropertyTable: skip the quarantine walk when the oldest stamp is not yet promotable
- PropertyTable: state the TSAN pairing rationale for relaxed constructor stores
- SparseArrayValueMap: decide flag-on putEntry/putDirect under the lock, throw and call setters after it
- SparseArrayValueMap: dispatch putEntry on the value word and lock every flag-on entry writer
- SparseArrayValueMap: insert a sparse entry only once the write is allowed (no placeholder)
- Structure: condense the DEFINE_BITFIELD perf narrative to the lost-update invariant
- Structure: drop the unused DeferredWatchpointFire parameter of firePropertyReplacementWatchpointSet
- Structure: gate SAL locker construction in Structure::create/createStructure on the latched option
- Structure: gate the lock-free transition precheck on useJSThreads for the IC/DFG callers
- Structure: name the lock-free republish store as the only unlocked chain writer
- Structure: pre-allocate the shrunk flatten butterfly outside the stop window
- Structure: re-copy seenProperties/propertyHash into a transition under the source m_lock
- Structure: remove the never-passed deferred parameter and its API comment
- Structure: replace transitionThreadLocalTIDOffset with a restampTransitionThreadLocalTID setter
- Structure: restore .set()/.setMayBeNull() at four slot writers; drop stale plain-store comments
- Structure: revalidate isDictionary and object->structure in the flatten stop closure
- Structure: snapshot forEachProperty entries under m_lock and run the functor unlocked
- Structure::add<ShouldPin::Yes>: recheck under m_lock that the table was not stolen
- StructureChain: bound finishCreation's lane walk by the size create() allocated
- StructureRareData: GCSafe, flag-on-only lock around the special property cache install
- StructureRareData: move retired enumerator watchpoint list out of the cell into the Heap
- TypeInfoBlob/Structure: make the blob, outOfLineTypeFlags and classInfo reader loads TSAN-only
- WriteBarrier: make the cell-pointer slot accessors relaxed atomics only under TSAN
- ensureLengthSlowConcurrent: drop the dead availableOldLength computation and T5 comment
- fastArrayJoin: snapshot the butterfly word once and re-probe it after user code
- shiftCountWithArrayStorageConcurrent: allocate the fresh AS before the scalar stores

sosukesuzuki pushed a commit that referenced this pull request

Sep 14, 2026
…nd lifetime races

Fixes for the per-hunk review of #249 (review finding ids: 070-1, 070-2, 070-3, 070-4, 070-5, 070-6, 071-1, 071-2, 072-5, 072-6, 074-3, 089-1, 089-2, 089-5, 090-1, 090-3, 091-1, 091-2, 091-4, 092-1, 092-2, 092-3, 092-4, 107-1, 107-3, 107-4, 108-1, 108-2, 108-3, 114-1, 114-2, 114-3, 114-4, 115-1, 116-1, 117-2, 124-3, 125-1, 125-2, 125-3, 125-4, 125-5, 126-1, 126-3, 126-4, 128-2, 148-2, 148-5).

- ArrayBuffer: allocate the GIL-off resizable transfer copy without a VM so it cannot collect
- ArrayBuffer: fail the GIL-off transferTo whose detach lost the flag race, as already detached
- ArrayBuffer: fail the racing transfer loser so exactly one transfer of a buffer succeeds
- ArrayBuffer: make isDetached() read a sticky GIL-off detached flag; drop the side-table probes
- ArrayBuffer: make isDetached() read the sticky GIL-off flag, drop isArrayBufferDetachedGILOff
- ArrayBuffer: neuter views before the mapping enters the quarantine in GIL-off detach
- ArrayBuffer: quarantine a relocated wasm mapping in the growing VM's heap quarantine
- ArrayBuffer: re-check isDetached() and maxByteLength under the lock on every resizeGILOff pass
- ArrayBuffer: register the quarantine safepoint hook per Heap at VM init, not per address
- ArrayBuffer: snapshot length and maxByteLength under the handle lock in GIL-off transferTo
- Atomics: delete the D8 single-flight TA sync-wait gate; lift the 4.5-1a spawned gate GIL-off only
- AtomicsObject: run the GIL-off detach re-check before ToIndex so the TA path keeps RangeError
- ConcatKeyAtomStringCache: read/store m_mode through relaxed atomics in getOrInsert
- DataView get/set: keep the plain byte loop flag-off, relaxed atomics only under gilOffWithProcessGate
- DataView get/set: snapshot the view base before the length proof, throw detached on null GIL-off
- DateCache: route GIL-off entry points to a per-thread cache instead of one VM-wide leaf lock
- JSArrayBufferView: convert shared flat views before the GIL-off wastage copy; retry a failed CAS
- JSArrayBufferView: give a segmented Fast/Oversize view a header fragment in slowDownAndWasteMemory
- JSString: derive every rope-walk decision from one per-node m_fiber snapshot
- JSString: plain constructor-time rope stores in production, relaxed atomics only under TSAN
- JSString: remove dead resolveRopeInternalNoSubstring
- KeyAtomStringCache: relaxed slot snapshot load in production, acquire only under TSAN
- KeyAtomStringCacheInlines: drop unused Options.h, stdlib.h and DataLog.h includes
- RegExp: make m_atom write-once so lock-free atom() readers never see it freed
- RegExp: publish bytecode before m_state=ByteCode; never hand Yarr::interpret a null pattern
- RegExp: take cellLock in reset(), route error-code reads through one relaxed accessor
- RegExp: write-once m_atom and bytecode-before-state publication (same fix as 114-1/114-2)
- RegExpCache: clear Yarr code under a stop-the-world window when gilOff
- SimpleTypedArrayController: actually defer the displaced dead wrapper Weak under GIL-off
- StringRecursionChecker: use the per-thread recursion state in every useJSThreads mode
- Symbol: return the canonical cell from finishCreation instead of re-probing symbolImplToSymbolMap
- ThreadAtomics: DeferGC around the Missing-add ArrayStorage cell-lock window
- ThreadAtomics: bump ArrayStorage length only after the conditional add publishes
- ThreadAtomics: drop the never-incremented g_threadAtomicsSlotCASRetries stub and its dump field
- ThreadAtomics: drop the never-incremented slotCASRetries counter
- ThreadAtomics: flip SW before the Missing-add ArrayStorage cell lock
- ThreadAtomics: grow dense shapes for beyond-vector Atomics.store adds GIL-off
- ThreadAtomics: release the waitAsync ticket at dequeue instead of at timer fire
- ThreadAtomics: state the in-window teardown-sweep finalizer contract
- ThreadAtomics: state why property waitAsync stays an uncounted keepalive registration
- TypedArray copyWithin: return early on a null base snapshot in the GIL-off lane loop
- TypedArray element accessors and sort: gate on g_jscConfig.gilOffProcess, not VM::isGILOffProcess()
- TypedArray fill: return early on a null base snapshot in the GIL-off lane loop
- TypedArray forEach: test the base snapshot instead of isDetached() in the arms that re-read the base
- TypedArray includes/indexOf/lastIndexOf/reverse/sort: handle a null base snapshot GIL-off
- TypedArray setFromTypedArray/sort/copyFrom*ShapeArray: never deref a base re-read after the bounds proof GIL-off
- WaiterListManager: settle a foreign VM's TA waitAsync under list->lock in the GIL-off notify arm
- jsAtomString: republish the atom when a lost GIL-off publish race left a non-atom impl

sosukesuzuki pushed a commit that referenced this pull request

Sep 14, 2026
…, Lock, Condition and ThreadLocal

Fixes for the per-hunk review of #249 (review finding ids: 051-1, 059-3, 081-1, 082-1, 082-2, 082-4, 096-2, 098-1, 098-2, 106-1, 106-4, 109-1, 109-2, 109-3, 109-4, 109-5, 111-5, 111-6, 129-1, 129-2, 129-3, 129-4, 129-5, 130-1, 130-2, 130-3, 130-4, 130-5, 131-1, 131-2, 131-3, 131-4, 134-4, 148-1, 148-3, 148-4, 149-2, 149-3).

- ConcurrentAccessError constructor: derive the Structure from newTarget
- ConditionObject: consume the async grant under m_queueLock before asyncWait's (b) release
- DeferredWorkTimer: capture the timer, not Ref<VM>, in gilOff run-loop dispatches
- DeferredWorkTimer: fix stale runRunLoop comment about the non-gilOff arm taking m_taskLock
- DeferredWorkTimer: make TicketData::m_isCancelled a relaxed std::atomic<bool>
- GILDroppedSection: stop publishing a coop GC root snapshot from the out-of-line ctor
- JSMicrotask: delete the unreferenced publishAsyncGeneratorResume host function
- JSMicrotask: gate the generatedJITCodeForCall mirror assert on !gilOff
- JSPromise: keep GIL-off spawned threads off VM::m_synchronousModuleQueue
- JSPromise: read m_asyncContextData directly at the five capture sites
- LockObject: count asyncHold registrations toward the spawned registrant's keepalive
- LockObject: keep a termination pending in the asyncHold(fn) settle instead of rejecting
- LockObject: keep the GILDroppedSection coop root snapshot on the park-site frame
- LockObject: open the park-resumption window at the holder's release, not at park entry
- LockObject: run the async-grant pump inline for a spawned head registrant under gilOff
- MicrotaskCall: relaxed entry/codeBlock loads, acquire fence only in the gilOff arm
- MicrotaskQueue: clearForGlobalObject also filters the GIL-off foreign inbox
- MicrotaskQueue: record that the marker takes the inbox lock under VMLiteRegistry::lock
- Thread.restrict: refuse realmless (wasm GC) receivers before the species check
- ThreadManager.h: drop the stale useThreads-alias paragraph from the gate comment
- ThreadManager.h: keepalive banner lists only the two real decrement sites
- ThreadManager.h: replace the stale U-T9-INT1 gate block with the current keepalive invariant
- ThreadManager: clear pending termination exception before publishing Error("Thread terminated")
- ThreadManager: decrement keepalive in retireUnsettled; document which sites count
- ThreadManager: default maxJSThreads to the 16383-id spawned TID partition and document the GIL-on lifetime cap
- ThreadManager: delete stale reviewer NOTE about unapplied threadRestrictCheck hooks
- ThreadManager: remove dead currentTID() and the VM-blind allocateSpawnedThreadState()
- ThreadManager: remove the dead ThreadWaitDeadline registrant-deadline machinery
- ThreadManager: remove the never-populated waitDeadlines expire/harvest path
- Threads: make spawned threads always blockable GIL-off; drop dead mayBlockSynchronously
- Watchdog.h: document the GIL-on cross-thread CPU-budget limitation for spawned servicers
- Watchdog.h: say GIL-on/flag-off are behavior-identical, noting the uncontended m_lock take
- Watchdog/LockObject: delete stale WIRING STATUS block and dead jsThreadParkTerminationRequested
- Watchdog: describe the W1 parked-carrier verdict as wall-clock authoritative, drop WIRING STATUS
- Watchdog: guard the GIL-off carrier depth decrement so a mid-entry-created watchdog cannot wrap
- threadMain: drop the AB18-I residual-exception fold and its dataLog line
- throwConcurrentAccessError: pass JSValue() so engine throws carry no own cause

sosukesuzuki pushed a commit that referenced this pull request

Sep 14, 2026
…stry, traps and stop-the-world

Fixes for the per-hunk review of #249 (review finding ids: 007-1, 016-1, 016-2, 016-3, 023-2, 027-2, 028-2, 038-4, 057-1, 057-3, 057-4, 057-5, 058-1, 058-2, 058-3, 058-4, 066-2, 073-3, 073-4, 074-2, 080-1, 083-2, 084-3, 093-1, 093-2, 093-3, 093-4, 093-5, 093-6, 094-1, 096-1, 096-3, 096-4, 097-1, 097-2, 097-3, 097-4, 097-5, 097-6, 098-3, 110-1, 111-2, 111-3, 114-5, 115-2, 115-3, 116-5, 128-1, 131-6, 133-1, 133-2, 133-3, 133-4, 133-5, 134-2, 134-3, 135-1, 135-2, 135-4, 136-3, 136-4, 136-5, 136-6, 137-1, 137-2, 138-1, 138-3, 138-4, 139-1, 139-2, 139-3, 139-4, 139-5, 139-6, 140-1, 140-2, 140-3, 140-4, 140-5, 141-1, 141-2, 141-3, 141-5, 141-6, 141-7, 142-1, 142-2, 142-3, 142-4, 142-5, 143-1, 143-2, 143-3, 143-5, 143-6, 144-1, 144-2, 144-3, 145-1, 146-1, 146-2, 146-3, 146-4, 147-1, 147-2, 147-3, 148-6, 149-4, 150-3, 150-5).

- AbstractModuleRecord: take cellLock() around m_resolutionCache reads and inserts
- CLoopStack: create segments lazily; register and bump the cache epoch only for stacks with segments
- CLoopStack: republish the running thread's stack limit at JSLock acquisition
- CLoopStack: setSoftReservedZoneSize grows only the caller's segment; zone size is a relaxed atomic
- CLoopStack: test top frame containment before topOfFrame(); read it through group3Primitives
- CachedCall: gate the foreign-drain skip and m_ownerThread on the per-VM gilOff mode
- CodeCache: take the GIL-off compilation lock in clear()
- CodeCache: use the shared GILOffCompilationLocker from JSThreadsSafepoint.h
- CommonSlowPaths: state that the fast-iteration-mode popcount bound is best effort under races
- ConcurrentAccessError: cache the per-realm Structure and inherit the constructor from Error
- ConcurrentButterfly.h: include VMLite.h unconditionally, drop the TID-0 __has_include shim
- Debugger: detach a destructing global inline instead of requesting a stop from the sweep
- Debugger: register spawned-thread CodeBlocks under a stop instead of dropping carrier breakpoints
- Debugger: state deleteAllCode's registry-keyed idle deferral at recompileAllJSFunctions
- Declare the jsThreads stop-protocol seams once in VMManager.h and VMLite.h
- Declare the park-site poll and carrier-park helpers in VMTraps.h/JSLock.h; drop five redeclarations
- ExceptionScope/VM: state RETURN_IF_EXCEPTION's flag-off Config byte-test cost in the comments
- FrameTracers/VM: remove uncalled pre-resolved tracer overloads and group3Primitives(preResolved)
- FrameTracers: drop stale NOTE claiming prepareCallOperation is unconverted under gilOff
- FunctionExecutable: drop dead codeBlockWithEntrypointFor and replaceCodeBlockWith
- Interpreter: relaxed CachedCall entry loads, gate absorb/snapshot on gilOffWithProcessGate()
- JSDollarVM: register sharedHeapTest allowIfNotFuzz like other crash-on-misuse entries
- JSGlobalObject: drop the dead per-lite AsyncLocalStorage cursor scaffolding
- JSGlobalObject: keep a global's own MicrotaskQueue when a spawned thread enqueues GIL-off
- JSGlobalObject: route generator claim/publish hooks through atomicInternalField()
- JSGlobalObject: state the eager-init invariant for the two arguments lazy properties
- JSGlobalObject: take the Function-constructor cache lock only under gilOff
- JSGlobalObject: visit per-lite realm entries only for a gilOff VM
- JSLock.h: document both unlockAllForThreadParking callers and the nested-bracket shape
- JSLock/VMLite: describe per-lite microtask queue routing as landed, drop 'not rerouted' notes
- JSLock: clear the thread-client slot when a gilOff carrier enters a GIL-on VM
- JSLock: drop the write-only spAtEntry and constant releaseAccessAtDepthZero token fields
- JSLock: gate the F.5 outer-carrier restore on this thread's own blocking-section drop
- JSLock: gate token retirement and the deferred carrier restore on useVMLite
- JSLock: release the carrier client's access at every gilOff depth-0 release
- JSLock: test g_jscConfig.gilOffProcess, not VM::isGILOffProcess(), on every lock()
- JSLock: unlockAllForThreadParking comment states the landed GILDroppedSection split
- JSPI: refuse pinball fulfill/reject resumption on spawned Threads (SD7)
- JSThreadsSafepoint: walk the parked thread's own topCallFrame for the epoch-overlap jettison
- MarkedVector: drop m_markSetLock, recover the shard lock from m_markSet under useSharedGCHeap
- Options: fail-stop when useProfiler/forceEagerCompilation undo useJSThreads => useConcurrentJIT
- Options: state that the gilOffProcess latch in notifyOptionsChanged is permanent
- Options: wire useThreadedDFG as a DFG/FTL tier kill switch under useJSThreads
- Options: wire useThreadedFTL as a tier kill switch (useFTLJIT off under useJSThreads)
- RaceAmplifier.h: describe the landed perturb() sites, drop the stale plan and unused isEnabled()
- Refuse import() and new ShadowRealm() on a spawned thread under GIL-off
- SamplingProfiler.h: drop never-instantiated WhileTargetSuspendedScope and the stale audit table
- SamplingProfiler: refuse to sample a gilOff VM with a logged diagnostic instead of silent dormancy
- ScratchBufferRegistry: one baked scratch index per size class instead of one per compile
- ScriptExecutable: delete dead replaceCodeBlockWith helpers; publish CodeBlock slots via one helper
- SharedVMState: fail-stop on same-thread StructureAllocationLocker nesting instead of hanging
- ThreadLocal: cache the per-realm instance Structure and honor newTarget
- VM.h: replace the exception-scope-verification review log with the member's invariant
- VM: correct the flag-off cost claims on the exception/trap mode-split accessors
- VM: count DrainMicrotaskDelayScope per thread GIL-off so spawned drains are never stranded
- VM: decide the inline soft-stack-limit and VMEntryScope gates on gilOffWithProcessGate()
- VM: decide whenIdle against the lite registry under gilOff and run pop listeners on the last thread out
- VM: document heapRandomUint64Concurrent as the concurrent-sweep-only path
- VM: fan notifyNeedTermination VM-wide so the carrier shield cannot swallow it
- VM: heap-allocate rejection handoff records so no Strong op runs under the queue lock
- VM: make the soft reserved zone size per-lite under gilOff and drop the RMW lock
- VM: remove the unused everHadSecondMutator/gilOffMultiMutator bit and its registerLite scan
- VM: replace the stale g_jscCurrentVMLite rationale block with the current contract
- VM: restore eager time zone initialization at VM creation (flag-off identity)
- VM: retire concurrent entry-scope service bits VM-wide under gilOff
- VM: retire the cross-thread-entry note from ~VM, not from the main carrier's ~VMLite
- VM: retire the cross-thread-entry note from ~VM, not from ~VMLite
- VM: retire the cross-thread-entry note from ~VM; ~VMLite never dereferences vm
- VM: route notifyNeedTermination through fireTrapVMWide so parked lites observe it
- VM: state that every JSPromise.cpp tracker call routes through the cross-thread gate
- VM: state the real VMLiteRegistry lock rank and drop the leaf claims
- VM: whenIdle uses the per-lite entry records under gilOff (same defect as 135-2)
- VMEntryScope: delete the dead N-entry refusal walk and the per-round status log
- VMEntryScope: whenIdle now honors the per-lite entered record the comment describes (same defect as 135-2)
- VMInspector: resolve GIL-off frames through the lite's VM group3Primitives()
- VMLite: delete dead lazyInit* block and mark GATE-3 landed in LazyPropertyInlines.h
- VMLite: delete the unused lazy-init owner side table
- VMLite: drop the dead Darwin TLS mirror; refuse GIL-off on non-Linux at option validation
- VMLite: drop the unused TLC chain verifier; assert the tlcTable/tlcTableBound mirror instead
- VMLite: drop the unused regExpAllocator and sizeOfLastScratchBuffer fields
- VMLite: fail-stop a compilation that asks the installed lite for a scratch buffer
- VMLite: key baked scratch indices by size class so the index space is bounded
- VMLite: never dereference vm in ~VMLite; retire the cross-thread-entry note from ~VM
- VMLite: remove the vacuous LZ1.3 teardown assert with its empty table
- VMLite: replace the Phase A/HARD GATE comments with the landed GIL-off routing
- VMLite: state the baked-scratch contract every tier now keeps
- VMLite: stop dereferencing vm in ~VMLite (a DETACHED carrier can outlive ~VM)
- VMLite: update the WS1.2 status list to match RegExpCache and ThreadManager as shipped
- VMLiteRegistry: document the real lock order; the registry lock is not a leaf
- VMLiteShared: call the STW-forbidden scope unconditionally; drop the N7 shim macro
- VMLiteShared: everHadSecondMutator scan already removed with VM finding 136-6; verified no residue
- VMLiteShared: state that the SAL locker is out-of-line and must be constructed only with the option on
- VMManager: delete the unused numberOfEnteredThreads helper
- VMManager: document jsThreadsStopPendingFor as the thread-granular-window probe only
- VMManager: gilOff cancelStop clears sibling lites through VM::clearVMWideEntryScopeService (135-1)
- VMManager: key the A.3 arbitration ParkingLot queue on the window token, not the Lock's address
- VMManager: let gilOff acquirers through the Mode-stop gate until a representative is elected
- VMManager: make a nested notifyVMStop from the servicing thread's STW callback a no-op
- VMManager: publish the function-scope root snapshot at the A.3 ticket park site too
- VMManager: remove BUGHUNT env-gated window-latency instrumentation and its includes
- VMManager: same Mode-stop gate fix as 144-1 (idle-VM debugger stop no longer parks every acquirer)
- VMTraps.h: replace the stale activation checklist with the current per-lite traps contract
- VMTraps: drop the stale VM-level DeferTermination keying note in handleTraps
- VMTraps: leave NeedWatchdogCheck pending when a GIL-off carrier polls without an entry scope
- VMTraps: make the per-thread defer counters plain scalars again
- VMTraps: resolve topCallFrame per-lite for the epoch jettison and debugger-break invalidation
- jsc: read hasPendingTerminationException while the lock keeps the carrier lite installed
- offlineasm: add cloop pseudo-instructions for the lite TLS read and the relaxed trap poll

sosukesuzuki pushed a commit that referenced this pull request

Sep 14, 2026
…and flag-off codegen

Fixes for the per-hunk review of #249 (review finding ids: 000-2, 000-3, 001-1, 002-1, 002-2, 002-3, 003-1, 003-2, 003-3, 004-1, 004-2, 004-3, 005-1, 006-1, 006-3, 006-5, 007-2, 007-3, 007-4, 007-5, 007-6, 008-1, 008-2, 008-3, 009-1, 009-2, 010-1, 010-2, 010-3, 011-1, 011-3, 012-2, 012-3, 012-4, 013-1, 013-2, 013-3, 014-1, 014-2, 014-4, 014-5, 014-6, 014-7, 015-1, 015-2, 015-3, 015-5, 015-6, 016-4, 016-5, 016-6, 017-1, 018-1, 018-2, 018-3, 019-1, 019-2, 020-1, 020-2, 020-3, 020-5, 020-6, 021-1, 021-3, 021-4, 022-1, 022-2, 022-3, 022-4, 022-5, 022-6, 022-7, 025-1, 025-2, 025-3, 025-4, 026-1, 026-2, 027-1, 027-3, 027-4, 027-5, 028-1, 028-3, 028-5, 029-1, 029-2, 029-3, 029-4, 030-1, 030-2, 031-2, 032-1, 032-2, 032-3, 041-2, 059-1, 059-2, 059-4, 059-5, 060-1, 060-2, 060-3, 060-4, 061-1, 061-2, 061-5, 062-1, 063-1, 063-2, 063-3, 064-1, 064-2, 064-3, 064-4, 064-5, 065-1, 065-2, 065-3, 065-4, 065-5, 066-3, 066-4, 067-2, 067-3, 067-4, 068-2, 068-3, 069-1, 074-1, 085-1, 103-3, 106-2, 120-1, 134-1, 147-4, 150-1, 150-6).

- AbstractMacroAssembler: remove dead initializeRandom() superseded by nextRandomSeed()
- AssemblyHelpers.h: state the real loadVMLite contract (any GPR, no scratch) at every gilOff helper
- AssemblyHelpers: RELEASE_ASSERT iso request fits cellSize in tlcSlotForConcurrentlyWithIso
- AssemblyHelpers: arity-check stack limit compares with GreaterThan again; contract requires the base condition
- AssemblyHelpers: collapse the dead Darwin loadVMLite leg now that non-Linux GIL-off is refused
- AssemblyHelpers: drop the wrong data-temp contract on loadVMLite; emitter clobbers only dest
- AssemblyHelpers: fold copyLLIntBaselineCalleeSaves into one VM&-keyed definition
- AssemblyHelpers: make loadVMLite the member implementation, declare the free form once, drop the macro guard
- AssemblyHelpers: rekey LLInt/Baseline callee-save spooler to VM&, drop duplicate in JITOpcodes
- Baseline enumerator_put_by_val: send flag-on out-of-line stores to the generic IC, not structureMismatch
- Baseline/thunk stack checks: pass the base's signed condition so flag-off bytes match
- Bytecode: fold if (@gilOffProcess) at codegen and drop the dead arm in builtins
- BytecodeGenerator: drop the last local GILOffCompilationLocker use; declaration now lives in one header
- BytecodeIntrinsicRegistry: derive @gilOffProcess via VM::isGILOffProcess(), drop stale comment
- CCallHelpers: drop __has_include scaffolding and unused includes, use ConcurrentButterfly.h constants
- CallLinkInfo: first polymorphic publish can no longer pair the new record with a null m_stub on ARM64
- CallLinkInfo: make the thunk's m_stub load address-dependent on the record load (ARM64)
- CallLinkInfo: pack Mode with the write-once callType/type byte, returning sizeof to base + m_record
- CallLinkInfo: state the real reason s_callLinkSerializationLock is recursive and ban GC-cell allocation under it
- CallLinkInfo: store the mode with relaxed byte accesses instead of seq_cst Atomic stores
- CodeBlock: drop the DFG JITData leak arm and the no-op retireOptimizedJITCode wrapper
- CodeBlock: free metadata, JITData and OpCatch buffers inline in ~CodeBlock with JS threads on
- CodeBlock: unlink leaked metadata/DFG-JITData call sites in ~CodeBlock so records release their pins
- CompactTDZEnvironmentMap: serialize the TDZ interning table itself instead of one codegen caller
- DFG AI: clobber structures across GIL-off parkable nodes instead of folding the clobber
- DFG EnumeratorPutByVal: run the butterfly write predicate before the out-of-line store
- DFG OSR exit ramp: use the invalidating scratch temp as the gilOff per-lite scratch base
- DFG compileSpread: copy from the butterfly snapshot the length came from flag-on
- DFG prologue stack check: pass GreaterThan so flag-off bytes match the merge base
- DFG/FTL: skip the PerformPromiseThenOneHandler inline install for a gilOff VM
- DFG: accept PutByValDirectResolved on the segmented-aware PutByVal path
- DFG: dispatch operationArrayPopAndRecoverLength on the butterfly regime; drop stale FIXME
- DFG: drop mergeOSREntryValue zero-StructureID bail and validated-freeze scaffolding
- DFG: drop the __has_include(ConcurrentButterfly.h) scaffolding and frozen fallback constants
- DFG: fail the compilation when a desired watchpoint set was fired before the link
- DFG: gate m_tierUpTriggersLock on useJSThreads in operationTriggerTierUpNowInLoop
- DFG: gate the clobberize validator suppression on vm().gilOff(), not the process option pair
- DFG: keep the segmented-butterfly bit for Convert+Original array modes
- DFG: make the segmented-aware Double GetByVal SaneChain arm pure and format-correct
- DFG: remove the dead DW-1 sort-comparator OSR-exit stash record
- DFG: resolve operand scratch buffers per lite under gilOff instead of baking VM addresses
- DFG: skip inline-offset by-offset nodes in the butterfly tag-discipline lint
- DFG: state the compilation lock's scope in Plan::finalize instead of a residual-race note
- DFG: state the landed usePollingTraps invariant at JumpReplacement::installVMTrapBreakpoint
- DFG: state the usePollingTraps invariant at the VMTrap breakpoint asserts
- DFG: use the shared GILOffCompilationLocker from JSThreadsSafepoint.h in Plan::finalize
- DFG: write MiscFields at the GIL-off CheckTraps poll so typed-array vector/length reload per poll
- DFGMayExit: report PutByOffset as Exits flag-on only for out-of-line offsets
- DFGOSRExitCompilerCommon: drop loadVMLite redeclaration, call the AssemblyHelpers member
- DFGThunks: drop the stale Release VM-block fallback from the OSR exit destination comments
- DFGThunks: use header loadVMLite; pin per-lite scratch offsets to the ARM64 ldr immediate range
- FTL ArithRandom: drop the GIL-off operation detour; inline path matches DFG and thunk tiers
- FTL MaterializeNewObject: say why the slow-path butterfly mask is required, not a no-op
- FTL MultiDeleteByOffset: RELEASE_ASSERT flag-off; remove the dead threaded slot-clear arm
- FTL compileDelBy: assert base != result before the handler-IC shuffle aliases them on ARM64
- FTL lazy slow path: consumer-side instruction sync before executing a foreign-thread stub (gilOff)
- FTL prologue: restore signed GreaterThan stack check so flag-off bytes match the base
- FTL varargs frame: restore signed GreaterThan soft-stack-limit check for flag-off byte identity
- FTL: TID-tag inline-allocated butterflies under useJSThreads, not only gilOff
- FTL: address the handler-IC dummy ArrayProfile off jitDataRegister like the DFG
- FTL: correct the E1 comment; the owner compare is not a segmented-word backstop
- FTL: drop the stale useThreadedFTL wiring comment in compilePutByOffset
- FTL: drop unreachable slow-path call from handler-IC GetById/GetByIdWithThis late paths
- FTL: include ConcurrentButterfly.h unconditionally; drop duplicated tag-encoding fallback
- FTL: skip E2 writeThreadLocal registration for KnownNonArrayStorage read plans
- FTLOSRExitCompiler: drop the loadVMLite self-declaration and call the AssemblyHelpers member
- FTLSaveRestore: make materializers clobber only dest; loadVMLite via member
- FTLSaveRestore: remove the loadVMLite self-declaration and bring-up comment
- FTLThunks: document why the baked exit-thunk scratch dump survives the generation call
- FunctionExecutable: remove the uncalled codeBlockWithEntrypointFor
- GCAwareJITStubRoutine: defer the zero-refcount delete only while the JITStubRoutineSet holds the routine
- GetByStatus::computeFromLLInt: read LLInt cache mode and structureID words with relaxed atomic loads
- InferredValue: add() reports a refused link so the DFG singleton fold is not installed stale
- InlineCacheCompiler ArrayLength stub: bail only for SW=1 ArrayStorage/SlowPut, not every SW=1 flat word
- InlineCacheCompiler: drop the false EOR zeroing-idiom claim from the ArrayLength dependency comment
- InlineCacheCompiler: give the shared stateless stub no owner CodeBlock
- InlineCacheCompiler: make the flag-on per-case Replace stub store through the write predicate
- InlineWatchpointSet: CAS thin-state stores and retry the inflateSlow publish flag-on
- JIT inline allocation: TID-tag the installed butterfly under GIL-on as well as GIL-off
- JIT: release a record's CodeBlock pin when the owning CallLinkInfo frees the record inline
- JITOperations: fail-stop operationReallocateButterflyAndTransition under useJSThreads
- JITThunks: gate hostFunctionStub/finalize m_lock on useJSThreads
- JITThunks: state the real m_lock scope, held across thunk generation
- JITWorklist: drop unused <wtf/NeverDestroyed.h> include and finalizingKeys history note
- JITWorklist: print duplicate-plan verbose log via locker dump to avoid re-locking m_lock
- JSThreadsSafepoint.h: declare gilOffCompilationLock and GILOffCompilationLocker once
- JSThreadsSafepoint.h: describe the live GIL-on stub and gilOff conductor paths and the live watchdog
- JSThreadsSafepoint: GIL-on Class-A fire tolerates a second entered VM; add regression test
- JSThreadsSafepoint: GIL-on stub no longer requires every other VM in the process to be idle
- JSThreadsSafepoint: accept only this thread's own stub depth as thread-stable stopped evidence
- JSThreadsSafepoint: declare the heap-fact rewrite epoch API in its own header, not VMTraps.h
- JSThreadsSafepoint: drop the __has_include probes, dead #else arms and the OM stub witness reads
- JSThreadsSafepoint: make the stop-the-world watchdog timeout an Option (0 = disabled)
- JSThreadsSafepoint: scope the entered-VM tripwires to VMs attached to the caller's server heap
- JSThreadsSafepoint: state the in-window bump as load-bearing and the ctor/dtor bumps as edges
- LLInt callHelper: name x6/a6 as the ARM64 register invokeForTailCall clobbers
- LLInt loadButterflyTIDTagToT6: state the non-Linux slow-path cliff, not a missing slot
- LLInt virtualThunkFor: state that the slot recompare is belt-and-braces, not the defense
- LLInt: drop the DW-1 sort-comparator stash cross-check and its release-build dataLogLn
- LLInt: drop the Group-3 break tripwire now that Options refuses GIL-off off Linux
- LLInt: drop the gilOffProcess fence test from op_put_internal_field on x86-64 (TSO)
- LLInt: gate the varargs frame echo and its RELEASE_ASSERTs on vm.gilOff()
- LLInt: load m_cache.structureID with a relaxed atomic in try_get_by_id/get_by_id_direct
- LLInt: remove the non-Linux Group-3 break tripwire from production code
- LLInt: restore flag-off memory-operand structure compares in enumerator ops and put_to_scope
- LLInt: revalidate the slot offset against the keyed structure before a GIL-off one-word publish
- LLInt: wire the useThreadedLLIntICs kill switch into the one-word cache publishers
- LOLJIT: pass signed GreaterThan to branchPtrAgainstSoftStackLimit to keep flag-off bytes
- MacroAssemblerARM64: make loadFromELFTLS64 scratch-free (mrs; add hi12; ldr lo12)
- OSR exit: crossModifyingCodeFence before reusing a ramp compiled on another thread
- OSR exit: share one generation lock between DFG and FTL exit compilers under gilOff
- PropertyInlineCache: document resetStubAsJumpInAccess as a live publish, not world-stopped
- PropertyInlineCache: make m_identifier an ICRacyCell so every writer is a relaxed store
- PropertyInlineCache: state the real flag-off per-IC footprint cost and its sizeof consumers
- Repatch.cpp: state that the cacheable-dictionary guard exists so ICs settle at GaveUp via the addAccessCase funnel
- Repatch/InlineCacheCompiler: name the real gate for flag-on put transitions
- Repatch: count only consecutive no-progress retries before GIL-off GaveUp demotion
- Repatch: gilOff linkMonomorphicCall loser bails unless the site is still Mode::Init
- RetiredJITArtifacts: drop __has_include scaffolding, leak arms and always-true epoch predicate
- RetiredJITArtifacts: replace unreachable lazy makeGCAware promotion with RELEASE_ASSERT(isGCAware)
- SetupVarargsFrame: restore signed GreaterThan soft-stack-limit compare (flag-off byte identity)
- SharedJITStubSet: make find() take its reference with tryRef so a dying routine is never resurrected
- UnlinkedFunctionExecutable: make recordParse fields dedicated relaxed-atomic bytes
- UnlinkedMetadataTable::link: drop TSAN-only relaxed zeroing, keep memset
- Watchpoint: drop the out-of-line Dependency::fence from InlineWatchpointSet fat reads
- Watchpoint: drop the unused fireEarlyForGILOff/hasClassAFirePending and state the real deferral ordering
- Watchpoint: refuse add() on an invalidated set flag-on; enumerator install falls back to traversing
- Watchpoint: remove the BUGHUNT Class-A fire instrumentation
- Watchpoint: remove the uncalled fireEarlyForGILOff/hasClassAFirePending scaffolding
- WatchpointSet: arm by CAS, refuse add() on an invalidated set, make callers honor the refusal
- WatchpointSet: route already-stopped Class-A fires through stopTheWorldAndRun's guarded path
- Yarr: drop the false matchLimit stop-latency bound claim and its static_assert ratchet
- YarrJIT: restore the signed LessThanOrEqual soft-stack-limit check so flag-off bytes match base
- resolve_scope slow paths: read m_resolveType with a relaxed atomic load like its writers
- resolve_scope: freeze op_resolve_scope metadata after linking flag-on in all three writers

sosukesuzuki pushed a commit that referenced this pull request

Sep 14, 2026
…support

Fixes for the per-hunk review of #249 (review finding ids: 150-2, 150-4, 150-7).

- Wasm: gate the spawned-thread refusal on useJSThreads so flag-off skips the TLS lookup
- Wasm: refuse GC-typed modules under useSharedGCHeap with CompileError/LinkError, not abort
- WasmMemory: mark GIL-off relocating-grow stop arm dormant, drop audit-closure claims

sosukesuzuki added a commit that referenced this pull request

Sep 17, 2026
Squashed from 151 commits on jarred/threads (merge-base 5851d47) so the
whole change can be rebased onto main as one unit.

sosukesuzuki pushed a commit that referenced this pull request

Sep 17, 2026
Fixes for the per-hunk review of #249 (review finding ids: 000-1).

- CMakeLists: export GCSafepointEpoch/GCThreadLocalCache/HeapClientSet/JSThreadsSafepoint headers

sosukesuzuki pushed a commit that referenced this pull request

Sep 17, 2026
…om table ordering

Fixes for the per-hunk review of #249 (review finding ids: 131-5, 151-1, 151-2, 152-1, 153-1, 153-2, 154-1, 154-2, 154-3).

- BitSet: gate relaxed-atomic zeroing constructor on TSAN_ENABLED, keep aggregate zero-init otherwise
- DeferrableRefCounted: gate the atomic refcount RMWs on a process-latched GIL-off Config byte
- StringImpl: keep the legacy load/modify/store in cost, setIsAtom and setHash when the shared atom table is off
- SymbolImpl: make the symbol hash counter atomic
- Thread: add WTF Thread::tryCreate and throw RangeError when the OS refuses a thread
- WTF Thread: reword dedicated-byte flag comments to name the real writer/reader race
- WTF: define SharedAtomStringTable::singleton and the latch in SharedAtomStringTable.cpp
- WTF: state the migrate-then-latch-then-clear order in enableSharedAtomStringTable without citing the spec

sosukesuzuki pushed a commit that referenced this pull request

Sep 17, 2026
…er, drop temporary diagnostics

Fixes for the per-hunk review of #249 (review finding ids: 033-1, 033-2, 033-3, 034-1, 034-2, 034-3, 034-5, 035-1, 035-2, 035-3, 036-1, 036-3, 036-4, 036-5, 036-6, 037-1, 037-2, 038-1, 038-2, 038-3, 039-1, 039-2, 039-3, 040-1, 041-1, 041-3, 042-1, 042-2, 042-3, 043-1, 043-2, 043-3, 043-4, 043-5, 044-1, 044-2, 045-1, 045-2, 045-3, 046-1, 046-2, 046-3, 046-4, 046-5, 046-6, 046-7, 047-2, 047-3, 047-4, 048-1, 048-2, 048-3, 048-4, 048-5, 049-1, 049-2, 050-1, 050-2, 051-3, 052-1, 052-2, 052-3, 052-4, 052-5, 053-1, 053-2, 053-3, 054-1, 054-2, 055-1, 055-2, 056-1, 056-2, 116-6, 135-3).

- BlockDirectory: assert the lock-free m_bits witness is this thread's exclusive MSPL or own stripe
- BlockDirectory: make assertSweeperIsSuspended a world-stopped/exclusive-owner assertion; drop sweeper-disabled claims
- BlockDirectory: remove findOwnEmptyBlockForRefill, whose target population cannot exist
- BlockDirectory: step the steal cursor past weak-bearing empties instead of declining them
- CompleteSubspace::allocate: test the server allocator before the useSharedGCHeap branch
- CompleteSubspace::allocate: trust the per-thread TLC snapshot only when vm is gilOff
- Drop the dead null-client disjunct from the TLC hit ASSERT and restate its invariant
- GCIncomingRefCountedSet: take the incoming-reference lock only under gilOffProcess
- GCIncomingRefCountedSet: walk the set unlocked in sweep/lastChanceToFinalize (world stopped)
- GCThreadLocalCache: remove uncalled allocatorFor(BlockDirectory&), stopAllocating, prepareForAllocation, server
- GCThreadLocalCache: replace unreachable growTable realloc leg with a fixed-capacity RELEASE_ASSERT
- HandleSet: fold the Strong leaf lock into the class, drop the process-global side table
- HandleSet: lock the live protected-cell walk; route the NODELETE counter through m_strongLock
- HandleSet: make m_strongLock a real member and rewrite the seam comments as invariants
- HandleSet: take m_strongLock in forEachStrongHandle under gilOff
- Heap: correct the F28 successor-open comments to the drain the code performs
- Heap: correct the Wlr comment: Auxiliary witnesses are marked, not traced
- Heap: count drainFromShared entrants for the marker pause; restore flag-off steal denominator
- Heap: create sibling-assist visitors in runBeginPhase, decline assists when the pool is empty
- Heap: delete dead allocationClientForJITCodegen and the duplicate free resolver
- Heap: delete the dead namespace-scope allocationClientForCurrentThread and its stale note
- Heap: delete the never-constructed SharedGCWindowOpen::TicketDrainSuccessor arm
- Heap: delete the unreferenced allocationClientForJITCodegen resolver
- Heap: describe the STW-forbidden scope depth as a release-mode per-thread counter
- Heap: document that a LambdaFinalizer may receive a null JSCell* under GIL-off
- Heap: document that shared-mode hooks/reclaim/rebias run once per drained ticket batch
- Heap: document the GIL-off LambdaFinalizer contract (null cell, runs after the world resumes)
- Heap: drain GCSafepointEpoch retired items in lastChanceToFinalize, before blocks are freed
- Heap: drain an orphaned needFinalizeBit inside the ISS flip before storing ISS
- Heap: drop dead sharedGCWindowedStagesEnabled(); Heap.cpp keeps the one stage-flag list
- Heap: drop stale NOTE claiming worldIsStopped() still does a plain read
- Heap: drop the untimed JSThreadsStopScope ctor; harness uses the watchdog ctor
- Heap: drop the unused 1-byte layout pad and state what the trailer guards check
- Heap: drop unused GCClient::CompleteSubspaceView, its members and bind hook
- Heap: exempt the PreventCollectionScope holder from the shared conduct-tenure gate
- Heap: fix comments still claiming the IncrementalSweeper is disabled when shared
- Heap: gate DeferGC slot routing on useSharedGCHeap and resolve both slots once
- Heap: gate allocationClientForCurrentThread on gilOffWithProcessGate, drop stale rationale
- Heap: gate the freelisted-block walk in stopThePeriphery on Options::verifyGC()
- Heap: gate the possibly-accessed-strings append lock on gilOff
- Heap: gate the shared-GC root-snapshot/endMarking/freelisted-block checks behind Options::verifyGC()
- Heap: make barrierThreshold()/mutatorShouldBeFenced() plain server-master reads
- Heap: make sharedGCMaxSiblingMarkingAssists=0 mean disabled and drop the dead auto branch
- Heap: read the server master barrier pair in mutatorShouldBeFenced/barrierThreshold
- Heap: register the epochReclaim safepoint hook per heap, make hook registry idempotent
- Heap: remove the unconsumed CompleteSubspaceView wrappers and bind hook
- Heap: route server-level acquire/release/hasAccess to the calling thread's client GIL-off
- Heap: run TID-rebias fires as the GC conductor and retire the stale tripwire banner
- Heap: run the conservative-scan constraint on the conductor when sibling assists are admissible
- Heap: run verifyStickySharedServerDesignation before HeapClientSet::add's sticky trigger
- Heap: scan and grant the shared collectAsync ticket under one m_threadLock hold
- Heap: serialize the server mutator mark stack with a Heap lock, not a MarkStackArray flag
- Heap: state the pin-lock-then-codeBlockSet-lock order at pinRetiredCallLinkRecordCodeBlock
- Heap: state the shared-mode no-runloop-push rule and log access-barrier stalls
- Heap: strip the TEMPORARY ring-liveness diagnostics from the shared-heap harness
- Heap: take m_possiblyAccessedStringsFromConcurrentThreadsLock only under gilOff
- Heap: take m_protectedValuesLock in protect/unprotect and statistics walks under gilOff
- Heap: test useSharedGCHeap before isSharedServer in the per-client slot dispatchers
- HeapClientSet: run the sticky-server designation check before the second-client ISS flip
- IsoSubspace: inline GCClient::IsoSubspace::tlcSlot, drop false out-of-line rationale
- IsoSubspace: remove unused GCClient::IsoSubspace::allocateForClient
- Key the TLC snapshot hit on vm.gilOff() so nested foreign-VM entry cannot allocate from the wrong heap
- MarkedBlock: correct the isMarkedRaw comment to name its callers' protocols
- MarkedBlock: drop the unreachable allocBit leg and last-era skip from the window snapshot
- MarkedBlock: state the real stale-true argument for the destructible hint; keep it in lockstep for false
- MarkedBlock: take the heapRandom lock in specializedSweep only when sweeps can run concurrently
- MarkedSpace: bound TLC slot reservation by numCompleteSubspaces * numSizeClasses
- MarkedSpace: say isPagedOut's only caller skips it when shared, not that it never fires
- MarkingConstraint: delete dead m_lock member and the comment deferring its removal
- SharedHeapTestHarness: remove the ring-liveness diagnostics and the Heap.cpp audit seam
- SlotVisitor: arm the per-batch helper pause checkpoint in the gilOff single-handoff shape
- Threads: relinquish a spawned thread's allocators while its lite is Live, not from the client dtor
- TinyBloomFilter: replace relaxed fetch_or in add() with relaxed load+store
- VMManager.h: declare the thread-granular conductor predicates once; drop seven hand copies

sosukesuzuki pushed a commit that referenced this pull request

Sep 17, 2026
…hared butterfly protocol

Fixes for the per-hunk review of #249 (review finding ids: 021-2, 036-2, 061-3, 061-4, 072-1, 072-2, 072-3, 072-4, 073-1, 073-2, 073-5, 075-1, 075-2, 075-3, 076-1, 076-2, 076-3, 077-1, 077-2, 078-1, 078-2, 078-3, 079-1, 079-2, 080-2, 080-3, 080-4, 083-1, 084-1, 084-2, 084-4, 086-1, 086-2, 086-3, 086-4, 086-5, 087-1, 087-2, 087-3, 087-4, 087-5, 088-1, 088-2, 089-3, 089-4, 090-2, 090-4, 090-5, 090-6, 091-3, 099-1, 099-2, 099-3, 100-1, 100-2, 100-3, 100-4, 100-5, 101-1, 101-2, 102-2, 102-3, 102-4, 102-6, 103-1, 103-2, 103-4, 104-2, 104-3, 104-4, 105-1, 105-2, 105-3, 106-5, 108-4, 110-2, 111-1, 112-1, 112-2, 113-1, 113-2, 113-3, 116-2, 116-3, 116-4, 117-1, 118-1, 118-2, 119-1, 119-2, 119-3, 120-2, 121-1, 121-2, 121-4, 122-1, 122-2, 123-1, 123-2, 123-3, 124-1, 124-4, 132-1, 149-1).

- ArrayPrototype: derive join/indexOf/concat fast paths from one tagged butterfly word snapshot
- ArrayPrototype: re-read indexing types after the concat result allocation flag-on
- ArrayPrototype: reverse fast path flips SW for foreign writers and uses one butterfly snapshot
- ButterflyInlines: keep optimalContiguousVectorLength within MAX_STORAGE_VECTOR_LENGTH
- ClonedArguments: copyToArguments reads one butterfly-word snapshot, bails on segmented/null
- ClonedArguments: serialize GIL-off materializeSpecials under a park-capable lock
- ConcurrentButterfly.h: document the gilOff StayFlatShared transition in the regime contract
- ConcurrentButterfly.h: read the verify/stress options directly instead of SFINAE probes
- ConcurrentButterfly: StayFlat copy-grow copies no element payload for typed-array views
- ConcurrentButterfly: assert non-null fragments under verifyConcurrentButterfly in the GC visit
- ConcurrentButterfly: bail out of the ensureLength/shrink drivers when an AS conversion lands
- ConcurrentButterfly: delete the uncalled segmentedTransition/structureOnlyTransition drivers
- ConcurrentButterfly: drop the process-global stub world-stopped witness
- ConcurrentButterfly: make butterflyWorldIsStopped the JSThreadsSafepoint predicate alone
- ConcurrentButterfly: name the useSharedGCHeap gate in the mode (b) rarity comments
- ConcurrentButterfly: register the quarantine epoch hook on every Heap, not per address
- ConcurrentButterfly: remove the uncalled spineOutOfLineFragment/spineIndexedFragment exports
- ConcurrentButterfly: route far-beyond-vector indexed stores to the sparse-map path flag-on
- ConcurrentButterfly: size typed-array view conversions from a zero indexed payload
- ConcurrentButterfly: state the GC visit bound as the spine's vectorLength in code comments
- ConcurrentButterflyOperations: drop __has_include scaffolding and the TID-0 shim
- ConcurrentButterflyOperations: remove the seven unreachable JIT operation shims
- DFG operationCreateThis: validate the allocation profile snapshot under gilOff like slow_path_create_this
- DirectArguments: serialize overrideThings puts and bitmap publication under gilOff
- FunctionRareData: GIL-off .prototype store is followed by a clear that waits for the initializer
- GetterSetter: restore WriteBarrier::set() in ctor, drop stale hand-expansion and comment
- JSArray AS shift/unshift concurrent: re-check the caller's range under the cell lock and bail
- JSArray/JSObject: replace GIL-only sparse-map iterators on flag-on paths with keyed locked access
- JSArray::appendMemcpy: re-read both indexing types after ensureLength before the memcpy
- JSArray::copyToArguments: clamp the flat scan to the caller's length as well as the snapshot
- JSArray::fastFill: bail when the flag-on relabel left indexingType != nextType
- JSArray::fastFlat: bail flag-on when pass 2 copied a different count than pass 1
- JSArray::fastFlat: bail when the source shape changed across the result allocation
- JSArray::fastSlice: hold one GCDeferralContext across butterfly allocation, copy and cell allocation
- JSArray::fastToReversed/fastWith/fastToSpliced: re-read indexingType after the result allocation
- JSArray::pop: return undefined when a racing shrink emptied the array before the generic tail
- JSArray::setLength/pop/fastShift: restart on a null word paired with an indexed mode
- JSArray::unshiftCountSlowCase: drop unreachable flag-on branches
- JSBigInt: throw OutOfMemoryError from createFromDigit instead of RELEASE_ASSERT
- JSCJSValue: make the 64-bit JSValue slot accessors relaxed atomics only under TSAN
- JSCell: drop no-op decontaminate() in structure(); state the nuke-bit contract
- JSCellInlines: delete orphaned comment describing the withdrawn H-CALLSITE-LASTSIZE-LA mechanism
- JSCellInlines: make tlcSlotForSubspace fail closed for non-CompleteSubspace kinds
- JSCellLock: maintain GCCellLockDepth in lock/tryLock/unlock so the no-park asserts are live
- JSFunction: CAS-publish FunctionRareData under gilOff so racing installs adopt one cell
- JSObject.h: drop the stale i03-i37 FIXME in tryMakeWritableInt32
- JSObject.h: remove uncalled butterflyRegime() and isSharedArrayStorage()
- JSObject: RESTART stop-published indexing transitions when a dictionary table was edited in place
- JSObject: always CAS-max publicLength after flag-on dense stores and ensureLength
- JSObject: barrier the owner after the AS-COPY growth publication
- JSObject: butterfly() contract drops the guard-then-reload witness; snapshot JSCellButterfly::createFromArray
- JSObject: check the ThrowScope when putInlineSlow's thread-restrict gate throws
- JSObject: check the ThrowScope when threadRestrictCheck fails in getNonIndexPropertySlot
- JSObject: correct the flatten re-check comment about renumberPropertyOffsets' edit stamp
- JSObject: dispatch flag-on indexed delete on one loaded word, never the flat switch
- JSObject: fence mode-then-word loads in indexed names walk and beyond-vector put
- JSObject: install a fresh sparse map under the cell lock only if none is installed (flag-on)
- JSObject: load mode before the fenced word in setIndexQuicklyConcurrent; putDirectIndex uses the try variant
- JSObject: publish dictionary attribute changes under the cell lock with a table-stamp re-check
- JSObject: putDirectIndex AS grow arm re-checks the vector bound under the lock before storing
- JSObject: re-check i < vectorLength under the lock after increaseVectorLength before storing
- JSObject: re-check vectorLength on the fresh word in setIndexQuicklyConcurrent and route putDirectIndex via try
- JSObject: re-dispatch putDirectIndex after createArrayStorage instead of indexing the returned vector
- JSObject: re-validate structureID after the word load in createInitialIndexedStorageConcurrent
- JSObject: recount m_numValuesInVector under the lock in sparse-map consolidation
- JSObject: return the settled ArrayStorage from convertToArrayStorageConcurrent when a racer converted first
- JSObject: route null-word foreign-keyed indexed first installs to the shared stop leg
- JSObject: run the F1 SW flip before cell-locked ArrayStorage stores in putByIndex and the AS funnels
- JSObjectWithButterfly: delete the uncalled getDirectConcurrent/putDirectConcurrent
- JSPropertyNameEnumerator: drop stale NOTE, state the relaxed store/load invariant
- LazyProperty: drop unreachable initializer-abandonment restore in callFunc
- MegamorphicCache: restore plain epoch bump; make bumpEpoch a no-op under useJSThreads
- ObjectConstructor: clone fast paths copy from one tagged-word snapshot paired with the structure
- PropertyTable: document that inline deleted offsets are quarantined too
- PropertyTable: fold deleted-offset bookkeeping into one side struct (cell 80 -> 48 bytes)
- PropertyTable: say seal()/freeze() edit a still-private table; keep the seqlock bracket
- PropertyTable: skip the quarantine walk when the oldest stamp is not yet promotable
- PropertyTable: state the TSAN pairing rationale for relaxed constructor stores
- SparseArrayValueMap: decide flag-on putEntry/putDirect under the lock, throw and call setters after it
- SparseArrayValueMap: dispatch putEntry on the value word and lock every flag-on entry writer
- SparseArrayValueMap: insert a sparse entry only once the write is allowed (no placeholder)
- Structure: condense the DEFINE_BITFIELD perf narrative to the lost-update invariant
- Structure: drop the unused DeferredWatchpointFire parameter of firePropertyReplacementWatchpointSet
- Structure: gate SAL locker construction in Structure::create/createStructure on the latched option
- Structure: gate the lock-free transition precheck on useJSThreads for the IC/DFG callers
- Structure: name the lock-free republish store as the only unlocked chain writer
- Structure: pre-allocate the shrunk flatten butterfly outside the stop window
- Structure: re-copy seenProperties/propertyHash into a transition under the source m_lock
- Structure: remove the never-passed deferred parameter and its API comment
- Structure: replace transitionThreadLocalTIDOffset with a restampTransitionThreadLocalTID setter
- Structure: restore .set()/.setMayBeNull() at four slot writers; drop stale plain-store comments
- Structure: revalidate isDictionary and object->structure in the flatten stop closure
- Structure: snapshot forEachProperty entries under m_lock and run the functor unlocked
- Structure::add<ShouldPin::Yes>: recheck under m_lock that the table was not stolen
- StructureChain: bound finishCreation's lane walk by the size create() allocated
- StructureRareData: GCSafe, flag-on-only lock around the special property cache install
- StructureRareData: move retired enumerator watchpoint list out of the cell into the Heap
- TypeInfoBlob/Structure: make the blob, outOfLineTypeFlags and classInfo reader loads TSAN-only
- WriteBarrier: make the cell-pointer slot accessors relaxed atomics only under TSAN
- ensureLengthSlowConcurrent: drop the dead availableOldLength computation and T5 comment
- fastArrayJoin: snapshot the butterfly word once and re-probe it after user code
- shiftCountWithArrayStorageConcurrent: allocate the fresh AS before the scalar stores

sosukesuzuki pushed a commit that referenced this pull request

Sep 17, 2026
…nd lifetime races

Fixes for the per-hunk review of #249 (review finding ids: 070-1, 070-2, 070-3, 070-4, 070-5, 070-6, 071-1, 071-2, 072-5, 072-6, 074-3, 089-1, 089-2, 089-5, 090-1, 090-3, 091-1, 091-2, 091-4, 092-1, 092-2, 092-3, 092-4, 107-1, 107-3, 107-4, 108-1, 108-2, 108-3, 114-1, 114-2, 114-3, 114-4, 115-1, 116-1, 117-2, 124-3, 125-1, 125-2, 125-3, 125-4, 125-5, 126-1, 126-3, 126-4, 128-2, 148-2, 148-5).

- ArrayBuffer: allocate the GIL-off resizable transfer copy without a VM so it cannot collect
- ArrayBuffer: fail the GIL-off transferTo whose detach lost the flag race, as already detached
- ArrayBuffer: fail the racing transfer loser so exactly one transfer of a buffer succeeds
- ArrayBuffer: make isDetached() read a sticky GIL-off detached flag; drop the side-table probes
- ArrayBuffer: make isDetached() read the sticky GIL-off flag, drop isArrayBufferDetachedGILOff
- ArrayBuffer: neuter views before the mapping enters the quarantine in GIL-off detach
- ArrayBuffer: quarantine a relocated wasm mapping in the growing VM's heap quarantine
- ArrayBuffer: re-check isDetached() and maxByteLength under the lock on every resizeGILOff pass
- ArrayBuffer: register the quarantine safepoint hook per Heap at VM init, not per address
- ArrayBuffer: snapshot length and maxByteLength under the handle lock in GIL-off transferTo
- Atomics: delete the D8 single-flight TA sync-wait gate; lift the 4.5-1a spawned gate GIL-off only
- AtomicsObject: run the GIL-off detach re-check before ToIndex so the TA path keeps RangeError
- ConcatKeyAtomStringCache: read/store m_mode through relaxed atomics in getOrInsert
- DataView get/set: keep the plain byte loop flag-off, relaxed atomics only under gilOffWithProcessGate
- DataView get/set: snapshot the view base before the length proof, throw detached on null GIL-off
- DateCache: route GIL-off entry points to a per-thread cache instead of one VM-wide leaf lock
- JSArrayBufferView: convert shared flat views before the GIL-off wastage copy; retry a failed CAS
- JSArrayBufferView: give a segmented Fast/Oversize view a header fragment in slowDownAndWasteMemory
- JSString: derive every rope-walk decision from one per-node m_fiber snapshot
- JSString: plain constructor-time rope stores in production, relaxed atomics only under TSAN
- JSString: remove dead resolveRopeInternalNoSubstring
- KeyAtomStringCache: relaxed slot snapshot load in production, acquire only under TSAN
- KeyAtomStringCacheInlines: drop unused Options.h, stdlib.h and DataLog.h includes
- RegExp: make m_atom write-once so lock-free atom() readers never see it freed
- RegExp: publish bytecode before m_state=ByteCode; never hand Yarr::interpret a null pattern
- RegExp: take cellLock in reset(), route error-code reads through one relaxed accessor
- RegExp: write-once m_atom and bytecode-before-state publication (same fix as 114-1/114-2)
- RegExpCache: clear Yarr code under a stop-the-world window when gilOff
- SimpleTypedArrayController: actually defer the displaced dead wrapper Weak under GIL-off
- StringRecursionChecker: use the per-thread recursion state in every useJSThreads mode
- Symbol: return the canonical cell from finishCreation instead of re-probing symbolImplToSymbolMap
- ThreadAtomics: DeferGC around the Missing-add ArrayStorage cell-lock window
- ThreadAtomics: bump ArrayStorage length only after the conditional add publishes
- ThreadAtomics: drop the never-incremented g_threadAtomicsSlotCASRetries stub and its dump field
- ThreadAtomics: drop the never-incremented slotCASRetries counter
- ThreadAtomics: flip SW before the Missing-add ArrayStorage cell lock
- ThreadAtomics: grow dense shapes for beyond-vector Atomics.store adds GIL-off
- ThreadAtomics: release the waitAsync ticket at dequeue instead of at timer fire
- ThreadAtomics: state the in-window teardown-sweep finalizer contract
- ThreadAtomics: state why property waitAsync stays an uncounted keepalive registration
- TypedArray copyWithin: return early on a null base snapshot in the GIL-off lane loop
- TypedArray element accessors and sort: gate on g_jscConfig.gilOffProcess, not VM::isGILOffProcess()
- TypedArray fill: return early on a null base snapshot in the GIL-off lane loop
- TypedArray forEach: test the base snapshot instead of isDetached() in the arms that re-read the base
- TypedArray includes/indexOf/lastIndexOf/reverse/sort: handle a null base snapshot GIL-off
- TypedArray setFromTypedArray/sort/copyFrom*ShapeArray: never deref a base re-read after the bounds proof GIL-off
- WaiterListManager: settle a foreign VM's TA waitAsync under list->lock in the GIL-off notify arm
- jsAtomString: republish the atom when a lost GIL-off publish race left a non-atom impl

sosukesuzuki pushed a commit that referenced this pull request

Sep 17, 2026
…, Lock, Condition and ThreadLocal

Fixes for the per-hunk review of #249 (review finding ids: 051-1, 059-3, 081-1, 082-1, 082-2, 082-4, 096-2, 098-1, 098-2, 106-1, 106-4, 109-1, 109-2, 109-3, 109-4, 109-5, 111-5, 111-6, 129-1, 129-2, 129-3, 129-4, 129-5, 130-1, 130-2, 130-3, 130-4, 130-5, 131-1, 131-2, 131-3, 131-4, 134-4, 148-1, 148-3, 148-4, 149-2, 149-3).

- ConcurrentAccessError constructor: derive the Structure from newTarget
- ConditionObject: consume the async grant under m_queueLock before asyncWait's (b) release
- DeferredWorkTimer: capture the timer, not Ref<VM>, in gilOff run-loop dispatches
- DeferredWorkTimer: fix stale runRunLoop comment about the non-gilOff arm taking m_taskLock
- DeferredWorkTimer: make TicketData::m_isCancelled a relaxed std::atomic<bool>
- GILDroppedSection: stop publishing a coop GC root snapshot from the out-of-line ctor
- JSMicrotask: delete the unreferenced publishAsyncGeneratorResume host function
- JSMicrotask: gate the generatedJITCodeForCall mirror assert on !gilOff
- JSPromise: keep GIL-off spawned threads off VM::m_synchronousModuleQueue
- JSPromise: read m_asyncContextData directly at the five capture sites
- LockObject: count asyncHold registrations toward the spawned registrant's keepalive
- LockObject: keep a termination pending in the asyncHold(fn) settle instead of rejecting
- LockObject: keep the GILDroppedSection coop root snapshot on the park-site frame
- LockObject: open the park-resumption window at the holder's release, not at park entry
- LockObject: run the async-grant pump inline for a spawned head registrant under gilOff
- MicrotaskCall: relaxed entry/codeBlock loads, acquire fence only in the gilOff arm
- MicrotaskQueue: clearForGlobalObject also filters the GIL-off foreign inbox
- MicrotaskQueue: record that the marker takes the inbox lock under VMLiteRegistry::lock
- Thread.restrict: refuse realmless (wasm GC) receivers before the species check
- ThreadManager.h: drop the stale useThreads-alias paragraph from the gate comment
- ThreadManager.h: keepalive banner lists only the two real decrement sites
- ThreadManager.h: replace the stale U-T9-INT1 gate block with the current keepalive invariant
- ThreadManager: clear pending termination exception before publishing Error("Thread terminated")
- ThreadManager: decrement keepalive in retireUnsettled; document which sites count
- ThreadManager: default maxJSThreads to the 16383-id spawned TID partition and document the GIL-on lifetime cap
- ThreadManager: delete stale reviewer NOTE about unapplied threadRestrictCheck hooks
- ThreadManager: remove dead currentTID() and the VM-blind allocateSpawnedThreadState()
- ThreadManager: remove the dead ThreadWaitDeadline registrant-deadline machinery
- ThreadManager: remove the never-populated waitDeadlines expire/harvest path
- Threads: make spawned threads always blockable GIL-off; drop dead mayBlockSynchronously
- Watchdog.h: document the GIL-on cross-thread CPU-budget limitation for spawned servicers
- Watchdog.h: say GIL-on/flag-off are behavior-identical, noting the uncontended m_lock take
- Watchdog/LockObject: delete stale WIRING STATUS block and dead jsThreadParkTerminationRequested
- Watchdog: describe the W1 parked-carrier verdict as wall-clock authoritative, drop WIRING STATUS
- Watchdog: guard the GIL-off carrier depth decrement so a mid-entry-created watchdog cannot wrap
- threadMain: drop the AB18-I residual-exception fold and its dataLog line
- throwConcurrentAccessError: pass JSValue() so engine throws carry no own cause

sosukesuzuki pushed a commit that referenced this pull request

Sep 17, 2026
…stry, traps and stop-the-world

Fixes for the per-hunk review of #249 (review finding ids: 007-1, 016-1, 016-2, 016-3, 023-2, 027-2, 028-2, 038-4, 057-1, 057-3, 057-4, 057-5, 058-1, 058-2, 058-3, 058-4, 066-2, 073-3, 073-4, 074-2, 080-1, 083-2, 084-3, 093-1, 093-2, 093-3, 093-4, 093-5, 093-6, 094-1, 096-1, 096-3, 096-4, 097-1, 097-2, 097-3, 097-4, 097-5, 097-6, 098-3, 110-1, 111-2, 111-3, 114-5, 115-2, 115-3, 116-5, 128-1, 131-6, 133-1, 133-2, 133-3, 133-4, 133-5, 134-2, 134-3, 135-1, 135-2, 135-4, 136-3, 136-4, 136-5, 136-6, 137-1, 137-2, 138-1, 138-3, 138-4, 139-1, 139-2, 139-3, 139-4, 139-5, 139-6, 140-1, 140-2, 140-3, 140-4, 140-5, 141-1, 141-2, 141-3, 141-5, 141-6, 141-7, 142-1, 142-2, 142-3, 142-4, 142-5, 143-1, 143-2, 143-3, 143-5, 143-6, 144-1, 144-2, 144-3, 145-1, 146-1, 146-2, 146-3, 146-4, 147-1, 147-2, 147-3, 148-6, 149-4, 150-3, 150-5).

- AbstractModuleRecord: take cellLock() around m_resolutionCache reads and inserts
- CLoopStack: create segments lazily; register and bump the cache epoch only for stacks with segments
- CLoopStack: republish the running thread's stack limit at JSLock acquisition
- CLoopStack: setSoftReservedZoneSize grows only the caller's segment; zone size is a relaxed atomic
- CLoopStack: test top frame containment before topOfFrame(); read it through group3Primitives
- CachedCall: gate the foreign-drain skip and m_ownerThread on the per-VM gilOff mode
- CodeCache: take the GIL-off compilation lock in clear()
- CodeCache: use the shared GILOffCompilationLocker from JSThreadsSafepoint.h
- CommonSlowPaths: state that the fast-iteration-mode popcount bound is best effort under races
- ConcurrentAccessError: cache the per-realm Structure and inherit the constructor from Error
- ConcurrentButterfly.h: include VMLite.h unconditionally, drop the TID-0 __has_include shim
- Debugger: detach a destructing global inline instead of requesting a stop from the sweep
- Debugger: register spawned-thread CodeBlocks under a stop instead of dropping carrier breakpoints
- Debugger: state deleteAllCode's registry-keyed idle deferral at recompileAllJSFunctions
- Declare the jsThreads stop-protocol seams once in VMManager.h and VMLite.h
- Declare the park-site poll and carrier-park helpers in VMTraps.h/JSLock.h; drop five redeclarations
- ExceptionScope/VM: state RETURN_IF_EXCEPTION's flag-off Config byte-test cost in the comments
- FrameTracers/VM: remove uncalled pre-resolved tracer overloads and group3Primitives(preResolved)
- FrameTracers: drop stale NOTE claiming prepareCallOperation is unconverted under gilOff
- FunctionExecutable: drop dead codeBlockWithEntrypointFor and replaceCodeBlockWith
- Interpreter: relaxed CachedCall entry loads, gate absorb/snapshot on gilOffWithProcessGate()
- JSDollarVM: register sharedHeapTest allowIfNotFuzz like other crash-on-misuse entries
- JSGlobalObject: drop the dead per-lite AsyncLocalStorage cursor scaffolding
- JSGlobalObject: keep a global's own MicrotaskQueue when a spawned thread enqueues GIL-off
- JSGlobalObject: route generator claim/publish hooks through atomicInternalField()
- JSGlobalObject: state the eager-init invariant for the two arguments lazy properties
- JSGlobalObject: take the Function-constructor cache lock only under gilOff
- JSGlobalObject: visit per-lite realm entries only for a gilOff VM
- JSLock.h: document both unlockAllForThreadParking callers and the nested-bracket shape
- JSLock/VMLite: describe per-lite microtask queue routing as landed, drop 'not rerouted' notes
- JSLock: clear the thread-client slot when a gilOff carrier enters a GIL-on VM
- JSLock: drop the write-only spAtEntry and constant releaseAccessAtDepthZero token fields
- JSLock: gate the F.5 outer-carrier restore on this thread's own blocking-section drop
- JSLock: gate token retirement and the deferred carrier restore on useVMLite
- JSLock: release the carrier client's access at every gilOff depth-0 release
- JSLock: test g_jscConfig.gilOffProcess, not VM::isGILOffProcess(), on every lock()
- JSLock: unlockAllForThreadParking comment states the landed GILDroppedSection split
- JSPI: refuse pinball fulfill/reject resumption on spawned Threads (SD7)
- JSThreadsSafepoint: walk the parked thread's own topCallFrame for the epoch-overlap jettison
- MarkedVector: drop m_markSetLock, recover the shard lock from m_markSet under useSharedGCHeap
- Options: fail-stop when useProfiler/forceEagerCompilation undo useJSThreads => useConcurrentJIT
- Options: state that the gilOffProcess latch in notifyOptionsChanged is permanent
- Options: wire useThreadedDFG as a DFG/FTL tier kill switch under useJSThreads
- Options: wire useThreadedFTL as a tier kill switch (useFTLJIT off under useJSThreads)
- RaceAmplifier.h: describe the landed perturb() sites, drop the stale plan and unused isEnabled()
- Refuse import() and new ShadowRealm() on a spawned thread under GIL-off
- SamplingProfiler.h: drop never-instantiated WhileTargetSuspendedScope and the stale audit table
- SamplingProfiler: refuse to sample a gilOff VM with a logged diagnostic instead of silent dormancy
- ScratchBufferRegistry: one baked scratch index per size class instead of one per compile
- ScriptExecutable: delete dead replaceCodeBlockWith helpers; publish CodeBlock slots via one helper
- SharedVMState: fail-stop on same-thread StructureAllocationLocker nesting instead of hanging
- ThreadLocal: cache the per-realm instance Structure and honor newTarget
- VM.h: replace the exception-scope-verification review log with the member's invariant
- VM: correct the flag-off cost claims on the exception/trap mode-split accessors
- VM: count DrainMicrotaskDelayScope per thread GIL-off so spawned drains are never stranded
- VM: decide the inline soft-stack-limit and VMEntryScope gates on gilOffWithProcessGate()
- VM: decide whenIdle against the lite registry under gilOff and run pop listeners on the last thread out
- VM: document heapRandomUint64Concurrent as the concurrent-sweep-only path
- VM: fan notifyNeedTermination VM-wide so the carrier shield cannot swallow it
- VM: heap-allocate rejection handoff records so no Strong op runs under the queue lock
- VM: make the soft reserved zone size per-lite under gilOff and drop the RMW lock
- VM: remove the unused everHadSecondMutator/gilOffMultiMutator bit and its registerLite scan
- VM: replace the stale g_jscCurrentVMLite rationale block with the current contract
- VM: restore eager time zone initialization at VM creation (flag-off identity)
- VM: retire concurrent entry-scope service bits VM-wide under gilOff
- VM: retire the cross-thread-entry note from ~VM, not from the main carrier's ~VMLite
- VM: retire the cross-thread-entry note from ~VM, not from ~VMLite
- VM: retire the cross-thread-entry note from ~VM; ~VMLite never dereferences vm
- VM: route notifyNeedTermination through fireTrapVMWide so parked lites observe it
- VM: state that every JSPromise.cpp tracker call routes through the cross-thread gate
- VM: state the real VMLiteRegistry lock rank and drop the leaf claims
- VM: whenIdle uses the per-lite entry records under gilOff (same defect as 135-2)
- VMEntryScope: delete the dead N-entry refusal walk and the per-round status log
- VMEntryScope: whenIdle now honors the per-lite entered record the comment describes (same defect as 135-2)
- VMInspector: resolve GIL-off frames through the lite's VM group3Primitives()
- VMLite: delete dead lazyInit* block and mark GATE-3 landed in LazyPropertyInlines.h
- VMLite: delete the unused lazy-init owner side table
- VMLite: drop the dead Darwin TLS mirror; refuse GIL-off on non-Linux at option validation
- VMLite: drop the unused TLC chain verifier; assert the tlcTable/tlcTableBound mirror instead
- VMLite: drop the unused regExpAllocator and sizeOfLastScratchBuffer fields
- VMLite: fail-stop a compilation that asks the installed lite for a scratch buffer
- VMLite: key baked scratch indices by size class so the index space is bounded
- VMLite: never dereference vm in ~VMLite; retire the cross-thread-entry note from ~VM
- VMLite: remove the vacuous LZ1.3 teardown assert with its empty table
- VMLite: replace the Phase A/HARD GATE comments with the landed GIL-off routing
- VMLite: state the baked-scratch contract every tier now keeps
- VMLite: stop dereferencing vm in ~VMLite (a DETACHED carrier can outlive ~VM)
- VMLite: update the WS1.2 status list to match RegExpCache and ThreadManager as shipped
- VMLiteRegistry: document the real lock order; the registry lock is not a leaf
- VMLiteShared: call the STW-forbidden scope unconditionally; drop the N7 shim macro
- VMLiteShared: everHadSecondMutator scan already removed with VM finding 136-6; verified no residue
- VMLiteShared: state that the SAL locker is out-of-line and must be constructed only with the option on
- VMManager: delete the unused numberOfEnteredThreads helper
- VMManager: document jsThreadsStopPendingFor as the thread-granular-window probe only
- VMManager: gilOff cancelStop clears sibling lites through VM::clearVMWideEntryScopeService (135-1)
- VMManager: key the A.3 arbitration ParkingLot queue on the window token, not the Lock's address
- VMManager: let gilOff acquirers through the Mode-stop gate until a representative is elected
- VMManager: make a nested notifyVMStop from the servicing thread's STW callback a no-op
- VMManager: publish the function-scope root snapshot at the A.3 ticket park site too
- VMManager: remove BUGHUNT env-gated window-latency instrumentation and its includes
- VMManager: same Mode-stop gate fix as 144-1 (idle-VM debugger stop no longer parks every acquirer)
- VMTraps.h: replace the stale activation checklist with the current per-lite traps contract
- VMTraps: drop the stale VM-level DeferTermination keying note in handleTraps
- VMTraps: leave NeedWatchdogCheck pending when a GIL-off carrier polls without an entry scope
- VMTraps: make the per-thread defer counters plain scalars again
- VMTraps: resolve topCallFrame per-lite for the epoch jettison and debugger-break invalidation
- jsc: read hasPendingTerminationException while the lock keeps the carrier lite installed
- offlineasm: add cloop pseudo-instructions for the lite TLS read and the relaxed trap poll

sosukesuzuki pushed a commit that referenced this pull request

Sep 17, 2026
…and flag-off codegen

Fixes for the per-hunk review of #249 (review finding ids: 000-2, 000-3, 001-1, 002-1, 002-2, 002-3, 003-1, 003-2, 003-3, 004-1, 004-2, 004-3, 005-1, 006-1, 006-3, 006-5, 007-2, 007-3, 007-4, 007-5, 007-6, 008-1, 008-2, 008-3, 009-1, 009-2, 010-1, 010-2, 010-3, 011-1, 011-3, 012-2, 012-3, 012-4, 013-1, 013-2, 013-3, 014-1, 014-2, 014-4, 014-5, 014-6, 014-7, 015-1, 015-2, 015-3, 015-5, 015-6, 016-4, 016-5, 016-6, 017-1, 018-1, 018-2, 018-3, 019-1, 019-2, 020-1, 020-2, 020-3, 020-5, 020-6, 021-1, 021-3, 021-4, 022-1, 022-2, 022-3, 022-4, 022-5, 022-6, 022-7, 025-1, 025-2, 025-3, 025-4, 026-1, 026-2, 027-1, 027-3, 027-4, 027-5, 028-1, 028-3, 028-5, 029-1, 029-2, 029-3, 029-4, 030-1, 030-2, 031-2, 032-1, 032-2, 032-3, 041-2, 059-1, 059-2, 059-4, 059-5, 060-1, 060-2, 060-3, 060-4, 061-1, 061-2, 061-5, 062-1, 063-1, 063-2, 063-3, 064-1, 064-2, 064-3, 064-4, 064-5, 065-1, 065-2, 065-3, 065-4, 065-5, 066-3, 066-4, 067-2, 067-3, 067-4, 068-2, 068-3, 069-1, 074-1, 085-1, 103-3, 106-2, 120-1, 134-1, 147-4, 150-1, 150-6).

- AbstractMacroAssembler: remove dead initializeRandom() superseded by nextRandomSeed()
- AssemblyHelpers.h: state the real loadVMLite contract (any GPR, no scratch) at every gilOff helper
- AssemblyHelpers: RELEASE_ASSERT iso request fits cellSize in tlcSlotForConcurrentlyWithIso
- AssemblyHelpers: arity-check stack limit compares with GreaterThan again; contract requires the base condition
- AssemblyHelpers: collapse the dead Darwin loadVMLite leg now that non-Linux GIL-off is refused
- AssemblyHelpers: drop the wrong data-temp contract on loadVMLite; emitter clobbers only dest
- AssemblyHelpers: fold copyLLIntBaselineCalleeSaves into one VM&-keyed definition
- AssemblyHelpers: make loadVMLite the member implementation, declare the free form once, drop the macro guard
- AssemblyHelpers: rekey LLInt/Baseline callee-save spooler to VM&, drop duplicate in JITOpcodes
- Baseline enumerator_put_by_val: send flag-on out-of-line stores to the generic IC, not structureMismatch
- Baseline/thunk stack checks: pass the base's signed condition so flag-off bytes match
- Bytecode: fold if (@gilOffProcess) at codegen and drop the dead arm in builtins
- BytecodeGenerator: drop the last local GILOffCompilationLocker use; declaration now lives in one header
- BytecodeIntrinsicRegistry: derive @gilOffProcess via VM::isGILOffProcess(), drop stale comment
- CCallHelpers: drop __has_include scaffolding and unused includes, use ConcurrentButterfly.h constants
- CallLinkInfo: first polymorphic publish can no longer pair the new record with a null m_stub on ARM64
- CallLinkInfo: make the thunk's m_stub load address-dependent on the record load (ARM64)
- CallLinkInfo: pack Mode with the write-once callType/type byte, returning sizeof to base + m_record
- CallLinkInfo: state the real reason s_callLinkSerializationLock is recursive and ban GC-cell allocation under it
- CallLinkInfo: store the mode with relaxed byte accesses instead of seq_cst Atomic stores
- CodeBlock: drop the DFG JITData leak arm and the no-op retireOptimizedJITCode wrapper
- CodeBlock: free metadata, JITData and OpCatch buffers inline in ~CodeBlock with JS threads on
- CodeBlock: unlink leaked metadata/DFG-JITData call sites in ~CodeBlock so records release their pins
- CompactTDZEnvironmentMap: serialize the TDZ interning table itself instead of one codegen caller
- DFG AI: clobber structures across GIL-off parkable nodes instead of folding the clobber
- DFG EnumeratorPutByVal: run the butterfly write predicate before the out-of-line store
- DFG OSR exit ramp: use the invalidating scratch temp as the gilOff per-lite scratch base
- DFG compileSpread: copy from the butterfly snapshot the length came from flag-on
- DFG prologue stack check: pass GreaterThan so flag-off bytes match the merge base
- DFG/FTL: skip the PerformPromiseThenOneHandler inline install for a gilOff VM
- DFG: accept PutByValDirectResolved on the segmented-aware PutByVal path
- DFG: dispatch operationArrayPopAndRecoverLength on the butterfly regime; drop stale FIXME
- DFG: drop mergeOSREntryValue zero-StructureID bail and validated-freeze scaffolding
- DFG: drop the __has_include(ConcurrentButterfly.h) scaffolding and frozen fallback constants
- DFG: fail the compilation when a desired watchpoint set was fired before the link
- DFG: gate m_tierUpTriggersLock on useJSThreads in operationTriggerTierUpNowInLoop
- DFG: gate the clobberize validator suppression on vm().gilOff(), not the process option pair
- DFG: keep the segmented-butterfly bit for Convert+Original array modes
- DFG: make the segmented-aware Double GetByVal SaneChain arm pure and format-correct
- DFG: remove the dead DW-1 sort-comparator OSR-exit stash record
- DFG: resolve operand scratch buffers per lite under gilOff instead of baking VM addresses
- DFG: skip inline-offset by-offset nodes in the butterfly tag-discipline lint
- DFG: state the compilation lock's scope in Plan::finalize instead of a residual-race note
- DFG: state the landed usePollingTraps invariant at JumpReplacement::installVMTrapBreakpoint
- DFG: state the usePollingTraps invariant at the VMTrap breakpoint asserts
- DFG: use the shared GILOffCompilationLocker from JSThreadsSafepoint.h in Plan::finalize
- DFG: write MiscFields at the GIL-off CheckTraps poll so typed-array vector/length reload per poll
- DFGMayExit: report PutByOffset as Exits flag-on only for out-of-line offsets
- DFGOSRExitCompilerCommon: drop loadVMLite redeclaration, call the AssemblyHelpers member
- DFGThunks: drop the stale Release VM-block fallback from the OSR exit destination comments
- DFGThunks: use header loadVMLite; pin per-lite scratch offsets to the ARM64 ldr immediate range
- FTL ArithRandom: drop the GIL-off operation detour; inline path matches DFG and thunk tiers
- FTL MaterializeNewObject: say why the slow-path butterfly mask is required, not a no-op
- FTL MultiDeleteByOffset: RELEASE_ASSERT flag-off; remove the dead threaded slot-clear arm
- FTL compileDelBy: assert base != result before the handler-IC shuffle aliases them on ARM64
- FTL lazy slow path: consumer-side instruction sync before executing a foreign-thread stub (gilOff)
- FTL prologue: restore signed GreaterThan stack check so flag-off bytes match the base
- FTL varargs frame: restore signed GreaterThan soft-stack-limit check for flag-off byte identity
- FTL: TID-tag inline-allocated butterflies under useJSThreads, not only gilOff
- FTL: address the handler-IC dummy ArrayProfile off jitDataRegister like the DFG
- FTL: correct the E1 comment; the owner compare is not a segmented-word backstop
- FTL: drop the stale useThreadedFTL wiring comment in compilePutByOffset
- FTL: drop unreachable slow-path call from handler-IC GetById/GetByIdWithThis late paths
- FTL: include ConcurrentButterfly.h unconditionally; drop duplicated tag-encoding fallback
- FTL: skip E2 writeThreadLocal registration for KnownNonArrayStorage read plans
- FTLOSRExitCompiler: drop the loadVMLite self-declaration and call the AssemblyHelpers member
- FTLSaveRestore: make materializers clobber only dest; loadVMLite via member
- FTLSaveRestore: remove the loadVMLite self-declaration and bring-up comment
- FTLThunks: document why the baked exit-thunk scratch dump survives the generation call
- FunctionExecutable: remove the uncalled codeBlockWithEntrypointFor
- GCAwareJITStubRoutine: defer the zero-refcount delete only while the JITStubRoutineSet holds the routine
- GetByStatus::computeFromLLInt: read LLInt cache mode and structureID words with relaxed atomic loads
- InferredValue: add() reports a refused link so the DFG singleton fold is not installed stale
- InlineCacheCompiler ArrayLength stub: bail only for SW=1 ArrayStorage/SlowPut, not every SW=1 flat word
- InlineCacheCompiler: drop the false EOR zeroing-idiom claim from the ArrayLength dependency comment
- InlineCacheCompiler: give the shared stateless stub no owner CodeBlock
- InlineCacheCompiler: make the flag-on per-case Replace stub store through the write predicate
- InlineWatchpointSet: CAS thin-state stores and retry the inflateSlow publish flag-on
- JIT inline allocation: TID-tag the installed butterfly under GIL-on as well as GIL-off
- JIT: release a record's CodeBlock pin when the owning CallLinkInfo frees the record inline
- JITOperations: fail-stop operationReallocateButterflyAndTransition under useJSThreads
- JITThunks: gate hostFunctionStub/finalize m_lock on useJSThreads
- JITThunks: state the real m_lock scope, held across thunk generation
- JITWorklist: drop unused <wtf/NeverDestroyed.h> include and finalizingKeys history note
- JITWorklist: print duplicate-plan verbose log via locker dump to avoid re-locking m_lock
- JSThreadsSafepoint.h: declare gilOffCompilationLock and GILOffCompilationLocker once
- JSThreadsSafepoint.h: describe the live GIL-on stub and gilOff conductor paths and the live watchdog
- JSThreadsSafepoint: GIL-on Class-A fire tolerates a second entered VM; add regression test
- JSThreadsSafepoint: GIL-on stub no longer requires every other VM in the process to be idle
- JSThreadsSafepoint: accept only this thread's own stub depth as thread-stable stopped evidence
- JSThreadsSafepoint: declare the heap-fact rewrite epoch API in its own header, not VMTraps.h
- JSThreadsSafepoint: drop the __has_include probes, dead #else arms and the OM stub witness reads
- JSThreadsSafepoint: make the stop-the-world watchdog timeout an Option (0 = disabled)
- JSThreadsSafepoint: scope the entered-VM tripwires to VMs attached to the caller's server heap
- JSThreadsSafepoint: state the in-window bump as load-bearing and the ctor/dtor bumps as edges
- LLInt callHelper: name x6/a6 as the ARM64 register invokeForTailCall clobbers
- LLInt loadButterflyTIDTagToT6: state the non-Linux slow-path cliff, not a missing slot
- LLInt virtualThunkFor: state that the slot recompare is belt-and-braces, not the defense
- LLInt: drop the DW-1 sort-comparator stash cross-check and its release-build dataLogLn
- LLInt: drop the Group-3 break tripwire now that Options refuses GIL-off off Linux
- LLInt: drop the gilOffProcess fence test from op_put_internal_field on x86-64 (TSO)
- LLInt: gate the varargs frame echo and its RELEASE_ASSERTs on vm.gilOff()
- LLInt: load m_cache.structureID with a relaxed atomic in try_get_by_id/get_by_id_direct
- LLInt: remove the non-Linux Group-3 break tripwire from production code
- LLInt: restore flag-off memory-operand structure compares in enumerator ops and put_to_scope
- LLInt: revalidate the slot offset against the keyed structure before a GIL-off one-word publish
- LLInt: wire the useThreadedLLIntICs kill switch into the one-word cache publishers
- LOLJIT: pass signed GreaterThan to branchPtrAgainstSoftStackLimit to keep flag-off bytes
- MacroAssemblerARM64: make loadFromELFTLS64 scratch-free (mrs; add hi12; ldr lo12)
- OSR exit: crossModifyingCodeFence before reusing a ramp compiled on another thread
- OSR exit: share one generation lock between DFG and FTL exit compilers under gilOff
- PropertyInlineCache: document resetStubAsJumpInAccess as a live publish, not world-stopped
- PropertyInlineCache: make m_identifier an ICRacyCell so every writer is a relaxed store
- PropertyInlineCache: state the real flag-off per-IC footprint cost and its sizeof consumers
- Repatch.cpp: state that the cacheable-dictionary guard exists so ICs settle at GaveUp via the addAccessCase funnel
- Repatch/InlineCacheCompiler: name the real gate for flag-on put transitions
- Repatch: count only consecutive no-progress retries before GIL-off GaveUp demotion
- Repatch: gilOff linkMonomorphicCall loser bails unless the site is still Mode::Init
- RetiredJITArtifacts: drop __has_include scaffolding, leak arms and always-true epoch predicate
- RetiredJITArtifacts: replace unreachable lazy makeGCAware promotion with RELEASE_ASSERT(isGCAware)
- SetupVarargsFrame: restore signed GreaterThan soft-stack-limit compare (flag-off byte identity)
- SharedJITStubSet: make find() take its reference with tryRef so a dying routine is never resurrected
- UnlinkedFunctionExecutable: make recordParse fields dedicated relaxed-atomic bytes
- UnlinkedMetadataTable::link: drop TSAN-only relaxed zeroing, keep memset
- Watchpoint: drop the out-of-line Dependency::fence from InlineWatchpointSet fat reads
- Watchpoint: drop the unused fireEarlyForGILOff/hasClassAFirePending and state the real deferral ordering
- Watchpoint: refuse add() on an invalidated set flag-on; enumerator install falls back to traversing
- Watchpoint: remove the BUGHUNT Class-A fire instrumentation
- Watchpoint: remove the uncalled fireEarlyForGILOff/hasClassAFirePending scaffolding
- WatchpointSet: arm by CAS, refuse add() on an invalidated set, make callers honor the refusal
- WatchpointSet: route already-stopped Class-A fires through stopTheWorldAndRun's guarded path
- Yarr: drop the false matchLimit stop-latency bound claim and its static_assert ratchet
- YarrJIT: restore the signed LessThanOrEqual soft-stack-limit check so flag-off bytes match base
- resolve_scope slow paths: read m_resolveType with a relaxed atomic load like its writers
- resolve_scope: freeze op_resolve_scope metadata after linking flag-on in all three writers

sosukesuzuki pushed a commit that referenced this pull request

Sep 17, 2026
…support

Fixes for the per-hunk review of #249 (review finding ids: 150-2, 150-4, 150-7).

- Wasm: gate the spawned-thread refusal on useJSThreads so flag-off skips the TLS lookup
- Wasm: refuse GC-typed modules under useSharedGCHeap with CompileError/LinkError, not abort
- WasmMemory: mark GIL-off relocating-grow stop arm dormant, drop audit-closure claims

sosukesuzuki added a commit that referenced this pull request

Sep 26, 2026
Squashed from 151 commits on jarred/threads (merge-base 5851d47) so the
whole change can be rebased onto main as one unit.

sosukesuzuki pushed a commit that referenced this pull request

Sep 26, 2026
Fixes for the per-hunk review of #249 (review finding ids: 000-1).

- CMakeLists: export GCSafepointEpoch/GCThreadLocalCache/HeapClientSet/JSThreadsSafepoint headers

sosukesuzuki pushed a commit that referenced this pull request

Sep 26, 2026
…om table ordering

Fixes for the per-hunk review of #249 (review finding ids: 131-5, 151-1, 151-2, 152-1, 153-1, 153-2, 154-1, 154-2, 154-3).

- BitSet: gate relaxed-atomic zeroing constructor on TSAN_ENABLED, keep aggregate zero-init otherwise
- DeferrableRefCounted: gate the atomic refcount RMWs on a process-latched GIL-off Config byte
- StringImpl: keep the legacy load/modify/store in cost, setIsAtom and setHash when the shared atom table is off
- SymbolImpl: make the symbol hash counter atomic
- Thread: add WTF Thread::tryCreate and throw RangeError when the OS refuses a thread
- WTF Thread: reword dedicated-byte flag comments to name the real writer/reader race
- WTF: define SharedAtomStringTable::singleton and the latch in SharedAtomStringTable.cpp
- WTF: state the migrate-then-latch-then-clear order in enableSharedAtomStringTable without citing the spec

sosukesuzuki pushed a commit that referenced this pull request

Sep 26, 2026
…er, drop temporary diagnostics

Fixes for the per-hunk review of #249 (review finding ids: 033-1, 033-2, 033-3, 034-1, 034-2, 034-3, 034-5, 035-1, 035-2, 035-3, 036-1, 036-3, 036-4, 036-5, 036-6, 037-1, 037-2, 038-1, 038-2, 038-3, 039-1, 039-2, 039-3, 040-1, 041-1, 041-3, 042-1, 042-2, 042-3, 043-1, 043-2, 043-3, 043-4, 043-5, 044-1, 044-2, 045-1, 045-2, 045-3, 046-1, 046-2, 046-3, 046-4, 046-5, 046-6, 046-7, 047-2, 047-3, 047-4, 048-1, 048-2, 048-3, 048-4, 048-5, 049-1, 049-2, 050-1, 050-2, 051-3, 052-1, 052-2, 052-3, 052-4, 052-5, 053-1, 053-2, 053-3, 054-1, 054-2, 055-1, 055-2, 056-1, 056-2, 116-6, 135-3).

- BlockDirectory: assert the lock-free m_bits witness is this thread's exclusive MSPL or own stripe
- BlockDirectory: make assertSweeperIsSuspended a world-stopped/exclusive-owner assertion; drop sweeper-disabled claims
- BlockDirectory: remove findOwnEmptyBlockForRefill, whose target population cannot exist
- BlockDirectory: step the steal cursor past weak-bearing empties instead of declining them
- CompleteSubspace::allocate: test the server allocator before the useSharedGCHeap branch
- CompleteSubspace::allocate: trust the per-thread TLC snapshot only when vm is gilOff
- Drop the dead null-client disjunct from the TLC hit ASSERT and restate its invariant
- GCIncomingRefCountedSet: take the incoming-reference lock only under gilOffProcess
- GCIncomingRefCountedSet: walk the set unlocked in sweep/lastChanceToFinalize (world stopped)
- GCThreadLocalCache: remove uncalled allocatorFor(BlockDirectory&), stopAllocating, prepareForAllocation, server
- GCThreadLocalCache: replace unreachable growTable realloc leg with a fixed-capacity RELEASE_ASSERT
- HandleSet: fold the Strong leaf lock into the class, drop the process-global side table
- HandleSet: lock the live protected-cell walk; route the NODELETE counter through m_strongLock
- HandleSet: make m_strongLock a real member and rewrite the seam comments as invariants
- HandleSet: take m_strongLock in forEachStrongHandle under gilOff
- Heap: correct the F28 successor-open comments to the drain the code performs
- Heap: correct the Wlr comment: Auxiliary witnesses are marked, not traced
- Heap: count drainFromShared entrants for the marker pause; restore flag-off steal denominator
- Heap: create sibling-assist visitors in runBeginPhase, decline assists when the pool is empty
- Heap: delete dead allocationClientForJITCodegen and the duplicate free resolver
- Heap: delete the dead namespace-scope allocationClientForCurrentThread and its stale note
- Heap: delete the never-constructed SharedGCWindowOpen::TicketDrainSuccessor arm
- Heap: delete the unreferenced allocationClientForJITCodegen resolver
- Heap: describe the STW-forbidden scope depth as a release-mode per-thread counter
- Heap: document that a LambdaFinalizer may receive a null JSCell* under GIL-off
- Heap: document that shared-mode hooks/reclaim/rebias run once per drained ticket batch
- Heap: document the GIL-off LambdaFinalizer contract (null cell, runs after the world resumes)
- Heap: drain GCSafepointEpoch retired items in lastChanceToFinalize, before blocks are freed
- Heap: drain an orphaned needFinalizeBit inside the ISS flip before storing ISS
- Heap: drop dead sharedGCWindowedStagesEnabled(); Heap.cpp keeps the one stage-flag list
- Heap: drop stale NOTE claiming worldIsStopped() still does a plain read
- Heap: drop the untimed JSThreadsStopScope ctor; harness uses the watchdog ctor
- Heap: drop the unused 1-byte layout pad and state what the trailer guards check
- Heap: drop unused GCClient::CompleteSubspaceView, its members and bind hook
- Heap: exempt the PreventCollectionScope holder from the shared conduct-tenure gate
- Heap: fix comments still claiming the IncrementalSweeper is disabled when shared
- Heap: gate DeferGC slot routing on useSharedGCHeap and resolve both slots once
- Heap: gate allocationClientForCurrentThread on gilOffWithProcessGate, drop stale rationale
- Heap: gate the freelisted-block walk in stopThePeriphery on Options::verifyGC()
- Heap: gate the possibly-accessed-strings append lock on gilOff
- Heap: gate the shared-GC root-snapshot/endMarking/freelisted-block checks behind Options::verifyGC()
- Heap: make barrierThreshold()/mutatorShouldBeFenced() plain server-master reads
- Heap: make sharedGCMaxSiblingMarkingAssists=0 mean disabled and drop the dead auto branch
- Heap: read the server master barrier pair in mutatorShouldBeFenced/barrierThreshold
- Heap: register the epochReclaim safepoint hook per heap, make hook registry idempotent
- Heap: remove the unconsumed CompleteSubspaceView wrappers and bind hook
- Heap: route server-level acquire/release/hasAccess to the calling thread's client GIL-off
- Heap: run TID-rebias fires as the GC conductor and retire the stale tripwire banner
- Heap: run the conservative-scan constraint on the conductor when sibling assists are admissible
- Heap: run verifyStickySharedServerDesignation before HeapClientSet::add's sticky trigger
- Heap: scan and grant the shared collectAsync ticket under one m_threadLock hold
- Heap: serialize the server mutator mark stack with a Heap lock, not a MarkStackArray flag
- Heap: state the pin-lock-then-codeBlockSet-lock order at pinRetiredCallLinkRecordCodeBlock
- Heap: state the shared-mode no-runloop-push rule and log access-barrier stalls
- Heap: strip the TEMPORARY ring-liveness diagnostics from the shared-heap harness
- Heap: take m_possiblyAccessedStringsFromConcurrentThreadsLock only under gilOff
- Heap: take m_protectedValuesLock in protect/unprotect and statistics walks under gilOff
- Heap: test useSharedGCHeap before isSharedServer in the per-client slot dispatchers
- HeapClientSet: run the sticky-server designation check before the second-client ISS flip
- IsoSubspace: inline GCClient::IsoSubspace::tlcSlot, drop false out-of-line rationale
- IsoSubspace: remove unused GCClient::IsoSubspace::allocateForClient
- Key the TLC snapshot hit on vm.gilOff() so nested foreign-VM entry cannot allocate from the wrong heap
- MarkedBlock: correct the isMarkedRaw comment to name its callers' protocols
- MarkedBlock: drop the unreachable allocBit leg and last-era skip from the window snapshot
- MarkedBlock: state the real stale-true argument for the destructible hint; keep it in lockstep for false
- MarkedBlock: take the heapRandom lock in specializedSweep only when sweeps can run concurrently
- MarkedSpace: bound TLC slot reservation by numCompleteSubspaces * numSizeClasses
- MarkedSpace: say isPagedOut's only caller skips it when shared, not that it never fires
- MarkingConstraint: delete dead m_lock member and the comment deferring its removal
- SharedHeapTestHarness: remove the ring-liveness diagnostics and the Heap.cpp audit seam
- SlotVisitor: arm the per-batch helper pause checkpoint in the gilOff single-handoff shape
- Threads: relinquish a spawned thread's allocators while its lite is Live, not from the client dtor
- TinyBloomFilter: replace relaxed fetch_or in add() with relaxed load+store
- VMManager.h: declare the thread-granular conductor predicates once; drop seven hand copies

sosukesuzuki pushed a commit that referenced this pull request

Sep 26, 2026
…hared butterfly protocol

Fixes for the per-hunk review of #249 (review finding ids: 021-2, 036-2, 061-3, 061-4, 072-1, 072-2, 072-3, 072-4, 073-1, 073-2, 073-5, 075-1, 075-2, 075-3, 076-1, 076-2, 076-3, 077-1, 077-2, 078-1, 078-2, 078-3, 079-1, 079-2, 080-2, 080-3, 080-4, 083-1, 084-1, 084-2, 084-4, 086-1, 086-2, 086-3, 086-4, 086-5, 087-1, 087-2, 087-3, 087-4, 087-5, 088-1, 088-2, 089-3, 089-4, 090-2, 090-4, 090-5, 090-6, 091-3, 099-1, 099-2, 099-3, 100-1, 100-2, 100-3, 100-4, 100-5, 101-1, 101-2, 102-2, 102-3, 102-4, 102-6, 103-1, 103-2, 103-4, 104-2, 104-3, 104-4, 105-1, 105-2, 105-3, 106-5, 108-4, 110-2, 111-1, 112-1, 112-2, 113-1, 113-2, 113-3, 116-2, 116-3, 116-4, 117-1, 118-1, 118-2, 119-1, 119-2, 119-3, 120-2, 121-1, 121-2, 121-4, 122-1, 122-2, 123-1, 123-2, 123-3, 124-1, 124-4, 132-1, 149-1).

- ArrayPrototype: derive join/indexOf/concat fast paths from one tagged butterfly word snapshot
- ArrayPrototype: re-read indexing types after the concat result allocation flag-on
- ArrayPrototype: reverse fast path flips SW for foreign writers and uses one butterfly snapshot
- ButterflyInlines: keep optimalContiguousVectorLength within MAX_STORAGE_VECTOR_LENGTH
- ClonedArguments: copyToArguments reads one butterfly-word snapshot, bails on segmented/null
- ClonedArguments: serialize GIL-off materializeSpecials under a park-capable lock
- ConcurrentButterfly.h: document the gilOff StayFlatShared transition in the regime contract
- ConcurrentButterfly.h: read the verify/stress options directly instead of SFINAE probes
- ConcurrentButterfly: StayFlat copy-grow copies no element payload for typed-array views
- ConcurrentButterfly: assert non-null fragments under verifyConcurrentButterfly in the GC visit
- ConcurrentButterfly: bail out of the ensureLength/shrink drivers when an AS conversion lands
- ConcurrentButterfly: delete the uncalled segmentedTransition/structureOnlyTransition drivers
- ConcurrentButterfly: drop the process-global stub world-stopped witness
- ConcurrentButterfly: make butterflyWorldIsStopped the JSThreadsSafepoint predicate alone
- ConcurrentButterfly: name the useSharedGCHeap gate in the mode (b) rarity comments
- ConcurrentButterfly: register the quarantine epoch hook on every Heap, not per address
- ConcurrentButterfly: remove the uncalled spineOutOfLineFragment/spineIndexedFragment exports
- ConcurrentButterfly: route far-beyond-vector indexed stores to the sparse-map path flag-on
- ConcurrentButterfly: size typed-array view conversions from a zero indexed payload
- ConcurrentButterfly: state the GC visit bound as the spine's vectorLength in code comments
- ConcurrentButterflyOperations: drop __has_include scaffolding and the TID-0 shim
- ConcurrentButterflyOperations: remove the seven unreachable JIT operation shims
- DFG operationCreateThis: validate the allocation profile snapshot under gilOff like slow_path_create_this
- DirectArguments: serialize overrideThings puts and bitmap publication under gilOff
- FunctionRareData: GIL-off .prototype store is followed by a clear that waits for the initializer
- GetterSetter: restore WriteBarrier::set() in ctor, drop stale hand-expansion and comment
- JSArray AS shift/unshift concurrent: re-check the caller's range under the cell lock and bail
- JSArray/JSObject: replace GIL-only sparse-map iterators on flag-on paths with keyed locked access
- JSArray::appendMemcpy: re-read both indexing types after ensureLength before the memcpy
- JSArray::copyToArguments: clamp the flat scan to the caller's length as well as the snapshot
- JSArray::fastFill: bail when the flag-on relabel left indexingType != nextType
- JSArray::fastFlat: bail flag-on when pass 2 copied a different count than pass 1
- JSArray::fastFlat: bail when the source shape changed across the result allocation
- JSArray::fastSlice: hold one GCDeferralContext across butterfly allocation, copy and cell allocation
- JSArray::fastToReversed/fastWith/fastToSpliced: re-read indexingType after the result allocation
- JSArray::pop: return undefined when a racing shrink emptied the array before the generic tail
- JSArray::setLength/pop/fastShift: restart on a null word paired with an indexed mode
- JSArray::unshiftCountSlowCase: drop unreachable flag-on branches
- JSBigInt: throw OutOfMemoryError from createFromDigit instead of RELEASE_ASSERT
- JSCJSValue: make the 64-bit JSValue slot accessors relaxed atomics only under TSAN
- JSCell: drop no-op decontaminate() in structure(); state the nuke-bit contract
- JSCellInlines: delete orphaned comment describing the withdrawn H-CALLSITE-LASTSIZE-LA mechanism
- JSCellInlines: make tlcSlotForSubspace fail closed for non-CompleteSubspace kinds
- JSCellLock: maintain GCCellLockDepth in lock/tryLock/unlock so the no-park asserts are live
- JSFunction: CAS-publish FunctionRareData under gilOff so racing installs adopt one cell
- JSObject.h: drop the stale i03-i37 FIXME in tryMakeWritableInt32
- JSObject.h: remove uncalled butterflyRegime() and isSharedArrayStorage()
- JSObject: RESTART stop-published indexing transitions when a dictionary table was edited in place
- JSObject: always CAS-max publicLength after flag-on dense stores and ensureLength
- JSObject: barrier the owner after the AS-COPY growth publication
- JSObject: butterfly() contract drops the guard-then-reload witness; snapshot JSCellButterfly::createFromArray
- JSObject: check the ThrowScope when putInlineSlow's thread-restrict gate throws
- JSObject: check the ThrowScope when threadRestrictCheck fails in getNonIndexPropertySlot
- JSObject: correct the flatten re-check comment about renumberPropertyOffsets' edit stamp
- JSObject: dispatch flag-on indexed delete on one loaded word, never the flat switch
- JSObject: fence mode-then-word loads in indexed names walk and beyond-vector put
- JSObject: install a fresh sparse map under the cell lock only if none is installed (flag-on)
- JSObject: load mode before the fenced word in setIndexQuicklyConcurrent; putDirectIndex uses the try variant
- JSObject: publish dictionary attribute changes under the cell lock with a table-stamp re-check
- JSObject: putDirectIndex AS grow arm re-checks the vector bound under the lock before storing
- JSObject: re-check i < vectorLength under the lock after increaseVectorLength before storing
- JSObject: re-check vectorLength on the fresh word in setIndexQuicklyConcurrent and route putDirectIndex via try
- JSObject: re-dispatch putDirectIndex after createArrayStorage instead of indexing the returned vector
- JSObject: re-validate structureID after the word load in createInitialIndexedStorageConcurrent
- JSObject: recount m_numValuesInVector under the lock in sparse-map consolidation
- JSObject: return the settled ArrayStorage from convertToArrayStorageConcurrent when a racer converted first
- JSObject: route null-word foreign-keyed indexed first installs to the shared stop leg
- JSObject: run the F1 SW flip before cell-locked ArrayStorage stores in putByIndex and the AS funnels
- JSObjectWithButterfly: delete the uncalled getDirectConcurrent/putDirectConcurrent
- JSPropertyNameEnumerator: drop stale NOTE, state the relaxed store/load invariant
- LazyProperty: drop unreachable initializer-abandonment restore in callFunc
- MegamorphicCache: restore plain epoch bump; make bumpEpoch a no-op under useJSThreads
- ObjectConstructor: clone fast paths copy from one tagged-word snapshot paired with the structure
- PropertyTable: document that inline deleted offsets are quarantined too
- PropertyTable: fold deleted-offset bookkeeping into one side struct (cell 80 -> 48 bytes)
- PropertyTable: say seal()/freeze() edit a still-private table; keep the seqlock bracket
- PropertyTable: skip the quarantine walk when the oldest stamp is not yet promotable
- PropertyTable: state the TSAN pairing rationale for relaxed constructor stores
- SparseArrayValueMap: decide flag-on putEntry/putDirect under the lock, throw and call setters after it
- SparseArrayValueMap: dispatch putEntry on the value word and lock every flag-on entry writer
- SparseArrayValueMap: insert a sparse entry only once the write is allowed (no placeholder)
- Structure: condense the DEFINE_BITFIELD perf narrative to the lost-update invariant
- Structure: drop the unused DeferredWatchpointFire parameter of firePropertyReplacementWatchpointSet
- Structure: gate SAL locker construction in Structure::create/createStructure on the latched option
- Structure: gate the lock-free transition precheck on useJSThreads for the IC/DFG callers
- Structure: name the lock-free republish store as the only unlocked chain writer
- Structure: pre-allocate the shrunk flatten butterfly outside the stop window
- Structure: re-copy seenProperties/propertyHash into a transition under the source m_lock
- Structure: remove the never-passed deferred parameter and its API comment
- Structure: replace transitionThreadLocalTIDOffset with a restampTransitionThreadLocalTID setter
- Structure: restore .set()/.setMayBeNull() at four slot writers; drop stale plain-store comments
- Structure: revalidate isDictionary and object->structure in the flatten stop closure
- Structure: snapshot forEachProperty entries under m_lock and run the functor unlocked
- Structure::add<ShouldPin::Yes>: recheck under m_lock that the table was not stolen
- StructureChain: bound finishCreation's lane walk by the size create() allocated
- StructureRareData: GCSafe, flag-on-only lock around the special property cache install
- StructureRareData: move retired enumerator watchpoint list out of the cell into the Heap
- TypeInfoBlob/Structure: make the blob, outOfLineTypeFlags and classInfo reader loads TSAN-only
- WriteBarrier: make the cell-pointer slot accessors relaxed atomics only under TSAN
- ensureLengthSlowConcurrent: drop the dead availableOldLength computation and T5 comment
- fastArrayJoin: snapshot the butterfly word once and re-probe it after user code
- shiftCountWithArrayStorageConcurrent: allocate the fresh AS before the scalar stores

sosukesuzuki pushed a commit that referenced this pull request

Sep 26, 2026
…nd lifetime races

Fixes for the per-hunk review of #249 (review finding ids: 070-1, 070-2, 070-3, 070-4, 070-5, 070-6, 071-1, 071-2, 072-5, 072-6, 074-3, 089-1, 089-2, 089-5, 090-1, 090-3, 091-1, 091-2, 091-4, 092-1, 092-2, 092-3, 092-4, 107-1, 107-3, 107-4, 108-1, 108-2, 108-3, 114-1, 114-2, 114-3, 114-4, 115-1, 116-1, 117-2, 124-3, 125-1, 125-2, 125-3, 125-4, 125-5, 126-1, 126-3, 126-4, 128-2, 148-2, 148-5).

- ArrayBuffer: allocate the GIL-off resizable transfer copy without a VM so it cannot collect
- ArrayBuffer: fail the GIL-off transferTo whose detach lost the flag race, as already detached
- ArrayBuffer: fail the racing transfer loser so exactly one transfer of a buffer succeeds
- ArrayBuffer: make isDetached() read a sticky GIL-off detached flag; drop the side-table probes
- ArrayBuffer: make isDetached() read the sticky GIL-off flag, drop isArrayBufferDetachedGILOff
- ArrayBuffer: neuter views before the mapping enters the quarantine in GIL-off detach
- ArrayBuffer: quarantine a relocated wasm mapping in the growing VM's heap quarantine
- ArrayBuffer: re-check isDetached() and maxByteLength under the lock on every resizeGILOff pass
- ArrayBuffer: register the quarantine safepoint hook per Heap at VM init, not per address
- ArrayBuffer: snapshot length and maxByteLength under the handle lock in GIL-off transferTo
- Atomics: delete the D8 single-flight TA sync-wait gate; lift the 4.5-1a spawned gate GIL-off only
- AtomicsObject: run the GIL-off detach re-check before ToIndex so the TA path keeps RangeError
- ConcatKeyAtomStringCache: read/store m_mode through relaxed atomics in getOrInsert
- DataView get/set: keep the plain byte loop flag-off, relaxed atomics only under gilOffWithProcessGate
- DataView get/set: snapshot the view base before the length proof, throw detached on null GIL-off
- DateCache: route GIL-off entry points to a per-thread cache instead of one VM-wide leaf lock
- JSArrayBufferView: convert shared flat views before the GIL-off wastage copy; retry a failed CAS
- JSArrayBufferView: give a segmented Fast/Oversize view a header fragment in slowDownAndWasteMemory
- JSString: derive every rope-walk decision from one per-node m_fiber snapshot
- JSString: plain constructor-time rope stores in production, relaxed atomics only under TSAN
- JSString: remove dead resolveRopeInternalNoSubstring
- KeyAtomStringCache: relaxed slot snapshot load in production, acquire only under TSAN
- KeyAtomStringCacheInlines: drop unused Options.h, stdlib.h and DataLog.h includes
- RegExp: make m_atom write-once so lock-free atom() readers never see it freed
- RegExp: publish bytecode before m_state=ByteCode; never hand Yarr::interpret a null pattern
- RegExp: take cellLock in reset(), route error-code reads through one relaxed accessor
- RegExp: write-once m_atom and bytecode-before-state publication (same fix as 114-1/114-2)
- RegExpCache: clear Yarr code under a stop-the-world window when gilOff
- SimpleTypedArrayController: actually defer the displaced dead wrapper Weak under GIL-off
- StringRecursionChecker: use the per-thread recursion state in every useJSThreads mode
- Symbol: return the canonical cell from finishCreation instead of re-probing symbolImplToSymbolMap
- ThreadAtomics: DeferGC around the Missing-add ArrayStorage cell-lock window
- ThreadAtomics: bump ArrayStorage length only after the conditional add publishes
- ThreadAtomics: drop the never-incremented g_threadAtomicsSlotCASRetries stub and its dump field
- ThreadAtomics: drop the never-incremented slotCASRetries counter
- ThreadAtomics: flip SW before the Missing-add ArrayStorage cell lock
- ThreadAtomics: grow dense shapes for beyond-vector Atomics.store adds GIL-off
- ThreadAtomics: release the waitAsync ticket at dequeue instead of at timer fire
- ThreadAtomics: state the in-window teardown-sweep finalizer contract
- ThreadAtomics: state why property waitAsync stays an uncounted keepalive registration
- TypedArray copyWithin: return early on a null base snapshot in the GIL-off lane loop
- TypedArray element accessors and sort: gate on g_jscConfig.gilOffProcess, not VM::isGILOffProcess()
- TypedArray fill: return early on a null base snapshot in the GIL-off lane loop
- TypedArray forEach: test the base snapshot instead of isDetached() in the arms that re-read the base
- TypedArray includes/indexOf/lastIndexOf/reverse/sort: handle a null base snapshot GIL-off
- TypedArray setFromTypedArray/sort/copyFrom*ShapeArray: never deref a base re-read after the bounds proof GIL-off
- WaiterListManager: settle a foreign VM's TA waitAsync under list->lock in the GIL-off notify arm
- jsAtomString: republish the atom when a lost GIL-off publish race left a non-atom impl

sosukesuzuki pushed a commit that referenced this pull request

Sep 26, 2026
…, Lock, Condition and ThreadLocal

Fixes for the per-hunk review of #249 (review finding ids: 051-1, 059-3, 081-1, 082-1, 082-2, 082-4, 096-2, 098-1, 098-2, 106-1, 106-4, 109-1, 109-2, 109-3, 109-4, 109-5, 111-5, 111-6, 129-1, 129-2, 129-3, 129-4, 129-5, 130-1, 130-2, 130-3, 130-4, 130-5, 131-1, 131-2, 131-3, 131-4, 134-4, 148-1, 148-3, 148-4, 149-2, 149-3).

- ConcurrentAccessError constructor: derive the Structure from newTarget
- ConditionObject: consume the async grant under m_queueLock before asyncWait's (b) release
- DeferredWorkTimer: capture the timer, not Ref<VM>, in gilOff run-loop dispatches
- DeferredWorkTimer: fix stale runRunLoop comment about the non-gilOff arm taking m_taskLock
- DeferredWorkTimer: make TicketData::m_isCancelled a relaxed std::atomic<bool>
- GILDroppedSection: stop publishing a coop GC root snapshot from the out-of-line ctor
- JSMicrotask: delete the unreferenced publishAsyncGeneratorResume host function
- JSMicrotask: gate the generatedJITCodeForCall mirror assert on !gilOff
- JSPromise: keep GIL-off spawned threads off VM::m_synchronousModuleQueue
- JSPromise: read m_asyncContextData directly at the five capture sites
- LockObject: count asyncHold registrations toward the spawned registrant's keepalive
- LockObject: keep a termination pending in the asyncHold(fn) settle instead of rejecting
- LockObject: keep the GILDroppedSection coop root snapshot on the park-site frame
- LockObject: open the park-resumption window at the holder's release, not at park entry
- LockObject: run the async-grant pump inline for a spawned head registrant under gilOff
- MicrotaskCall: relaxed entry/codeBlock loads, acquire fence only in the gilOff arm
- MicrotaskQueue: clearForGlobalObject also filters the GIL-off foreign inbox
- MicrotaskQueue: record that the marker takes the inbox lock under VMLiteRegistry::lock
- Thread.restrict: refuse realmless (wasm GC) receivers before the species check
- ThreadManager.h: drop the stale useThreads-alias paragraph from the gate comment
- ThreadManager.h: keepalive banner lists only the two real decrement sites
- ThreadManager.h: replace the stale U-T9-INT1 gate block with the current keepalive invariant
- ThreadManager: clear pending termination exception before publishing Error("Thread terminated")
- ThreadManager: decrement keepalive in retireUnsettled; document which sites count
- ThreadManager: default maxJSThreads to the 16383-id spawned TID partition and document the GIL-on lifetime cap
- ThreadManager: delete stale reviewer NOTE about unapplied threadRestrictCheck hooks
- ThreadManager: remove dead currentTID() and the VM-blind allocateSpawnedThreadState()
- ThreadManager: remove the dead ThreadWaitDeadline registrant-deadline machinery
- ThreadManager: remove the never-populated waitDeadlines expire/harvest path
- Threads: make spawned threads always blockable GIL-off; drop dead mayBlockSynchronously
- Watchdog.h: document the GIL-on cross-thread CPU-budget limitation for spawned servicers
- Watchdog.h: say GIL-on/flag-off are behavior-identical, noting the uncontended m_lock take
- Watchdog/LockObject: delete stale WIRING STATUS block and dead jsThreadParkTerminationRequested
- Watchdog: describe the W1 parked-carrier verdict as wall-clock authoritative, drop WIRING STATUS
- Watchdog: guard the GIL-off carrier depth decrement so a mid-entry-created watchdog cannot wrap
- threadMain: drop the AB18-I residual-exception fold and its dataLog line
- throwConcurrentAccessError: pass JSValue() so engine throws carry no own cause

sosukesuzuki pushed a commit that referenced this pull request

Sep 26, 2026
…stry, traps and stop-the-world

Fixes for the per-hunk review of #249 (review finding ids: 007-1, 016-1, 016-2, 016-3, 023-2, 027-2, 028-2, 038-4, 057-1, 057-3, 057-4, 057-5, 058-1, 058-2, 058-3, 058-4, 066-2, 073-3, 073-4, 074-2, 080-1, 083-2, 084-3, 093-1, 093-2, 093-3, 093-4, 093-5, 093-6, 094-1, 096-1, 096-3, 096-4, 097-1, 097-2, 097-3, 097-4, 097-5, 097-6, 098-3, 110-1, 111-2, 111-3, 114-5, 115-2, 115-3, 116-5, 128-1, 131-6, 133-1, 133-2, 133-3, 133-4, 133-5, 134-2, 134-3, 135-1, 135-2, 135-4, 136-3, 136-4, 136-5, 136-6, 137-1, 137-2, 138-1, 138-3, 138-4, 139-1, 139-2, 139-3, 139-4, 139-5, 139-6, 140-1, 140-2, 140-3, 140-4, 140-5, 141-1, 141-2, 141-3, 141-5, 141-6, 141-7, 142-1, 142-2, 142-3, 142-4, 142-5, 143-1, 143-2, 143-3, 143-5, 143-6, 144-1, 144-2, 144-3, 145-1, 146-1, 146-2, 146-3, 146-4, 147-1, 147-2, 147-3, 148-6, 149-4, 150-3, 150-5).

- AbstractModuleRecord: take cellLock() around m_resolutionCache reads and inserts
- CLoopStack: create segments lazily; register and bump the cache epoch only for stacks with segments
- CLoopStack: republish the running thread's stack limit at JSLock acquisition
- CLoopStack: setSoftReservedZoneSize grows only the caller's segment; zone size is a relaxed atomic
- CLoopStack: test top frame containment before topOfFrame(); read it through group3Primitives
- CachedCall: gate the foreign-drain skip and m_ownerThread on the per-VM gilOff mode
- CodeCache: take the GIL-off compilation lock in clear()
- CodeCache: use the shared GILOffCompilationLocker from JSThreadsSafepoint.h
- CommonSlowPaths: state that the fast-iteration-mode popcount bound is best effort under races
- ConcurrentAccessError: cache the per-realm Structure and inherit the constructor from Error
- ConcurrentButterfly.h: include VMLite.h unconditionally, drop the TID-0 __has_include shim
- Debugger: detach a destructing global inline instead of requesting a stop from the sweep
- Debugger: register spawned-thread CodeBlocks under a stop instead of dropping carrier breakpoints
- Debugger: state deleteAllCode's registry-keyed idle deferral at recompileAllJSFunctions
- Declare the jsThreads stop-protocol seams once in VMManager.h and VMLite.h
- Declare the park-site poll and carrier-park helpers in VMTraps.h/JSLock.h; drop five redeclarations
- ExceptionScope/VM: state RETURN_IF_EXCEPTION's flag-off Config byte-test cost in the comments
- FrameTracers/VM: remove uncalled pre-resolved tracer overloads and group3Primitives(preResolved)
- FrameTracers: drop stale NOTE claiming prepareCallOperation is unconverted under gilOff
- FunctionExecutable: drop dead codeBlockWithEntrypointFor and replaceCodeBlockWith
- Interpreter: relaxed CachedCall entry loads, gate absorb/snapshot on gilOffWithProcessGate()
- JSDollarVM: register sharedHeapTest allowIfNotFuzz like other crash-on-misuse entries
- JSGlobalObject: drop the dead per-lite AsyncLocalStorage cursor scaffolding
- JSGlobalObject: keep a global's own MicrotaskQueue when a spawned thread enqueues GIL-off
- JSGlobalObject: route generator claim/publish hooks through atomicInternalField()
- JSGlobalObject: state the eager-init invariant for the two arguments lazy properties
- JSGlobalObject: take the Function-constructor cache lock only under gilOff
- JSGlobalObject: visit per-lite realm entries only for a gilOff VM
- JSLock.h: document both unlockAllForThreadParking callers and the nested-bracket shape
- JSLock/VMLite: describe per-lite microtask queue routing as landed, drop 'not rerouted' notes
- JSLock: clear the thread-client slot when a gilOff carrier enters a GIL-on VM
- JSLock: drop the write-only spAtEntry and constant releaseAccessAtDepthZero token fields
- JSLock: gate the F.5 outer-carrier restore on this thread's own blocking-section drop
- JSLock: gate token retirement and the deferred carrier restore on useVMLite
- JSLock: release the carrier client's access at every gilOff depth-0 release
- JSLock: test g_jscConfig.gilOffProcess, not VM::isGILOffProcess(), on every lock()
- JSLock: unlockAllForThreadParking comment states the landed GILDroppedSection split
- JSPI: refuse pinball fulfill/reject resumption on spawned Threads (SD7)
- JSThreadsSafepoint: walk the parked thread's own topCallFrame for the epoch-overlap jettison
- MarkedVector: drop m_markSetLock, recover the shard lock from m_markSet under useSharedGCHeap
- Options: fail-stop when useProfiler/forceEagerCompilation undo useJSThreads => useConcurrentJIT
- Options: state that the gilOffProcess latch in notifyOptionsChanged is permanent
- Options: wire useThreadedDFG as a DFG/FTL tier kill switch under useJSThreads
- Options: wire useThreadedFTL as a tier kill switch (useFTLJIT off under useJSThreads)
- RaceAmplifier.h: describe the landed perturb() sites, drop the stale plan and unused isEnabled()
- Refuse import() and new ShadowRealm() on a spawned thread under GIL-off
- SamplingProfiler.h: drop never-instantiated WhileTargetSuspendedScope and the stale audit table
- SamplingProfiler: refuse to sample a gilOff VM with a logged diagnostic instead of silent dormancy
- ScratchBufferRegistry: one baked scratch index per size class instead of one per compile
- ScriptExecutable: delete dead replaceCodeBlockWith helpers; publish CodeBlock slots via one helper
- SharedVMState: fail-stop on same-thread StructureAllocationLocker nesting instead of hanging
- ThreadLocal: cache the per-realm instance Structure and honor newTarget
- VM.h: replace the exception-scope-verification review log with the member's invariant
- VM: correct the flag-off cost claims on the exception/trap mode-split accessors
- VM: count DrainMicrotaskDelayScope per thread GIL-off so spawned drains are never stranded
- VM: decide the inline soft-stack-limit and VMEntryScope gates on gilOffWithProcessGate()
- VM: decide whenIdle against the lite registry under gilOff and run pop listeners on the last thread out
- VM: document heapRandomUint64Concurrent as the concurrent-sweep-only path
- VM: fan notifyNeedTermination VM-wide so the carrier shield cannot swallow it
- VM: heap-allocate rejection handoff records so no Strong op runs under the queue lock
- VM: make the soft reserved zone size per-lite under gilOff and drop the RMW lock
- VM: remove the unused everHadSecondMutator/gilOffMultiMutator bit and its registerLite scan
- VM: replace the stale g_jscCurrentVMLite rationale block with the current contract
- VM: restore eager time zone initialization at VM creation (flag-off identity)
- VM: retire concurrent entry-scope service bits VM-wide under gilOff
- VM: retire the cross-thread-entry note from ~VM, not from the main carrier's ~VMLite
- VM: retire the cross-thread-entry note from ~VM, not from ~VMLite
- VM: retire the cross-thread-entry note from ~VM; ~VMLite never dereferences vm
- VM: route notifyNeedTermination through fireTrapVMWide so parked lites observe it
- VM: state that every JSPromise.cpp tracker call routes through the cross-thread gate
- VM: state the real VMLiteRegistry lock rank and drop the leaf claims
- VM: whenIdle uses the per-lite entry records under gilOff (same defect as 135-2)
- VMEntryScope: delete the dead N-entry refusal walk and the per-round status log
- VMEntryScope: whenIdle now honors the per-lite entered record the comment describes (same defect as 135-2)
- VMInspector: resolve GIL-off frames through the lite's VM group3Primitives()
- VMLite: delete dead lazyInit* block and mark GATE-3 landed in LazyPropertyInlines.h
- VMLite: delete the unused lazy-init owner side table
- VMLite: drop the dead Darwin TLS mirror; refuse GIL-off on non-Linux at option validation
- VMLite: drop the unused TLC chain verifier; assert the tlcTable/tlcTableBound mirror instead
- VMLite: drop the unused regExpAllocator and sizeOfLastScratchBuffer fields
- VMLite: fail-stop a compilation that asks the installed lite for a scratch buffer
- VMLite: key baked scratch indices by size class so the index space is bounded
- VMLite: never dereference vm in ~VMLite; retire the cross-thread-entry note from ~VM
- VMLite: remove the vacuous LZ1.3 teardown assert with its empty table
- VMLite: replace the Phase A/HARD GATE comments with the landed GIL-off routing
- VMLite: state the baked-scratch contract every tier now keeps
- VMLite: stop dereferencing vm in ~VMLite (a DETACHED carrier can outlive ~VM)
- VMLite: update the WS1.2 status list to match RegExpCache and ThreadManager as shipped
- VMLiteRegistry: document the real lock order; the registry lock is not a leaf
- VMLiteShared: call the STW-forbidden scope unconditionally; drop the N7 shim macro
- VMLiteShared: everHadSecondMutator scan already removed with VM finding 136-6; verified no residue
- VMLiteShared: state that the SAL locker is out-of-line and must be constructed only with the option on
- VMManager: delete the unused numberOfEnteredThreads helper
- VMManager: document jsThreadsStopPendingFor as the thread-granular-window probe only
- VMManager: gilOff cancelStop clears sibling lites through VM::clearVMWideEntryScopeService (135-1)
- VMManager: key the A.3 arbitration ParkingLot queue on the window token, not the Lock's address
- VMManager: let gilOff acquirers through the Mode-stop gate until a representative is elected
- VMManager: make a nested notifyVMStop from the servicing thread's STW callback a no-op
- VMManager: publish the function-scope root snapshot at the A.3 ticket park site too
- VMManager: remove BUGHUNT env-gated window-latency instrumentation and its includes
- VMManager: same Mode-stop gate fix as 144-1 (idle-VM debugger stop no longer parks every acquirer)
- VMTraps.h: replace the stale activation checklist with the current per-lite traps contract
- VMTraps: drop the stale VM-level DeferTermination keying note in handleTraps
- VMTraps: leave NeedWatchdogCheck pending when a GIL-off carrier polls without an entry scope
- VMTraps: make the per-thread defer counters plain scalars again
- VMTraps: resolve topCallFrame per-lite for the epoch jettison and debugger-break invalidation
- jsc: read hasPendingTerminationException while the lock keeps the carrier lite installed
- offlineasm: add cloop pseudo-instructions for the lite TLS read and the relaxed trap poll

sosukesuzuki pushed a commit that referenced this pull request

Sep 26, 2026
…and flag-off codegen

Fixes for the per-hunk review of #249 (review finding ids: 000-2, 000-3, 001-1, 002-1, 002-2, 002-3, 003-1, 003-2, 003-3, 004-1, 004-2, 004-3, 005-1, 006-1, 006-3, 006-5, 007-2, 007-3, 007-4, 007-5, 007-6, 008-1, 008-2, 008-3, 009-1, 009-2, 010-1, 010-2, 010-3, 011-1, 011-3, 012-2, 012-3, 012-4, 013-1, 013-2, 013-3, 014-1, 014-2, 014-4, 014-5, 014-6, 014-7, 015-1, 015-2, 015-3, 015-5, 015-6, 016-4, 016-5, 016-6, 017-1, 018-1, 018-2, 018-3, 019-1, 019-2, 020-1, 020-2, 020-3, 020-5, 020-6, 021-1, 021-3, 021-4, 022-1, 022-2, 022-3, 022-4, 022-5, 022-6, 022-7, 025-1, 025-2, 025-3, 025-4, 026-1, 026-2, 027-1, 027-3, 027-4, 027-5, 028-1, 028-3, 028-5, 029-1, 029-2, 029-3, 029-4, 030-1, 030-2, 031-2, 032-1, 032-2, 032-3, 041-2, 059-1, 059-2, 059-4, 059-5, 060-1, 060-2, 060-3, 060-4, 061-1, 061-2, 061-5, 062-1, 063-1, 063-2, 063-3, 064-1, 064-2, 064-3, 064-4, 064-5, 065-1, 065-2, 065-3, 065-4, 065-5, 066-3, 066-4, 067-2, 067-3, 067-4, 068-2, 068-3, 069-1, 074-1, 085-1, 103-3, 106-2, 120-1, 134-1, 147-4, 150-1, 150-6).

- AbstractMacroAssembler: remove dead initializeRandom() superseded by nextRandomSeed()
- AssemblyHelpers.h: state the real loadVMLite contract (any GPR, no scratch) at every gilOff helper
- AssemblyHelpers: RELEASE_ASSERT iso request fits cellSize in tlcSlotForConcurrentlyWithIso
- AssemblyHelpers: arity-check stack limit compares with GreaterThan again; contract requires the base condition
- AssemblyHelpers: collapse the dead Darwin loadVMLite leg now that non-Linux GIL-off is refused
- AssemblyHelpers: drop the wrong data-temp contract on loadVMLite; emitter clobbers only dest
- AssemblyHelpers: fold copyLLIntBaselineCalleeSaves into one VM&-keyed definition
- AssemblyHelpers: make loadVMLite the member implementation, declare the free form once, drop the macro guard
- AssemblyHelpers: rekey LLInt/Baseline callee-save spooler to VM&, drop duplicate in JITOpcodes
- Baseline enumerator_put_by_val: send flag-on out-of-line stores to the generic IC, not structureMismatch
- Baseline/thunk stack checks: pass the base's signed condition so flag-off bytes match
- Bytecode: fold if (@gilOffProcess) at codegen and drop the dead arm in builtins
- BytecodeGenerator: drop the last local GILOffCompilationLocker use; declaration now lives in one header
- BytecodeIntrinsicRegistry: derive @gilOffProcess via VM::isGILOffProcess(), drop stale comment
- CCallHelpers: drop __has_include scaffolding and unused includes, use ConcurrentButterfly.h constants
- CallLinkInfo: first polymorphic publish can no longer pair the new record with a null m_stub on ARM64
- CallLinkInfo: make the thunk's m_stub load address-dependent on the record load (ARM64)
- CallLinkInfo: pack Mode with the write-once callType/type byte, returning sizeof to base + m_record
- CallLinkInfo: state the real reason s_callLinkSerializationLock is recursive and ban GC-cell allocation under it
- CallLinkInfo: store the mode with relaxed byte accesses instead of seq_cst Atomic stores
- CodeBlock: drop the DFG JITData leak arm and the no-op retireOptimizedJITCode wrapper
- CodeBlock: free metadata, JITData and OpCatch buffers inline in ~CodeBlock with JS threads on
- CodeBlock: unlink leaked metadata/DFG-JITData call sites in ~CodeBlock so records release their pins
- CompactTDZEnvironmentMap: serialize the TDZ interning table itself instead of one codegen caller
- DFG AI: clobber structures across GIL-off parkable nodes instead of folding the clobber
- DFG EnumeratorPutByVal: run the butterfly write predicate before the out-of-line store
- DFG OSR exit ramp: use the invalidating scratch temp as the gilOff per-lite scratch base
- DFG compileSpread: copy from the butterfly snapshot the length came from flag-on
- DFG prologue stack check: pass GreaterThan so flag-off bytes match the merge base
- DFG/FTL: skip the PerformPromiseThenOneHandler inline install for a gilOff VM
- DFG: accept PutByValDirectResolved on the segmented-aware PutByVal path
- DFG: dispatch operationArrayPopAndRecoverLength on the butterfly regime; drop stale FIXME
- DFG: drop mergeOSREntryValue zero-StructureID bail and validated-freeze scaffolding
- DFG: drop the __has_include(ConcurrentButterfly.h) scaffolding and frozen fallback constants
- DFG: fail the compilation when a desired watchpoint set was fired before the link
- DFG: gate m_tierUpTriggersLock on useJSThreads in operationTriggerTierUpNowInLoop
- DFG: gate the clobberize validator suppression on vm().gilOff(), not the process option pair
- DFG: keep the segmented-butterfly bit for Convert+Original array modes
- DFG: make the segmented-aware Double GetByVal SaneChain arm pure and format-correct
- DFG: remove the dead DW-1 sort-comparator OSR-exit stash record
- DFG: resolve operand scratch buffers per lite under gilOff instead of baking VM addresses
- DFG: skip inline-offset by-offset nodes in the butterfly tag-discipline lint
- DFG: state the compilation lock's scope in Plan::finalize instead of a residual-race note
- DFG: state the landed usePollingTraps invariant at JumpReplacement::installVMTrapBreakpoint
- DFG: state the usePollingTraps invariant at the VMTrap breakpoint asserts
- DFG: use the shared GILOffCompilationLocker from JSThreadsSafepoint.h in Plan::finalize
- DFG: write MiscFields at the GIL-off CheckTraps poll so typed-array vector/length reload per poll
- DFGMayExit: report PutByOffset as Exits flag-on only for out-of-line offsets
- DFGOSRExitCompilerCommon: drop loadVMLite redeclaration, call the AssemblyHelpers member
- DFGThunks: drop the stale Release VM-block fallback from the OSR exit destination comments
- DFGThunks: use header loadVMLite; pin per-lite scratch offsets to the ARM64 ldr immediate range
- FTL ArithRandom: drop the GIL-off operation detour; inline path matches DFG and thunk tiers
- FTL MaterializeNewObject: say why the slow-path butterfly mask is required, not a no-op
- FTL MultiDeleteByOffset: RELEASE_ASSERT flag-off; remove the dead threaded slot-clear arm
- FTL compileDelBy: assert base != result before the handler-IC shuffle aliases them on ARM64
- FTL lazy slow path: consumer-side instruction sync before executing a foreign-thread stub (gilOff)
- FTL prologue: restore signed GreaterThan stack check so flag-off bytes match the base
- FTL varargs frame: restore signed GreaterThan soft-stack-limit check for flag-off byte identity
- FTL: TID-tag inline-allocated butterflies under useJSThreads, not only gilOff
- FTL: address the handler-IC dummy ArrayProfile off jitDataRegister like the DFG
- FTL: correct the E1 comment; the owner compare is not a segmented-word backstop
- FTL: drop the stale useThreadedFTL wiring comment in compilePutByOffset
- FTL: drop unreachable slow-path call from handler-IC GetById/GetByIdWithThis late paths
- FTL: include ConcurrentButterfly.h unconditionally; drop duplicated tag-encoding fallback
- FTL: skip E2 writeThreadLocal registration for KnownNonArrayStorage read plans
- FTLOSRExitCompiler: drop the loadVMLite self-declaration and call the AssemblyHelpers member
- FTLSaveRestore: make materializers clobber only dest; loadVMLite via member
- FTLSaveRestore: remove the loadVMLite self-declaration and bring-up comment
- FTLThunks: document why the baked exit-thunk scratch dump survives the generation call
- FunctionExecutable: remove the uncalled codeBlockWithEntrypointFor
- GCAwareJITStubRoutine: defer the zero-refcount delete only while the JITStubRoutineSet holds the routine
- GetByStatus::computeFromLLInt: read LLInt cache mode and structureID words with relaxed atomic loads
- InferredValue: add() reports a refused link so the DFG singleton fold is not installed stale
- InlineCacheCompiler ArrayLength stub: bail only for SW=1 ArrayStorage/SlowPut, not every SW=1 flat word
- InlineCacheCompiler: drop the false EOR zeroing-idiom claim from the ArrayLength dependency comment
- InlineCacheCompiler: give the shared stateless stub no owner CodeBlock
- InlineCacheCompiler: make the flag-on per-case Replace stub store through the write predicate
- InlineWatchpointSet: CAS thin-state stores and retry the inflateSlow publish flag-on
- JIT inline allocation: TID-tag the installed butterfly under GIL-on as well as GIL-off
- JIT: release a record's CodeBlock pin when the owning CallLinkInfo frees the record inline
- JITOperations: fail-stop operationReallocateButterflyAndTransition under useJSThreads
- JITThunks: gate hostFunctionStub/finalize m_lock on useJSThreads
- JITThunks: state the real m_lock scope, held across thunk generation
- JITWorklist: drop unused <wtf/NeverDestroyed.h> include and finalizingKeys history note
- JITWorklist: print duplicate-plan verbose log via locker dump to avoid re-locking m_lock
- JSThreadsSafepoint.h: declare gilOffCompilationLock and GILOffCompilationLocker once
- JSThreadsSafepoint.h: describe the live GIL-on stub and gilOff conductor paths and the live watchdog
- JSThreadsSafepoint: GIL-on Class-A fire tolerates a second entered VM; add regression test
- JSThreadsSafepoint: GIL-on stub no longer requires every other VM in the process to be idle
- JSThreadsSafepoint: accept only this thread's own stub depth as thread-stable stopped evidence
- JSThreadsSafepoint: declare the heap-fact rewrite epoch API in its own header, not VMTraps.h
- JSThreadsSafepoint: drop the __has_include probes, dead #else arms and the OM stub witness reads
- JSThreadsSafepoint: make the stop-the-world watchdog timeout an Option (0 = disabled)
- JSThreadsSafepoint: scope the entered-VM tripwires to VMs attached to the caller's server heap
- JSThreadsSafepoint: state the in-window bump as load-bearing and the ctor/dtor bumps as edges
- LLInt callHelper: name x6/a6 as the ARM64 register invokeForTailCall clobbers
- LLInt loadButterflyTIDTagToT6: state the non-Linux slow-path cliff, not a missing slot
- LLInt virtualThunkFor: state that the slot recompare is belt-and-braces, not the defense
- LLInt: drop the DW-1 sort-comparator stash cross-check and its release-build dataLogLn
- LLInt: drop the Group-3 break tripwire now that Options refuses GIL-off off Linux
- LLInt: drop the gilOffProcess fence test from op_put_internal_field on x86-64 (TSO)
- LLInt: gate the varargs frame echo and its RELEASE_ASSERTs on vm.gilOff()
- LLInt: load m_cache.structureID with a relaxed atomic in try_get_by_id/get_by_id_direct
- LLInt: remove the non-Linux Group-3 break tripwire from production code
- LLInt: restore flag-off memory-operand structure compares in enumerator ops and put_to_scope
- LLInt: revalidate the slot offset against the keyed structure before a GIL-off one-word publish
- LLInt: wire the useThreadedLLIntICs kill switch into the one-word cache publishers
- LOLJIT: pass signed GreaterThan to branchPtrAgainstSoftStackLimit to keep flag-off bytes
- MacroAssemblerARM64: make loadFromELFTLS64 scratch-free (mrs; add hi12; ldr lo12)
- OSR exit: crossModifyingCodeFence before reusing a ramp compiled on another thread
- OSR exit: share one generation lock between DFG and FTL exit compilers under gilOff
- PropertyInlineCache: document resetStubAsJumpInAccess as a live publish, not world-stopped
- PropertyInlineCache: make m_identifier an ICRacyCell so every writer is a relaxed store
- PropertyInlineCache: state the real flag-off per-IC footprint cost and its sizeof consumers
- Repatch.cpp: state that the cacheable-dictionary guard exists so ICs settle at GaveUp via the addAccessCase funnel
- Repatch/InlineCacheCompiler: name the real gate for flag-on put transitions
- Repatch: count only consecutive no-progress retries before GIL-off GaveUp demotion
- Repatch: gilOff linkMonomorphicCall loser bails unless the site is still Mode::Init
- RetiredJITArtifacts: drop __has_include scaffolding, leak arms and always-true epoch predicate
- RetiredJITArtifacts: replace unreachable lazy makeGCAware promotion with RELEASE_ASSERT(isGCAware)
- SetupVarargsFrame: restore signed GreaterThan soft-stack-limit compare (flag-off byte identity)
- SharedJITStubSet: make find() take its reference with tryRef so a dying routine is never resurrected
- UnlinkedFunctionExecutable: make recordParse fields dedicated relaxed-atomic bytes
- UnlinkedMetadataTable::link: drop TSAN-only relaxed zeroing, keep memset
- Watchpoint: drop the out-of-line Dependency::fence from InlineWatchpointSet fat reads
- Watchpoint: drop the unused fireEarlyForGILOff/hasClassAFirePending and state the real deferral ordering
- Watchpoint: refuse add() on an invalidated set flag-on; enumerator install falls back to traversing
- Watchpoint: remove the BUGHUNT Class-A fire instrumentation
- Watchpoint: remove the uncalled fireEarlyForGILOff/hasClassAFirePending scaffolding
- WatchpointSet: arm by CAS, refuse add() on an invalidated set, make callers honor the refusal
- WatchpointSet: route already-stopped Class-A fires through stopTheWorldAndRun's guarded path
- Yarr: drop the false matchLimit stop-latency bound claim and its static_assert ratchet
- YarrJIT: restore the signed LessThanOrEqual soft-stack-limit check so flag-off bytes match base
- resolve_scope slow paths: read m_resolveType with a relaxed atomic load like its writers
- resolve_scope: freeze op_resolve_scope metadata after linking flag-on in all three writers

sosukesuzuki pushed a commit that referenced this pull request

Sep 26, 2026
…support

Fixes for the per-hunk review of #249 (review finding ids: 150-2, 150-4, 150-7).

- Wasm: gate the spawned-thread refusal on useJSThreads so flag-off skips the TLS lookup
- Wasm: refuse GC-typed modules under useSharedGCHeap with CompileError/LinkError, not abort
- WasmMemory: mark GIL-off relocating-grow stop arm dormant, drop audit-closure claims