Skip to content

jit: route strict inline-callee guards through the multi-frame snapshot#453

Merged
youknowone merged 1 commit into
mainfrom
wasm-jit
Jul 9, 2026
Merged

jit: route strict inline-callee guards through the multi-frame snapshot#453
youknowone merged 1 commit into
mainfrom
wasm-jit

Conversation

@youknowone

Copy link
Copy Markdown
Owner

Follow-up to #440. #440 fixed the four wasm-only #420 benches, but its strict-callee handling relied on machinery with no RPython/PyPy analog — a per-callee opcode-scanning predicate (strict_callee_collapse_unsound), gated by a PYRE_FBW_STRICT_MULTIFRAME env flag, that chose collapse-vs-decline. This replaces that with the faithful multi-frame resume.

The un-faithful machinery (deleted)

For a strict straight-line inline callee, the callee frame/ec portal reds were seeded only inside if try_multiframe { (i.e. only for branch-bearing callees). A strict callee therefore had portal_frame_reg == OpRef::NONE, so collect_callee_active_boxes returned Unsupported and walker_capture_multi_frame_inline_snapshot always declined. The multi-frame path never actually resumed a strict callee at its own coordinate — it only chose between declining to a residual call and collapsing to the caller CALL boundary.

strict_callee_collapse_unsound was the valve for that choice: it scanned the callee body for heap side effects (residual_call_r_*, residual_call_*_v, setfield, setarrayitem, setinteriorfield) and pushed the paused caller frame (→ MF decline → residual) only for side-effecting callees, keeping pure leaves on the single-frame collapse. That is a pyre-specific heuristic; RPython captures one Snapshot frame per MIFrame and re-enters each at its saved pc — there is no opcode-scan and no collapse.

Faithful replacement

jit: route strict inline-callee guards through the multi-frame snapshot:

  • Seed the strict callee's frame/ec portal reds at the top inline level (un-gated from the try_multiframe path, via a strict_seed = strict_inlinable && inline_depth < FBW_MAX_MULTIFRAME_DEPTH guard and a 'seed: labeled block). collect_callee_active_boxes now sources the callee frame red, so walker_capture_multi_frame_inline_snapshot succeeds rather than declining.
  • Route strict in-callee guards through compute_inline_caller_frame — the seeded callee pushes a paused caller frame and its guards resume at the callee's own coordinate, with the caller paused at the CALL return point (the RPython Snapshot.frames / resume.py rebuild_from_resumedata shape), instead of collapsing to the caller boundary.
  • Delete strict_callee_collapse_unsound, fbw_strict_multiframe_enabled, and the PYRE_FBW_STRICT_MULTIFRAME env var.
  • Single-frame collapse is retained only as a structural fallback, not a heuristic choice: nested strict callees (inline_depth >= FBW_MAX_MULTIFRAME_DEPTH, task fib_recursive: recursive CALL_ASSEMBLER lands (now faster than CPython); residual ~4-5x-vs-pypy floor needs flat/virtualized jitframe #126), un-seedable callees, and caller shapes compute_inline_caller_frame cannot build yet (a CALL inside a try-block, or no result on the operand stack at the return point).

Fully retiring the single-frame collapse is a follow-up coupled to #126 (raising FBW_MAX_MULTIFRAME_DEPTH) and #73 (kept operand-stack temps) — it needs the void / try-block caller-frame shapes the multi-frame path cannot yet build.

Results (full pyre/check.py, all three backends)

backend result
dynasm 159/159
cranelift 159/159
wasm 159/159

The four #420 benches (inline_callee_constructs_object, inlined_helper_mutation, inlined_mutation_before_abort, sre_pattern_methods) and inline_helper compile and pass on all three backends. The side-effecting callees (inline_callee_constructs_object, inlined_mutation_before_abort) now inline via the multi-frame resume (loops_compiled=1) instead of residualizing.

🤖 Generated with Claude Code

Seed the callee `frame`/`ec` portal reds for a strict straight-line inline
callee at the top inline level (un-gate the seeding from `try_multiframe`), so
`collect_callee_active_boxes` sources the callee frame red and
`walker_capture_multi_frame_inline_snapshot` succeeds instead of declining. A
seeded strict callee then pushes a paused caller frame via
`compute_inline_caller_frame`, so its in-callee guards resume at the callee's
own coordinate; `compute_inline_caller_frame` returning `None` (a CALL inside a
try-block, or no result on the operand stack at the return point) falls back to
the single-frame collapse.

Delete `strict_callee_collapse_unsound`, `fbw_strict_multiframe_enabled`, and
the `PYRE_FBW_STRICT_MULTIFRAME` env var: the per-callee opcode-scanning
predicate that chose collapse-vs-decline is replaced by the multi-frame
routing. Nested strict callees (`inline_depth >= FBW_MAX_MULTIFRAME_DEPTH`) and
un-seedable callees keep the single-frame collapse fallback.

check.py: dynasm 159/159, cranelift 159/159, wasm 159/159. The four wasm #420
benches (inline_callee_constructs_object, inlined_helper_mutation,
inlined_mutation_before_abort, sre_pattern_methods) and inline_helper compile
and pass on all three backends.

Assisted-by: Claude
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@youknowone, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 16 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e7aa9361-2bf3-4e20-ac45-6948b5f985d1

📥 Commits

Reviewing files that changed from the base of the PR and between 2929d4e and 5680c04.

📒 Files selected for processing (1)
  • pyre/pyre-jit-trace/src/jitcode_dispatch.rs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch wasm-jit

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 9, 2026

Copy link
Copy Markdown

🤖 Codex parity review

Static analysis of this diff vs the local RPython/PyPy sources (commit 628be7f).

Codex did not produce a report (exit 1). Last log lines:

--------
user
Assess by static analysis whether our changes in git diff upstream/main are equivalent
to the corresponding RPython/PyPy source code. The RPython and PyPy sources
are available locally (under `rpython/` and `pypy/` in this repository).

If anything was ported incorrectly, report every instance in detail. After
collecting all differences, organize the report into separate sections:

1. Cases where our patch regressed PyPy parity compared to main
2. Other mismatches introduced by our patch
3. Mismatches that already existed before this patch
4. Structural adaptations

Exceptions: some differences cannot be ported 1:1 because of Python 3.11 vs
3.14 differences, opcode mismatches caused by using a CPython-compatible
compiler, GIL/free-threading differences, and fundamental implementation-
language differences between RPython and Rust. Mark those separately under
"Structural adaptations".

---

Output format requirements (so the report can be parsed mechanically and
posted/triaged automatically). Use these four headings VERBATIM, in this
order, and nothing else at heading level 2:

## 1. Regressions to PyPy parity introduced by this patch
## 2. Other mismatches introduced by this patch
## 3. Pre-existing mismatches (already present before this patch)
## 4. Structural adaptations

Under each heading, list every finding as a bullet. For each finding cite the
concrete `our_file.rs:line ↔ rpython_or_pypy_file.py:line` pair and quote the
divergence concisely. If a section has no findings, still emit the heading
followed by a single line `None.` so all four sections are always present.
Do not modify any files; produce the report only.
2026-07-09T09:52:41.442300Z ERROR codex_login::auth::manager: Failed to refresh token: Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.
2026-07-09T09:52:41.483249Z ERROR rmcp::transport::worker: worker quit with fatal: Transport channel closed, when UnexpectedServerResponse("HTTP 401: {\n  \"error\": {\n    \"message\": \"Provided authentication token is expired. Please try signing in again.\",\n    \"type\": null,\n    \"code\": \"token_expired\",\n    \"param\": null\n  },\n  \"status\": 401\n}")
2026-07-09T09:52:41.520077Z ERROR codex_login::auth::manager: Failed to refresh token: Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.
2026-07-09T09:52:41.574229Z ERROR rmcp::transport::worker: worker quit with fatal: Transport channel closed, when UnexpectedServerResponse("HTTP 401: {\n  \"error\": {\n    \"message\": \"Provided authentication token is expired. Please try signing in again.\",\n    \"type\": null,\n    \"code\": \"token_expired\",\n    \"param\": null\n  },\n  \"status\": 401\n}")
2026-07-09T09:52:41.652200Z ERROR codex_login::auth::manager: Failed to refresh token: Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.
2026-07-09T09:52:41.677573Z ERROR codex_login::auth::manager: Failed to refresh token: Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.
2026-07-09T09:52:41.699215Z ERROR codex_login::auth::manager: Failed to refresh token: Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.
2026-07-09T09:52:41.866978Z ERROR codex_api::endpoint::responses_websocket: failed to connect to websocket: HTTP error: 401 Unauthorized, url: wss://chatgpt.com/backend-api/codex/responses
2026-07-09T09:52:41.900443Z ERROR codex_login::auth::manager: Failed to refresh token: Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.
2026-07-09T09:52:41.915152Z ERROR codex_login::auth::manager: Failed to refresh token: Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.
2026-07-09T09:52:41.930031Z ERROR codex_login::auth::manager: Failed to refresh token: Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.
2026-07-09T09:52:42.082003Z ERROR codex_api::endpoint::responses_websocket: failed to connect to websocket: HTTP error: 401 Unauthorized, url: wss://chatgpt.com/backend-api/codex/responses
2026-07-09T09:52:42.101023Z ERROR codex_login::auth::manager: Failed to refresh token: Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.
2026-07-09T09:52:42.201811Z ERROR codex_login::auth::manager: Failed to refresh token: Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.
2026-07-09T09:52:42.301664Z ERROR codex_login::auth::manager: Failed to refresh token: Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.
2026-07-09T09:52:42.317621Z ERROR codex_login::auth::manager: Failed to refresh token: Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.
2026-07-09T09:52:42.333522Z ERROR codex_login::auth::manager: Failed to refresh token: Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.
2026-07-09T09:52:42.511670Z ERROR codex_api::endpoint::responses_websocket: failed to connect to websocket: HTTP error: 401 Unauthorized, url: wss://chatgpt.com/backend-api/codex/responses
2026-07-09T09:52:42.544971Z ERROR codex_login::auth::manager: Failed to refresh token: Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.
2026-07-09T09:52:42.559683Z ERROR codex_login::auth::manager: Failed to refresh token: Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.
2026-07-09T09:52:42.575215Z ERROR codex_login::auth::manager: Failed to refresh token: Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.
2026-07-09T09:52:42.725536Z ERROR codex_api::endpoint::responses_websocket: failed to connect to websocket: HTTP error: 401 Unauthorized, url: wss://chatgpt.com/backend-api/codex/responses
ERROR: Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.
ERROR: Your access token could not be refreshed because your refresh token was already used. Please log out and sign in again.

@youknowone youknowone merged commit 012289c into main Jul 9, 2026
30 checks passed
@youknowone youknowone deleted the wasm-jit branch July 9, 2026 11:08
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