ReviewOS

zig-utils/zig-js

GC compaction: prove weak, embedding, and WebAssembly boundaries

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

Parent: #335 Depends on: #350 Roadmap: #134

Exercise the audited non-ordinary roots through real repeated compaction, not helper-only relocation plans.

Scope

  • Verify WeakRef/WeakMap/WeakSet/FinalizationRegistry reachability and cleanup ordering across moves.
  • Verify public C protected handles, private strong/weak handles, and Objective-C JSManagedValue inheritance keep stable handle addresses while rewriting/clearing payloads.
  • Verify WebAssembly externref/hostref tables, globals, execution roots, exceptions, and wrapper identity across moves.
  • Add a post-commit stale-old-address verifier over audited roots and cell edges.

Acceptance

  • Live weak/ephemeron targets relocate; dead targets clear and finalize exactly once.
  • Stable embedding handle addresses do not change while payloads do.
  • WebAssembly JS-bearing roots preserve canonical identity.
  • No audited root or edge resolves to an old payload after commit.
  • Focused normal/ReleaseSafe/TSan and full matrix pass.
9 days ago

Post-commit stale-address verification landed in dd96dd82, backed by zig-gc 5883b02 (#36). After all destination publication/index commits, zig-gc walks current roots and live cells with the forwarding plan still available. zig-js reuses non-mutating tracing and explicitly adds weak-map keys/values, finalization target/token/held slots, and the pointer-keyed weak cache invariant. Any retained old payload traps before forwarding scratch is released.

The end-to-end compaction test proves the hook ran for both successful moves and did not run for planning OOM. Focused Debug and TSan pass 3/3 with zero leaks; inventory remains green. Remaining #351 work is real weak/finalization, embedding, and WebAssembly compaction witnesses.

9 days ago

a12cc1b adds the real repeated-move boundary witness and fixes the native WebAssembly gap it exposed.

Evidence after two successful moves:

  • WeakRef live/dead behavior, WeakMap/WeakSet identity, and FinalizationRegistry cleanup all pass.
  • C API and private strong/weak handle addresses remain stable while their payloads rewrite; dead private weak roots clear.
  • Standalone WebAssembly.Table and WebAssembly.Global preserve canonical JS identity.
  • Table/global atomic mirrors and native execution slots now relocate together. Native owner slots also participate in the post-commit stale-address audit without adding plain native reads to concurrent marking.
  • Deterministic planning OOM still leaves graph/accounting unchanged.

Local gates: focused Debug, ReleaseSafe, and TSan each pass 3/3 with zero leaks; relocation inventory is green at 9 cell kinds, 26 pointer surfaces, and 21 boundary tags.

The head CI run is queued. I am keeping #351 open for a direct Objective-C JSManagedValue inheritance witness and descendant full-matrix evidence.

9 days ago

d31db8c completes the direct Objective-C boundary witness and exposes the checked moving heap to embedders.

  • Added ZJSGlobalContextCreateGarbageCollected(enableJIT) and ZJSContextCompactGarbage. The factory owns a real C context group, so public JSContext contextWithJSGlobalContextRef discovers a valid JSVirtualMachine rather than relying on test-private initialization.
  • The Objective-C runtime host proves an owner-retained JSManagedValue survives compaction with the same JSValue wrapper and stable JSValueRef handle, then clears after removeManagedReference and a second compaction.
  • A clean rebuild exposed Apple libtool silently dropping the Zig archive member. The build now preserves the Zig archive, appends the Objective-C object, and rebuilds its symbol index; clean Objective-C linking is covered by the host.
  • Debug and ReleaseSafe Objective-C hosts pass. C/C++ embedding fixtures, the 117-symbol/21-extension C API audit, the 108-declaration Objective-C audit, and relocation inventory all pass.

All #351 behavioral acceptance items now have local evidence. The issue remains open only for descendant full CI, whose newest main run is queued.

9 days ago

Additional embedding-boundary evidence landed in #355 / 15e6b552: a C host callback cannot reenter compaction while its interpreter is active, but a protected C wrapper on the same fragmented realm survives movement at the next quiescent host boundary with a changed payload address and intact property semantics. Debug/ReleaseSafe/TSan focused runs are green with zero leaks.

9 days ago

Embedding evidence/API improvement from #356 / b50bbd7e: exact C compaction statuses and movement metrics are now public and machine-inventoried. The Objective-C host was corrected to construct purposeful tail fragmentation under #352's policy, then proves nonzero movement with stable managed wrapper/value identity. C/C++ and Objective-C hosts/audits plus Debug/ReleaseSafe/TSan are green.

9 days ago

The moving embedding boundary now also supports safe scheduling from C/Objective-C in 7b82cf9 / #360. Objective-C requests movement through the public extension and consumes it at the checked direct boundary; the C callback witness additionally proves scheduled consumption at the precise native checkpoint with a protected handle. Public direct reentrant movement remains rejected.

9 days ago

Completed and accepted. The implementation-specific local evidence is recorded above, and descendant full CI at https://github.com/zig-utils/zig-js/actions/runs/29716788619 completed with 42 successful jobs, one intentional nightly skip, zero failures, and zero cancellations.

Sign in to comment on this issue.