Parent: #1
Goal
Keep the public contract for JavaScript-defined races, engine-state races, synchronization, and GC publication precise as the runtime evolves.
Current baseline
docs/threads/memory-model.md now defines:
- Lock/Atomics.Mutex release-to-acquire publication.
- Condition wait release/reacquire semantics, predicate-loop requirements, non-buffered notifications, and the fact that notify alone is not a publication substitute.
- Sequentially consistent typed-array Atomics and per-
(object, key)property-Atomics linearization/publication. - Thread join/asyncJoin completion, result/exception identity, and prior-side-effect publication.
- Per-queue microtask FIFO and synchronized cross-thread queue handoff without a promised global order across independent producers.
- The boundary between ordinary racing values, explicit
ConcurrentAccessErrorrestriction, and engine-state corruption. - GC reachability publication as an internal safety mechanism that does not create JavaScript happens-before.
ThreadSanitizer currently runs without a suppression file. Intentional JavaScript shared-buffer byte races are either synchronized in the engine paths or must be handled by a future narrow, load-bearing suppression witness; engine metadata, synchronization, GC, root, lifetime, and handle state remain unsuppressed. Recent maintenance also hardened engine-owned lifetime/handle state: SharedBufferStorage retain counts and C-API protected-handle counts use checked increments, and C value/object boxes carry owner-context tags so context-taking APIs fail closed on wrong-realm handles.
Completed milestone
- Specify ordering guarantees for Lock, Condition, property Atomics, typed-array Atomics, Thread join/asyncJoin, and task/microtask delivery.
- Document which ordinary object races have unspecified values versus explicit
ConcurrentAccessErrorbehavior. - Align GC write-barrier/publication rules with the landed nursery and concurrent full collector.
- Add litmus tests for the documented happens-before guarantees.
- Audit the memory-model docs and suppression boundary for the nursery/shared-state changes.
- Remove stale TSan suppression wiring and keep required gates running suppression-free.
- Harden shared-buffer and C-API handle lifetime accounting against refcount/protection-count wraparound and wrong-context handle use.
Ongoing maintenance
- Re-run the focused
memory model:normal and TSan tests whenever synchronization or queue handoff changes. - Add a minimized litmus test before strengthening any public ordering claim.
- Keep GC publication explicitly separate from program synchronization.
- Keep test-only controls excluded from the stable embedder API.
- Re-audit the no-suppression ThreadSanitizer policy whenever a new raw program-byte access helper is introduced. If a future suppression becomes necessary, land it with a deterministic witness that fails without the suppression and passes with it.
- Keep owner-context and lifetime/refcount invariants regression-gated whenever public C handles or shared backing storage change.
Acceptance criteria
- Public guarantees have executable witnesses.
- TSan runs remain suppression-free, or any future suppression is narrow and load-bearing.
- Test-only controls remain clearly excluded from the stable embedder API.