Skip to content

jit(fbw): drop the unwired PendingInlineFrame vref residue; record _MULTIFRAME's measured corpus coverage - #795

Merged
youknowone merged 1 commit into
mainfrom
jitcode
Jul 25, 2026
Merged

jit(fbw): drop the unwired PendingInlineFrame vref residue; record _MULTIFRAME's measured corpus coverage#795
youknowone merged 1 commit into
mainfrom
jitcode

Conversation

@youknowone

@youknowone youknowone commented Jul 25, 2026

Copy link
Copy Markdown
Owner

One commit: delete FBW walker residue that a call-graph search shows is
unreachable, correct three comments that name mechanisms which do not exist,
and record a measurement of the multi-frame blackhole path in the gate ledger.

Dead state

PendingInlineFrame::drop_frame_opref is constructed at exactly one site,
always None, and never read. Its comment said None "skips the
opimpl_virtual_ref emission in push_inline_frame". push_inline_frame
(majit-metainterp/src/compile.rs) does exist, but it is a depth guard — it
pushes a (code_ptr, pc) greenkey onto inline_frames and returns bool. It
takes no PendingInlineFrame, mutates no framestack, and contains no vref
code. The emission the comment names was never built.

InlineTraceStepAction — the enum that would have carried a
PendingInlineFrame into such a push — is declared and referenced nowhere in
the tree. Both go.

Comments corrected against the call graph

  • MetaInterpreter::push_inline_frame: the identifier MetaInterpreter occurs
    exactly once in the whole tree, inside that comment. There is no such type.
  • opimpl_virtual_ref's "Called from metainterp push_inline_frame": its only
    callers, in both the majit-metainterp and the pyre-jit-trace port, are
    #[test]. virtualref_boxes is therefore always empty and no live trace
    records a VIRTUAL_REF. The replacement says that, and names upstream's real
    caller (executioncontext.py:89 enter, which the tracer reaches by tracing
    the interpreter's own frame-entry code — something the pyre walker, which
    builds its inline levels itself, never does).
  • "push_inline_frame stamps parent_frames.first().pending_result_*":
    pending_result_stack_idx is never assigned a Some value anywhere in the
    tree.

Measurement recorded in gate-triage §1

