ReviewOS

zig-utils/zig-js

JIT: admit loop OSR after managed bytecode constants

#1014
Closed glennmichael123 opened this 9 days ago ·
9 days ago

Parents: #466, #469 Performance evidence: #473

Executed evidence

On clean main after #1013, the frozen representative_json row is slower with native tiering enabled: 357.280 ms versus 350.702 ms with enable_jit=false across seven alternating samples (exact checksum 324952086). Attribution records 3 optimizer attempts, 1 publication, 2 rejections; VM dispatch differs by only 22,215 of roughly 23.16 million dispatches.

A module-root compile of the exact representativeJson bytecode found the first rejection at the managed string constant "row-". Replacing only that hard rejection with an opaque interpreter-owned graph value produces a valid 131-bytecode / 11-block / 147-node plan and exposes the next independent blocker: whole-function SSA IDs exceed the 128-slot native scratch capacity.

Scope

  • Represent managed string/object constants as opaque exact-bytecode values during graph planning instead of embedding raw managed pointers.
  • Keep whole-entry lowering fail-closed when it would execute an unsupported opaque value.
  • Permit a selected loop OSR region to import the already-materialized managed value from the exact VM frame.
  • Publish precise stack-map roots and recover the same value on every side exit.
  • File the 147-node/128-slot region-compaction blocker separately; do not disguise it with a larger scratch array or benchmark-shaped admission.

Acceptance

  • A focused native test starts after a managed constant, executes the loop region, recovers the exact value, and proves its scratch root bit.
  • Whole-entry lowering still rejects unsupported managed-value execution.
  • Moving-GC rewrite, invalidation, forced-tier differential, no-GIL, and TSan behavior remain exact.
  • Exact-parent evidence reports admission/dispatch and timing without claiming a JSON win while the independent region-capacity blocker remains.
  • No raw managed pointer is copied into the optimizer plan or compiled artifact.
9 days ago

Landed and pushed as 5ff1bba.

Verified before push:

  • focused production JIT root with the real moving-GC checkout: 446 passed, 1 platform skip, 0 failed (2.073 GB bounded peak);
  • targeted ReleaseFast: 3 passed, 0 failed (227 MB);
  • targeted TSan: 3 passed, 0 failed (140 MB).

The focused native case proves whole-entry lowering stays disabled, OSR imports the managed value from the exact frame, side-exit recovery preserves the identical bits, and the stack map marks its scratch slot. No managed pointer is embedded in the graph or artifact.

I am leaving this issue open until the full forced-tier integration differential can run alongside the next blocker. The frozen JSON row is intentionally not claimed as improved yet: its exact graph now reaches the independent 147-node/128-slot region-capacity rejection.

9 days ago

Completed by 5ff1bba and re-audited on current main at a4d47ae. The focused real-GC optimizer-loop set passes 14/14 and pins exact VM-frame import, managed-value identity, scratch root publication, moving-safepoint rewrite, side exits, and irreducible rejection; the same 14/14 pass under unsuppressed TSan. The combined parallel_js + TSan seeded optimizer differential passes 3/3. Frozen production attribution preserves checksum 324952086 with two optimizer publications and cuts scored VM dispatch from 23,184,279 required-VM to 9,224,978 JIT-on. Whole-entry managed-value execution remains fail-closed; no managed pointer is embedded in the plan or artifact. The independent fixed-scratch boundary was implemented in #1015.

Sign in to comment on this issue.