ReviewOS

zig-utils/zig-js

VM: add activation-local scratch storage for program lowering

#706
Closed chris opened this 8 days ago ·
8 days ago

Parents: #498, #502 Related: #705, #491

Problem

Program-mode bytecode runs without a frame. Compiler lowering that must retain private intermediate state across observable calls cannot safely use synthesized global/environment bindings: nested evaluation can collide on the same hidden name, and shared-realm parallel execution can race or corrupt another invocation. Plain functions have frame slots and suspendable functions have activation environments; programs need an equivalent native per-execution facility.

Scope

  • Add bounded activation-local scratch storage for program bytecode, with explicit load/store/release operations or an equivalent verified operand-stack contract.
  • Root managed Values across GC relocation and preserve them across debugger checkpoints, exceptions, and native-tier fallback.
  • Keep scratch state private from global lexical/object reflection and separate across recursive, nested-eval, and parallel shared-realm executions.
  • Give the compiler a backend-neutral way to retain resolved references and other short-lived intermediates without heap wrappers or global names.

No-workaround rules

  • No process/global mutable scratch, hidden global properties/bindings, guessed NUL-name isolation, repeated observable evaluation, heap wrapper per reference, GIL-only serialization, or tree-walker callback presented as program lowering.

Acceptance

  • Recursive, nested direct/indirect eval, debugger, exception, GC relocation, and no-GIL parallel witnesses prove invocation isolation.
  • Interpreter, VM, baseline, optimizer, and deopt paths agree on scratch liveness and reconstruction.
  • TSan is clean and OOM/overflow fail explicitly without partial publication.
  • #705 top-level member logical assignments use the facility with exact one-shot reference semantics.
  • Full correctness gates and quantified overhead/code-size evidence pass.
8 days ago

#705 landed the activation-safe function subset in 8fe68869. Program-mode obj[key] ??= rhs remains deliberately rejected: no hidden global/environment scratch or re-evaluation was introduced. #706 now has a concrete first consumer and exact reference-isolation witnesses to promote once native program-local storage exists.

8 days ago

#707 landed activation-local member compound assignment in a0450f16 without adding program scratch. Plain functions use frame locals; generator/async functions use private activation environments and the suspendable operand stack. Top-level obj[key] op= rhs remains causally rejected because hidden globals/environment names would be reentrancy and no-GIL races. This leaves #706 as the explicit prerequisite for safe program-mode lowering.

8 days ago

#708 landed function-activation member updates in 1f925020 while retaining an exact program-admission rejection for holder.value++. Once #706 provides safe program-local scratch, the existing one-Reference helper/lowering can be admitted at top level without global synthesized names or another runtime primitive.

8 days ago

Landed in be928fbd (`feat(vm): add activation-local scratch for program lowering (#706)`).

Design: chunks declare `scratch_count`; each execution allocates an Exec-owned, GC-rooted `Value` array (traced in `traceInterpreterRoots`, relocated with the other precise Exec roots), addressed by new `scratch_store`/`scratch_load` opcodes with chunk-bounded indices. Per-Exec ownership gives recursive, nested-eval, and parallel shared-realm executions disjoint slots with no locks and no global state; debugger checkpoints, exceptions, and native-tier fallback are unaffected because scratch lives on the Exec like the operand stack.

Evidence:

  • compiler admission tests prove every program using member references publishes a nonzero scratch_count and moves temporaries only through the new opcodes; explicit disposal remains the stable rejection probe
  • forced tree-walker vs required-bytecode differential matches byte-for-byte on compound assignment plus p

Sign in to comment on this issue.