fix(jit): task code stays interpreted at every JIT entry point (#533)#534
Merged
Conversation
The #408 ruling — task code runs interpreted — was enforced only at the fresh-entry gate. Three other entry points weren't task-gated: the OSR back-edge counter/handoff, and the OP_CALL / OP_DISPATCH thunk entries. A task's hot loop crossing the OSR threshold was JIT-compiled MID-TASK, and jit_helper_call has no g_task_suspend_request check: a blocking task_recv's placeholder null flowed onward as the received message and the leaked suspend flag suspended the task mid-expression at a later interpreted call site. Symptom: mass task death, null from task_recv, corrupted locals after ~OSR-threshold loop iterations — first seen as liferaft node tasks dying en masse under chaos (#523), reachable at all only once #530 lifted the lifetime spawn cap. All four entry points now check g_task_sched (plus a belt-and-braces bail in jit_helper_call). Regression: tests/test_task_osr.eigs drives a recv loop past a lowered EIGS_JIT_OSR_THRESHOLD — red pre-fix (worker receives the placeholder null), green post-fix. Root-caused with a suspend-flag ledger + __builtin_return_address on the blocking-recv path; 70-line shrink repro in #533. 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.
Closes #533
The bug
The #408 ruling ("task code runs interpreted") was enforced only at the fresh-entry JIT gate. The OSR back-edge counter/handoff and the OP_CALL / OP_DISPATCH thunk entries weren't task-gated — so a task's hot mailbox loop crossing the OSR threshold (default 5000) got JIT-compiled mid-task. Inside native code, a blocking
task_recvruns viajit_helper_call, which has nog_task_suspend_requestcheck: the placeholder null flowed onward as the "received" message, and the leaked flag suspended the task mid-expression at the next interpreted call site.Symptoms:
task_recvreturns null, suspended-task locals read as garbage, mass task death right around the OSR threshold. First seen as liferaft's node tasks dying en masse under chaos (#523) — reachable at all only once #530 lifted the 255-spawn lifetime cap (nothing before it could run a task loop hot). Full forensic chain (suspend-flag ledger,__builtin_return_addresson the blocking-recv path, 70-line shrink repro) in #533.The fix
All four entry points now check
g_task_sched, mirroring the fresh-entry gate: OSR counter+handoff, both thunk entries, and a belt-and-braces bail injit_helper_call. Non-task programs keep the JIT exactly as before.Tests
tests/test_task_osr.eigs+ suite wiring withEIGS_JIT_OSR_THRESHOLD=20: a worker recv-loop driven 200 messages past the threshold must receive real strings throughout. Red pre-fix (FAILED got=-1— placeholder null received), green post-fix.Validation
detect_leaks=1: 2705/2705, leak tally 0🤖 Generated with Claude Code