jit: close the #73 walk-side coordinate split — twin flip, resume-marker census, py_coord fold - #1012
Conversation
…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
WalkthroughThe PR adds centralized JIT-code-to-Python coordinate helpers in ChangesJIT/Python coordinate refactor
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
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
🤖 Codex parity reviewStatic analysis of this diff vs the local RPython/PyPy sources (commit 3871c71). Files in the reviewed diff1. Regressions to PyPy parity introduced by this patchNone. 2. Other mismatches introduced by this patchNone. 3. Pre-existing mismatches (already present before this patch)
4. Structural adaptations
|
There was a problem hiding this comment.
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
📒 Files selected for processing (17)
pyre/pyre-jit-trace/src/jitcode_dispatch/branch.rspyre/pyre-jit-trace/src/jitcode_dispatch/bridge_subwalk.rspyre/pyre-jit-trace/src/jitcode_dispatch/diag.rspyre/pyre-jit-trace/src/jitcode_dispatch/fbw_state.rspyre/pyre-jit-trace/src/jitcode_dispatch/inline_call.rspyre/pyre-jit-trace/src/jitcode_dispatch/mod.rspyre/pyre-jit-trace/src/jitcode_dispatch/residual_call.rspyre/pyre-jit-trace/src/jitcode_dispatch/resume_snapshot.rspyre/pyre-jit-trace/src/jitcode_dispatch/specialize.rspyre/pyre-jit-trace/src/jitcode_dispatch/vstack_mirror.rspyre/pyre-jit-trace/src/lib.rspyre/pyre-jit-trace/src/py_coord.rspyre/pyre-jit-trace/src/pyjitcode.rspyre/pyre-jit-trace/src/state.rspyre/pyre-jit-trace/src/trace.rspyre/pyre-jit/src/call_jit.rspyre/pyre-jit/src/jit/codewriter.rs
| 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); |
There was a problem hiding this comment.
🗄️ 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.rsRepository: 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:
- 1: JIT: port portable abort_permanent opcodes to residual calls (gh#373) #378
- 2: jit: drop the WITH_EXCEPT_START gate + with-frame exception-correctness fixes (#389) #532
- 3: jit: #369 pc-word flip — resume frame collapses to RPython 2-word shape #536
- 4: https://github.com/python/cpython/blob/main/Python/jit_publish.c
- 5: https://github.com/python/cpython/blob/main/Python/jit.c
- 6: https://github.com/python/cpython/blob/b35c3791/Include/internal/pycore_jit.h
- 7: 6d06463
- 8: JIT #73: retire the carried jitcode_pc resume side-channel (Artifact 3) #369
- 9: https://pypi.org/project/jitcode/
- 10: https://github.com/neurophysik/jitcode/
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-L669pyre/pyre-jit/src/call_jit.rs#L2470-L2470pyre/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.
Closes the remaining #73 phase-2/3 work on the jitcode↔python coordinate split. Three commits:
jit: census the py_pc resume markers derive_resume_marker cannot reproduce— build-timePYRE_PCMAP_RESIDUAL_CENSUScensus of the residual divergence classes (corpus: 1,410/68,322 py PCs, all in the no-own-op tier; theown=1tier reproduces the dense table exactly).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 underPYRE_M73_BACKXLAT_TWIN_AUDIT/PYRE_PCMAP_AFTERRESIDUAL_AUDIT.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_pcare built forward in the codewriter at lowering, and the floor result equals what pyopcode.py:200's per-bytecodelast_instrstore (elided by vable optimization) would leave, memoized at build time. This commit folds the helpers intopyre-jit-trace/src/py_coord.rswith 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 aPYRE_M73_EMPTYTWIN_CENSUSgate reporting empty-twin fallback trips at the 5 twin-first seams.Verification
exception_try_call_inlined_callee_raiseloops_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.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_instras 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
Documentation