Skip to content

Commit fa71b01

Browse files
committed
docs(threads): publish PR-249 terminal inventory (#428)
1 parent e6d15b1 commit fa71b01

6 files changed

Lines changed: 65 additions & 127 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ Run `zig build --help` for the full command list.
7373
## What Is Not Implemented
7474

7575
- remaining JSC framework/private and Bun/Home ABI surfaces;
76-
- 24 dispositioned PR-249 shell/JIT/GC/Wasm cases ([inventory](docs/.data/pr249-reference-inventory.json));
76+
- 10 optimizing-JIT PR-249 cases remain blocked; 6 JSC-private or incompatible premises have terminal dispositions ([inventory](docs/.data/pr249-reference-inventory.json));
7777
- automatic/concurrent compaction, a moving nursery, and an optimizing JIT; explicit C/Zig compaction supports quiescent realms and scheduled precise baseline-JIT checkpoints, while age-three parallel minor collection is implemented.
7878

7979
The [release matrix](docs/.data/release-compatibility-matrix.json) tracks [#134](https://github.com/zig-utils/zig-js/issues/134); removal of this section is gated by [#246](https://github.com/zig-utils/zig-js/issues/246).

docs/threads/P6-thread-api.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,8 @@ mode is independently shippable and testable; for this engine it is the
7777
threads-test`) that evaluates each file in an enable_threads Context with
7878
the shim prelude. Start with `api/thread-basic.js`, `api/lock-basic.js`,
7979
`api/condition-basic.js`, `atomics/property-load-store.js` and grow.
80-
Their `cve/`, `jit/`, `gc-stress/` dirs stay reference-only (target
81-
machinery a GIL'd tree-walker structurally lacks); record skips with
82-
reasons.
80+
Keep growing to the exact inventory; current blockers and terminal premises
81+
are verifier-owned rather than directory-wide skips.
8382

8483
## Order of work (each its own commit)
8584

docs/threads/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ rules.
4141
| `$262.agent` and typed-array `Atomics.wait` / `notify` / `waitAsync` | Implemented in `src/agent.zig` with hooks in the interpreter and VM. | Unit tests and real test262 agent cases. |
4242
| Structured clone and ArrayBuffer transfer/detach | Implemented in `src/structured_clone.zig`. | Unit tests, workers, and agents. |
4343
| Embedder `Worker` API | Implemented in `src/worker.zig` with C-API hooks in `src/c_api.zig`. | Worker unit tests, exact host-hook wake coverage, and C-API round trips. |
44-
| Shared-realm `Thread` API | Implemented in `src/jsthread.zig`, `src/gil.zig`, and `src/context.zig`; parallel by default, GIL opt-out available. | PR-249 green coverage: 235 compatible promoted files out of 259 executable files (233 default `zig build threads-test`, plus 2 `parallel_js`-only witnesses); the [complete inventory](../.data/pr249-reference-inventory.json) checksums all 339 vendored files and assigns dependencies, required hooks, and owners to all 24 reference-only executables. Negative promotion probes, the no-GIL TSan corpus sweep, and fuzzers guard the executable surface. |
44+
| Shared-realm `Thread` API | Implemented in `src/jsthread.zig`, `src/gil.zig`, and `src/context.zig`; parallel by default, GIL opt-out available. | PR-249 coverage: 243 promoted of 259 executable files (241 default plus 2 `parallel_js`-only); the [inventory](../.data/pr249-reference-inventory.json) checksums all 339 files and distinguishes 10 optimizing-tier blockers from 6 terminal premises. Disposition probes, no-GIL TSan, and fuzzers guard the surface. |
4545
| Concurrent GC / root safety | GC-managed parallel contexts use thread-safe allocation, write barriers, per-structure locks, precise VM frame roots, and conservative native-stack rooting where applicable. | Unit tests, `parallel_gc` soak, no-GIL corpus TSan, test262-parallel. |
4646

4747
## Core Rules

docs/threads/limits.md

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ The core JavaScript multithreading architecture for issue #1 is implemented:
44
isolated agents/workers, shared memory, structured clone, Workers, and
55
shared-realm `Thread`s are all present, and shared-realm threads run
66
true-parallel by default. The remaining work is production hardening:
7-
performance, documentation, stress breadth, and promotion of reference-only
8-
tests as the matching engine features land.
7+
performance, documentation, stress breadth, and the 10 optimizing-tier PR-249
8+
cases tracked by #429.
99

1010
## Supported Today
1111

@@ -708,23 +708,12 @@ Issue #1 remains the umbrella status page.
708708
race-gated while deeper sanitizer expansion continues. Keep extending it
709709
toward more teardown ordering, broader cross-realm scheduling, and richer
710710
cleanup/finalization interleavings.
711-
- **Reference-only PR-249 files.** Promote only when the engine implements the
712-
behavior and the file is reliable under Zig `0.17-dev`, especially the
713-
WebAssembly-required files, the incompatible JSC worker-Wasm refusal policy,
714-
JIT/shell-hook witnesses, JSC-specific mark-list
715-
or the shared-collector `preventCollection` probe, detached-buffer fresh-view
716-
reference assumptions, and typed-array race-shape probes.
717-
The portable graph/parse/ownership portion of the heap-snapshot case is now
718-
covered by `zig build test-private-heap-snapshot`; the JSC-only collector
719-
election gate remains explicitly outside that promotion.
720-
Run
721-
`python3 tools/threads-reference-audit.py --run-probes --expect-current-blockers --probe-timeout 60`
722-
to keep the nearest-probe negative baseline honest: it passes only while
723-
those files still fail or time out with their documented blocker evidence,
724-
and fails when a candidate starts passing or changes failure shape. Use
725-
`python3 tools/threads-reference-audit.py --format json` when automation needs
726-
the same counts, blocker categories, promotion probes, and expected blocker
727-
evidence without scraping human-readable output.
711+
- **PR-249 tail.** The exact inventory has 243 promoted files, 10
712+
optimizing-tier blockers owned by #429, and 6 terminal JSC-private or
713+
intentionally incompatible premises. Run
714+
`zig build threads-reference-audit threads-reference-probes`; use
715+
`python3 tools/threads-reference-audit.py --format json` for automation or
716+
`--scan-unpromoted` for a deliberate full tail audit.
728717
- **TC39 structs tracking.** Keep `proposal-structs` tracking in
729718
[P8-structs.md](./P8-structs.md) and this issue; do not split it into a
730719
parallel tracker.

docs/threads/production-readiness.md

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,12 @@ than new correctness architecture.
5454
the mid-script parallel-GC use-after-free found by the fuzzer.
5555
- `-Dtest262-parallel-js` runs a broad language-surface slice in GIL-free
5656
parallel contexts and asserts no new failures versus the baseline.
57-
- PR-249 coverage contains 235 compatible promoted files out of 259 executable
58-
PR-249 files: 233 in normal mode plus 2 `parallel_js`-only witnesses, covered
57+
- PR-249 coverage contains 243 promoted files out of 259 executable files: 241
58+
in normal mode plus 2 `parallel_js`-only witnesses, covered
5959
by the sharded no-GIL
6060
ThreadSanitizer corpus gate.
61-
- The excluded JSC-specific spawned-thread WebAssembly-refusal case conflicts
62-
with zig-js's supported worker-Wasm contract; a native unit test covers
63-
validation, compilation, instantiation, and execution in both GIL modes.
61+
- Six JSC-private or intentionally incompatible premises have terminal
62+
dispositions; the remaining 10 optimizing-tier cases are owned by #429.
6463
- The no-GIL `cve/mc-dos-waiter-table-storm.js` focused gate covers property
6564
`Atomics.waitAsync` tickets removed by a peer while their owning spawned
6665
thread is closing its stack-local microtask queue; late settlements reroute to
@@ -70,10 +69,9 @@ than new correctness architecture.
7069
between `asyncJoin` publication and native thread teardown without weakening
7170
the waiter-root reclamation threshold. Arm labels and failure-only engine
7271
diagnostics keep future stalls attributable.
73-
- The reference-only PR-249 tail is checked by
74-
`zig build threads-reference-audit`, so unsupported shell hooks, JIT,
75-
WebAssembly, and heap-cap/OOM witnesses stay explicit instead of
76-
becoming accidental no-op passes.
72+
- The PR-249 tail is checked by
73+
`zig build threads-reference-audit threads-reference-probes`, so blockers and
74+
terminal premises cannot become accidental no-op passes.
7775

7876
Remaining: keep widening generated and hand-written stress toward exceptions,
7977
termination, cleanup, waiters, and cross-thread lifecycle.

docs/threads/testing.md

Lines changed: 46 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ zig build threads-test
1313
zig build threads-test -Dthreads-shard-index=0 -Dthreads-shard-count=4
1414
zig build threads-test -Dthreads-case=atomics/property-waitasync-timeout.js
1515
zig build threads-test -Dthreads-parallel-js=true -Dthreads-case=sync/condition-wait-notify.js
16-
zig build threads-reference-audit
17-
python3 tools/threads-reference-audit.py --run-probes --expect-current-blockers --probe-timeout 60
16+
zig build threads-reference-audit threads-reference-probes
1817
zig build test -Dtsan=true
1918
zig build test -Dtsan=true -Dtest-filter=parallel_js
2019
zig build threadfuzz -Dfuzz-iters=20
@@ -161,12 +160,13 @@ world-stopped finish.
161160
plain command, while a stuck shard prints the active `RUN` case before executing
162161
it. The required matrix gate is also bounded so a true hang becomes an archived,
163162
diagnosable failed job instead of an opaque spinner. The current coverage
164-
contains 235 compatible promoted files out of 259 executable PR-249 files: 233
165-
in the default `zig build threads-test` allowlist plus 2 `parallel_js`-only
166-
witnesses. The JSC-specific `api/wasm-refused-sd7.js` case stays reference-only:
167-
its required refusal conflicts with zig-js intentionally supporting WebAssembly
168-
inside shared-realm Threads. The native unit suite checks module validation,
169-
compilation, instantiation, and execution from a Thread in both GIL modes.
163+
contains 243 promoted files out of 259 executable PR-249 files: 241 in the
164+
default `zig build threads-test` allowlist plus 2 `parallel_js`-only witnesses.
165+
Ten optimizing-tier files remain blocked by
166+
[#429](https://github.com/zig-utils/zig-js/issues/429); six JSC-private or
167+
intentionally incompatible premises have verifier-enforced terminal
168+
dispositions. The native unit suite checks WebAssembly validation, compilation,
169+
instantiation, and execution from a Thread in both GIL modes.
170170
It covers:
171171

172172
- `api/` and `lifecycle/`: constructor shape, lifecycle, ids, constructor
@@ -528,10 +528,10 @@ baseline arena engine.
528528

529529
`zig build threads-reference-audit` verifies the checked-in [PR-249
530530
inventory](../.data/pr249-reference-inventory.json): all 339 vendored files are
531-
checksummed, all 259 executable cases have an explicit state, and every one of
532-
the 24 reference-only executables names stable dependencies, required hooks,
533-
and owner issues. The gate rejects file, checksum, allowlist, hook, and
534-
disposition drift without inflating the green allowlist with no-op passes.
531+
checksummed and all 259 executable cases are exactly classified as 243
532+
promoted, 10 blocked, or 6 terminal. The gate rejects file, checksum,
533+
allowlist, hook, dependency, and disposition drift without inflating the green
534+
allowlist with no-op passes.
535535

536536
`zig build threads-profile` is not a pass/fail correctness gate. It is the local
537537
scaling and contention profiler for issue #1. The wall-clock columns compare the
@@ -879,93 +879,45 @@ zig build threadfuzz-bin
879879
./zig-out/bin/threadfuzz moduleworkerclose 5 1
880880
```
881881

882-
## Remaining Reference-Only Areas
883-
884-
The default corpus is intentionally not a "run every file" mode. Remaining
885-
PR-249 files stay reference-only for concrete reasons:
886-
887-
- WebAssembly-required CVE files remain out until this engine has the matching
888-
WebAssembly construction, compilation, relocation, and grow behavior.
889-
- `api/wasm-refused-sd7.js` remains out because it requires JSC's v1 policy of
890-
throwing `TypeError` for every WebAssembly entry point on a spawned Thread.
891-
zig-js deliberately supports that surface; the unit witness `threads:
892-
WebAssembly compiles and executes in shared-realm workers` verifies the
893-
supported contract under both parallel and serialized/GIL execution.
894-
- JIT/CVE files that require JSC-specific code artifact hooks, ASAN controls,
895-
stop counters, disassembly controls, or retired-artifact machinery remain out
896-
until real engine behavior backs those hooks.
897-
- `cve/mc-df-arraycopy-relabel.js` remains out because it depends on JSC's
898-
butterfly verification shell option and a typed-array set length race shape
899-
whose current zig-js failure is still the documented `RangeError` blocker.
900-
The portable zig-js contract is covered by
901-
`TypedArray set snapshots array-like source length` and
902-
`parallel_js: TypedArray set snapshots array-like source length under no-GIL grow`:
903-
source length is snapshotted once, so growth before the snapshot can reject
904-
when it no longer fits the destination, while growth after the snapshot does
905-
not extend the copy.
906-
- `cve/mc-life-creator-thread-dies.js` still depends on a reference-shell
907-
detach race that constructs fresh `Int32Array` views after the source
908-
`ArrayBuffer` has been transferred. zig-js keeps the normal detached-buffer
909-
constructor `TypeError` there instead of weakening `TypedArray` validation.
910-
The portable creator-owned storage subset is covered by the unit witness
911-
`threads: creator-owned ArrayBuffer storage survives creator exit, GC, resize,
912-
and transfer` plus `threadfuzz creatorbuffers`. Together they check
913-
child-created `SharedArrayBuffer` / `ArrayBuffer` storage after creator exit,
914-
sibling reads, GC pressure, post-creator resize, and post-creator
915-
`ArrayBuffer.transfer()`.
916-
- `dw2-marklistset-storm.js` remains out because it targets JSC's shared-GC
917-
mark-list machinery. The portable graph/parse/ownership half of
918-
`w16-c1-prevent-collection.js` is promoted by
919-
`zig build test-private-heap-snapshot`: both WebKit and V8 forms are parsed
920-
across repeated snapshots under Debug, ReleaseSafe, and TSan. The original
921-
concurrent `Heap::preventCollection` gate remains reference-only because it
922-
is a JSC shared-collector election hook, not a portable snapshot property.
923-
- Helper/preload files such as `harness.js`, `bench/harness.js`,
924-
`scaling/harness.js`, `resources/assert.js`, and
925-
`vmstate/resources/workload.js` are not counted as standalone remaining
926-
tests.
927-
928-
Promote a reference-only file only when the engine implements the behavior, the
929-
file passes reliably under Zig `0.17-dev`, and the docs/issue counts are updated
930-
in the same change.
931-
932-
Run the reference audit after promotion attempts:
882+
## PR-249 Terminal Inventory
883+
884+
Eight #428 files now run maintained behavior in both serialized and no-GIL
885+
modes: `congc-t{3,4,5,9,11}`, the weak-global registry race, the buffer-growth
886+
storm, and the sort/apply marker-pressure storm. `$vm.createGlobalObject()` is
887+
a real child-realm constructor with fresh intrinsics, VM-shared symbols, and
888+
collector synchronization.
889+
890+
The 16 unpromoted executables are explicit:
891+
892+
- 10 optimizing-tier cases are blocked by #146/#429.
893+
- 3 incompatible premises require spawned-thread Wasm refusal, suppress a
894+
specification-permitted `TypedArray.set` `RangeError`, or construct a view
895+
after transfer detaches its buffer.
896+
- 3 JSC-private premises require `$vm.sharedHeapTest` or
897+
`Heap::preventCollection` internals that zig-js does not pretend to expose.
898+
899+
Six promoted files also record branch-level terminal premises for JSC-private
900+
diagnostic machinery while their portable stress paths execute normally. Five
901+
helper/preload files are not standalone tests. The inventory stores every
902+
reason, required hook, owner issue, and expected default/no-GIL outcome; the
903+
[exact evidence](../.data/pr249-non-jit-resolution-2026-07-21.json) records the
904+
28 default/no-GIL release runs plus 8 focused TSan passes.
933905

934906
```sh
935-
zig build threads-reference-audit
936-
python3 tools/threads-reference-audit.py --print-inventory
937-
python3 tools/threads-reference-audit.py --format markdown
907+
zig build threads-reference-audit threads-reference-probes
938908
python3 tools/threads-reference-audit.py --format json
939-
python3 tools/threads-reference-audit.py --probe-candidates
940-
python3 tools/threads-reference-audit.py --run-probes --probe-timeout 60
941-
python3 tools/threads-reference-audit.py --run-probes --expect-current-blockers --probe-timeout 60
942-
python3 tools/threads-reference-audit.py --scan-reference-only --probe-timeout 20
909+
python3 tools/threads-reference-audit.py --print-disposition-probes
910+
python3 tools/threads-reference-audit.py --scan-unpromoted --probe-timeout 60
943911
```
944912

945-
`--run-probes` executes the closest reference-only candidates with focused
946-
`threads-test` commands and returns nonzero on any failure or timeout. A timed
947-
out or failing probe is not promotion evidence; keep the file reference-only
948-
until the underlying behavior lands and the focused run passes reliably. Failed
949-
probes print focused runner evidence before the Zig build tail so the concrete
950-
JS error, corpus failure, or timeout is visible in one command.
951-
`--format json` emits the same allowlist counts, reference-only categories,
952-
closest probe commands, and expected current blocker evidence in a stable
953-
machine-readable form for CI reports, dashboards, or issue-tracker updates. The
954-
top-level `promoted_executable`, `executable_total`,
955-
`reference_only_executable`, and `helper_preload` fields mirror the nested
956-
sections so simple status scripts can read coverage without understanding the
957-
full category schema.
958-
`--expect-current-blockers` flips that maintenance check into a negative gate:
959-
it succeeds only while the nearest probes still fail or time out with the
960-
documented blocker evidence. If it starts failing because a probe passes, or
961-
because the failure shape changed, re-run that single `-Dthreads-case=...`
962-
probe, promote the file only when the underlying behavior is implemented, and
963-
update the docs/issue tracker in the same change.
964-
`--scan-reference-only` is a slower opt-in broom for issue audits: it runs every
965-
remaining executable reference-only file and fails only if one unexpectedly
966-
passes. Expected reference-only passes are machine-listed separately for cases
967-
that are known to skip JSC-only premises or that pass only in serialized mode
968-
while their no-GIL promotion arm remains too expensive.
913+
`threads-reference-probes` builds the runner once, then verifies the bounded
914+
terminal outcomes and their exact error evidence. The slower unpromoted scan is
915+
for deliberate issue audits, not every local edit.
916+
917+
TSan runs `dw2-marklistset-storm.js` with 2 workers × 18 rounds plus the main
918+
mutator. Worker seed 0 requests GC at round 16 while the other lanes mutate;
919+
normal and no-GIL release runs execute the untouched 16 lanes × 120 rounds.
920+
The exact Debug+TSan CI build completes this profile in 326.285 seconds.
969921

970922
## Docs Checks
971923

0 commit comments

Comments
 (0)