feat(jit): poll the async abort flag at native loop back-edges (#410)#464
Merged
Conversation
Hard timeouts (eigs_set_abort_flag) now hold at full speed. The gap was the FROM-ZERO thunk: a call-hot function's loop closes natively via the backward patch and never crosses an interpreted back-edge (the OSR tier exits at its own back-edge each iteration and re-enters through the interpreted JUMP_BACK, so it always polled — root-caused during this work; the EMBEDDING caveat overstated the gap). The emitter plants movabs/deref/cmpl before every native back-edge and bails to the interpreter AT the JUMP_BACK when set (r13d still holds the op's offset) — the interpreter re-runs the back-edge, consumes the flag, and raises the ordinary catchable 'aborted' error. No error machinery in native code. g_vm_abort_flag is now never NULL (unregistered -> static zero sentinel), so both tiers poll with one unconditional deref. embed_smoke gains the from-zero abort test, placed BEFORE the spawn test (g_vm_multithreaded permanently gates JIT compiles off for the process) and validated as a planted fault: it FAILS against the pre-fix jit.c (loop runs to the 100M cap ignoring the timer) and passes after. Gates: jit-smoke, embed-smoke, embed_stack_soak, release 2584/2584, ASan+UBSan detect_leaks=1 2584/2584. Bench n=5 medians within noise: dmg_shape 326.3 -> 323.4 ms, idxset 39.6 -> 38.8 ms. Closes #410 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hard timeouts (
eigs_set_abort_flag) now hold at full speed — noEIGS_JIT_OFFrequired.Root cause (narrower than the issue assumed)
The gap was only the from-zero thunk: a call-hot function's loop closes natively via the backward patch and never crosses an interpreted back-edge. The OSR tier already polled — its thunk stops before the loop's own
JUMP_BACKand re-enters through the interpreted back-edge every iteration, which is where the #379 poll lives. Root-caused during this work; the EMBEDDING.md caveat overstated the gap.The fix
g_vm_abort_flagis never NULL now: unregistered points at a static always-zero int (eigs_set_abort_flag(NULL)maps back to it), so both tiers poll with a single unconditional deref. The interpreter's check simplifies accordingly.movabs &g_vm_abort_flag / mov (%rax),%rax / cmpl $0,(%rax) / jne →epiloguebefore every native back-edge. On set it bails to the interpreter at the JUMP_BACK (r13d still holds the op's offset, the standard pre-effect bail shape) — the interpreter re-runs the back-edge, consumes the flag, and raises the ordinary catchableabortederror. No error machinery in native code.Planted-fault validation
The new embed_smoke test warms a function past the call threshold then runs one long call (bounded at 200M adds so a regression fails loudly instead of hanging). It FAILS against pre-fix jit.c (the loop ran to the 100M iteration cap ignoring a 150ms timer) and passes after. It sits before the spawn/channel test deliberately —
g_vm_multithreadedpermanently gates JIT compiles off for the process, so a later placement would test the interpreter twice (verified: zero compiles happen after that test).Gates
make jit-smoke(with the newg_vm_abort_flagstub),make embed-smoke,tools/embed_stack_soak.shdetect_leaks=12584/2584Closes #410
🤖 Generated with Claude Code