From: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Date: Wed, 5 Nov 2025 18:48:37 +0000 (+0000) Subject: Use a different chain depth for dynamic exits X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ffa2b72975c13fbea4a3ab068c7f6844ca3266b4;p=thirdparty%2FPython%2Fcpython.git Use a different chain depth for dynamic exits --- diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index 3ea62eab1f46..daa5d36da474 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -132,6 +132,9 @@ static inline uint16_t uop_get_error_target(const _PyUOpInstruction *inst) // handle before rejoining the rest of the program. #define MAX_CHAIN_DEPTH 4 +// The maximum number of side exits arising from unpredictable control-flow. +#define MAX_DYNAMIC_CHAIN_DEPTH 6 + /* Symbols */ /* See explanation in optimizer_symbols.c */ diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 3b14415f540b..0ecfd0ff993c 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -5412,7 +5412,6 @@ dummy_func( #ifndef _Py_JIT assert(current_executor == (_PyExecutorObject*)executor); #endif - assert(tstate->jit_exit != NULL || tstate->jit_exit->executor == current_executor); tstate->current_executor = (PyObject *)executor; if (!current_executor->vm_data.valid) { assert(tstate->jit_exit->executor == current_executor); @@ -5507,7 +5506,7 @@ dummy_func( if (target->op.code == ENTER_EXECUTOR) { PyCodeObject *code = _PyFrame_GetCode(frame); executor = code->co_executors->executors[target->op.arg]; - if (executor->trace[2].opcode == _GUARD_EXECUTOR_IP && executor->vm_data.valid) { + if (executor->trace[0].opcode == _START_DYNAMIC_EXECUTOR && executor->vm_data.valid) { Py_INCREF(executor); assert(tstate->jit_exit == exit); exit->executor = executor; diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 28c139bf9e57..d613e4fa67f0 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -7445,7 +7445,6 @@ #ifndef _Py_JIT assert(current_executor == (_PyExecutorObject*)executor); #endif - assert(tstate->jit_exit != NULL || tstate->jit_exit->executor == current_executor); tstate->current_executor = (PyObject *)executor; if (!current_executor->vm_data.valid) { assert(tstate->jit_exit->executor == current_executor); @@ -7556,7 +7555,7 @@ if (target->op.code == ENTER_EXECUTOR) { PyCodeObject *code = _PyFrame_GetCode(frame); executor = code->co_executors->executors[target->op.arg]; - if (executor->trace[2].opcode == _GUARD_EXECUTOR_IP && executor->vm_data.valid) { + if (executor->trace[0].opcode == _START_DYNAMIC_EXECUTOR && executor->vm_data.valid) { Py_INCREF(executor); assert(tstate->jit_exit == exit); exit->executor = executor; diff --git a/Python/optimizer.c b/Python/optimizer.c index 1035f310c984..24ca1c5c0394 100644 --- a/Python/optimizer.c +++ b/Python/optimizer.c @@ -133,7 +133,12 @@ _PyOptimizer_Optimize( // make progress in order to avoid infinite loops or excessively-long // side-exit chains. We can only insert the executor into the bytecode if // this is true, since a deopt won't infinitely re-enter the executor: - chain_depth %= MAX_CHAIN_DEPTH; + if (tstate->interp->jit_state.code_buffer[0].opcode == _START_DYNAMIC_EXECUTOR) { + chain_depth %= MAX_DYNAMIC_CHAIN_DEPTH; + } + else { + chain_depth %= MAX_CHAIN_DEPTH; + } bool progress_needed = chain_depth == 0; PyCodeObject *code = (PyCodeObject *)tstate->interp->jit_state.initial_code; _Py_CODEUNIT *start = tstate->interp->jit_state.insert_exec_instr; @@ -951,10 +956,7 @@ _PyJit_TryInitializeTracing(PyThreadState *tstate, _PyInterpreterFrame *frame, _ if (oparg > 0xFFFF) { return 0; } - // Dynamic exits with progress is wonky. - if (is_dynamic_target && chain_depth >= MAX_CHAIN_DEPTH) { - return 0; - } + PyCodeObject *code = _PyFrame_GetCode(frame); #ifdef Py_DEBUG char *python_lltrace = Py_GETENV("PYTHON_LLTRACE");