Skip to content

jit: close the #73 walk-side coordinate split — twin flip, resume-marker census, py_coord fold - #1012

Merged
youknowone merged 3 commits into
mainfrom
rewrite-tracer
Aug 3, 2026
Merged

jit: close the #73 walk-side coordinate split — twin flip, resume-marker census, py_coord fold#1012
youknowone merged 3 commits into
mainfrom
rewrite-tracer

Conversation

@youknowone

@youknowone youknowone commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Closes the remaining #73 phase-2/3 work on the jitcode↔python coordinate split. Three commits:

  1. jit: census the py_pc resume markers derive_resume_marker cannot reproduce — build-time PYRE_PCMAP_RESIDUAL_CENSUS census of the residual divergence classes (corpus: 1,410/68,322 py PCs, all in the no-own-op tier; the own=1 tier reproduces the dense table exactly).

  2. jit: cut six jitcode->py inversion consumers over to the forward py twins — flips the flippable consumers (capture seam, inline-caller fallthrough, call-site py in specialize/inline_call, trace entry-carrier/midbody, P2-drain) to the codewriter-built jitcode-pc-keyed twins, with the legacy path retained as audit oracle under PYRE_M73_BACKXLAT_TWIN_AUDIT / PYRE_PCMAP_AFTERRESIDUAL_AUDIT.

  3. jit: fold the jitcode->py coordinate helpers into py_coord — the surviving walk-side "what python op am I at" reads (traceback nodes, bare-reraise, last_instr publish, foriter green key, inline-abort paths) are not a runtime inversion: block_head_py_by_jit_pc + py_floor_by_jit_pc are built forward in the codewriter at lowering, and the floor result equals what pyopcode.py:200's per-bytecode last_instr store (elided by vable optimization) would leave, memoized at build time. This commit folds the helpers into pyre-jit-trace/src/py_coord.rs with names matching that semantics (containing_py_pc_for_jitcode_pc, trivia_normalized_py_pc_for_jitcode_pc, resume_py_pc_for_jitcode_word), rewrites the "legacy inversion" comment framing, and adds a PYRE_M73_EMPTYTWIN_CENSUS gate reporting empty-twin fallback trips at the 5 twin-first seams.

Verification

  • check.py dynasm 371/371. cranelift/wasm each show 1 failure (exception_try_call_inlined_callee_raise loops_compiled 3 -> 2) that reproduces on the clean committed tip too — the machine-keyed baseline red inherited from jit/wasm: lower LOAD_LOCALS and LOAD_BUILD_CLASS, make wasm loops_aborted attributable, close the jitstats field gap #1009's fresh baselines, not caused by this branch; not re-recorded.
  • Full 371-fixture synth corpus + fannkuch with PYRE_M73_BACKXLAT_TWIN_AUDIT + PYRE_PCMAP_AFTERRESIDUAL_AUDIT + PYRE_PCMAP_CONTAINING_AUDIT + PYRE_M73_EMPTYTWIN_CENSUS: 0 audit divergences, 0 empty-twin fallback trips, fannkuch 0.69s (no compile-time regression).

Per-bytecode last_instr as a genuine red stays with the stale-inline-frame epic; codewriter emission is blocked by the 256-entry pool-const cap.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added centralized coordinate mapping for translating JIT execution positions to Python locations.
    • Improved resume and traceback location handling, including fallback behavior for missing or empty mappings.
    • Added optional diagnostics for auditing coordinate mappings and reporting residual entries.
  • Documentation

    • Clarified coordinate terminology and mapping behavior throughout JIT tracing documentation.

…produce

`carryfwd_resume_pc` holds the py_pcs where the on-demand derivation diverges
from the dense marker map; the size and shape of that residual was never
measured. Add `PYRE_PCMAP_RESIDUAL_CENSUS=1`, a build-time-only gate that
names each divergent py_pc with its opcode, whether it emitted an op of its
own, and the derived vs dense offsets.

Synth corpus: 815 jitcodes / 68,322 py PCs / 1,410 residual (2.1%). Every
residual PC emitted no op of its own, so the "own first op" tier reproduces
the dense marker exactly corpus-wide. By opcode: Cache 729, EndFor 266,
ToBool 176, JumpForward 146, JumpBackwardNoInterrupt 74, rest under 15.

Also record that restricting the table to the trace-entry greens is unsound:
`resolve_marker` is called on `skipped_py` and fallthrough coordinates too,
which are the trivia and jump PCs the residual consists of. That restriction
leaves every green resolving identically and costs fannkuch 0.6s -> >10min.

Assisted-by: Claude
…wins

Six call sites computed a resume python pc at runtime by inverting a JitCode
byte offset (python_pc_for_jitcode_pc / backxlat_py_pc) and then normalizing
trivia or taking the semantic fallthrough. Each now reads the codewriter-built
jitcode-pc-keyed twin first and keeps the inversion only for the empty-twin
class (skeleton / fixture jitcodes) and as the gated audit oracle:

