@@ -824,27 +824,26 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
824824 /* support for generator.throw() */
825825 if (throwflag ) {
826826 if (_Py_EnterRecursivePy (tstate )) {
827- goto exit_unwind ;
827+ goto early_exit ;
828828 }
829- /* Because this avoids the RESUME,
830- * we need to update instrumentation */
831829#ifdef Py_GIL_DISABLED
832830 /* Load thread-local bytecode */
833831 if (frame -> tlbc_index != ((_PyThreadStateImpl * )tstate )-> tlbc_index ) {
834832 _Py_CODEUNIT * bytecode =
835833 _PyEval_GetExecutableCode (tstate , _PyFrame_GetCode (frame ));
836834 if (bytecode == NULL ) {
837- goto exit_unwind ;
835+ goto early_exit ;
838836 }
839837 ptrdiff_t off = frame -> instr_ptr - _PyFrame_GetBytecode (frame );
840838 frame -> tlbc_index = ((_PyThreadStateImpl * )tstate )-> tlbc_index ;
841839 frame -> instr_ptr = bytecode + off ;
842840 }
843841#endif
842+ /* Because this avoids the RESUME, we need to update instrumentation */
844843 _Py_Instrument (_PyFrame_GetCode (frame ), tstate -> interp );
845- monitor_throw (tstate , frame , frame -> instr_ptr );
846844 next_instr = frame -> instr_ptr ;
847845 stack_pointer = _PyFrame_GetStackPointer (frame );
846+ monitor_throw (tstate , frame , next_instr );
848847 goto error ;
849848 }
850849
@@ -854,33 +853,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
854853 const _PyUOpInstruction * next_uop = NULL ;
855854#endif
856855
857- start_frame :
858- if (_Py_EnterRecursivePy (tstate )) {
859- goto exit_unwind ;
860- }
861-
862- next_instr = frame -> instr_ptr ;
863- resume_frame :
864- stack_pointer = _PyFrame_GetStackPointer (frame );
865-
866- #ifdef LLTRACE
867- {
868- int lltrace = maybe_lltrace_resume_frame (frame , GLOBALS ());
869- frame -> lltrace = lltrace ;
870- if (lltrace < 0 ) {
871- goto exit_unwind ;
872- }
873- }
874- #endif
875-
876- #ifdef Py_DEBUG
877- /* _PyEval_EvalFrameDefault() must not be called with an exception set,
878- because it can clear it (directly or indirectly) and so the
879- caller loses its exception */
880- assert (!_PyErr_Occurred (tstate ));
881- #endif
882-
883- DISPATCH ();
856+ goto start_frame ;
884857
885858#include "generated_cases.c.h"
886859
@@ -1019,6 +992,20 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
1019992
1020993#endif // _Py_TIER2
1021994
995+ early_exit :
996+ assert (_PyErr_Occurred (tstate ));
997+ _Py_LeaveRecursiveCallPy (tstate );
998+ assert (frame -> owner != FRAME_OWNED_BY_INTERPRETER );
999+ // GH-99729: We need to unlink the frame *before* clearing it:
1000+ _PyInterpreterFrame * dying = frame ;
1001+ frame = tstate -> current_frame = dying -> previous ;
1002+ _PyEval_FrameClearAndPop (tstate , dying );
1003+ frame -> return_offset = 0 ;
1004+ assert (frame -> owner == FRAME_OWNED_BY_INTERPRETER );
1005+ /* Restore previous frame and exit */
1006+ tstate -> current_frame = frame -> previous ;
1007+ tstate -> c_recursion_remaining += PY_EVAL_C_STACK_UNITS ;
1008+ return NULL ;
10221009}
10231010
10241011#if defined(__GNUC__ )
0 commit comments