]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Fix INTERPRETER_EXIT tracing
authorKen Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Tue, 28 Oct 2025 22:13:19 +0000 (22:13 +0000)
committerKen Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Tue, 28 Oct 2025 22:13:19 +0000 (22:13 +0000)
12 files changed:
Include/internal/pycore_ceval.h
Include/internal/pycore_code.h
Include/internal/pycore_global_objects_fini_generated.h
Include/internal/pycore_global_strings.h
Include/internal/pycore_opcode_metadata.h
Include/internal/pycore_runtime_init_generated.h
Include/internal/pycore_unicodeobject_generated.h
Python/bytecodes.c
Python/ceval.c
Python/generated_cases.c.h
Python/optimizer.c
Python/specialize.c

index 102a378f8f08bc6d5057e4eaa2bf4706858bc7e4..61917b01b7cb1351520f1653880f3adaa82249eb 100644 (file)
@@ -391,6 +391,9 @@ _PyForIter_VirtualIteratorNext(PyThreadState* tstate, struct _PyInterpreterFrame
 #define SPECIAL___AEXIT__   3
 #define SPECIAL_MAX   3
 
+struct _PyCode12 _PyCode_DEF(12);
+PyAPI_DATA(const struct _PyCode12) _PyEntryFrameCode;
+
 #ifdef __cplusplus
 }
 #endif
index 2d7d81d491c157adc196d332fe3d0eb4147828ac..434f47374f793fb00372b2bfe2d72fc79f9427dd 100644 (file)
@@ -672,6 +672,12 @@ PyAPI_FUNC(int) _PyCode_ReturnsOnlyNone(PyCodeObject *);
  * compare bytes and str which can raise a BytesWarning exception. */
 extern PyObject* _PyCode_ConstantKey(PyObject *obj);
 
+#define NO_LOC_4 (128 | (PY_CODE_LOCATION_INFO_NONE << 3) | 3)
+
+static const PyBytesObject no_location = {
+    PyVarObject_HEAD_INIT(&PyBytes_Type, 1)
+    .ob_sval = { NO_LOC_4 }
+};
 
 #ifdef __cplusplus
 }
index 92ded14891a1013dd35b3ad45f41bba32d358a6e..4e0a2a452728da6de505ef20e575159239cf36fd 100644 (file)
@@ -1344,6 +1344,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(TextIOWrapper));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(True));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(WarningMessage));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_PyEval_EvalFrameDefault));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(_WindowsConsoleIO));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__IOBase_closed));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(__abc_tpflags__));
index cd21b0847b7cdde18de62d2be406ee102a796564..c150948e432ca5fd61007a88aaceae56fd529049 100644 (file)
@@ -67,6 +67,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(TextIOWrapper)
         STRUCT_FOR_ID(True)
         STRUCT_FOR_ID(WarningMessage)
+        STRUCT_FOR_ID(_PyEval_EvalFrameDefault)
         STRUCT_FOR_ID(_WindowsConsoleIO)
         STRUCT_FOR_ID(__IOBase_closed)
         STRUCT_FOR_ID(__abc_tpflags__)
index 8dda65a55b345349e6f8b543e944b8e23889c572..aa99a0c50406fb3af5e380aa41a1a5c47db7c839 100644 (file)
@@ -1148,7 +1148,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = {
     [END_ASYNC_FOR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG },
     [END_FOR] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG | HAS_NO_SAVE_IP_FLAG },
     [END_SEND] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG | HAS_PURE_FLAG },
