Skip to content

GH-128563: Add new frame owner type for interpreter entry frames #129078

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Include/internal/pycore_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ enum _frameowner {
FRAME_OWNED_BY_THREAD = 0,
FRAME_OWNED_BY_GENERATOR = 1,
FRAME_OWNED_BY_FRAME_OBJECT = 2,
FRAME_OWNED_BY_CSTACK = 3,
FRAME_OWNED_BY_INTERPRETER = 3,
FRAME_OWNED_BY_CSTACK = 4,
};

typedef struct _PyInterpreterFrame {
Expand Down Expand Up @@ -264,7 +265,7 @@ _PyFrame_SetStackPointer(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer)
static inline bool
_PyFrame_IsIncomplete(_PyInterpreterFrame *frame)
{
if (frame->owner == FRAME_OWNED_BY_CSTACK) {
if (frame->owner >= FRAME_OWNED_BY_INTERPRETER) {
return true;
}
return frame->owner != FRAME_OWNED_BY_GENERATOR &&
Expand Down
2 changes: 1 addition & 1 deletion Modules/_testexternalinspection.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ parse_frame_object(
return -1;
}

if (owner == FRAME_OWNED_BY_CSTACK) {
if (owner >= FRAME_OWNED_BY_INTERPRETER) {
return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion Objects/frameobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -2142,7 +2142,7 @@ _PyFrame_IsEntryFrame(PyFrameObject *frame)
assert(frame != NULL);
_PyInterpreterFrame *f = frame->f_frame;
assert(!_PyFrame_IsIncomplete(f));
return f->previous && f->previous->owner == FRAME_OWNED_BY_CSTACK;
return f->previous && f->previous->owner == FRAME_OWNED_BY_INTERPRETER;
}

PyCodeObject *
Expand Down
12 changes: 4 additions & 8 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ dummy_func(
}

tier1 inst(INTERPRETER_EXIT, (retval --)) {
assert(frame == &entry_frame);
assert(frame->owner == FRAME_OWNED_BY_INTERPRETER);
assert(_PyFrame_IsIncomplete(frame));
/* Restore previous frame and return. */
tstate->current_frame = frame->previous;
Expand All @@ -1105,9 +1105,7 @@ dummy_func(
// retval is popped from the stack, but res
// is pushed to a different frame, the callers' frame.
inst(RETURN_VALUE, (retval -- res)) {
#if TIER_ONE
assert(frame != &entry_frame);
#endif
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
_PyStackRef temp = retval;
DEAD(retval);
SAVE_STACK();
Expand Down Expand Up @@ -1205,7 +1203,7 @@ dummy_func(
PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver);

PyObject *retval_o;
assert(frame != &entry_frame);
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
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 @@ -1278,9 +1276,7 @@ dummy_func(
// NOTE: It's important that YIELD_VALUE never raises an exception!
// The compiler treats any exception raised here as a failed close()
// or throw() call.
#if TIER_ONE
assert(frame != &entry_frame);
#endif
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
frame->instr_ptr++;
PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame);
assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1);
Expand Down
10 changes: 5 additions & 5 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ lltrace_instruction(_PyInterpreterFrame *frame,
int opcode,
int oparg)
{
if (frame->owner == FRAME_OWNED_BY_CSTACK) {
if (frame->owner >= FRAME_OWNED_BY_INTERPRETER) {
return;
}
dump_stack(frame, stack_pointer);
Expand Down 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->owner >= FRAME_OWNED_BY_INTERPRETER) {
return 0;
}
int r = PyDict_Contains(globals, &_Py_ID(__lltrace__));
Expand Down Expand Up @@ -818,7 +818,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
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.owner = FRAME_OWNED_BY_INTERPRETER;
entry_frame.visited = 0;
entry_frame.return_offset = 0;
/* Push frame */
Expand Down Expand Up @@ -880,7 +880,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 Down
4 changes: 2 additions & 2 deletions Python/ceval_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,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) { \
goto exit_unwind; \
} \
Expand Down Expand Up @@ -238,7 +238,7 @@ GETITEM(PyObject *v, Py_ssize_t i) {
#endif

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

/* Data access macros */
#define FRAME_CO_CONSTS (_PyFrame_GetCode(frame)->co_consts)
Expand Down
8 changes: 2 additions & 6 deletions Python/executor_cases.c.h

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

4 changes: 2 additions & 2 deletions Python/frame.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame)
static void
take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame)
{
assert(frame->owner != FRAME_OWNED_BY_CSTACK);
assert(frame->owner < FRAME_OWNED_BY_INTERPRETER);
assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT);
Py_ssize_t size = ((char*)frame->stackpointer) - (char *)frame;
memcpy((_PyInterpreterFrame *)f->_f_frame_data, frame, size);
Expand All @@ -69,7 +69,7 @@ take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame)
_PyInterpreterFrame *prev = _PyFrame_GetFirstComplete(frame->previous);
frame->previous = NULL;
if (prev) {
assert(prev->owner != FRAME_OWNED_BY_CSTACK);
assert(prev->owner < FRAME_OWNED_BY_INTERPRETER);
/* Link PyFrameObjects.f_back and remove link through _PyInterpreterFrame.previous */
PyFrameObject *back = _PyFrame_GetFrameObject(prev);
if (back == NULL) {
Expand Down
2 changes: 1 addition & 1 deletion Python/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1476,7 +1476,7 @@ mark_stacks(PyInterpreterState *interp, PyGC_Head *visited, int visited_space, b
while (ts) {
_PyInterpreterFrame *frame = ts->current_frame;
while (frame) {
if (frame->owner == FRAME_OWNED_BY_CSTACK) {
if (frame->owner >= FRAME_OWNED_BY_INTERPRETER) {
frame = frame->previous;
continue;
}
Expand Down
20 changes: 6 additions & 14 deletions Python/generated_cases.c.h

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

2 changes: 1 addition & 1 deletion Python/instrumentation.c
Original file line number Diff line number Diff line change
Expand Up @@ -1898,7 +1898,7 @@ instrument_all_executing_code_objects(PyInterpreterState *interp) {
while (ts) {
_PyInterpreterFrame *frame = ts->current_frame;
while (frame) {
if (frame->owner != FRAME_OWNED_BY_CSTACK) {
if (frame->owner < FRAME_OWNED_BY_INTERPRETER) {
if (instrument_lock_held(_PyFrame_GetCode(frame), interp)) {
return -1;
}
Expand Down
6 changes: 3 additions & 3 deletions Python/traceback.c
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,7 @@ _Py_DumpASCII(int fd, PyObject *text)
static void
dump_frame(int fd, _PyInterpreterFrame *frame)
{
assert(frame->owner != FRAME_OWNED_BY_CSTACK);
assert(frame->owner < FRAME_OWNED_BY_INTERPRETER);

PyCodeObject *code =_PyFrame_GetCode(frame);
PUTS(fd, " File ");
Expand Down Expand Up @@ -965,15 +965,15 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header)

unsigned int depth = 0;
while (1) {
if (frame->owner == FRAME_OWNED_BY_CSTACK) {
if (frame->owner == FRAME_OWNED_BY_INTERPRETER) {
/* Trampoline frame */
frame = frame->previous;
if (frame == NULL) {
break;
}

/* Can't have more than one shim frame in a row */
assert(frame->owner != FRAME_OWNED_BY_CSTACK);
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
}

if (MAX_FRAME_DEPTH <= depth) {
Expand Down
4 changes: 2 additions & 2 deletions Tools/gdb/libpython.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def interp_frame_has_tlbc_index():
Py_TPFLAGS_TYPE_SUBCLASS = (1 << 31)

#From pycore_frame.h
FRAME_OWNED_BY_CSTACK = 3
FRAME_OWNED_BY_INTERPRETER = 3

MAX_OUTPUT_LEN=1024

Expand Down Expand Up @@ -1113,7 +1113,7 @@ def _f_lasti(self):
return int(instr_ptr - first_instr)

def is_shim(self):
return self._f_special("owner", int) == FRAME_OWNED_BY_CSTACK
return self._f_special("owner", int) == FRAME_OWNED_BY_INTERPRETER

def previous(self):
return self._f_special("previous", PyFramePtr)
Expand Down
Loading