8000 GH-128563: Move some labels, to simplify implementing tailcalling int… · srinivasreddy/cpython@fea9de8 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit fea9de8

Browse files
markshannonsrinivasreddy
authored andcommitted
pythonGH-128563: Move some labels, to simplify implementing tailcalling interpreter. (pythonGH-129525)
1 parent 6a8d880 commit fea9de8

File tree

5 files changed

+86
-51
lines changed

5 files changed

+86
-51
lines changed

Python/bytecodes.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5303,14 +5303,40 @@ dummy_func(
53035303
tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
53045304
return NULL;
53055305
}
5306-
goto resume_with_error;
5306+
next_instr = frame->instr_ptr;
5307+
stack_pointer = _PyFrame_GetStackPointer(frame);
5308+
goto error;
53075309
}
53085310

5309-
label(resume_with_error) {
5311+
label(start_frame) {
5312+
if (_Py_EnterRecursivePy(tstate)) {
5313+
goto exit_unwind;
5314+
}
53105315
next_instr = frame->instr_ptr;
53115316
stack_pointer = _PyFrame_GetStackPointer(frame);
5312-
goto error;
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();
53135336
}
5337+
5338+
5339+
53145340
// END BYTECODES //
53155341

53165342
}
@@ -5320,7 +5346,6 @@ dummy_func(
53205346
exit_unwind:
53215347
handle_eval_breaker:
53225348
resume_frame:
5323-
resume_with_error:
53245349
start_frame:
53255350
unbound_local_error:
53265351
;

Python/ceval.c

Lines changed: 29 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
792792
return NULL;
793793
}
794794

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+
795800
#if defined(Py_DEBUG) && !defined(Py_STACKREF_DEBUG)
796801
/* Set these to invalid but identifiable values for debugging. */
797802
entry_frame.f_funcobj = (_PyStackRef){.bits = 0xaaa0};
@@ -819,67 +824,36 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
819824
/* support for generator.throw() */
820825
if (throwflag) {
821826
if (_Py_EnterRecursivePy(tstate)) {
822-
goto exit_unwind;
827+
goto early_exit;
823828
}
824-
/* Because this avoids the RESUME,
825-
* we need to update instrumentation */
826829
#ifdef Py_GIL_DISABLED
827830
/* Load thread-local bytecode */
828831
if (frame->tlbc_index != ((_PyThreadStateImpl *)tstate)->tlbc_index) {
829832
_Py_CODEUNIT *bytecode =
830833
_PyEval_GetExecutableCode(tstate, _PyFrame_GetCode(frame));
831834
if (bytecode == NULL) {
832-
goto exit_unwind;
835+
goto early_exit;
833836
}
834837
ptrdiff_t off = frame->instr_ptr - _PyFrame_GetBytecode(frame);
835838
frame->tlbc_index = ((_PyThreadStateImpl *)tstate)->tlbc_index;
836839
frame->instr_ptr = bytecode + off;
837840
}
838841
#endif
842+
/* Because this avoids the RESUME, we need to update instrumentation */
839843
_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;
843848
}
844849

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-
850850
#if defined(_Py_TIER2) && !defined(_Py_JIT)
851851
/* Tier 2 interpreter state */
852852
_PyExecutorObject *current_executor = NULL;
853853
const _PyUOpInstruction *next_uop = NULL;
854854
#endif
855855

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;
883857

884858
#include "generated_cases.c.h"
885859

@@ -983,10 +957,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
983957
OPT_HIST(trace_uop_execution_counter, trace_run_length_hist);
984958
assert(next_uop[-1].format == UOP_FORMAT_TARGET);
985959
frame->return_offset = 0; // Don't leave this random
986-
_PyFrame_SetStackPointer(frame, stack_pointer);
987960
Py_DECREF(current_executor);
988961
tstate->previous_executor = NULL;
989-
goto resume_with_error;
962+
next_instr = frame->instr_ptr;
963+
goto error;
990964

991965
jump_to_jump_target:
992966
assert(next_uop[-1].format == UOP_FORMAT_JUMP);
@@ -1018,6 +992,20 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
1018992

1019993
#endif // _Py_TIER2
1020994

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;
10211009
}
10221010

10231011
#if defined(__GNUC__)

Python/ceval_macros.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,9 @@ do { \
381381
tstate->previous_executor = NULL; \
382382
frame = tstate->current_frame; \
383383
if (next_instr == NULL) { \
384-
goto resume_with_error; \
384+
next_instr = frame->instr_ptr; \
385+
stack_pointer = _PyFrame_GetStackPointer(frame); \
386+
goto error; \
385387
} \
386388
stack_pointer = _PyFrame_GetStackPointer(frame); \
387389
DISPATCH(); \

Python/generated_cases.c.h

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

Tools/cases_generator/analyzer.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,6 @@ def has_error_with_pop(op: parser.InstDef) -> bool:
511511
variable_used(op, "ERROR_IF")
512512
or variable_used(op, "pop_1_error")
513513
or variable_used(op, "exception_unwind")
514-
or variable_used(op, "resume_with_error")
515514
)
516515

517516

@@ -520,7 +519,6 @@ def has_error_without_pop(op: parser.InstDef) -> bool:
520519
variable_used(op, "ERROR_NO_POP")
521520
or variable_used(op, "pop_1_error")
522521
or variable_used(op, "exception_unwind")
523-
or variable_used(op, "resume_with_error")
524522
)
525523

526524

0 commit comments

Comments
 (0)
0