-    [ENTER_EXECUTOR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
+    [ENTER_EXECUTOR] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
     [EXIT_INIT_CHECK] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
     [EXTENDED_ARG] = { true, INSTR_FMT_IB, HAS_ARG_FLAG },
     [FORMAT_SIMPLE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
@@ -1187,7 +1187,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = {
     [INSTRUMENTED_RESUME] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
     [INSTRUMENTED_RETURN_VALUE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
     [INSTRUMENTED_YIELD_VALUE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG },
-    [INTERPRETER_EXIT] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG },
+    [INTERPRETER_EXIT] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
     [IS_OP] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ESCAPES_FLAG },
     [JUMP_BACKWARD] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
     [JUMP_BACKWARD_JIT] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EVAL_BREAK_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
index 50d82d0a365037501a2ca81f0c64ad0241132860..0212a141fe2e36f460801bee5b116af4f3349788 100644 (file)
@@ -1342,6 +1342,7 @@ extern "C" {
     INIT_ID(TextIOWrapper), \
     INIT_ID(True), \
     INIT_ID(WarningMessage), \
+    INIT_ID(_PyEval_EvalFrameDefault), \
     INIT_ID(_WindowsConsoleIO), \
     INIT_ID(__IOBase_closed), \
     INIT_ID(__abc_tpflags__), \
index b4d920154b6e836f7857cee33a4d3d20dc44a5a0..e1a5838dd07444bd0ddad337666ac1851f601b41 100644 (file)
@@ -56,6 +56,10 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
     _PyUnicode_InternStatic(interp, &string);
     assert(_PyUnicode_CheckConsistency(string, 1));
     assert(PyUnicode_GET_LENGTH(string) != 1);
+    string = &_Py_ID(_PyEval_EvalFrameDefault);
+    _PyUnicode_InternStatic(interp, &string);
+    assert(_PyUnicode_CheckConsistency(string, 1));
+    assert(PyUnicode_GET_LENGTH(string) != 1);
     string = &_Py_ID(_WindowsConsoleIO);
     _PyUnicode_InternStatic(interp, &string);
     assert(_PyUnicode_CheckConsistency(string, 1));
index beed5e091b6f3036f17b2cfa22b3dd815cd8ae4d..d665f7db9c5dda8b6d03443f452e805b0d6c4982 100644 (file)
@@ -170,7 +170,9 @@ dummy_func(
 
         op(_QUICKEN_RESUME, (--)) {
             #if ENABLE_SPECIALIZATION_FT
-            if (tstate->tracing == 0 && this_instr->op.code == RESUME) {
+            PyCodeObject *code = _PyFrame_GetCode(frame);
+            if (tstate->tracing == 0 && this_instr->op.code == RESUME &&
+                code != (PyCodeObject *)&_Py_InitCleanup && code != (PyCodeObject *)&_PyEntryFrameCode) {
                 FT_ATOMIC_STORE_UINT8_RELAXED(this_instr->op.code, RESUME_CHECK);
             }
             #endif  /* ENABLE_SPECIALIZATION_FT */
@@ -1218,19 +1220,33 @@ dummy_func(
             tstate->current_frame = frame->previous;
             assert(!_PyErr_Occurred(tstate));
             PyObject *result = PyStackRef_AsPyObjectSteal(retval);
+            if (IS_JIT_TRACING()) {
+#if _Py_TIER2
+                _PyJit_translate_single_bytecode_to_trace(tstate, frame, next_instr);
+                LEAVE_TRACING();
+                int err = bail_tracing_and_jit(tstate, frame);
+                if (err < 0) {
+                    Py_DECREF(result);
+                    ERROR_IF(true);
+                }
+                return result;
+#endif
+            }
+            else {
 #if !_Py_TAIL_CALL_INTERP
-            assert(frame == &entry.frame);
+                assert(frame == &entry.frame);
 #endif
 #ifdef _Py_TIER2
-            _PyStackRef executor = frame->localsplus[0];
-            assert(tstate->current_executor == NULL);
-            if (!PyStackRef_IsNull(executor)) {
-                tstate->current_executor = PyStackRef_AsPyObjectBorrow(executor);
-                PyStackRef_CLOSE(executor);
-            }
+                _PyStackRef executor = frame->localsplus[0];
+                assert(tstate->current_executor == NULL);
+                if (!PyStackRef_IsNull(executor)) {
+                    tstate->current_executor = PyStackRef_AsPyObjectBorrow(executor);
+                    PyStackRef_CLOSE(executor);
+                }
 #endif
-            LLTRACE_RESUME_FRAME();
-            return result;
+                LLTRACE_RESUME_FRAME();
+                return result;
+            }
         }
 
         // The stack effect here is a bit misleading.
@@ -3020,15 +3036,6 @@ dummy_func(
 
         tier1 inst(ENTER_EXECUTOR, (--)) {
             #ifdef _Py_TIER2
-            // We want to end any current trace here, before we possibly need
-            // to start tracing new ones due to recursive traces in any inner C functions
-            // in tier2 code.
-            if (IS_JIT_TRACING()) {
-                _PyJit_translate_single_bytecode_to_trace(tstate, frame, next_instr);
-                LEAVE_TRACING();
-                int err = bail_tracing_and_jit(tstate, frame);
-                ERROR_IF(err < 0);
-            }
             PyCodeObject *code = _PyFrame_GetCode(frame);
             _PyExecutorObject *executor = code->co_executors->executors[oparg & 255];
             assert(executor->vm_data.index == INSTR_OFFSET() - 1);
@@ -3038,14 +3045,19 @@ dummy_func(
             /* If the eval breaker is set then stay in tier 1.
              * This avoids any potentially infinite loops
              * involving _RESUME_CHECK */
-            if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) {
+            if (IS_JIT_TRACING() || _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) {
                 opcode = executor->vm_data.opcode;
                 oparg = (oparg & ~255) | executor->vm_data.oparg;
                 next_instr = this_instr;
                 if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) {
                     PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter);
                 }
-                DISPATCH_GOTO();
+                if (IS_JIT_TRACING()) {
+                    DISPATCH_GOTO_NON_TRACING();
+                }
+                else {
+                    DISPATCH_GOTO();
+                }
             }
             assert(executor != tstate->interp->cold_executor);
             tstate->jit_exit = NULL;
index 76b09488c3b85495a3adc174bd091ebb05a4b7ef..f2dd8fc6e8d79265164693521b0427b753c248a1 100644 (file)
@@ -931,14 +931,39 @@ int _Py_CheckRecursiveCallPy(
     return 0;
 }
 
-static const _Py_CODEUNIT _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS[] = {
-    /* Put a NOP at the start, so that the IP points into
-    * the code, rather than before it */
-    { .op.code = NOP, .op.arg = 0 },
-    { .op.code = INTERPRETER_EXIT, .op.arg = 0 },  /* reached on return */
-    { .op.code = NOP, .op.arg = 0 },
-    { .op.code = INTERPRETER_EXIT, .op.arg = 0 },  /* reached on yield */
-    { .op.code = RESUME, .op.arg = RESUME_OPARG_DEPTH1_MASK | RESUME_AT_FUNC_START }
+
+#ifdef Py_GIL_DISABLED
+static _PyCodeArray emtry_cleanup_tlbc = {
+    .size = 1,
+    .entries = {(char*) &_PyEntryFrameCode.co_code_adaptive},
+};
+#endif
+
+const struct _PyCode12 _PyEntryFrameCode = {
+    _PyVarObject_HEAD_INIT(&PyCode_Type, 5),
+    .co_consts = (PyObject *)&_Py_SINGLETON(tuple_empty),
+    .co_names = (PyObject *)&_Py_SINGLETON(tuple_empty),
+    .co_exceptiontable = (PyObject *)&_Py_SINGLETON(bytes_empty),
+    .co_flags = CO_OPTIMIZED | CO_NO_MONITORING_EVENTS,
+    .co_localsplusnames = (PyObject *)&_Py_SINGLETON(tuple_empty),
+    .co_localspluskinds = (PyObject *)&_Py_SINGLETON(bytes_empty),
+    .co_filename = &_Py_ID(_PyEval_EvalFrameDefault),
+    .co_name = &_Py_ID(_PyEval_EvalFrameDefault),
+    .co_qualname = &_Py_ID(_PyEval_EvalFrameDefault),
+    .co_linetable = (PyObject *)&no_location,
+    ._co_firsttraceable = 4,
+    .co_stacksize = 2,
+    .co_framesize = 2 + FRAME_SPECIALS_SIZE,
+#ifdef Py_GIL_DISABLED
+    .co_tlbc = &emtry_cleanup_tlbc,
+#endif
+    .co_code_adaptive = {
+        NOP, 0,
+        INTERPRETER_EXIT, 0, /* reached on return */
+        NOP, 0,
+        INTERPRETER_EXIT, 0, /* reached on yield */
+        RESUME, RESUME_OPARG_DEPTH1_MASK | RESUME_AT_FUNC_START
+    }
 };
 
 #ifdef Py_DEBUG
@@ -1014,7 +1039,13 @@ bail_tracing_and_jit(PyThreadState *tstate, _PyInterpreterFrame *frame)
         // Likewise, we hold a strong reference to the executor containing this exit, so the exit is guaranteed
         // to be valid to access.
         if (err <= 0) {
-            exit->temperature = restart_backoff_counter(exit->temperature);
+            // Some opcodes will forever be unchanged. Don't ever bother specializing for them ever again.
+            if (tstate->interp->jit_state.prev_instr->op.code == INTERPRETER_EXIT) {
+                exit->temperature = initial_unreachable_backoff_counter();
+            }
+            else {
+                exit->temperature = restart_backoff_counter(exit->temperature);
+            }
         }
         else {
             exit->temperature = initial_temperature_backoff_counter();
@@ -1105,8 +1136,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
     entry.frame.f_globals = (PyObject*)0xaaa3;
     entry.frame.f_builtins = (PyObject*)0xaaa4;
 #endif
-    entry.frame.f_executable = PyStackRef_None;
-    entry.frame.instr_ptr = (_Py_CODEUNIT *)_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS + 1;
+    entry.frame.f_executable = PyStackRef_FromPyObjectBorrow((PyObject *)&_PyEntryFrameCode);
+    entry.frame.instr_ptr = ((_Py_CODEUNIT *)_PyEntryFrameCode.co_code_adaptive) + 1;
     entry.frame.stackpointer = entry.stack;
     entry.frame.owner = FRAME_OWNED_BY_INTERPRETER;
     entry.frame.visited = 0;
index c0dbf3091f45df1b39ef3bf07743a7e55ccf7b72..10a1793ad284cba8ab01f23fce48017a8d287350 100644 (file)
             INSTRUCTION_STATS(ENTER_EXECUTOR);
             opcode = ENTER_EXECUTOR;
             #ifdef _Py_TIER2
-
-            if (IS_JIT_TRACING()) {
-                _PyFrame_SetStackPointer(frame, stack_pointer);
-                _PyJit_translate_single_bytecode_to_trace(tstate, frame, next_instr);
-                stack_pointer = _PyFrame_GetStackPointer(frame);
-                LEAVE_TRACING();
-                _PyFrame_SetStackPointer(frame, stack_pointer);
-                int err = bail_tracing_and_jit(tstate, frame);
-                stack_pointer = _PyFrame_GetStackPointer(frame);
-                if (err < 0) {
-                    JUMP_TO_LABEL(error);
-                }
-            }
             PyCodeObject *code = _PyFrame_GetCode(frame);
             _PyExecutorObject *executor = code->co_executors->executors[oparg & 255];
             assert(executor->vm_data.index == INSTR_OFFSET() - 1);
             assert(executor->vm_data.code == code);
             assert(executor->vm_data.valid);
             assert(tstate->current_executor == NULL);
-            if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) {
+            if (IS_JIT_TRACING() || _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) {
                 opcode = executor->vm_data.opcode;
                 oparg = (oparg & ~255) | executor->vm_data.oparg;
                 next_instr = this_instr;
                 if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) {
                     PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter);
                 }
-                DISPATCH_GOTO();
+                if (IS_JIT_TRACING()) {
+                    DISPATCH_GOTO_NON_TRACING();
+                }
+                else {
+                    DISPATCH_GOTO();
+                }
             }
             assert(executor != tstate->interp->cold_executor);
             tstate->jit_exit = NULL;
             tstate->current_frame = frame->previous;
             assert(!_PyErr_Occurred(tstate));
             PyObject *result = PyStackRef_AsPyObjectSteal(retval);
-            #if !_Py_TAIL_CALL_INTERP
-            assert(frame == &entry.frame);
-            #endif
-            #ifdef _Py_TIER2
-            _PyStackRef executor = frame->localsplus[0];
-            assert(tstate->current_executor == NULL);
-            if (!PyStackRef_IsNull(executor)) {
-                tstate->current_executor = PyStackRef_AsPyObjectBorrow(executor);
+            if (IS_JIT_TRACING()) {
+                #if _Py_TIER2
                 stack_pointer += -1;
                 assert(WITHIN_STACK_BOUNDS());
                 _PyFrame_SetStackPointer(frame, stack_pointer);
-                PyStackRef_CLOSE(executor);
+                _PyJit_translate_single_bytecode_to_trace(tstate, frame, next_instr);
                 stack_pointer = _PyFrame_GetStackPointer(frame);
-                stack_pointer += 1;
+                LEAVE_TRACING();
+                _PyFrame_SetStackPointer(frame, stack_pointer);
+                int err = bail_tracing_and_jit(tstate, frame);
+                stack_pointer = _PyFrame_GetStackPointer(frame);
+                if (err < 0) {
+                    _PyFrame_SetStackPointer(frame, stack_pointer);
+                    Py_DECREF(result);
+                    stack_pointer = _PyFrame_GetStackPointer(frame);
+                    JUMP_TO_LABEL(error);
+                }
+                return result;
+                #endif
+            }
+            else {
+                #if !_Py_TAIL_CALL_INTERP
+                assert(frame == &entry.frame);
+                #endif
+                #ifdef _Py_TIER2
+                _PyStackRef executor = frame->localsplus[0];
+                assert(tstate->current_executor == NULL);
+                if (!PyStackRef_IsNull(executor)) {
+                    tstate->current_executor = PyStackRef_AsPyObjectBorrow(executor);
+                    stack_pointer += -1;
+                    assert(WITHIN_STACK_BOUNDS());
+                    _PyFrame_SetStackPointer(frame, stack_pointer);
+                    PyStackRef_CLOSE(executor);
+                    stack_pointer = _PyFrame_GetStackPointer(frame);
+                    stack_pointer += 1;
+                }
+                #endif
+                LLTRACE_RESUME_FRAME();
+                return result;
             }
-            #endif
-            LLTRACE_RESUME_FRAME();
-            return result;
         }
 
         TARGET(IS_OP) {
             // _QUICKEN_RESUME
             {
                 #if ENABLE_SPECIALIZATION_FT
-                if (tstate->tracing == 0 && this_instr->op.code == RESUME) {
+                PyCodeObject *code = _PyFrame_GetCode(frame);
+                if (tstate->tracing == 0 && this_instr->op.code == RESUME &&
+                    code != (PyCodeObject *)&_Py_InitCleanup && code != (PyCodeObject *)&_PyEntryFrameCode) {
                     FT_ATOMIC_STORE_UINT8_RELAXED(this_instr->op.code, RESUME_CHECK);
                 }
                 #endif  /* ENABLE_SPECIALIZATION_FT */
index 4a61509112ba0985d0ff59e181fdcfea0ffec42f..a3ae74fd944ae834e6341601054c5b60ed4d5356 100644 (file)
@@ -34,7 +34,7 @@
 static bool
 has_space_for_executor(PyCodeObject *code, _Py_CODEUNIT *instr)
 {
-    if (code == (PyCodeObject *)&_Py_InitCleanup) {
+    if (code == (PyCodeObject *)&_Py_InitCleanup || code == (PyCodeObject *)&_PyEntryFrameCode) {
         return false;
     }
     if (instr->op.code == ENTER_EXECUTOR) {
@@ -133,11 +133,6 @@ _PyOptimizer_Optimize(
     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;
-    // A recursive trace might've cleared the values. In that case, bail.
-    if (code == NULL) {
-        interp->compiling = false;
-        return 0;
-    }
     if (progress_needed && !has_space_for_executor(code, start)) {
         interp->compiling = false;
         return 0;
@@ -619,11 +614,6 @@ _PyJit_translate_single_bytecode_to_trace(
     }
 
     if (opcode == ENTER_EXECUTOR) {
-        int is_first_instr = tstate->interp->jit_state.close_loop_instr == next_instr || tstate->interp->jit_state.insert_exec_instr == next_instr;
-        if (is_first_instr && tstate->interp->jit_state.code_curr_size > 5) {
-            ADD_TO_TRACE(_JUMP_TO_TOP, 0, 0, 0);
-            goto done;
-        }
         goto full;
     }
 
@@ -658,11 +648,6 @@ _PyJit_translate_single_bytecode_to_trace(
 
     if (opcode == WITH_EXCEPT_START || opcode == RERAISE || opcode == CLEANUP_THROW || opcode == PUSH_EXC_INFO) {
         DPRINTF(2, "Unsupported: strange control-flow\n");
-        goto unsupported;
-    }
-
-    if (frame->owner >= FRAME_OWNED_BY_INTERPRETER) {
-        DPRINTF(2, "Unsupported: frame owned by interpreter\n");
         unsupported:
         {
             // Rewind to previous instruction and replace with _EXIT_TRACE.
@@ -977,7 +962,7 @@ _PyJit_TryInitializeTracing(PyThreadState *tstate, _PyInterpreterFrame *frame, _
     tstate->interp->jit_state.insert_exec_instr = insert_exec_instr;
     tstate->interp->jit_state.close_loop_instr = close_loop_instr;
     tstate->interp->jit_state.initial_code = (PyCodeObject *)Py_NewRef(code);
-    tstate->interp->jit_state.initial_func = (PyFunctionObject *)Py_NewRef(_PyFrame_GetFunction(frame));
+    tstate->interp->jit_state.initial_func = (PyFunctionObject *)Py_XNewRef(PyStackRef_AsPyObjectBorrow(frame->f_funcobj));
     tstate->interp->jit_state.prev_exit = exit;
     tstate->interp->jit_state.initial_stack_depth = curr_stackdepth;
     tstate->interp->jit_state.initial_chain_depth = chain_depth;
@@ -1580,11 +1565,15 @@ _Py_ExecutorDetach(_PyExecutorObject *executor)
         return;
     }
     _Py_CODEUNIT *instruction = &_PyCode_CODE(code)[executor->vm_data.index];
-    assert(instruction->op.code == ENTER_EXECUTOR);
     int index = instruction->op.arg;
-    assert(code->co_executors->executors[index] == executor);
-    instruction->op.code = executor->vm_data.opcode;
-    instruction->op.arg = executor->vm_data.oparg;
+    // Due to a combination of re-entrancy and tracing, it's possible for an
+    // instruction to no longer be ENTER_EXECUTOR. In which case, no-op.
+    if (instruction->op.code == ENTER_EXECUTOR) {
+        assert(instruction->op.code == ENTER_EXECUTOR);
+        assert(code->co_executors->executors[index] == executor);
+        instruction->op.code = executor->vm_data.opcode;
+        instruction->op.arg = executor->vm_data.oparg;
+    }
     executor->vm_data.code = NULL;
     code->co_executors->executors[index] = NULL;
     Py_DECREF(executor);
index a1c5dedd61563bea2a046897ea4a3085f2c82dc6..0583873e09d2be13091ad7f165b5b543f919bc38 100644 (file)
@@ -3196,12 +3196,6 @@ _Py_GatherStats_GetIter(_PyStackRef iterable)
  * be lifted.
  */
 
-#define NO_LOC_4 (128 | (PY_CODE_LOCATION_INFO_NONE << 3) | 3)
-
-static const PyBytesObject no_location = {
-    PyVarObject_HEAD_INIT(&PyBytes_Type, 1)
-    .ob_sval = { NO_LOC_4 }
-};
 
 #ifdef Py_GIL_DISABLED
 static _PyCodeArray init_cleanup_tlbc = {