Skip to content

Commit

Permalink
Fix tests, move entry_frame into frame
Browse files Browse the repository at this point in the history
  • Loading branch information
Fidget-Spinner committed Jan 10, 2025
1 parent a27ee2d commit 56c6349
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 70 deletions.
7 changes: 6 additions & 1 deletion Include/internal/pycore_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ typedef struct _PyInterpreterFrame {
_PyStackRef *stackpointer;
uint16_t return_offset; /* Only relevant during a function call */
char owner;
char visited;
char visited:4;
char is_entry_frame:4;
/* Locals and stack */
_PyStackRef localsplus[1];
} _PyInterpreterFrame;
Expand Down Expand Up @@ -214,6 +215,8 @@ _PyFrame_Initialize(
frame->localsplus[i] = PyStackRef_NULL;
}

frame->is_entry_frame = 0;

#ifdef Py_GIL_DISABLED
// On GIL disabled, we walk the entire stack in GC. Since stacktop
// is not always in sync with the real stack pointer, we have
Expand Down Expand Up @@ -394,6 +397,8 @@ _PyFrame_PushTrampolineUnchecked(PyThreadState *tstate, PyCodeObject *code, int
frame->visited = 0;
frame->return_offset = 0;

frame->is_entry_frame = 0;

#ifdef Py_GIL_DISABLED
assert(code->co_nlocalsplus == 0);
for (int i = 0; i < code->co_stacksize; i++) {
Expand Down
18 changes: 9 additions & 9 deletions Lib/test/test_generated_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ def test_error_if_plain(self):
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(OP);
if (cond) goto label;
if (cond) CEVAL_GOTO(label);
DISPATCH();
}
"""
Expand All @@ -555,7 +555,7 @@ def test_error_if_plain_with_comment(self):
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(OP);
if (cond) goto label;
if (cond) CEVAL_GOTO(label);
// Comment is ok
DISPATCH();
}
Expand All @@ -582,7 +582,7 @@ def test_error_if_pop(self):
right = stack_pointer[-1];
left = stack_pointer[-2];
SPAM(left, right);
if (cond) goto pop_2_label;
if (cond) CEVAL_GOTO(pop_2_label);
res = 0;
stack_pointer[-2] = res;
stack_pointer += -1;
Expand Down Expand Up @@ -611,7 +611,7 @@ def test_error_if_pop_with_result(self):
right = stack_pointer[-1];
left = stack_pointer[-2];
res = SPAM(left, right);
if (cond) goto pop_2_label;
if (cond) CEVAL_GOTO(pop_2_label);
stack_pointer[-2] = res;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
Expand Down Expand Up @@ -929,7 +929,7 @@ def test_array_error_if(self):
if (oparg == 0) {
stack_pointer += -1 - oparg;
assert(WITHIN_STACK_BOUNDS());
goto somewhere;
CEVAL_GOTO(somewhere);
}
stack_pointer += -1 - oparg;
assert(WITHIN_STACK_BOUNDS());
Expand Down Expand Up @@ -1392,7 +1392,7 @@ def test_pop_on_error_peeks(self):
// THIRD
{
// Mark j and k as used
if (cond) goto pop_2_error;
if (cond) CEVAL_GOTO(pop_2_error);
}
stack_pointer += -2;
assert(WITHIN_STACK_BOUNDS());
Expand Down Expand Up @@ -1435,7 +1435,7 @@ def test_push_then_error(self):
stack_pointer[1] = b;
stack_pointer += 2;
assert(WITHIN_STACK_BOUNDS());
goto error;
CEVAL_GOTO(error);
}
}
stack_pointer[0] = a;
Expand All @@ -1462,14 +1462,14 @@ def test_error_if_true(self):
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(OP1);
goto here;
CEVAL_GOTO(here);
}
TARGET(OP2) {
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(OP2);
goto there;
CEVAL_GOTO(there);
}
"""
self.run_cases_test(input, output)
Expand Down
9 changes: 4 additions & 5 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ dummy_func(
PyObject *codeobj;
PyObject *cond;
PyObject *descr;
_PyInterpreterFrame entry_frame;
PyObject *exc;
PyObject *exit;
PyObject *fget;
Expand Down Expand Up @@ -1018,7 +1017,7 @@ dummy_func(
}

tier1 inst(INTERPRETER_EXIT, (retval --)) {
assert(frame == entry_frame);
assert(frame->is_entry_frame);
assert(_PyFrame_IsIncomplete(frame));
/* Restore previous frame and return. */
tstate->current_frame = frame->previous;
Expand All @@ -1034,7 +1033,7 @@ dummy_func(
// is pushed to a different frame, the callers' frame.
inst(RETURN_VALUE, (retval -- res)) {
#if TIER_ONE
assert(frame != entry_frame);
assert(!frame->is_entry_frame);
#endif
_PyStackRef temp = retval;
DEAD(retval);
Expand Down Expand Up @@ -1133,7 +1132,7 @@ dummy_func(
PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver);

PyObject *retval_o;
assert(frame != entry_frame);
assert(!frame->is_entry_frame);
if ((tstate->interp->eval_frame == NULL) &&
(Py_TYPE(receiver_o) == &PyGen_Type || Py_TYPE(receiver_o) == &PyCoro_Type) &&
((PyGenObject *)receiver_o)->gi_frame_state < FRAME_EXECUTING)
Expand Down Expand Up @@ -1207,7 +1206,7 @@ dummy_func(
// The compiler treats any exception raised here as a failed close()
// or throw() call.
#if TIER_ONE
assert(frame != entry_frame);
assert(!frame->is_entry_frame);
#endif
frame->instr_ptr++;
PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame);
Expand Down
54 changes: 27 additions & 27 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,12 @@ lltrace_resume_frame(_PyInterpreterFrame *frame)
}

static int
maybe_lltrace_resume_frame(_PyInterpreterFrame *frame, _PyInterpreterFrame *skip_frame, PyObject *globals)
maybe_lltrace_resume_frame(_PyInterpreterFrame *frame, PyObject *globals)
{
if (globals == NULL) {
return 0;
}
if (frame == skip_frame) {
if (frame->is_entry_frame) {
return 0;
}
int r = PyDict_Contains(globals, &_Py_ID(__lltrace__));
Expand Down Expand Up @@ -787,9 +787,9 @@ static inline PyObject *_TAIL_CALL_shim(TAIL_CALL_PARAMS)
{
opcode = next_instr->op.code;
#ifdef LLTRACE
return (INSTRUCTION_TABLE[opcode])(frame, stack_pointer, tstate, next_instr, opcode, next_instr->op.arg, entry_frame, lltrace);
return (INSTRUCTION_TABLE[opcode])(frame, stack_pointer, tstate, next_instr, opcode, next_instr->op.arg, lltrace);
#else
return (INSTRUCTION_TABLE[opcode])(frame, stack_pointer, tstate, next_instr, opcode, next_instr->op.arg, entry_frame);
return (INSTRUCTION_TABLE[opcode])(frame, stack_pointer, tstate, next_instr, opcode, next_instr->op.arg);
#endif
}
#endif
Expand All @@ -816,28 +816,28 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
int lltrace = 0;
#endif

_PyInterpreterFrame entry_f;
_PyInterpreterFrame *entry_frame = &entry_f;
_PyInterpreterFrame entry_frame;



#if defined(Py_DEBUG) && !defined(Py_STACKREF_DEBUG)
/* Set these to invalid but identifiable values for debugging. */
entry_f.f_funcobj = (_PyStackRef){.bits = 0xaaa0};
entry_f.f_locals = (PyObject*)0xaaa1;
entry_f.frame_obj = (PyFrameObject*)0xaaa2;
entry_f.f_globals = (PyObject*)0xaaa3;
entry_f.f_builtins = (PyObject*)0xaaa4;
entry_frame.f_funcobj = (_PyStackRef){.bits = 0xaaa0};
entry_frame.f_locals = (PyObject*)0xaaa1;
entry_frame.frame_obj = (PyFrameObject*)0xaaa2;
entry_frame.f_globals = (PyObject*)0xaaa3;
entry_frame.f_builtins = (PyObject*)0xaaa4;
#endif
entry_f.f_executable = PyStackRef_None;
entry_f.instr_ptr = (_Py_CODEUNIT *)_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS + 1;
entry_f.stackpointer = entry_f.localsplus;
entry_f.owner = FRAME_OWNED_BY_CSTACK;
entry_f.visited = 0;
entry_f.return_offset = 0;
entry_frame.f_executable = PyStackRef_None;
entry_frame.instr_ptr = (_Py_CODEUNIT *)_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS + 1;
entry_frame.stackpointer = entry_frame.localsplus;
entry_frame.owner = FRAME_OWNED_BY_CSTACK;
entry_frame.visited = 0;
entry_frame.return_offset = 0;
/* Push frame */
entry_f.previous = tstate->current_frame;
frame->previous = entry_frame;
entry_frame.previous = tstate->current_frame;
entry_frame.is_entry_frame = 1;
frame->previous = &entry_frame;
tstate->current_frame = frame;

tstate->c_recursion_remaining -= (PY_EVAL_C_STACK_UNITS - 1);
Expand Down Expand Up @@ -894,7 +894,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
stack_pointer = _PyFrame_GetStackPointer(frame);

#ifdef LLTRACE
lltrace = maybe_lltrace_resume_frame(frame, entry_frame, GLOBALS());
lltrace = maybe_lltrace_resume_frame(frame, GLOBALS());
if (lltrace < 0) {
goto exit_unwind;
}
Expand All @@ -909,9 +909,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int

#ifdef Py_TAIL_CALL_INTERP
#ifdef LLTRACE
return _TAIL_CALL_shim(frame, stack_pointer, tstate, next_instr, 0, 0, entry_frame, lltrace);
return _TAIL_CALL_shim(frame, stack_pointer, tstate, next_instr, 0, 0, lltrace);
#else
return _TAIL_CALL_shim(frame, stack_pointer, tstate, next_instr, 0, 0, entry_frame);
return _TAIL_CALL_shim(frame, stack_pointer, tstate, next_instr, 0, 0);
#endif
#else
DISPATCH();
Expand Down Expand Up @@ -968,7 +968,7 @@ TAIL_CALL_TARGET(error):
#endif

/* Log traceback info. */
assert(frame != entry_frame);
assert(!frame->is_entry_frame);
if (!_PyFrame_IsIncomplete(frame)) {
PyFrameObject *f = _PyFrame_GetFrameObject(frame);
if (f != NULL) {
Expand Down Expand Up @@ -1033,9 +1033,9 @@ TAIL_CALL_TARGET(exception_unwind):
DISPATCH();
# else
# ifdef LLTRACE
return _TAIL_CALL_shim(frame, stack_pointer, tstate, next_instr, 0, 0, entry_frame, lltrace);
return _TAIL_CALL_shim(frame, stack_pointer, tstate, next_instr, 0, 0, lltrace);
# else
return _TAIL_CALL_shim(frame, stack_pointer, tstate, next_instr, 0, 0, entry_frame);
return _TAIL_CALL_shim(frame, stack_pointer, tstate, next_instr, 0, 0);
# endif
# endif
#else
Expand All @@ -1046,13 +1046,13 @@ TAIL_CALL_TARGET(exception_unwind):
TAIL_CALL_TARGET(exit_unwind):
assert(_PyErr_Occurred(tstate));
_Py_LeaveRecursiveCallPy(tstate);
assert(frame != entry_frame);
assert(!frame->is_entry_frame);
// GH-99729: We need to unlink the frame *before* clearing it:
_PyInterpreterFrame *dying = frame;
frame = tstate->current_frame = dying->previous;
_PyEval_FrameClearAndPop(tstate, dying);
frame->return_offset = 0;
if (frame == entry_frame) {
if (frame->is_entry_frame) {
/* Restore previous frame and exit */
tstate->current_frame = frame->previous;
tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
Expand Down
18 changes: 9 additions & 9 deletions Python/ceval_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,11 @@
#endif

#ifdef LLTRACE
# define TAIL_CALL_PARAMS _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate, _Py_CODEUNIT *next_instr, int opcode, int oparg, _PyInterpreterFrame *entry_frame, int lltrace
# define TAIL_CALL_ARGS frame, stack_pointer, tstate, next_instr, opcode, oparg, entry_frame, lltrace
# define TAIL_CALL_PARAMS _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate, _Py_CODEUNIT *next_instr, int opcode, int oparg, int lltrace
# define TAIL_CALL_ARGS frame, stack_pointer, tstate, next_instr, opcode, oparg, lltrace
#else
# define TAIL_CALL_PARAMS _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate, _Py_CODEUNIT *next_instr, int opcode, int oparg, _PyInterpreterFrame *entry_frame
# define TAIL_CALL_ARGS frame, stack_pointer, tstate, next_instr, opcode, oparg, entry_frame
# define TAIL_CALL_PARAMS _PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate, _Py_CODEUNIT *next_instr, int opcode, int oparg
# define TAIL_CALL_ARGS frame, stack_pointer, tstate, next_instr, opcode, oparg
#endif

#ifdef Py_TAIL_CALL_INTERP
Expand Down Expand Up @@ -116,7 +116,7 @@
#if LLTRACE
#define LLTRACE_RESUME_FRAME() \
do { \
lltrace = maybe_lltrace_resume_frame(frame, entry_frame, GLOBALS()); \
lltrace = maybe_lltrace_resume_frame(frame, GLOBALS()); \
if (lltrace < 0) { \
CEVAL_GOTO(exit_unwind); \
} \
Expand Down Expand Up @@ -162,7 +162,7 @@ do { \
} \
next_instr = frame->instr_ptr; \
stack_pointer = _PyFrame_GetStackPointer(frame); \
lltrace = maybe_lltrace_resume_frame(frame, entry_frame, GLOBALS()); \
lltrace = maybe_lltrace_resume_frame(frame, GLOBALS()); \
if (lltrace < 0) { \
CEVAL_GOTO(exit_unwind); \
} \
Expand Down Expand Up @@ -307,7 +307,7 @@ GETITEM(PyObject *v, Py_ssize_t i) {
#endif

#define WITHIN_STACK_BOUNDS() \
(frame == entry_frame || (STACK_LEVEL() >= 0 && STACK_LEVEL() <= STACK_SIZE()))
(frame->is_entry_frame || (STACK_LEVEL() >= 0 && STACK_LEVEL() <= STACK_SIZE()))

/* Data access macros */
#define FRAME_CO_CONSTS (_PyFrame_GetCode(frame)->co_consts)
Expand All @@ -331,12 +331,12 @@ GETITEM(PyObject *v, Py_ssize_t i) {
#ifdef LLTRACE
#define GO_TO_INSTRUCTION(op) do { \
Py_MUSTTAIL \
return (INSTRUCTION_TABLE[op])(frame, stack_pointer, tstate, next_instr - 1 - _PyOpcode_Caches[_PyOpcode_Deopt[op]], opcode, oparg, entry_frame, lltrace); \
return (INSTRUCTION_TABLE[op])(frame, stack_pointer, tstate, next_instr - 1 - _PyOpcode_Caches[_PyOpcode_Deopt[op]], opcode, oparg, lltrace); \
} while (0)
#else
#define GO_TO_INSTRUCTION(op) do { \
Py_MUSTTAIL \
return (INSTRUCTION_TABLE[op])(frame, stack_pointer, tstate, next_instr - 1 - _PyOpcode_Caches[_PyOpcode_Deopt[op]], opcode, oparg, entry_frame); \
return (INSTRUCTION_TABLE[op])(frame, stack_pointer, tstate, next_instr - 1 - _PyOpcode_Caches[_PyOpcode_Deopt[op]], opcode, oparg); \
} while (0)
#endif
#else
Expand Down
4 changes: 2 additions & 2 deletions Python/executor_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 56c6349

Please sign in to comment.