Skip to content

pyre-jit-trace: jitcode_dispatch follow-up — macro reflection + fbw/residual/inline/specialize extraction - #671

Merged
youknowone merged 6 commits into
mainfrom
jitcode
Jul 20, 2026
Merged

pyre-jit-trace: jitcode_dispatch follow-up — macro reflection + fbw/residual/inline/specialize extraction#671
youknowone merged 6 commits into
mainfrom
jitcode

Conversation

@youknowone

@youknowone youknowone commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Follow-up to #666 (merged), continuing the jitcode_dispatch decomposition. Five commits on top of the merged per-cluster split.

Macro reflection

  • route float-comparison record arms via the macro table — adds a binop_float_to_int_record family (float_lt/le/eq/ne/gt/ge) to regular_record_table!, so the six float-comparison arms dispatch from the generated table instead of the per-opname match. These are part of the pyjitpl.py:284-292 exec-generated binary opimpl loop (result in the int bank, ff>i). Consolidates the record-family parity citations into the table in arith.rs and drops the orphaned comment block the arms left in mod.rs.

    This completes the principle that pyre should generate what pyjitpl.py generates and hand-port only what it hand-writes: an audit of all four exec-generated opimpl families found these six were the sole remaining hand-spelled uniform arms; everything else is already table-routed, has no pyre arm, or is a bank-crossing cast needing a bespoke helper.

Relocations (pure behavior-preserving moves)

  • fbw_state.rs — 86 fbw_* / capture_fbw_* helpers (force-before-writeback state machine: feature gates, store/append/for-iter journals + rollback, executed-effect/residual counters, finish-payload channel, abort-resume carriers).
  • residual_call.rs — 17 residual-call helpers (per-shape dispatchers, executor fast paths, opcode selection, arg binding, pre-call vable/vref sync, result writeback, body classification). t3_audit scans this file so its residual match arms stay in the handler set.
  • inline_call.rs — 24 inline-call helpers (callee recognition/inlinability, active-box/call-stack reconstruction, register-bank allocation, sub-jitcode walk, self-recursive CALL_ASSEMBLER fold, inline specializers, per-shape dispatchers).
  • specialize.rs — 31 try_walker_* specialization entry points + 3 exclusive orthodox_list_append_* helpers. Shared walker_* primitives stay in mod.rs.

The opname dispatch arms stay in handle (mod.rs) throughout and call into the moved helpers.

Result

mod.rs drops from 21,780 → 8,497 lines (the dispatch core now holds handle, the walk driver, and shared walker_* primitives). Each step verified with cargo test and both JIT backends; check.py dynasm 225/225 · cranelift 225/225.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Improved JIT performance via expanded specialization and optimized dispatch for arithmetic, comparisons, attribute access (load method/attr), subscripting, list/tuple construction, list updates, and global/name access.
    • Added broader inline execution for eligible user calls (including select numeric and exception-string override paths) and stronger support for loop and iterator patterns.
    • Enhanced residual-call handling with a concrete “executor” fast path for pure calls.
  • Bug Fixes
    • Improved correctness and result propagation across optimized traces, including exception plumbing and FOR_ITER continuation behavior.
    • Added float comparison dispatch coverage to improve numeric comparison accuracy in optimized paths.

@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 43d46010-e614-41ca-9bf7-183097f9fc58

📥 Commits

Reviewing files that changed from the base of the PR and between f3d64ca and b411890.

📒 Files selected for processing (14)
  • pyre/pyre-jit-trace/src/jitcode_dispatch/arith.rs
  • pyre/pyre-jit-trace/src/jitcode_dispatch/branch.rs
  • pyre/pyre-jit-trace/src/jitcode_dispatch/bridge_subwalk.rs
  • pyre/pyre-jit-trace/src/jitcode_dispatch/diag.rs
  • pyre/pyre-jit-trace/src/jitcode_dispatch/fbw_state.rs
  • pyre/pyre-jit-trace/src/jitcode_dispatch/heapcache_ops.rs
  • pyre/pyre-jit-trace/src/jitcode_dispatch/inline_call.rs
  • pyre/pyre-jit-trace/src/jitcode_dispatch/mod.rs
  • pyre/pyre-jit-trace/src/jitcode_dispatch/residual_call.rs
  • pyre/pyre-jit-trace/src/jitcode_dispatch/resume_snapshot.rs
  • pyre/pyre-jit-trace/src/jitcode_dispatch/specialize.rs
  • pyre/pyre-jit-trace/src/jitcode_dispatch/tests.rs
  • pyre/pyre-jit-trace/src/jitcode_dispatch/vable_ops.rs
  • pyre/pyre-jit-trace/src/jitcode_dispatch/vstack_mirror.rs

Walkthrough

This PR modularizes Pyre’s JIT trace dispatcher into FBW state, residual-call, inline-call, and specialization modules. It adds concrete residual execution, recursive and user-call inlining, mutation journaling, abort/resume handling, walker-native folds, and float comparison routing.

