]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Use a different chain depth for dynamic exits
authorKen Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Wed, 5 Nov 2025 18:48:37 +0000 (18:48 +0000)
committerKen Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Wed, 5 Nov 2025 18:48:37 +0000 (18:48 +0000)
Include/internal/pycore_optimizer.h
Python/bytecodes.c
Python/executor_cases.c.h
Python/optimizer.c

index 3ea62eab1f4693a9949d27130df199418f7c5b49..daa5d36da474fbec7c3f7fe094126bee54c99e95 100644 (file)
@@ -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 */
 
index 3b14415f540b9125c4e07202d57bc2d36c3e1abb..0ecfd0ff993c8c9707bd55915667cbee114c9bd2 100644 (file)
@@ -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;
index 28c139bf9e5760655d89e5e9f52d2eaa81eda0b2..d613e4fa67f0575f72d5a6d35d40fc2ca8ccdd9f 100644 (file)
             #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);
             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;
index 1035f310c9848b1d4204016c6ba123d67e5f8782..24ca1c5c03940bd06fafe857241deee0529569bc 100644 (file)
@@ -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");