ReviewOS

zig-utils/zig-js

ABI: migrate private global lifecycle to shared precise GC

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

Parent: #414 Depends on: #415 ABI parent: #412 Profiles: #163, #164 Roadmap: #134

Use the ownership-aware sibling-realm heap to complete the physical reclamation and terminal evidence missing from the arena-backed #412 lifecycle.

Acceptance:

  • Create private mini/full VMs on the shared precise-GC path without changing the three pinned signatures.
  • Create test-isolation realms on the same heap/VM and atomically transfer process identity plus embedder metadata.
  • Retire the old realm roots, clear module/job/embedding state, run a full collection, and prove its global graph is reclaimed while VM-scoped state survives.
  • Prove retained old handles remain valid only for their explicit lifetime and do not republish the retired execution-context identity.
  • Prove external C-API class and buffer/string owners finalize exactly once during replacement or final teardown.
  • Cover wrong-thread replacement/destruction and concurrent identifier lookup under TSan.
  • Refresh the #412 machine contract, concise docs, inventories if needed, and Debug/ReleaseSafe/TSan/relocation CI evidence.
  • Reconcile exact main CI and close #412/#414 only after their remaining acceptance is complete.
9 days ago

Implemented and pushed in four cohesive main commits:

  • 15fd8386 routes first-use GlobalSymbolRegistry cells to the hidden heap owner.
  • 7d7bd8a9 makes precise owner/sibling bootstrap failure-atomic.
  • 1801083a migrates private mini/full VMs and test isolation to shared precise GC.
  • 7d114f27 refreshes the machine contract, ABI docs, concise API docs, and README evidence link.

Focused evidence:

  • Debug internal lifecycle: 3/3 passed, 0 leaked.
  • Debug Home/Bun independently compiled fixtures: passed.
  • ReleaseSafe internal + Home/Bun fixtures: 17/17 build steps passed, 0 leaked.
  • TSan internal + Home/Bun fixtures: 17/17 build steps passed, 0 leaked and no race report.
  • Private VM batch: 6/6 passed, including bounded failure injection across the ~12,000-allocation precise bootstrap transaction.
  • ABI audits: Home 446/471, Bun 437/461, zero unclassified.

The focused proof covers same heap/VM/JIT/Symbol identity, independent realm arenas and globals, atomic process-identity transfer, retained Context lifetime, a VM-protected outgoing value across compaction, delayed physical retirement until unprotect, old-realm finalizer activity, weak canonical-box rekey/removal, and exact-once C class/no-copy buffer/external buffer/string cleanup. Wrong-thread replacement/destruction remains covered by the independent fixtures.

Fresh exact main CI is https://github.com/zig-utils/zig-js/actions/runs/29800228129 and remains the only unchecked acceptance gate.

9 days ago

Exact-main CI exposed one missing ownership edge in unit shard 3/4: direct structured-clone deserialization could allocate a SharedArrayBuffer wrapper after Context.evaluate restored thread-local GC state, so publication observed no_realm.

Fixed on main in 51097394 by making both public structured-clone entry points install and restore the interpreter's precise realm themselves. This covers direct engine, worker, and private C-API callers at the actual allocation boundary. Focused validation on the retained near-CI Zig toolchain passes all 11 structured-clone tests with 0 failures and 0 leaks.

Fresh exact gate: https://github.com/zig-utils/zig-js/actions/runs/29800753036

9 days ago

The second exact run reached the combined private-ABI gate and exposed a separate semantic-owner regression in the 392-symbol Home fixture: stable private EncodedJSValue boxes correctly lived in the hidden VM owner, but the same owner field was also used to select JavaScript intrinsics. A native FormData append therefore created a File with the hidden realm's prototype; the exposed realm observed the right contents/name but correctly rejected value instanceof File.

Fixed on main in a70b6161:

  • private boxes now retain distinct semantic-realm and stable-storage owners;
  • protection remains rooted in the hidden owner and can still outlive an outgoing realm;
  • all C-API allocation scopes install the complete context/realm instead of collapsing a shared heap to its owner.

Validated locally on the retained near-CI Zig toolchain: Home private 392/392 runtime matrix, Bun SQL 4/4, precise Home/Bun lifecycle, 11/11 structured-clone tests, ReleaseSafe Home+lifecycle, and TSan lifecycle all pass. The attempted full Home TSan executable is not a behavioral failure: that existing build step does not propagate sanitize_thread to the executable and therefore cannot link the TSan-instrumented static library; CI's actual TSan lifecycle fixture is correctly wired and green locally.

Fresh exact gate: https://github.com/zig-utils/zig-js/actions/runs/29801586207

9 days ago

Complete. Exact main run 29801586207 is green across all 43 jobs. The private ABI boundary passed the 392/392 Home runtime matrix after the semantic/storage realm split; focused precise lifecycle evidence remains green in Debug, ReleaseSafe, and TSan. This unblocks #414 and #412.

Sign in to comment on this issue.