jit: narrow the wasm bridge decline to exception-resume (GuardException)#416
Conversation
#407 declined every CallMayForce bridge on wasm, which also dropped the non-raising loop-closing bridges wasm relies on for speed (bool_arithmetic ~6x slower, ~+11% on the synthetic suite). Only exception-resume bridges are actually broken: a bridge containing `GuardException` resumes into the exception handler by re-entering the interpreter at the raising bytecode, reading the pre-call operand stack. Constant stack entries (e.g. a float dividend) live only in the guard's `rd_consts` resume data, not in a spilled frame slot, and the compiled bridge — reconstructing state from inputargs alone — cannot see `rd_consts`, so the constant materialises as NULL and the re-entered interpreter runs e.g. `truediv(NULL, int)`. Narrow the decline from `is_call_may_force()` to `GuardException`: the broken shape blackholes (rematerialising constants from `rd_consts`, the native path) while `GuardNoException` loop-closing bridges keep their compiled fast path. wasm synthetic suite 173/173 (float_div correct), no CallMayForce-bridge regression, and faster overall than both #407 and the #404 workaround.
|
Warning Review limit reached
Next review available in: 36 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
✨ Finishing Touches🧪 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 0e5ab08). 1. Regressions to PyPy parity introduced by this patch
2. Other mismatches introduced by this patchNone. 3. Pre-existing mismatches (already present before this patch)None. 4. Structural adaptations
|
Summary
Follow-up to #407. #407 declined every
CallMayForcebridge on wasm, which also dropped the non-raising loop-closing bridges wasm relies on for speed —bool_arithmetic~6× slower, ~+11% on the synthetic suite. This narrows the decline to only the bridges that are actually broken.Root cause (pinned via in-guest instrumentation)
Only exception-resume bridges are broken. A bridge containing
GuardExceptionresumes into the exception handler by re-entering the interpreter at the raising bytecode, reading the pre-call operand stack. Constant stack entries (e.g. afloatdividend1.5) live only in the guard'srd_constsresume data, not in a spilled frame slot. The compiled bridge reconstructs its state from inputargs (spilled slots) alone and cannot seerd_consts, so the constant materialises as NULL and the re-entered interpreter runstruediv(NULL, int)→ spuriousunsupported operand type(s) for /.Dumping every
CallMayForcebridge gave a crisp discriminator:float_div_zero_caught_loopGuardExceptionFinish(interp re-entry)bool_arithmetic/is_op/string_opsGuardNoExceptionJump(loop-closing)Fix
Decline only bridges containing
OpCode::GuardException(wasis_call_may_force()). The broken shape blackholes — rematerialising constants fromrd_consts, the native path — whileGuardNoExceptionloop-closing bridges keep their compiled fast path.Verification (on current
mainbase)float_div_zero_caught_loop→37500.0, 0.41s)bool_arithmetic2.77s (was 15.84s under the jit: decline wasm bridges with CallMayForce re-entry (real fix for the #404 workaround) #407 blanket decline) — regression removed