Skip to content

Compiler: scan deferred class frame captures once #619

Description

@chrisbbreuer

Parents: #465, #493, #496
Related: #615, #616, #618

Problem

classDeferredBodiesCaptureFrame walks every deferred class member body once for every frame binding in the current and enclosing plain-function scopes. A function with many locals plus a large method/field/static-block surface therefore multiplies frame-binding count by deferred-class AST size during bytecode admission, even when the class references only globals.

At the original classifier baseline, eval_class could capture Environment-backed bindings but could not recover an arbitrary VM frame slot, so real captures required rejection. #803 has since implemented exact live frame projections. The classifier still must remain conservative and exact; broad class rejection is not an optimization.

Scope

  • Freeze production parse + plain-function admission/compile rows at 1K/2K/4K frame widths with method/field/static-block and early/late/global-only controls.
  • Collect frame-slot names across the exact FnScope ancestry once, excluding bindings already backed by Environment Records.
  • Traverse deferred class bodies once against exact frame-name membership while leaving eager superclass and computed-key evaluation unchanged.
  • Preserve conservative shadowing, TDZ policy, class template/chunk structure, unsupported-reason identity, and allocation accounting.
  • Keep the zero/one-frame-name common path allocation-free.

No-workaround rules

  • No class syntax refusal, heuristic cutoff, skipped deferred member kind, eager-key conflation, tree-walker fallback presented as optimization, source rewriting, or process-global cache.
  • A new class member/AST node kind must not silently create a frame-capture false negative.

Acceptance

  • Benchmark-first rows preserve exact admission/rejection reason, structural checksum, and allocation replay across every control.
  • Parent → candidate exact evidence demonstrates bounded classifier scaling and names the complete scored boundary.
  • The original classifier change preserved real-frame rejection and global/Environment-backed admission. Subsequent VM: retain live frame bindings in deferred class members #803 implements real-frame admission through live projections; global-only and Environment-backed controls remain admitted.
  • Focused compiler/class tests, full units, relevant Test262 class/function/lexical subtrees, and applicable TSan gates pass with exact before → after accounting.
  • Evidence and parent issues are cross-linked without promoting diagnostic host noise.

Subsequent capture implementation boundary

f83c4191 — feat(vm): retain live deferred class captures (#803) implements the previously rejected capture boundary and updates production compiler guards/checksums to validate actual capture plans, including complete binding descriptors. Ten class-frame and two TDZ diagnostic rows pass, with structural checks and allocation observations; exact rows are retained under /Users/chris/.cache/zig-js-803.Ll0xKj/bench-class-validation.tsv and bench-tdz-final.tsv.

These are one-sample dirty-tree diagnostics, not publishable classifier scaling evidence. The original reports describe the earlier rejection boundary. Keep this issue open: a complete parent/candidate bounded-scaling comparison still needs to name its exact classifier versus capture-plan compilation boundary. The semantic/GC changes and their four required-bytecode gains are tracked in #803, with construction prerequisites #804/#805; they must not be described as a classifier throughput improvement.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestjitBytecode, baseline JIT, optimizer, and code generationperformanceMeasured runtime, memory, scaling, or build performanceruntimeJavaScript runtime and builtin implementation

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions