@@ -792,6 +792,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
792
792
return NULL ;
793
793
}
794
794
795
+ /* Local "register" variables.
796
+ * These are cached values from the frame and code object. */
797
+ _Py_CODEUNIT * next_instr ;
798
+ _PyStackRef * stack_pointer ;
799
+
795
800
#if defined(Py_DEBUG ) && !defined(Py_STACKREF_DEBUG )
796
801
/* Set these to invalid but identifiable values for debugging. */
797
802
entry_frame .f_funcobj = (_PyStackRef ){.bits = 0xaaa0 };
@@ -819,67 +824,36 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
819
824
/* support for generator.throw() */
820
825
if (throwflag ) {
821
826
if (_Py_EnterRecursivePy (tstate )) {
822
- goto exit_unwind ;
827
+ goto early_exit ;
823
828
}
824
- /* Because this avoids the RESUME,
825
- * we need to update instrumentation */
826
829
#ifdef Py_GIL_DISABLED
827
830
/* Load thread-local bytecode */
828
831
if (frame -> tlbc_index != ((_PyThreadStateImpl * )tstate )-> tlbc_index ) {
829
832
_Py_CODEUNIT * bytecode =
830
833
_PyEval_GetExecutableCode (tstate , _PyFrame_GetCode (frame ));
831
834
if (bytecode == NULL ) {
832
- goto exit_unwind ;
835
+ goto early_exit ;
833
836
}
834
837
ptrdiff_t off = frame -> instr_ptr - _PyFrame_GetBytecode (frame );
835
838
frame -> tlbc_index = ((_PyThreadStateImpl * )tstate )-> tlbc_index ;
836
839
frame -> instr_ptr = bytecode + off ;
837
840
}
838
841
#endif
842
+ /* Because this avoids the RESUME, we need to update instrumentation */
839
843
_Py_Instrument (_PyFrame_GetCode (frame ), tstate -> interp );
840
- monitor_throw (tstate , frame , frame -> instr_ptr );
841
- /* TO DO -- Monitor throw entry. */
842
- goto resume_with_error ;
844
+ next_instr = frame -> instr_ptr ;
845
+ stack_pointer = _PyFrame_GetStackPointer (frame );
846
+ monitor_throw (tstate , frame , next_instr );
847
+ goto error ;
843
848
}
844
849
845
- /* Local "register" variables.
846
- * These are cached values from the frame and code object. */
847
- _Py_CODEUNIT * next_instr ;
848
- _PyStackRef * stack_pointer ;
849
-
850
850
#if defined(_Py_TIER2 ) && !defined(_Py_JIT )
851
851
/* Tier 2 interpreter state */
852
852
_PyExecutorObject * current_executor = NULL ;
853
853
const _PyUOpInstruction * next_uop = NULL ;
854
854
#endif
855
855
856
- start_frame :
857
- if (_Py_EnterRecursivePy (tstate )) {
858
- goto exit_unwind ;
859
- }
860
-
861
- next_instr = frame -> instr_ptr ;
862
- resume_frame :
863
- stack_pointer = _PyFrame_GetStackPointer (frame );
864
-
865
- #ifdef LLTRACE
866
- {
867
- int lltrace = maybe_lltrace_resume_frame (frame , GLOBALS ());
868
- frame -> lltrace = lltrace ;
869
- if (lltrace < 0 ) {
870
- goto exit_unwind ;
871
- }
872
- }
873
- #endif
874
-
875
- #ifdef Py_DEBUG
876
- /* _PyEval_EvalFrameDefault() must not be called with an exception set,
877
- because it can clear it (directly or indirectly) and so the
878
- caller loses its exception */
879
- assert (!_PyErr_Occurred (tstate ));
880
- #endif
881
-
882
- DISPATCH ();
856
+ goto start_frame ;
883
857
884
858
#include "generated_cases.c.h"
885
859
@@ -983,10 +957,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
983
957
OPT_HIST (trace_uop_execution_counter , trace_run_length_hist );
984
958
assert (next_uop [-1 ].format == UOP_FORMAT_TARGET );
985
959
frame -> return_offset = 0 ; // Don't leave this random
986
- _PyFrame_SetStackPointer (frame , stack_pointer );
987
960
Py_DECREF (current_executor );
988
961
tstate -> previous_executor = NULL ;
989
- goto resume_with_error ;
962
+ next_instr = frame -> instr_ptr ;
963
+ goto error ;
990
964
991
965
jump_to_jump_target :
992
966
assert (next_uop [-1 ].format == UOP_FORMAT_JUMP );
@@ -1018,6 +992,20 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
1018
992
1019
993
#endif // _Py_TIER2
1020
994
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 ;
1021
1009
}
1022
1010
1023
1011
#if defined(__GNUC__ )
0 commit comments