ReviewOS

zig-utils/zig-js

GC relocation: add concurrent, native, and JIT-safe barriers

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

Parent: #144\nDepends on: #333, #334, #335\nRelated: #132, #133, #145, #146\nRoadmap: #134\n\nMake relocation safe at every mutator/native boundary and define the stack-map contract required by generated code.\n\n## Scope\n\n- Add the read/load and write/store barriers required while forwarding metadata is observable.\n- Coordinate shared-realm no-GIL mutators, Worker/Thread safepoints, parked peers, native callbacks, and collector phase transitions.\n- Define handle scopes and forbidden raw-pointer lifetimes across C, Objective-C, Bun/Home private ABI, inspector, and host callbacks.\n- Emit and consume precise stack maps for existing native JIT regions, including exceptions, OSR/fallback exits, and deoptimization handoff.\n- Prove atomics and memory ordering for forwarded pointers and concurrent root publication.\n\n## Acceptance\n\n- [ ] Running and parked mutators cannot observe stale or partially moved cells.\n- [ ] Existing native JIT regions survive relocation at every declared safepoint.\n- [ ] Native callbacks either hold stable handles or are rejected from crossing a relocation safepoint.\n- [ ] Deterministic no-GIL overlap tests and suppression-free TSan witnesses are green.\n- [ ] Unsupported architecture/ABI combinations fail explicitly rather than exposing partial relocation.

9 days ago

#355 is complete in 15e6b552. This closes one native-boundary acceptance slice: public C compaction is explicitly rejected during host-callback reentry with an active interpreter, then the same realm moves safely at the quiescent host boundary. The test proves a counted protected wrapper remains stable, its underlying cell address changes, and post-move property semantics remain correct. Debug/ReleaseSafe/TSan: 3/3, zero leaks.

9 days ago

#356 is complete in b50bbd7e. The C/native boundary no longer collapses all non-success states into false: invalid and in-callback calls report unsupported, packed heaps report no_candidates, deterministic scratch failure reports out_of_memory, and real movement reports compacted with exact nonzero cell/byte totals. All non-moving outputs are zero. Focused Debug/ReleaseSafe/TSan and both C/Objective-C embedding hosts/audits are green.

9 days ago

#357 is complete in 3e38a5ac. The native/embedding safety story now includes first-class opaque Zig handles: raw Value copies are explicitly bounded by the next movement, while ProtectedValue.get() reads the rewritten slot after compaction. Root synchronization, teardown, foreign-context rejection, stale-pointer verification, and focused Debug/ReleaseSafe/TSan evidence are all covered.

9 days ago

#358 is complete in cc0837d. The current baseline tier is now admitted only at the fully quiescent explicit boundary: generated code embeds no managed pointer, compiled mappings/tier metadata/chunks do not move, and the existing active-interpreter gate proves no NativeFrame exists. Live native execution and conservative stack modes remain rejected pending precise stack maps or pinning. The inventory gate now pins both the boundary gates and compiler object/string rejection.

9 days ago

#359 is complete in ca92af0. One live native boundary is now movement-safe: the current AArch64 numeric checkpoint publishes canonical frame locals, spills operands, records exact state, and sets a distinct movement-resumption token only during the runtime callback. A marking-precise quick path is explicitly proven unable to consume the request, preventing accidental widening. Running peers, generic/native-host boundaries, conservative scans, active collectors, and public reentrant compaction remain fail-closed. Debug/ReleaseSafe/TSan: 7/7, zero leaks.

9 days ago

#360 is complete in 7b82cf9. C/Objective-C native callbacks now have a safe scheduling primitive rather than attempting movement reentrantly. The callback witness proves direct movement stays unsupported, a protected argument is rooted, and the request is consumed only after unwind at the declared baseline checkpoint. Null/arena contexts reject deterministically; generic live-native boundaries remain fail-closed.

9 days ago

Acceptance is complete after #361 / 373181a. Running and parked peers are deterministically fail-closed and cannot observe forwarding state; the admitted AArch64 numeric baseline checkpoint publishes canonical locals and survives useful relocation; marking-only, generic JIT, native-host, active-collector, conservative-stack, and unsupported architecture boundaries reject explicitly. Native callbacks use protected handles plus scheduled movement or receive unsupported for direct reentry. The complete compaction witness passes 9/9 with zero leaks in Debug, ReleaseSafe, and suppression-free no-GIL TSan. Because forwarding metadata is never observable concurrently in the admitted stop-the-world paths, no mutator read/write barrier is required for those paths; future tiers must provide and inventory their own exact movement checkpoint before admission.

Sign in to comment on this issue.