Changes

FBW JIT dispatch

Layer / File(s) Summary
Dispatcher modularization
pyre/pyre-jit-trace/src/jitcode_dispatch/mod.rs, pyre/pyre-jit-trace/src/jitcode_dispatch/*.rs
Splits dispatch responsibilities into dedicated modules, preserves re-export paths, updates FOR_ITER and record routing, and adds parity documentation.
FBW state and abort journals
pyre/pyre-jit-trace/src/jitcode_dispatch/fbw_state.rs
Adds feature gates, finish payloads, mutation journals, FOR_ITER tracking, abort/resume carriers, effect accounting, root walkers, and replay-safety checks.
Residual-call recording and execution
pyre/pyre-jit-trace/src/jitcode_dispatch/residual_call.rs
Adds typed residual-call dispatch, pure folding, concrete execution, result writeback, guard emission, and exception propagation.
Inline-call tracing and sub-walks
pyre/pyre-jit-trace/src/jitcode_dispatch/inline_call.rs
Adds callee eligibility checks, recursive CALL_ASSEMBLER handling, user-call sub-walks, exception-string and numeric dunder inlining, and typed inline-call dispatch.
Walker-native specialization and arithmetic routing
pyre/pyre-jit-trace/src/jitcode_dispatch/specialize.rs, pyre/pyre-jit-trace/src/jitcode_dispatch/arith.rs, pyre/pyre-jit-trace/src/jitcode_dispatch/tests.rs
Adds arithmetic, container, attribute, exception, iteration, mutation, and namespace folds, float comparison registrations, and expanded opcode inventory scanning.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related issues

Possibly related PRs

Poem

A rabbit hops through traced code,
With journals tucked beneath its load.
Calls fold, floats compare bright,
Frames resume through guarded night—
FBW paths bloom in moonlit mode.

🚥 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 matches the main change: jitcode_dispatch decomposition plus macro reflection for float-comparison records.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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

github-actions Bot commented Jul 19, 2026

Copy link
Copy Markdown

🤖 Codex parity review

Static analysis of this diff vs the local RPython/PyPy sources (commit b411890).
Updated: 2026-07-19T23:52:24.502Z

Files in the reviewed diff
pyre/pyre-jit-trace/src/jitcode_dispatch/arith.rs
pyre/pyre-jit-trace/src/jitcode_dispatch/branch.rs
pyre/pyre-jit-trace/src/jitcode_dispatch/bridge_subwalk.rs
pyre/pyre-jit-trace/src/jitcode_dispatch/diag.rs
pyre/pyre-jit-trace/src/jitcode_dispatch/fbw_state.rs
pyre/pyre-jit-trace/src/jitcode_dispatch/heapcache_ops.rs
pyre/pyre-jit-trace/src/jitcode_dispatch/inline_call.rs
pyre/pyre-jit-trace/src/jitcode_dispatch/mod.rs
pyre/pyre-jit-trace/src/jitcode_dispatch/residual_call.rs
pyre/pyre-jit-trace/src/jitcode_dispatch/resume_snapshot.rs
pyre/pyre-jit-trace/src/jitcode_dispatch/specialize.rs
pyre/pyre-jit-trace/src/jitcode_dispatch/tests.rs
pyre/pyre-jit-trace/src/jitcode_dispatch/vable_ops.rs
pyre/pyre-jit-trace/src/jitcode_dispatch/vstack_mirror.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)

  • majit/majit-translate/src/codewriter/insns.rs:834 ↔ rpython/jit/metainterp/pyjitpl.py:356: “int_is_true and int_is_zero are absent from the runtime opcode table.” The dispatcher contains int_is_true, but neither truth opcode is registered, so neither can reach it.

  • pyre/pyre-jit-trace/src/jitcode_dispatch/arith.rs:576 ↔ rpython/jit/metainterp/pyjitpl.py:356: “float_abs/f>f is registered but unhandled.” The regular table routes only float_neg, while the canonical table exposes float_abs/f>f.

  • pyre/pyre-jit-trace/src/jitcode_dispatch/arith.rs:526 ↔ rpython/jit/metainterp/pyjitpl.py:279: “The registered uint_rshift, uint_mul_high, uint_lt, uint_le, uint_gt, and uint_ge families have no walker route.” PyPy generates all six through the binary-op implementation loop.

  • pyre/pyre-jit-trace/src/jitcode_dispatch/arith.rs:580 ↔ rpython/jit/metainterp/pyjitpl.py:326: “instance_ptr_eq and instance_ptr_ne are registered but unhandled.” The walker accepts only ptr_eq and ptr_ne, whereas PyPy’s comparison loop includes both instance-pointer variants.

  • pyre/pyre-jit-trace/src/jitcode_dispatch/mod.rs:7088 ↔ rpython/jit/metainterp/pyjitpl.py:356: “cast_float_to_int/f>i is registered but has no dispatch arm.” The upstream unary-op loop includes it alongside the implemented cast_int_to_float.

4. Structural adaptations

  • pyre/pyre-jit-trace/src/jitcode_dispatch/arith.rs:492 ↔ rpython/jit/metainterp/pyjitpl.py:279: Rust’s regular_record_table! replaces PyPy’s runtime exec-generated opimpl_* methods. This is a language-level structural adaptation; the added float-comparison entries preserve the upstream float-pair-to-int result shape.

  • pyre/pyre-jit-trace/src/jitcode_dispatch/branch.rs:5 ↔ rpython/jit/codewriter/jtransform.py:196: pyre’s CPython-compatible compiler emits a separate comparison plus goto_if_not, while PyPy fuses eligible comparisons into goto_if_not_<comparison>. This is an opcode-shape adaptation, not a tracer mismatch.

  • pyre/pyre-jit-trace/src/jitcode_dispatch/vstack_mirror.rs:4 ↔ rpython/jit/metainterp/pyjitpl.py:165: pyre’s FBW value-stack mirror exists to reconstruct CPython-frame stack state; PyPy’s MIFrame directly uses typed register banks.

Add a binop_float_to_int_record family (float_lt/le/eq/ne/gt/ge) to
regular_record_table!, so the six float-comparison arms dispatch from
dispatch_regular_record instead of the per-opname match. These are part
of the pyjitpl.py:284-292 exec-generated binary opimpl loop; their result
lands in the int bank (ff>i).

Consolidate the record-family parity citations (int/float arithmetic,
the b1-is-b2 comparison fast path, float_mul-absent note, int-unary and
ptr_eq/ptr_ne notes) into the table in arith.rs, and drop the orphaned
comment block the arms left behind in mod.rs.

Assisted-by: Claude
Relocate the 86 fbw_* / capture_fbw_* helpers — feature gates, the
store / append / for-iter journals and rollback, executed-effect and
residual counters, the finish-payload channel, and abort-resume carriers
— from jitcode_dispatch/mod.rs into fbw_state.rs. Pure relocation; the
two thread_local! blocks these functions own (FBW_FINISH_PAYLOAD and the
SELFREC_CA_FOLD_ACTIVE / EXCEPTION_STRING_INLINE_ACTIVE gates) move with
them, the latter two promoted to pub(crate) for the scoped-setter guards
that stay in mod.rs.

Assisted-by: Claude
Relocate the 17 residual-call helpers — the per-shape dispatchers
(dispatch_residual_call_{iRd,iIRd,iIRFd}_kind), the executor fast paths
(try_fold_pure_call_via_executor, try_execute_residual_call_via_executor),
opcode selection, arg binding, pre-call vable/vref sync, result writeback,
and the body classification helpers — from jitcode_dispatch/mod.rs into
residual_call.rs. Pure relocation; the residual_call_* opname arms stay in
handle and call into the moved dispatchers.

t3_audit_opname_gap_inventory now scans residual_call.rs alongside mod.rs
and arith.rs so the moved residual-call match arms stay in its
source-of-truth handler set.

Assisted-by: Claude
Relocate the 24 inline-call helpers — callee recognition and inlinability
checks, active-box / call-stack reconstruction, callee register-bank
allocation, the sub-jitcode walk driver, the self-recursive CALL_ASSEMBLER
fold, the inline user-call / binop / compareop / exception-string
specializers, and the dispatch_inline_call_* per-shape dispatchers — from
jitcode_dispatch/mod.rs into inline_call.rs. Pure relocation; the
inline_call_* opname arms stay in handle and call into the moved
dispatchers.

Assisted-by: Claude
Relocate the 31 try_walker_* specialization entry points (int/long/float
arithmetic and comparisons, attribute and method loads, container builds
and subscript, list-append, exception construction/raise, for-iter, slice,
and the module/name cell folds) plus the three exclusive
orthodox_list_append_* helpers from jitcode_dispatch/mod.rs into
specialize.rs. Pure relocation; the shared walker_* primitives stay in
mod.rs and the specialization opname arms stay in handle.

Assisted-by: Claude
…unterpart

The FBW jitcode walker has no single rpython/jit/metainterp/ file
counterpart — the file-for-file parity mirror is the majit-metainterp
crate (pyjitpl.rs, executor.rs, heapcache.rs, resume.rs, virtualizable.rs,
blackhole.rs, ...). Document that in mod.rs and give every submodule header
a Parity line naming the pyjitpl.py opimpl group / metainterp file it is
the trace-side counterpart of, or declaring it pyre-specific where there is
no upstream analogue (fbw_state, vstack_mirror, diag).

Records the codewriter-level divergence in branch.rs: pyre emits an
unfused goto_if_not/iL plus a separate compare_op, so PyPy's fused
goto_if_not_int_lt family (pyjitpl.py:541) has no pyre opname.

Comments only; no behaviour change.

Assisted-by: Claude
@youknowone
youknowone merged commit b5dd59c into main Jul 20, 2026
31 checks passed
@youknowone
youknowone deleted the jitcode branch July 20, 2026 01:21
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