You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Summary:
Trivial JIT-compiled functions like `typing.cast` — which just returns its second argument — generate ~70 instructions of prologue (frame setup, callee-save spills, RunPeriodicTasks check) and ~20 of epilogue, while the actual work is only 2 instructions (Incref + mov). This diff reduces that overhead for "leaf" functions.
A function is a leaf if its bytecode contains only opcodes from a conservative allowlist that cannot invoke user Python code (LOAD_FAST, STORE_FAST, LOAD_CONST, RETURN_VALUE, POP_TOP, COPY, SWAP, etc.) and has no backward jumps (loops). The allowlist approach is safe against future bytecode additions since new opcodes are excluded by default.
For leaf functions, two optimizations apply:
1. Skip the RunPeriodicTasks check at RESUME. This eliminates a LoadEvalBreaker, CondBranch, snapshot, and cold-path call to `_Py_HandlePending` from the function entry. This is safe because leaf functions execute a bounded, small number of instructions and return quickly — the caller will check periodic tasks at its next check point. The no-backward-jumps constraint ensures the function cannot loop, bounding its execution time.
2. Use a specialized `JITRT_UnlinkLeafFrame` at function exit. Since the function has no DeoptBase instructions, its interpreter frame can never be materialized at runtime, so we skip the materialization check (`header->rtfs & JIT_FRAME_INITIALIZED`) that `JITRT_UnlinkLightweightFrameFast` performs. A shared `cleanupLightweightFrameExecutable` helper is extracted to deduplicate the reifier cleanup logic between the two unlink functions.
The `can_deopt` flag on Environ (set from `Function::canDeopt()` after all HIR passes) propagates this information from the HIR layer to the LIR exit block generator, which selects between `JITRT_UnlinkLeafFrame`, `JITRT_UnlinkLightweightFrameFast`, and `JITRT_UnlinkFrame` at JIT compile time.
Before (def f(x): return x):
3 basic blocks, 11 HIR instructions including LoadEvalBreaker + CondBranch + RunPeriodicTasks
After:
1 basic block, 5 HIR instructions (LoadArg, LoadCurrentFunc, LoadFrame, Snapshot, Return)
Reviewed By: alexmalyshev
Differential Revision: D103112548
fbshipit-source-id: 92eb90ee6935619c1498a0f02f1e21bca95c74fb
0 commit comments