ReviewOS

zig-utils/zig-js

Debug: resolve no-GIL validation and futex corpus timeouts

#1105
Closed chris opened this 9 days ago ·
9 days ago

The full Debug no-GIL functional gate on 4010bc5, with the candidate #1103 condition fixture correction, passed 250/253 cases. It recorded two timeouts under the unchanged 600-second per-case watchdog:

  • cve/mc-val-fire-vs-link.js
  • sync/atomics-futex-lock.js

Runtime samples show JavaScript loops executing, rather than an idle blocked driver. The separate lifecycle assertion failure is tracked independently. The full ReleaseSafe gate passed 253/253.

Compare both cases against a pinned Debug before runner and isolate workload growth, contention, and startup/registration ordering before assigning a cause. In particular, the futex fixture declares assumptions about the former cooperative scheduler; those assumptions need executed probes under independent scheduling.

Acceptance: each original intended invariant remains checked; any fixture correction proves the registration/ordering edge and is explicitly audited. Both Debug and ReleaseSafe pass the unchanged functional gate and relevant unsuppressed TSan controls. Do not reduce loops or cases, add sleeps, weaken assertions, hide a timeout as a pass, or raise the watchdog.

Related: #1103; queue #933.

9 days ago

The futex timeout is fixed in 729837d. The validation-storm timeout remains open.

The original sync/atomics-futex-lock.js times out at 600 seconds on the pinned 80e4595 Debug no-GIL runner. A controlled worker-first probe proves the first ordering bug: the worker starts before main publishes its turn, throws the original out-of-turn error, and main can then wait without a notifier. Even with the turn published first, an early notification does not establish that main has parked.

The owned fixture publishes the worker turn before spawn and advances it only after Atomics.notify actually dequeues main. This follows the registration proof already used by the case's separate parked-main stage. The obsolete 5ms mutex wait workaround is removed: the three-state mutex uses untimed waits. Every original assertion line is preserved, as are all four workers, 300 mutex laps and ten ping-pong rounds. The pinned upstream fixture is untouched; the runner checks its SHA-256 before selecting the audited owned fixture.

Validation:

  • Corrected full case on pinned before engine: 10/10 in each threading mode.
  • Candidate Debug: 10/10 per mode; ReleaseSafe: 25/25 per mode.
  • Instrumented ReleaseSafe TSan: 5/5 per mode, with TSAN_OPTIONS unset and no supplied suppressions; linked init/read/write instrumentation verified.
  • Full ReleaseSafe no-GIL functional gate: 253/253 under the unchanged 600-second per-case watchdog.
  • Reference inventory audit and all five terminal-disposition probes pass; the pinned 51-page documentation manifest matches.
  • Deliberately changed upstream source is rejected with CorpusFixtureDrift before execution; the isolated archive is restored afterward.

Engine sources are unchanged, so this fixture correction flips 0 test262 cases. cve/mc-val-fire-vs-link.js and the full Debug gate still require resolution; #1103 remains open.

9 days ago

Resolved in 969c0f5c, together with the futex registration correction in 729837d.

The remaining Debug validation-storm timeout is resolved by retaining owned binding storage for one exact uncaptured block statement list. Values and parent/ownership fields are cleared through the existing Environment trace-lock/marker-handshake protocol. A different block frees the retained layout; captured scopes retain distinct environments, and aliases/dynamic eval bindings are fully cleared.

The pinned 80e4595 Debug no-GIL runner times out cve/mc-val-fire-vs-link.js at the unchanged 600-second deadline. Runtime samples locate repeated putConst → putTaggedBinding → owned-name/table allocation and shared allocator contention. The unchanged fixture still runs 40 generations, 20,000 hot calls per generation, its transition worker, and every original oracle. It now passes Debug, ReleaseSafe and instrumented TSan in both threading modes. These diagnostic runtimes establish watchdog completion, not a published throughput comparison.

Completed validation:

  • Full Darwin Debug no-GIL gate: 253/253, unchanged 600-second per-case watchdog.

  • Full Darwin ReleaseSafe no-GIL gate: 253/253, same watchdog.

  • Exact-parent test262 comparison: 7,621 default-tier cases across 14 affected subtrees pass on both binaries; 0 flips. Exact VM failure sets are unchanged, including nine existing proper-tail-call divergences in block/for/try.

  • Allocation control: 1,000 reset/rebind cycles make no additional binding allocations and clear stale values; switching away fully frees owned bytes.

  • Node-confirmed TDZ, const assignment, captured closure, eval, changing-block and throwing-exit controls pass in tree and automatic modes.

  • Moving-GC active-interpreter container relocation passes.

  • TSan workload passes serialized and no-GIL; init/read/write instrumentation verified, TSAN_OPTIONS unset, no supplied suppressions.

  • Focused ReleaseSafe TSan block tests: 4/4; failure-atomic binding publication/OOM controls: 2/2.

  • Seeded threadfuzz: default 400, exact-value verify 300, and mid-GC 900 generated programs (20 iterations), all zero failures.

  • Unsuppressed TSan threadfuzz: 60/60, zero failures; the exact executable's init/read/write instrumentation is verified.

Full combined local units remain subject to #933's documented cold-link memory limit. The new push's CI integration checks are pending; the earlier 729837d run was cancelled and is not claimed as a full integration pass.

Sign in to comment on this issue.