ReviewOS

zig-utils/zig-js

Compiler: scan pending TDZ references once

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

Parents: #465, #493, #496

Problem

Compiler.tdzRefsPending iterates every not-yet-declared lexical spelling and runs a complete nameRefInClosure AST walk for each one. An attacker-sized function with many lexical declarations and a large expression before them can therefore multiply pending-binding count by expression size during bytecode admission, even when the expression references none of those bindings.

This is a compiler-classification cost, not an execution shortcut: TDZ detection must remain conservative and exact.

Scope

  • Add an owned parse-plus-plain-function-compile growth witness at 1K/2K/4K widths, including no-reference, forward-reference, self-reference, nested-function/class deferred-reference, and declare-before-use controls.
  • Record exact admission/chunk/checksum, allocations/bytes, instructions/cycles, wall diagnostics, and complete raw commands through the exact-parent A/B pipeline.
  • Replace per-pending-binding whole-subtree walks with one exhaustive identifier traversal using exact pending-lexical membership lookups.
  • Preserve the exhaustive AST-node contract so a new node kind cannot silently create a TDZ false negative.
  • Keep ordinary functions on unchecked hot opcodes when proven hazard-free; do not broaden runtime TDZ checks as a performance workaround.

Acceptance

  • Growth evidence demonstrates bounded near-linear classifier work as binding and expression width scale together.
  • All witness variants preserve exact admission, chunk shape/checksum, allocation accounting, and TDZ behavior.
  • Self/forward and hoisted/nested-function references retain checked lexical loads; field initializers and static fields retain exact hazardous classification and conservative frame-capture rejection.
  • Declare-before-use and unrelated-identifier controls remain bytecode-eligible without checked lexical opcodes.
  • Focused compiler/frontend tests, forced tree-walker/required-bytecode differentials, full units, and relevant test262 lexical/function/class subtrees pass with zero flips.
  • Exact-parent evidence and documentation name exact revisions and do not convert noisy wall observations into claims.
9 days ago

Benchmark contract landed on main in e9412de8. It adds ten exact parse-plus-compile rows: hazard-free 1K/2K/4K growth plus unrelated, declared-use, forward, self, nested-closure, instance-field, and static-field controls. Each row validates admission, TDZ opcode policy, chunk shape, structural checksum, and allocation replay. All rows and one pre-existing parser control pass; exact-parent self-tests and the 15-edge/60-tool dependency audit are green. No timing claim is published from these contract checks. The single-traversal implementation is now in progress against this exact first parent.

9 days ago

Implementation is durable on main in 8da47d8e, whose exact first parent is the benchmark contract e9412de8. The compiler now performs one exhaustive identifier traversal with exact pending-lexical membership checks; the existing exact-name capture specialization remains unchanged and the new path allocates nothing.

Validation completed before the host entered low-battery mode:

  • all 10 benchmark admission/TDZ-policy/structural checksums exactly match the parent;
  • 68/68 compiler-filtered units pass with zero skips, failures, or leaks;
  • the new 8-case hazard classifier matrix passes;
  • focused frontend passes 12/12;
  • formatting and diff checks pass.

The machine is now at the OS low-battery warning while disconnected from AC. #615 remains open: full units, relevant Test262 before/after, and exact-parent evidence are deliberately pending rather than being run or claimed under an unsafe/invalid power state.

9 days ago

Current-main full-suite evidence is green after the #615 implementation: zig build test-parallel completed 1,732 passed, 1 platform skip, 0 failed, 0 leaked across 10 shards in 167.1 s wall time. The existing focused compiler/TDZ and forced tree-walker↔required-bytecode gates remain green.

Relevant Test262 before→after accounting and exact-parent performance evidence are still pending; a new user-owned Home unit compile began immediately after this suite, so corpus execution remains serialized rather than overlapped.

9 days ago