The multi-frame blackhole path has no corpus coverage. The vable-escape latch
site was instrumented and all 318 benchmarks (pyre/bench/*.py +
pyre/bench/synth/*.py) were run under PYRE_FBW_MULTIFRAME=1. The site is
reached in 3 benches — getframe_escape_flush_writethrough_regression,
synth/getframe_inlined_callee_own_frame, synth/getframe_stored_fback_walk
5 events each, and all 15 have inline_subwalk=false, so every one takes
the single-frame arm and adopts. build_multi_frame_miframe is never called,
the image is never latched, and try_adopt_multi_frame_blackhole never sees a
candidate.

Consequences recorded in the ledger: flipping _MULTIFRAME ON is a no-op
across the corpus; the three items §1 lists as its remaining work are all
unexercised, so porting any of them would be unvalidatable until a benchmark
reaches inline_subwalk=true at a vable escape. §4's _BLACKHOLE_RESUME row is
amended — its retirement was conditioned on _MULTIFRAME landing, which that
measurement makes unevaluable. (The multi-frame latch is also nested inside
single_frame_blackhole_resume_enabled(), so it depends on _BLACKHOLE_RESUME
staying ON regardless.)

The instrumentation was temporary and is not in this diff; a pre-existing
[s2-gate] eprintln under PYRE_FBW_DEBUG_ABORT already reports
inline_subwalk at that site.

Gates

cargo check -p pyre-jit-trace --no-default-features --features dynasm is clean
(one pre-existing unreachable_patterns warning, unrelated).

An earlier full gate on this diff — pyre-jit-trace + majit-metainterp unit
tests green (1399 / 294 / …) and check.py --backend dynasm 313/313 — was run
against the pre-rebase base 7b70e1ebff, so it does not certify the current
base. The re-gate on 0b706504dd is in flight at the time of writing; CI on
this PR is the authoritative x86_64 check. A first attempt at that re-gate
produced a spurious E0609: no field frame_value_count_fn — the compile raced a
mid-session pull of #751, which adds that field to jitdriver.rs and its
assignment in unpack_state.rs in the same commit. cargo check on the settled
tree passes, so that error was a torn-tree artifact, not a base break.

The diff is dead-code deletion plus comments plus markdown; nothing in it
changes codegen.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Documentation

    • Updated gate-triage records with the latest audit outcomes and measured multi-frame coverage.
    • Clarified prerequisites, instrumentation findings, and retirement criteria for blackhole-related feature gates.
  • Refactor

    • Simplified inline-call resume and guard-state handling.
    • Removed obsolete inline trace-step routing and clarified virtual-reference tracing behavior.

…ULTIFRAME's measured corpus coverage

`PendingInlineFrame::drop_frame_opref` was constructed at one site, always
`None`, and never read. Its comment said `None` "skips the opimpl_virtual_ref
emission in push_inline_frame"; `push_inline_frame`
(`majit-metainterp/src/compile.rs`) is a depth guard that pushes a
`(code_ptr, pc)` greenkey and contains no vref code, and the emission the
comment names was never built. `InlineTraceStepAction` — the enum that would
have carried a `PendingInlineFrame` into such a push — is declared and
referenced nowhere in the tree. Remove both.

Three comments corrected against the call graph rather than restated:
`MetaInterpreter::push_inline_frame` (the identifier `MetaInterpreter` occurs
exactly once in the tree, inside that comment); `opimpl_virtual_ref`'s "Called
from metainterp push_inline_frame" (its only callers, in both the
`majit-metainterp` and `pyre-jit-trace` ports, are `#[test]`, so
`virtualref_boxes` stays empty and no live trace records a VIRTUAL_REF); and
`push_inline_frame stamps parent_frames.first().pending_result_*`
(`pending_result_stack_idx` is never assigned a `Some` value anywhere).

gate-triage §1 records a measurement of the multi-frame path: the
vable-escape latch site was instrumented and all 318 benchmarks
(`pyre/bench` + `pyre/bench/synth`) run under `PYRE_FBW_MULTIFRAME=1`. The site
is reached in 3 benches, 5 events each, and all 15 have `inline_subwalk=false`
— every one takes the single-frame arm. `build_multi_frame_miframe` is never
called, so the image is never latched and `try_adopt_multi_frame_blackhole`
never sees a candidate. §4's `_BLACKHOLE_RESUME` row is amended: its retirement
was conditioned on `_MULTIFRAME` landing, which that measurement makes
unevaluable.

Gates from the workspace root: `pyre-jit-trace` + `majit-metainterp` unit tests
green (1399 / 294 / …), `check.py --backend dynasm` 313/313.

Assisted-by: Claude
@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The PR documents multi-frame blackhole coverage and updates related gate decisions. It also simplifies inline pending-frame state by removing drop_frame_opref, retaining caller results in PendingInlineFrame, and deleting InlineTraceStepAction.

Changes

JIT trace and gate updates

Layer / File(s) Summary
Inline pending state cleanup
pyre/pyre-jit-trace/src/state.rs
Documents the unpopulated virtual-reference wiring, removes drop_frame_opref, keeps caller results on PendingInlineFrame, and removes InlineTraceStepAction.
Multi-frame coverage and gate triage
pyre/gate-triage.md
Records that corpus execution does not reach multi-frame construction and revises the PYRE_FBW_BLACKHOLE_RESUME retirement condition.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: lifthrasiir

Poem

I hopped through frames both wide and thin,
Found three small paths, but none went in.
The blackhole gates now wait and see,
While pending crumbs stay close to me.
No enum thumps its foot tonight—
Squeak, the trace is tidy and light!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the dead-code cleanup and the added _MULTIFRAME corpus coverage documentation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jitcode

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

🤖 Codex parity review

Static analysis of this diff vs the local RPython/PyPy sources (commit ade259b).
Updated: 2026-07-25T17:34:12.244Z

Files in the reviewed diff
pyre/gate-triage.md
pyre/pyre-jit-trace/src/state.rs

1. Regressions to PyPy parity introduced by this patch

None.

2. Other mismatches introduced by this patch

None.

3. Pre-existing mismatches (already present before this patch)

  • pyre/pyre-jit-trace/src/state.rs:5494 ↔ pypy/interpreter/executioncontext.py:89 — PyPy’s frame entry always executes jit.virtual_ref(frame), while pyre has no caller for opimpl_virtual_ref; consequently its virtualref_boxes remains empty. This was already true in upstream/main; the patch only corrects the comment describing it.

  • pyre/pyre-jit-trace/src/state.rs:5526 ↔ rpython/jit/metainterp/pyjitpl.py:1819 — pyre silently returns when fewer than two virtual-reference entries exist, whereas PyPy unconditionally pops the pair and verifies LIFO frame identity. This behavior was present before the patch and is presently masked by the missing frame-entry virtual_ref call.

4. Structural adaptations

None.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ade259b614

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread pyre/gate-triage.md
Comment on lines +199 to +200
vable-escape latch site was instrumented and all **318** benchmarks
(`pyre/bench` + `pyre/bench/synth`) run under `PYRE_FBW_MULTIFRAME=1`. The site

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Rerun the coverage census on the rebased corpus

This 318-case measurement matches the pre-rebase tree (7b70e1ebff: 299 top-level synthetic scripts plus 19 regular scripts), but the reviewed tree contains 307 top-level synthetic scripts plus the same 19 regular scripts. Eight newly added cases—several involving inlined callees and frame/exception handling—were therefore not measured, so the conclusions that _MULTIFRAME has no coverage and is a corpus-wide no-op are not established for this commit. Rerun the instrumentation on the current base or explicitly qualify the ledger as a pre-rebase result.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pyre/pyre-jit-trace/src/state.rs (1)

12165-12167: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Remove the stale drop_frame_opref reference.

That field was deleted from PendingInlineFrame, so this comment now documents an impossible requirement. Refer to the current replay fields or describe the actual gate instead.

Proposed comment update
-        // back-edge CALL_ASSEMBLER path requires drop_frame_opref and is gated out for them anyway.
+        // Reconstructed frames carry no CALL-site OpRefs, so the inline
+        // back-edge CALL_ASSEMBLER path remains gated out for them.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pyre/pyre-jit-trace/src/state.rs` around lines 12165 - 12167, Update the
comment near the reconstructed-frame handling to remove the obsolete
drop_frame_opref reference. Describe the current replay fields or the actual
gate that excludes reconstructed frames from the inline back-edge CALL_ASSEMBLER
path, without implying PendingInlineFrame still contains that deleted field.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pyre/gate-triage.md`:
- Line 207: Replace the nonstandard term “unvalidatable” in the affected
sentence with “not independently validated” or “unverifiable,” while preserving
the sentence’s meaning and surrounding wording.
- Around line 198-212: Update the benchmark coverage section documenting the
318-benchmark measurement to include the exact command used, repository
revision, relevant environment variables (including PYRE_FBW_MULTIFRAME,
PYRE_FBW_DEBUG_ABORT, and _BLACKHOLE_RESUME), and a reference to the preserved
output artifact. Ensure the provenance is sufficient to independently reproduce
and audit the reported results.

---

Outside diff comments:
In `@pyre/pyre-jit-trace/src/state.rs`:
- Around line 12165-12167: Update the comment near the reconstructed-frame
handling to remove the obsolete drop_frame_opref reference. Describe the current
replay fields or the actual gate that excludes reconstructed frames from the
inline back-edge CALL_ASSEMBLER path, without implying PendingInlineFrame still
contains that deleted field.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 3c97bed4-8dc1-484d-8749-40da33055cbf

📥 Commits

Reviewing files that changed from the base of the PR and between 0b70650 and ade259b.

📒 Files selected for processing (2)
  • pyre/gate-triage.md
  • pyre/pyre-jit-trace/src/state.rs

Comment thread pyre/gate-triage.md
Comment on lines +198 to +212
**Measured 2026-07-25: the multi-frame path has no corpus coverage.** The
vable-escape latch site was instrumented and all **318** benchmarks
(`pyre/bench` + `pyre/bench/synth`) run under `PYRE_FBW_MULTIFRAME=1`. The site
is reached in **3 benches** (`getframe_escape_flush_writethrough_regression`,
`synth/getframe_inlined_callee_own_frame`, `synth/getframe_stored_fback_walk`),
5 events each, and **all 15 have `inline_subwalk=false`** — every one takes the
single-frame arm and adopts. `build_multi_frame_miframe` is therefore never
called, the image is never latched, and the adopt never sees a candidate. So
flipping `_MULTIFRAME` ON is a no-op across the corpus, none of the three items
above is exercised, and any port of them would be unvalidatable until a
benchmark that reaches `inline_subwalk=true` at a vable escape exists. Building
that benchmark is the prerequisite for the rest. Note the multi-frame latch is
nested inside `single_frame_blackhole_resume_enabled()`, so it also requires
`_BLACKHOLE_RESUME` to stay ON. The pre-existing `[s2-gate]` eprintln (under
`PYRE_FBW_DEBUG_ABORT`) already reports `inline_subwalk` at that site.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial

Record reproducible benchmark provenance.

These measurements determine whether _MULTIFRAME and _BLACKHOLE_RESUME can be retired. Add the exact command, revision, environment, and output artifact so the 318-benchmark result can be independently re-audited.

🧰 Tools
🪛 LanguageTool

[grammar] ~207-~207: Ensure spelling is correct
Context: ...three items above is exercised, and any port of them would be unvalidatable until a ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[grammar] ~208-~208: Ensure spelling is correct
Context: ...that reaches inline_subwalk=true at a vable escape exists. Building that benchmark...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pyre/gate-triage.md` around lines 198 - 212, Update the benchmark coverage
section documenting the 318-benchmark measurement to include the exact command
used, repository revision, relevant environment variables (including
PYRE_FBW_MULTIFRAME, PYRE_FBW_DEBUG_ABORT, and _BLACKHOLE_RESUME), and a
reference to the preserved output artifact. Ensure the provenance is sufficient
to independently reproduce and audit the reported results.

Comment thread pyre/gate-triage.md
single-frame arm and adopts. `build_multi_frame_miframe` is therefore never
called, the image is never latched, and the adopt never sees a candidate. So
flipping `_MULTIFRAME` ON is a no-op across the corpus, none of the three items
above is exercised, and any port of them would be unvalidatable until a

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Replace nonstandard wording.

Use “not independently validated” or “unverifiable” instead of unvalidatable.

🧰 Tools
🪛 LanguageTool

[grammar] ~207-~207: Ensure spelling is correct
Context: ...three items above is exercised, and any port of them would be unvalidatable until a ...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pyre/gate-triage.md` at line 207, Replace the nonstandard term
“unvalidatable” in the affected sentence with “not independently validated” or
“unverifiable,” while preserving the sentence’s meaning and surrounding wording.

Source: Linters/SAST tools

@youknowone

Copy link
Copy Markdown
Owner Author

Gate update on the current base (ade259b614 on 0b706504dd), and a follow-up
finding that supersedes part of this PR's ledger text.

Gates — green

  • pyre-jit-trace + majit-metainterp unit tests: all pass (exit 0).
  • check.py --backend dynasm: 320 passed, one perf bench over gate —
    synth/comprehension_object_append_hot at 43.6x vs its 40x gate. Discriminated
    as machine load, not a regression: that run had load average 28.76 with 52
    concurrent build/cargo processes
    from sibling worktrees; re-run in isolation
    three times it is 35.5x / 33.0x / 31.8x, all under the gate.

A first attempt at this re-gate failed differently (two list_append unit tests
panicking, synth/getframe_force_cancel_journal wrong output, and
synth/const_arg_call_resume 34.0x). Root cause was a stale
build/llbc/pyre-object.ullbcw_list_append_inner lives in pyre-object,
and only pyre-interpreter had been re-extracted. All three cleared after
extracting pyre-object and pyre-jit. Recorded here because the three
symptoms look unrelated but share one cause.

An E0609: no field frame_value_count_fn seen earlier was a torn-tree artifact:
the compile raced a mid-session pull of #751, which adds that field to
jitdriver.rs and its assignment in unpack_state.rs in the same commit.
cargo check on the settled tree is clean.

Superseding finding: the multi-frame path IS reachable

This PR's gate-triage.md §1 addition says building a benchmark that reaches
inline_subwalk=true at a vable escape is the prerequisite for the rest. That
benchmark now exists, and the result goes further than expected — the
multi-frame image is not just latched, it is built.

The §1 text also says there are declines to clear before the adopt can fire, and
names the jit.virtual_ref emit as the prerequisite for the root-mismatch
decline. That framing is wrong for this path and will be corrected in a
follow-up commit; the measurement below is what should be recorded instead.

Five candidate programs, all sharing one shape — a while loop calling a
straight-line inlined callee that calls sys._getframe — produce, per run:

[s2-gate] inline_subwalk fs=1 flag=true writes_live=true odo_unchanged=true
          committed_none=false not_bridge=true bh_result_some=true sym_nonnull=true
[s2-build-decline] BUILT multi-frame depth=2
[fbw-blackhole] adopted single-frame terminal ...

Minimal form:

import sys
_gf = sys._getframe

def leaf(x):
    _gf()
    return x + 1

def main():
    total = 0
    i = 0
    while i < 30000:
        total = leaf(total)
        i = i + 1
    return total

print(main())

Three things this establishes:

  1. [s2-gate] has never fired for any of the 318 corpus benchmarks. It fires
    here. (Note [s2-gate] is itself gated on inline_subwalk, so it can only
    ever print true — its presence alone is the signal.)
  2. build_multi_frame_miframe succeeds: depth=2, so none of the build-side
    conditions is the blocker.
  3. The adopt still declines — try_adopt_force_blackhole is
    try_adopt_multi_frame_blackhole(..) || try_adopt_single_frame_blackhole(..),
    and the single-frame arm is what adopts. So the remaining blocker is entirely
    inside try_adopt_multi_frame_blackhole, downstream of a successfully built
    image.

Why every existing bench misses: all five getframe_* benches drive with for.
With a FOR_ITER item in flight the callee's nested residual is declined by
fbw_abort_nested_unjournaled_residual before execute_residual_call runs, so
the force never happens inside the sub-walk. The driving loop must be while.

A depth-3 variant (outerinner, both inlined) additionally reports
[s2-build-decline] frame 1: parent.blackhole None (capture missing), so the
nested-parent capture is a separate, deeper gap.

Locating the adopt-side decline is in progress. The follow-up commit will carry
the corrected §1 text plus a benchmark for the corpus, so the path stops being
uncovered.

commented by Claude

@youknowone

Copy link
Copy Markdown
Owner Author

Follow-up to the previous comment: the adopt-side decline is located, and it is
one line whose own comment misdescribes it.

The decline

try_adopt_multi_frame_blackhole (pyre/pyre-jit-trace/src/trace.rs):

if per_frame.first().map(|&(frame_ptr, _)| frame_ptr) != Some(cf_addr as i64) {
    return false;
}

The comment above it attributes the decline to "a chain rooted at an
intermediate frame … the walk descended into a residual call and inlined inside
it", and names the jit.virtual_ref emit at the inline push as what is needed
to close it. Instrumenting the repro shows that is not what happens. All five
events print:

first = 0xa4be2db40    live (ec.topframeref) = 0xa4be2db40    cf_addr = 0xa4c0515e8
all   = [0xa4be2db40, 0xa4be89e70]        # [main, leaf] — depth 2

per_frame[0] equals the live frame exactly. The chain is rooted at the
walked frame. The two sides are different representations of that same frame,
and the source says so:

let cf_addr = &*concrete_frame as *const PyFrame as usize;
// "The snapshot stands in for concrete stepping only"
sym.set_live_vable_frame_addr(live_frame_addr);
// "gap 10 slice 2b: set this BEFORE `init_symbolic` so the root vable identity
//  (seed_virtualizable_boxes) is baked against the live frame address, not the
//  discarded snapshot's."

The root vable identity that lands in the blackhole's frame register is the
live pointer by construction; the check compares it against the snapshot
pointer. The two can never be equal, so for this shape the decline is
unconditional — and no vref emit is involved.

What this means for the ledger text in this PR

Two things in the §1 paragraph this PR adds are wrong and I will correct them in
a follow-up rather than silently leave them:

  • It carries forward the decline comment's claim that the jit.virtual_ref emit
    gates the root-mismatch. It does not, on this path.
  • It implies the §1 items (per-frame vable binding, outer-locals materialization)
    are what stand between here and a working multi-frame adopt. The build side
    already succeeds — build_multi_frame_miframe returns an image at depth=2
    so those items are downstream of a gate that never opens.

What the paragraph got right and should keep: the multi-frame path has no corpus
coverage, and a benchmark reaching inline_subwalk=true at a vable escape was
the prerequisite. That benchmark now exists.

Not fixing it in this PR

Swapping the comparison to the live address is a one-line change but not
obviously correct: cf_addr is used downstream in the same function for
drive_multi_frame_blackhole(..., cf_addr, stack_base, ..),
stack_base = concrete_nlocals(cf_addr), apply_blackhole_crn(cf_addr, ..), and
the root f_backref link. Each needs deciding on its own, and the result wants
its own gating and A/B. This PR stays a dead-code-and-comments change.

A depth-3 variant (outerinner, both inlined) additionally reports
[s2-build-decline] frame 1: parent.blackhole None (capture missing), a
separate gap in the nested-parent capture.

Gate status unchanged from the previous comment

Unit tests pass; check.py --backend dynasm 320 passed with the one perf bench
discriminated as machine load (isolated 35.5x / 33.0x / 31.8x vs its 40x gate,
against 43.6x under load average 28.76).

commented by Claude

@youknowone
youknowone merged commit ca8d601 into main Jul 25, 2026
19 checks passed
@youknowone
youknowone deleted the jitcode branch July 25, 2026 21:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant