ReviewOS

zig-utils/zig-js

Optimizer: verify native recovery maps and operation metadata

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

Parent: #469; follows #1088; related: #466, #491.

Extend verification from SSA recovery graphs to native lowering output. Program already owns deoptimization values/handlers, precise stack maps, OSR imports, runtime-operation descriptors, and control/safepoint targets. Their common contract needs an independent callable verifier and test-build phase hooks before code emission.

Scope:

  • Validate frame/scratch dimensions, slot and slice bounds, recovery sources/constants, handler and exceptional-target shape, and aligned map/deopt identities.
  • Validate runtime input spans, descriptor/deopt references, output/operand slot ranges, and optional side-table lengths.
  • Check root coverage for recovery frame slots, non-primitive scratch values, and callback inputs; omitted roots require a primitive proof.
  • Validate OSR imports and control/safepoint references before any emitter dereference.
  • Invoke validation after lowering in test builds and before test-build emission. Production compilation remains excluded at compile time.
  • Preserve current valid numeric/boxed/runtime/loop plans and allocator-failure cleanup; reject deterministic metadata mutations with stable errors.

Definition of done:

  • Existing straight-line, branch, catch/finally, runtime-effect, OSR, loop-region, and moving-map programs pass validation.
  • Corrupt dimensions/slices/slots, missing roots, malformed callback/control/OSR references, and unsafe embedded constants fail closed.
  • Test phase hooks, OOM cleanup, Debug/ReleaseSafe/unsuppressed TSan and native GC/semantic gates pass.
  • Saved-parent/current corpus outcomes and docs/build audits pass with scoped evidence.

This completes the native-metadata side of verification; it does not claim completion of #469 optimization passes or performance acceptance.

9 days ago

Implemented in bc83af30, pushed directly to main over exact parent bbeab18f.

Program.verify independently checks native frame/scratch dimensions, recovery slices and sources, stack-map identities and masks, root coverage, runtime descriptors and callback spans, exceptional-handler shape, OSR imports, and control/safepoint references. It rejects embedded managed constants and propagates possible managed values through scratch copies; guarded numeric imports and primitive results supply the proof for omitted roots. Fixed ABI-bounded buffers require no allocations. Test builds invoke it after all lowering paths and before emission; production compilation excludes those hooks.

The checks exposed a map-contract omission: whole-entry lowering used a frame-only map builder outside runtime callback points, leaving boxed scratch recovery values unmarked there. It now uses the existing typed recovery-map builder, and the duplicate frame-only implementation is removed. A pinned boxed property-result recovery test proves the root is present and deleting it fails verification. This is a metadata-contract finding; no runtime UAF is claimed.

Qualification:

  • Five new cases cover dimensions, recovery/descriptor ranges, operation destinations, callback and frame roots, boxed scratch roots, unsafe constants, exceptional targets, OSR import bounds, control references, and allocator-failure cleanup.
  • 186/186 optimizer tests pass in Debug, ReleaseSafe, and unsuppressed TSan, including native effects, branch/catch/finally, OSR/fused regions, real moving-GC, no-GIL, invalidation, exact steps, and seeded optimizer-off/on witnesses.
  • Broader JIT: 144 passed / one platform skip / zero failures or leaks. VM/concurrency smokes: four each. Default/verify threadfuzz: 400/300 programs, zero failures.
  • Exact parent/current diagnostic and tree/VM reports match across seven subtrees: for 385, while 38, try 201, call 92, function expressions 264, property accessors 21, and in 36. 1,037 cases, zero default-tier failures, the same 11 existing tree/VM differences. Flips 0 test262 cases.
  • Parent/changed runner SHA-256: 70614d098a2a514162628ce102234595fef4eead2bf6fac9a9a82159c3e2a544 / 97cfe1a6c07e98538ada1010093497c7525c4dba96a4d8b19b717fd3c6e68ac8.
  • Production build, GC relocation inventory, docs-link audit, and regenerated/checked 51-page docs manifest pass; only the optimizer page's manifest entry changes.

The full combined local unit link remains blocked by #933's unchanged memory cap. Hosted integration is pending. Together with #1088 this supplies #469's verifier foundation; its optimization-pass and performance acceptance remain open.

Sign in to comment on this issue.