Skip to content

Commit 80b3c36

Browse files
committed
Reduce entry points to interpreter loop down to two.
1 parent b57948e commit 80b3c36

File tree

3 files changed

+75
-32
lines changed

3 files changed

+75
-32
lines changed

Python/bytecodes.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5308,6 +5308,35 @@ dummy_func(
53085308
goto error;
53095309
}
53105310

5311+
label(start_frame) {
5312+
if (_Py_EnterRecursivePy(tstate)) {
5313+
goto exit_unwind;
5314+
}
5315+
next_instr = frame->instr_ptr;
5316+
stack_pointer = _PyFrame_GetStackPointer(frame);
5317+
5318+
#ifdef LLTRACE
5319+
{
5320+
int lltrace = maybe_lltrace_resume_frame(frame, GLOBALS());
5321+
frame->lltrace = lltrace;
5322+
if (lltrace < 0) {
5323+
goto exit_unwind;
5324+
}
5325+
}
5326+
#endif
5327+
5328+
#ifdef Py_DEBUG
5329+
/* _PyEval_EvalFrameDefault() must not be called with an exception set,
5330+
because it can clear it (directly or indirectly) and so the
5331+
caller loses its exception */
5332+
assert(!_PyErr_Occurred(tstate));
5333+
#endif
5334+
5335+
DISPATCH();
5336+
}
5337+
5338+
5339+
53115340
// END BYTECODES //
53125341

53135342
}

Python/ceval.c

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -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__)

Python/generated_cases.c.h

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)