https://github.com/python/cpython/commit/ebf3427615b3a3d1e6048f84a4adc47331c3803d
commit: ebf3427615b3a3d1e6048f84a4adc47331c3803d
branch: main
author: Ken Jin <[email protected]>
committer: Fidget-Spinner <[email protected]>
date: 2025-12-10T19:39:11Z
summary:
gh-141976: Protect against non-progressing specializations in tracing JIT
(GH-141989)
files:
A
Misc/NEWS.d/next/Core_and_Builtins/2025-11-26-20-01-07.gh-issue-141976.K8NDmR.rst
M Include/cpython/pystats.h
M Python/optimizer.c
diff --git a/Include/cpython/pystats.h b/Include/cpython/pystats.h
index 1c94603c08b9b6..10ac98f2dfebe6 100644
--- a/Include/cpython/pystats.h
+++ b/Include/cpython/pystats.h
@@ -142,6 +142,7 @@ typedef struct _optimization_stats {
uint64_t recursive_call;
uint64_t low_confidence;
uint64_t unknown_callee;
+ uint64_t trace_immediately_deopts;
uint64_t executors_invalidated;
UOpStats opcode[PYSTATS_MAX_UOP_ID + 1];
uint64_t unsupported_opcode[256];
diff --git
a/Misc/NEWS.d/next/Core_and_Builtins/2025-11-26-20-01-07.gh-issue-141976.K8NDmR.rst
b/Misc/NEWS.d/next/Core_and_Builtins/2025-11-26-20-01-07.gh-issue-141976.K8NDmR.rst
new file mode 100644
index 00000000000000..654681515e43e5
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2025-11-26-20-01-07.gh-issue-141976.K8NDmR.rst
@@ -0,0 +1 @@
+Protect against specialization failures in the tracing JIT compiler for
performance reasons.
diff --git a/Python/optimizer.c b/Python/optimizer.c
index 9db894f0bf054a..7fe914a7a426b9 100644
--- a/Python/optimizer.c
+++ b/Python/optimizer.c
@@ -610,6 +610,25 @@ _PyJit_translate_single_bytecode_to_trace(
target--;
}
+ if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]] > 0) {
+ uint16_t backoff = (this_instr + 1)->counter.value_and_backoff;
+ // adaptive_counter_cooldown is a fresh specialization.
+ // trigger_backoff_counter is what we set during tracing.
+ // All tracing backoffs should be freshly specialized or untouched.
+ // If not, that indicates a deopt during tracing, and
+ // thus the "actual" instruction executed is not the one that is
+ // in the instruction stream, but rather the deopt.
+ // It's important we check for this, as some specializations might make
+ // no progress (they can immediately deopt after specializing).
+ // We do this to improve performance, as otherwise a compiled trace
+ // will just deopt immediately.
+ if (backoff != adaptive_counter_cooldown().value_and_backoff &&
+ backoff != trigger_backoff_counter().value_and_backoff) {
+ OPT_STAT_INC(trace_immediately_deopts);
+ opcode = _PyOpcode_Deopt[opcode];
+ }
+ }
+
int old_stack_level =
_tstate->jit_tracer_state.prev_state.instr_stacklevel;
// Strange control-flow
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]