Exact parent→candidate Test262 accounting is now complete for the #615 semantic surface:

  • test/language/statements/let: 0 fail / 145 pass → 0 / 145
  • test/language/statements/const: 0 / 136 → 0 / 136
  • test/language/statements/function: 0 / 451 → 0 / 451
  • test/language/expressions/function: 0 / 264 → 0 / 264
  • test/language/expressions/class: 0 / 4,059 → 0 / 4,059

Total: 0 fail / 5,055 pass → 0 / 5,055. Each parent/candidate diagnostic transcript is byte-for-byte identical; denominators are nonzero and come from the explicitly configured populated Test262 root. Together with the 1,732-pass full suite and focused tier differentials, the correctness acceptance row is complete.

Only exact-parent growth evidence and its documentation remain before closure.

9 days ago

Follow-up #621 owns a separate residual cost discovered during review: plain-function admission still rebuilds the parameter/declaration spelling inventory for shadowing and TDZ classification. #615 remains scoped to the completed single pending-reference traversal and its frozen exact-parent evidence.

9 days ago

Exact-parent evidence resumed on a quiet host with both immutable revisions built using the historical performance-workflow pin, Zig 0.17.0-dev.1441+d5181a9c9:

  • parent: e9412de8
  • candidate: 8da47d8e
  • exact first-parent identity: confirmed
  • generated source, admission/structural checksums, allocation replay: exact
  • thermals: nominal throughout

The full-efficiency harness correctly rejected both seven-pair 1K attempts, so no timing claim or repository artifact is being published:

  • 10 jobs: parent/candidate wall medians 81.340/4.000 ms; instructions RSD 0.03%/0.09%, but candidate energy RSD 105%. Status: blocked_efficiency_evidence.
  • 100 jobs: parent/candidate wall medians 807.813/37.237 ms; instructions RSD 0.01%/0.14%, but candidate wall/cycles/energy RSD 25.1%/11.4%/9.3%. Status: blocked_efficiency_evidence.

This is a profile-boundary problem created by the intended quadratic→linear improvement: enough identical repetitions to lift the candidate above every counter's resolution makes the 4K exact parent disproportionately long. I opened #670 for a separate versioned algorithmic-growth artifact based on exact normalized work and stable retired instructions, while retaining the existing all-metrics profile unchanged. #615 remains open and fail-closed pending that evidence contract.

9 days ago

The additive evidence prerequisite is now landed in fabf6c7c via #670. It keeps the ordinary full-efficiency gate unchanged while allowing stable normalized retired-instruction growth and exact allocation replay to be scored across three or more widths; all wall/cycle/energy observations and ordinary rejection decisions remain embedded.

The first collection attempt after landing was rejected before sampling because the competing-process guard detected unrelated Home/Bun test builds. No artifact was accepted or published. I will resume the exact 1024/2048/4096 collection only after the host is clean.

9 days ago

AC power is restored at 100%, so the prior power-state blocker is cleared. A guarded 2K TDZ-clear exact-parent attempt was started after five quiet preflight samples, but exact-parent-regression.ts rejected it before the first benchmark invocation when a Home Zig test link appeared. No JSON/Markdown artifact or timing sample is retained, and no performance acceptance box changes. The frozen parent/candidate runners and checksums remain ready for an uninterrupted host window.

9 days ago

Exact algorithmic-growth evidence landed in 0abebd1a (`evidence(compiler): land tdz-clear algorithmic growth rows (#615)`).

Collection contract: parent `e9412de` -> candidate `8da47d8` (candidate first-parent verified), Zig `0.17.0-dev.1441+d5181a9`, zig-gc `89b6652`, zig-regex `87e9ca2`, host class `quiet_reference`, AC power throughout, seven order-balanced pairs per width at jobs=10 over the deterministic `bench/frontend_parse.zig` TDZ-clear witness (single frozen source file shared by all widths; per-row checksums 152135090 / 8124090670 / 765513290 matched exactly on both variants at every sample).

Scored boundary (normalized retired instructions per logical job + exact allocation replay only):

widthparent instr RSDcandidate instr RSDcandidate/parentparent exponentcandidate exponent
10240.11%1.37%0.0447x——
20480.02%0.32%0.0229x1

Sign in to comment on this issue.