ReviewOS

zig-utils/zig-js

VM: remove legacy numeric call loops and immediate closure reuse

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

Parent: #498 Related: #1074, #1076, #1077, #1078, #1079, #1081, #491

The inventory's last two legacy_pattern_kernel / legacy_narrow families are exact numeric counted-call loops and immediate-call closure reuse. The closure path consumes the same structural call-loop plan to reuse a materialized function object at make_closure; it has no independent general metadata contract. Removing the loop machinery therefore removes both connected families.

Executed baseline on 60ad2657: the existing witness passes 2/2, asserting direct/local/method/arguments/closure loop hits and reusable-closure hits. The native-enabled and native-disabled/loop-disabled runs both return 23,190,741,181 in 31,563 logical steps, matching Node.

Acceptance:

  • Remove exact loop recognizers/executor, reusable immediate-closure dispatch/helper, loop-only plan/callee/bound types, counters/test toggle, candidate hint/flag, and per-instruction call-loop metadata tables.
  • Retain independently bounded numeric leaf calls, arguments leaves, general call/receiver/global/property guards, ordinary fresh closure creation, and activation reuse.
  • Preserve the baseline result/steps and live callee/receiver/captured binding semantics, fresh observable closure identity, argument/coercion order, partial exceptions, and GC roots.
  • Check actual no-GIL workers, explicit moving-GC roots, source hooks, exact budget/stop behavior, and allocation failures in normal/ReleaseSafe/unsuppressed TSan.
  • Exact before/after affected test262 and tree/required-VM comparisons have no new failures; regenerate inventory/docs/manifest with zero remaining legacy families while preserving historical evidence.

Zero legacy inventory families is not completion of #498's broader adaptive-dispatch, forced-no-JIT differential, memory, or throughput contract.

8 days ago

The expanded OOM probe initially reused a non-capturing activation-pool invariant for a capturing closure. The parent reproduces the same mismatch when its loop shortcut is disabled: captured frames are deliberately Context-arena owned and excluded from reuse.

The original non-capturing test keeps its exact allocation/free-pool accounting. A separate escaped-closure fault test now verifies restored caller/driver roots and state, forbids escaped frames in the reusable pool, accounts for the one captured defining frame, and confirms the returned closure still reads its binding after the defining call finishes. Both checks pass normally; sanitizer/ReleaseSafe verification is in progress. No engine ownership workaround or frame-reuse relaxation is introduced.

The call/closure semantic group already passes 8/8 in normal, ReleaseSafe, and unsuppressed TSan. The inventory and docs gates pass with zero live legacy families, and the validator rejects reintroduced legacy implementations/classifications.

8 days ago

Landed in b64cc348.

Removed the exact direct/method/arguments/closure counted-call kernels and their connected immediate-closure reuse, including loop-only plan/callee/bound types, counters/test toggle, final structural hints/flags, and per-instruction call-loop tables. make_closure always takes the ordinary fresh-closure path. Independently bounded numeric/arguments leaves, native direct calls, general guards, and safe activation reuse remain.

Validation:

  • Measured baseline retains 23,190,741,181 / 31,563 steps with native tiers enabled or disabled. Forced no-JIT isolated/shared contexts return the same result.
  • Semantic group 8/8 in normal, ReleaseSafe, and unsuppressed TSan covers four actual no-GIL workers, live callee/captured/receiver bindings, getter/call order, mapped arguments, eight distinct observable closure identities, partial exceptions, explicit Function/receiver relocation, ten source-hook events, and exact budget/stop accounting.
  • Original non-capturing allocation-failure check retains exact reusable-pool accounting and passes 2/2. Separate escaped-closure fault/lifetime check passes 2/2 in each mode, preserving restored driver roots/state and the Context-owned captured frame outside that pool; returned closures still read their binding correctly.
  • Effects oracle returns true in Node and in both engine modes on both binaries.
  • Exact parent/after call 92, function expressions 264, declarations 451, arrows 343, Function built-ins 509, for 385, while 38, assignment 485, addition 48, remainder 40 comparisons: 2,655 total, 0 diagnostic failures before → after, 0 flips, and the same eight pre-existing tail-call differences. Distinct binary hashes are verified.
  • Inventory self-test/validation pass: 8 guarded families, 0 live legacy families, 5 explicit unsupported families, 0 structural candidate flags. Negative checks reject reintroduced legacy implementation kinds and classifications. Docs links pass for 378 files, and the 51-page build matches the refreshed manifest.

These are scoped local checks; full integration gates run in CI. Historical performance evidence is unchanged. Zero legacy families does not complete #498's broader adaptive-dispatch, no-JIT differential, memory, or throughput requirements.

Sign in to comment on this issue.