- resume_snapshot.rs walker_capture_snapshot_for_last_guard_impl: capture-seam
  py from forward_py_pc_for_jitcode_pc; the trivia skip stays and is an
  identity on the twin path.
- resume_snapshot.rs compute_inline_caller_frame: fallthrough py from
  after_residual_fallthrough_py_pc_for_jitcode_pc, legacy closure as fallback
  and PYRE_PCMAP_AFTERRESIDUAL_AUDIT oracle (the audit previously ran the
  other way around, twin checked against a primary inversion).
- specialize.rs orthodox_list_append_commit and inline_call.rs
  try_walker_inline_builtin_call: call-site py from
  forward_py_pc_for_jitcode_pc.
- trace.rs resolve_entry_carrier_call_py_pc / resolve_midbody_flush_words:
  route through forward_py_pc_or_backxlat.
- trace.rs P2 drain compile-root raise leg: backxlat_py_pc ->
  forward_py_pc_or_backxlat, matching the neighboring legs.

Remaining inversion consumers keep raw (non-trivia-normalized) coordinate
semantics (last_instr publication, traceback nodes, green keys) or are
diagnostics; they are not equivalent to the trivia-normalized twins and stay.

Verified: check.py dynasm 371/371, cranelift 371/371; wasm 366/367 where the
one failure (exception_try_call_inlined_callee_raise loops_compiled 3 -> 2)
reproduces identically on unmodified origin/main content on this machine.
Audit-gated corpus run (PYRE_M73_BACKXLAT_TWIN_AUDIT=1
PYRE_PCMAP_AFTERRESIDUAL_AUDIT=1, fannkuch + all synth benches): no
divergence.

Assisted-by: Claude
Move the JitCode-PC-keyed Python-coordinate helpers out of
jitcode_dispatch/diag.rs and state.rs into a dedicated
pyre-jit-trace/src/py_coord.rs module, renaming them after their
semantics: python_pc_for_jitcode_pc -> containing_py_pc_for_jitcode_pc
(exact block-head match, else the floor segment containing the pc),
backxlat_py_pc -> trivia_normalized_py_pc_for_jitcode_pc, and
forward_py_pc_or_backxlat -> resume_py_pc_for_jitcode_word.  The
floor-boundary helpers and skip_python_trivia_forward_public move with
them.  Call sites across pyre-jit-trace and pyre-jit/call_jit.rs are
repointed; comments describing these lookups as a "legacy inversion"
are rewritten around the containing-coordinate framing.  Env-gate names
and audit assert messages are unchanged.

Add a PYRE_M73_EMPTYTWIN_CENSUS gate that reports every empty-twin
fallback trip ([m73-emptytwin] site/jitcode/pc) at the resume-word
wrapper and the four twin-first consumer seams (capture seam,
inline-caller fallthrough, list-append commit, builtin call).

Verified: dynasm/cranelift/wasm check.py (the one red,
exception_try_call_inlined_callee_raise loops_compiled 3 -> 2 on
cranelift/wasm, reproduces on the clean committed tip and is the #1009
baseline red on this machine); audit-gated corpus pass
(PYRE_M73_BACKXLAT_TWIN_AUDIT + PYRE_PCMAP_AFTERRESIDUAL_AUDIT +
PYRE_PCMAP_CONTAINING_AUDIT + PYRE_M73_EMPTYTWIN_CENSUS) over all 371
synth fixtures and fannkuch: zero divergence, zero fallback trips.

Assisted-by: Claude
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

The PR adds centralized JIT-code-to-Python coordinate helpers in py_coord, removes legacy inversion helpers, and updates dispatch, resume, trace, traceback, and diagnostic paths to use containing or forward coordinate mappings.

Changes

JIT/Python coordinate refactor

Layer / File(s) Summary
Shared coordinate helpers and metadata contracts
pyre/pyre-jit-trace/src/py_coord.rs, pyre/pyre-jit-trace/src/lib.rs, pyre/pyre-jit/src/jit/codewriter.rs, pyre/pyre-jit-trace/src/pyjitcode.rs
The crate exposes py_coord helpers for containing, trivia-normalized, and resume coordinates. The helpers use metadata tables, forward twins, fallbacks, and optional diagnostics. Related metadata documentation uses the new resolver terminology.
Dispatch coordinate migration
pyre/pyre-jit-trace/src/jitcode_dispatch/*, pyre/pyre-jit-trace/src/state.rs
Dispatch and state paths use shared coordinate helpers. Diagnostic inversion helpers and local state translators are removed.
Resume and trace integration
pyre/pyre-jit-trace/src/jitcode_dispatch/inline_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/trace.rs
Resume paths prefer forward Python-PC twins and use containing-coordinate fallbacks. Trace and inline handling use centralized resume and containing conversions.
Traceback and audit integration
pyre/pyre-jit/src/call_jit.rs
Traceback recording and audit diagnostics use the public containing-coordinate resolver.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TracePath
  participant py_coord
  participant JitCodeMetadata
  TracePath->>py_coord: request containing or resume Python PC
  py_coord->>JitCodeMetadata: read forward twin and floor metadata
  JitCodeMetadata-->>py_coord: coordinate or fallback data
  py_coord-->>TracePath: return resolved Python coordinate
Loading

Possibly related PRs

  • youknowone/pyre#602: Refactors JIT-code/Python coordinate resolution toward JitCode-keyed containing mappings.
  • youknowone/pyre#727: Continues the coordinate-mapping refactor by replacing legacy translation helpers.
  • youknowone/pyre#745: Updates forward Python-PC twin and midbody coordinate handling.

Poem

A rabbit hops through mapped PCs,
With twins and floors in tidy rows.
Old translators leave the burrow,
New helpers guide each resume home.
Audit lights blink soft and bright—
Coordinate paths now align.

🚥 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 summarizes the coordinate migration, resume-marker census, and py_coord consolidation described in the changeset.
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 rewrite-tracer

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 Aug 3, 2026

Copy link
Copy Markdown

🤖 Codex parity review

Static analysis of this diff vs the local RPython/PyPy sources (commit 3871c71).
Updated: 2026-08-03T22:40:32.542Z

Files in the reviewed diff
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/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/vstack_mirror.rs
pyre/pyre-jit-trace/src/lib.rs
pyre/pyre-jit-trace/src/py_coord.rs
pyre/pyre-jit-trace/src/pyjitcode.rs
pyre/pyre-jit-trace/src/state.rs
pyre/pyre-jit-trace/src/trace.rs
pyre/pyre-jit/src/call_jit.rs
pyre/pyre-jit/src/jit/codewriter.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/src/jit/codewriter.rs:15110 ↔ pypy/interpreter/pyframe.py:128: an inlined non-portal callee retains register-form namespace and frame operands even though the code documents that portal_frame_reg can alias the outer caller frame. PyPy resolves globals from the live frame’s own pycode.w_globals; this can therefore resolve a callee LOAD_GLOBAL against caller globals. This region is unchanged from upstream/main.

  • pyre/pyre-jit-trace/src/py_coord.rs:88 ↔ rpython/jit/metainterp/pyjitpl.py:2615: negative resume words are documented as pass-through, but are passed to containing_py_pc_for_jitcode_pc_public, which casts them to usize at py_coord.rs:61 and floor-resolves them as a real PC. PyPy preserves the stored PC unless resumepc >= 0, then passes it directly into per-frame resume setup (rpython/jit/metainterp/resume.py:1049). This behavior was rehomed from upstream/main’s state.rs, not introduced by the patch.

4. Structural adaptations

  • pyre/pyre-jit-trace/src/py_coord.rs:37 ↔ rpython/jit/metainterp/resume.py:1049: Pyre needs JitCode-PC-to-CPython-instruction-coordinate metadata because its generated JitCode is separate from the Rust interpreter’s bytecode dispatch; PyPy resumes each MIFrame directly with its jitcode and native PC.

  • pyre/pyre-jit-trace/src/jitcode_dispatch/resume_snapshot.rs:391 ↔ pypy/interpreter/pyopcode.py:197: forward-skipping Cache, NotTaken, and related resume trivia is a CPython 3.11–3.14 compiler/opcode adaptation. PyPy’s interpreter loop uses its own two-byte opcode stream and does not have this CPython cache-trivia shape.

  • pyre/pyre-jit/src/jit/codewriter.rs:14246 ↔ rpython/jit/codewriter/codewriter.py:74: Pyre’s sparse carry-forward resume-marker sidecar and optional residual census are Rust/code-generation metadata adaptations. PyPy keeps JitCode assembly and native resume positions together during make_jitcodes().

@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: 1

🤖 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/pyre-jit/src/call_jit.rs`:
- Around line 715-719: The coordinate-resolution sites in call_jit.rs currently
use the global JIT-code mapping with runtime novable indices. Update the sites
at lines 669-669, 715-719, 2470-2470, and 2589-2589 to resolve through the
active JitCode/novable registry instead, preserving correct Python bytecode
coordinates for caught, guard-failure, blackhole, and audit traceback paths.
🪄 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: 9cc7f422-b194-444f-982a-9792fa9b9673

📥 Commits

Reviewing files that changed from the base of the PR and between 2c86af5 and 3871c71.

📒 Files selected for processing (17)
  • 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/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/vstack_mirror.rs
  • pyre/pyre-jit-trace/src/lib.rs
  • pyre/pyre-jit-trace/src/py_coord.rs
  • pyre/pyre-jit-trace/src/pyjitcode.rs
  • pyre/pyre-jit-trace/src/state.rs
  • pyre/pyre-jit-trace/src/trace.rs
  • pyre/pyre-jit/src/call_jit.rs
  • pyre/pyre-jit/src/jit/codewriter.rs

Comment on lines +715 to +719
let last_instruction = pyre_jit_trace::py_coord::containing_py_pc_for_jitcode_pc_public(
jitcode_index,
opcode_position,
)
.map_or(unsafe { (*frame_ptr).last_instr as i64 }, i64::from);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 4 \
  'get_jitcode_by_index|pyjitcode_for_jitcode_index|containing_py_pc_for_jitcode_pc_public|record_caught_blackhole_traceback|try_index' \
  pyre/pyre-jit/src/call_jit.rs \
  pyre/pyre-jit-trace/src/py_coord.rs

Repository: youknowone/pyre

Length of output: 2043


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Repo: '; git rev-parse --show-toplevel || exit 0
printf '\nTop-level files:\n'; git ls-files | sed -n '1,80p'

printf '\nLocate relevant symbols:\n'
rg -n -C 5 \
  'containing_py_pc_for_jitcode_pc_public|pyjitcode_for_jitcode_index|get_jitcode_by_index|jitcode_runtime|novable|record_caught_blackhole_traceback|m73_lastinstr_audit|guard-exception|blackhole' \
  . --glob '*.rs' --glob '*.py' 2>/dev/null | sed -n '1,240p'

Repository: youknowone/pyre

Length of output: 2014


🌐 Web query:

PyRe pyre-jit call_jit.rs containing_py_pc_for_jitcode_pc_public pyjitcode_for_jitcode_index

💡 Result:

The terms you are inquiring about are specific internal identifiers within the PyRe JIT codebase [1][2][3]. PyRe is an experimental project separate from the main CPython JIT implementation [4][5][6]. In the PyRe codebase, particularly within pyre/pyre-jit/src/call_jit.rs and related modules [1][7][3], these identifiers relate to the mechanics of JIT trace execution, specifically how the JIT recovers or "resumes" the interpreter state when a JIT-compiled trace fails (e.g., due to a guard failure) or when transitioning back to the interpreter (blackhole calls) [1][2][3]. 1. pyjitcode_for_jitcode_index and containing_py_pc_for_jitcode_pc_public: These are internal components used in resolving and back-translating resume coordinates [3]. They facilitate the mapping between JIT-specific instruction offsets (JitCode indices/PCs) and the original CPython bytecode positions [2][3]. Recent development in the project involved "pc-word flips" and simplifying the resume frame layout to match a two-word shape (jitcode_index, jitcode_pc), ensuring consistent state reconstruction during guard recovery [8][3]. 2. call_jit.rs: This file serves as a core module for JIT residual helpers and code generation [1]. It manages the "blackhole" (bh) paths—the fallback mechanisms invoked when the JIT cannot continue execution and must return control to the interpreter [1][3]. It contains logic to pin parent frames, handle exception disposition, and coordinate the state restoration required to resume execution correctly [1][2][3]. These identifiers are unrelated to the standard CPython jit module [4][5] or the scientific library named JiTCODE [9][10]. If you are analyzing the PyRe repository, these symbols are standard parts of its meta-interpreter and bridge-recovery infrastructure [1][3].

Citations:


Resolve traceback coordinates from the runtime JIT-code index space.

containing_py_pc_for_jitcode_pc_public resolves through state::pyjitcode_for_jitcode_index, while novable resume frames use their own runtime JIT-code index. Use the active JitCode/novable registry at these coordinate-resolution sites so caught, guard-failure, blackhole, and audit traceback coordinates do not map to the wrong Python bytecode location.

📍 Affects 1 file
  • pyre/pyre-jit/src/call_jit.rs#L715-L719 (this comment)
  • pyre/pyre-jit/src/call_jit.rs#L669-L669
  • pyre/pyre-jit/src/call_jit.rs#L2470-L2470
  • pyre/pyre-jit/src/call_jit.rs#L2589-L2589
🤖 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/src/call_jit.rs` around lines 715 - 719, The
coordinate-resolution sites in call_jit.rs currently use the global JIT-code
mapping with runtime novable indices. Update the sites at lines 669-669,
715-719, 2470-2470, and 2589-2589 to resolve through the active JitCode/novable
registry instead, preserving correct Python bytecode coordinates for caught,
guard-failure, blackhole, and audit traceback paths.

@youknowone
youknowone merged commit fb00dfb into main Aug 3, 2026
15 of 19 checks passed
@youknowone
youknowone deleted the rewrite-tracer branch August 3, 2026 23:58
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