mirror of
https://github.com/python/cpython.git
synced 2025-09-18 14:40:43 +00:00
GH-128563: Add new frame owner type for interpreter entry frames (GH-129078)
Add new frame owner type for interpreter entry frames
This commit is contained in:
parent
d3b1bb228c
commit
f5b6356a11
13 changed files with 33 additions and 48 deletions
|
@ -56,7 +56,8 @@ enum _frameowner {
|
||||||
FRAME_OWNED_BY_THREAD = 0,
|
FRAME_OWNED_BY_THREAD = 0,
|
||||||
FRAME_OWNED_BY_GENERATOR = 1,
|
FRAME_OWNED_BY_GENERATOR = 1,
|
||||||
FRAME_OWNED_BY_FRAME_OBJECT = 2,
|
FRAME_OWNED_BY_FRAME_OBJECT = 2,
|
||||||
FRAME_OWNED_BY_CSTACK = 3,
|
FRAME_OWNED_BY_INTERPRETER = 3,
|
||||||
|
FRAME_OWNED_BY_CSTACK = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _PyInterpreterFrame {
|
typedef struct _PyInterpreterFrame {
|
||||||
|
@ -264,7 +265,7 @@ _PyFrame_SetStackPointer(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer)
|
||||||
static inline bool
|
static inline bool
|
||||||
_PyFrame_IsIncomplete(_PyInterpreterFrame *frame)
|
_PyFrame_IsIncomplete(_PyInterpreterFrame *frame)
|
||||||
{
|
{
|
||||||
if (frame->owner == FRAME_OWNED_BY_CSTACK) {
|
if (frame->owner >= FRAME_OWNED_BY_INTERPRETER) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return frame->owner != FRAME_OWNED_BY_GENERATOR &&
|
return frame->owner != FRAME_OWNED_BY_GENERATOR &&
|
||||||
|
|
|
@ -508,7 +508,7 @@ parse_frame_object(
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (owner == FRAME_OWNED_BY_CSTACK) {
|
if (owner >= FRAME_OWNED_BY_INTERPRETER) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2133,7 +2133,7 @@ _PyFrame_IsEntryFrame(PyFrameObject *frame)
|
||||||
assert(frame != NULL);
|
assert(frame != NULL);
|
||||||
_PyInterpreterFrame *f = frame->f_frame;
|
_PyInterpreterFrame *f = frame->f_frame;
|
||||||
assert(!_PyFrame_IsIncomplete(f));
|
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 *
|
PyCodeObject *
|
||||||
|
|
|
@ -1090,7 +1090,7 @@ dummy_func(
|
||||||
}
|
}
|
||||||
|
|
||||||
tier1 inst(INTERPRETER_EXIT, (retval --)) {
|
tier1 inst(INTERPRETER_EXIT, (retval --)) {
|
||||||
assert(frame == &entry_frame);
|
assert(frame->owner == FRAME_OWNED_BY_INTERPRETER);
|
||||||
assert(_PyFrame_IsIncomplete(frame));
|
assert(_PyFrame_IsIncomplete(frame));
|
||||||
/* Restore previous frame and return. */
|
/* Restore previous frame and return. */
|
||||||
tstate->current_frame = frame->previous;
|
tstate->current_frame = frame->previous;
|
||||||
|
@ -1105,9 +1105,7 @@ dummy_func(
|
||||||
// retval is popped from the stack, but res
|
// retval is popped from the stack, but res
|
||||||
// is pushed to a different frame, the callers' frame.
|
// is pushed to a different frame, the callers' frame.
|
||||||
inst(RETURN_VALUE, (retval -- res)) {
|
inst(RETURN_VALUE, (retval -- res)) {
|
||||||
#if TIER_ONE
|
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
|
||||||
assert(frame != &entry_frame);
|
|
||||||
#endif
|
|
||||||
_PyStackRef temp = retval;
|
_PyStackRef temp = retval;
|
||||||
DEAD(retval);
|
DEAD(retval);
|
||||||
SAVE_STACK();
|
SAVE_STACK();
|
||||||
|
@ -1205,7 +1203,7 @@ dummy_func(
|
||||||
PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver);
|
PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver);
|
||||||
|
|
||||||
PyObject *retval_o;
|
PyObject *retval_o;
|
||||||
assert(frame != &entry_frame);
|
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
|
||||||
if ((tstate->interp->eval_frame == NULL) &&
|
if ((tstate->interp->eval_frame == NULL) &&
|
||||||
(Py_TYPE(receiver_o) == &PyGen_Type || Py_TYPE(receiver_o) == &PyCoro_Type) &&
|
(Py_TYPE(receiver_o) == &PyGen_Type || Py_TYPE(receiver_o) == &PyCoro_Type) &&
|
||||||
((PyGenObject *)receiver_o)->gi_frame_state < FRAME_EXECUTING)
|
((PyGenObject *)receiver_o)->gi_frame_state < FRAME_EXECUTING)
|
||||||
|
@ -1278,9 +1276,7 @@ dummy_func(
|
||||||
// NOTE: It's important that YIELD_VALUE never raises an exception!
|
// NOTE: It's important that YIELD_VALUE never raises an exception!
|
||||||
// The compiler treats any exception raised here as a failed close()
|
// The compiler treats any exception raised here as a failed close()
|
||||||
// or throw() call.
|
// or throw() call.
|
||||||
#if TIER_ONE
|
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
|
||||||
assert(frame != &entry_frame);
|
|
||||||
#endif
|
|
||||||
frame->instr_ptr++;
|
frame->instr_ptr++;
|
||||||
PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame);
|
PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame);
|
||||||
assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1);
|
assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1);
|
||||||
|
|
|
@ -178,7 +178,7 @@ lltrace_instruction(_PyInterpreterFrame *frame,
|
||||||
int opcode,
|
int opcode,
|
||||||
int oparg)
|
int oparg)
|
||||||
{
|
{
|
||||||
if (frame->owner == FRAME_OWNED_BY_CSTACK) {
|
if (frame->owner >= FRAME_OWNED_BY_INTERPRETER) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dump_stack(frame, stack_pointer);
|
dump_stack(frame, stack_pointer);
|
||||||
|
@ -229,12 +229,12 @@ lltrace_resume_frame(_PyInterpreterFrame *frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
maybe_lltrace_resume_frame(_PyInterpreterFrame *frame, _PyInterpreterFrame *skip_frame, PyObject *globals)
|
maybe_lltrace_resume_frame(_PyInterpreterFrame *frame, PyObject *globals)
|
||||||
{
|
{
|
||||||
if (globals == NULL) {
|
if (globals == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (frame == skip_frame) {
|
if (frame->owner >= FRAME_OWNED_BY_INTERPRETER) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int r = PyDict_Contains(globals, &_Py_ID(__lltrace__));
|
int r = PyDict_Contains(globals, &_Py_ID(__lltrace__));
|
||||||
|
@ -818,7 +818,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
|
||||||
entry_frame.f_executable = PyStackRef_None;
|
entry_frame.f_executable = PyStackRef_None;
|
||||||
entry_frame.instr_ptr = (_Py_CODEUNIT *)_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS + 1;
|
entry_frame.instr_ptr = (_Py_CODEUNIT *)_Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS + 1;
|
||||||
entry_frame.stackpointer = entry_frame.localsplus;
|
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.visited = 0;
|
||||||
entry_frame.return_offset = 0;
|
entry_frame.return_offset = 0;
|
||||||
/* Push frame */
|
/* Push frame */
|
||||||
|
@ -880,7 +880,7 @@ resume_frame:
|
||||||
stack_pointer = _PyFrame_GetStackPointer(frame);
|
stack_pointer = _PyFrame_GetStackPointer(frame);
|
||||||
|
|
||||||
#ifdef LLTRACE
|
#ifdef LLTRACE
|
||||||
lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS());
|
lltrace = maybe_lltrace_resume_frame(frame, GLOBALS());
|
||||||
if (lltrace < 0) {
|
if (lltrace < 0) {
|
||||||
goto exit_unwind;
|
goto exit_unwind;
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@
|
||||||
#if LLTRACE
|
#if LLTRACE
|
||||||
#define LLTRACE_RESUME_FRAME() \
|
#define LLTRACE_RESUME_FRAME() \
|
||||||
do { \
|
do { \
|
||||||
lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS()); \
|
lltrace = maybe_lltrace_resume_frame(frame, GLOBALS()); \
|
||||||
if (lltrace < 0) { \
|
if (lltrace < 0) { \
|
||||||
goto exit_unwind; \
|
goto exit_unwind; \
|
||||||
} \
|
} \
|
||||||
|
@ -238,7 +238,7 @@ GETITEM(PyObject *v, Py_ssize_t i) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define WITHIN_STACK_BOUNDS() \
|
#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 */
|
/* Data access macros */
|
||||||
#define FRAME_CO_CONSTS (_PyFrame_GetCode(frame)->co_consts)
|
#define FRAME_CO_CONSTS (_PyFrame_GetCode(frame)->co_consts)
|
||||||
|
|
8
Python/executor_cases.c.h
generated
8
Python/executor_cases.c.h
generated
|
@ -1441,9 +1441,7 @@
|
||||||
_PyStackRef retval;
|
_PyStackRef retval;
|
||||||
_PyStackRef res;
|
_PyStackRef res;
|
||||||
retval = stack_pointer[-1];
|
retval = stack_pointer[-1];
|
||||||
#if TIER_ONE
|
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
|
||||||
assert(frame != &entry_frame);
|
|
||||||
#endif
|
|
||||||
_PyStackRef temp = retval;
|
_PyStackRef temp = retval;
|
||||||
stack_pointer += -1;
|
stack_pointer += -1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
|
@ -1579,9 +1577,7 @@
|
||||||
// NOTE: It's important that YIELD_VALUE never raises an exception!
|
// NOTE: It's important that YIELD_VALUE never raises an exception!
|
||||||
// The compiler treats any exception raised here as a failed close()
|
// The compiler treats any exception raised here as a failed close()
|
||||||
// or throw() call.
|
// or throw() call.
|
||||||
#if TIER_ONE
|
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
|
||||||
assert(frame != &entry_frame);
|
|
||||||
#endif
|
|
||||||
frame->instr_ptr++;
|
frame->instr_ptr++;
|
||||||
PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame);
|
PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame);
|
||||||
assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1);
|
assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1);
|
||||||
|
|
|
@ -48,7 +48,7 @@ _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame)
|
||||||
static void
|
static void
|
||||||
take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame)
|
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);
|
assert(frame->owner != FRAME_OWNED_BY_FRAME_OBJECT);
|
||||||
Py_ssize_t size = ((char*)frame->stackpointer) - (char *)frame;
|
Py_ssize_t size = ((char*)frame->stackpointer) - (char *)frame;
|
||||||
memcpy((_PyInterpreterFrame *)f->_f_frame_data, frame, size);
|
memcpy((_PyInterpreterFrame *)f->_f_frame_data, frame, size);
|
||||||
|
@ -69,7 +69,7 @@ take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame)
|
||||||
_PyInterpreterFrame *prev = _PyFrame_GetFirstComplete(frame->previous);
|
_PyInterpreterFrame *prev = _PyFrame_GetFirstComplete(frame->previous);
|
||||||
frame->previous = NULL;
|
frame->previous = NULL;
|
||||||
if (prev) {
|
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 */
|
/* Link PyFrameObjects.f_back and remove link through _PyInterpreterFrame.previous */
|
||||||
PyFrameObject *back = _PyFrame_GetFrameObject(prev);
|
PyFrameObject *back = _PyFrame_GetFrameObject(prev);
|
||||||
if (back == NULL) {
|
if (back == NULL) {
|
||||||
|
|
|
@ -1476,7 +1476,7 @@ mark_stacks(PyInterpreterState *interp, PyGC_Head *visited, int visited_space, b
|
||||||
while (ts) {
|
while (ts) {
|
||||||
_PyInterpreterFrame *frame = ts->current_frame;
|
_PyInterpreterFrame *frame = ts->current_frame;
|
||||||
while (frame) {
|
while (frame) {
|
||||||
if (frame->owner == FRAME_OWNED_BY_CSTACK) {
|
if (frame->owner >= FRAME_OWNED_BY_INTERPRETER) {
|
||||||
frame = frame->previous;
|
frame = frame->previous;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
20
Python/generated_cases.c.h
generated
20
Python/generated_cases.c.h
generated
|
@ -5046,9 +5046,7 @@
|
||||||
// _RETURN_VALUE
|
// _RETURN_VALUE
|
||||||
{
|
{
|
||||||
retval = val;
|
retval = val;
|
||||||
#if TIER_ONE
|
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
|
||||||
assert(frame != &entry_frame);
|
|
||||||
#endif
|
|
||||||
_PyStackRef temp = retval;
|
_PyStackRef temp = retval;
|
||||||
stack_pointer += -1;
|
stack_pointer += -1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
|
@ -5100,9 +5098,7 @@
|
||||||
// NOTE: It's important that YIELD_VALUE never raises an exception!
|
// NOTE: It's important that YIELD_VALUE never raises an exception!
|
||||||
// The compiler treats any exception raised here as a failed close()
|
// The compiler treats any exception raised here as a failed close()
|
||||||
// or throw() call.
|
// or throw() call.
|
||||||
#if TIER_ONE
|
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
|
||||||
assert(frame != &entry_frame);
|
|
||||||
#endif
|
|
||||||
frame->instr_ptr++;
|
frame->instr_ptr++;
|
||||||
PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame);
|
PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame);
|
||||||
assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1);
|
assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1);
|
||||||
|
@ -5145,7 +5141,7 @@
|
||||||
INSTRUCTION_STATS(INTERPRETER_EXIT);
|
INSTRUCTION_STATS(INTERPRETER_EXIT);
|
||||||
_PyStackRef retval;
|
_PyStackRef retval;
|
||||||
retval = stack_pointer[-1];
|
retval = stack_pointer[-1];
|
||||||
assert(frame == &entry_frame);
|
assert(frame->owner == FRAME_OWNED_BY_INTERPRETER);
|
||||||
assert(_PyFrame_IsIncomplete(frame));
|
assert(_PyFrame_IsIncomplete(frame));
|
||||||
/* Restore previous frame and return. */
|
/* Restore previous frame and return. */
|
||||||
tstate->current_frame = frame->previous;
|
tstate->current_frame = frame->previous;
|
||||||
|
@ -7309,9 +7305,7 @@
|
||||||
_PyStackRef retval;
|
_PyStackRef retval;
|
||||||
_PyStackRef res;
|
_PyStackRef res;
|
||||||
retval = stack_pointer[-1];
|
retval = stack_pointer[-1];
|
||||||
#if TIER_ONE
|
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
|
||||||
assert(frame != &entry_frame);
|
|
||||||
#endif
|
|
||||||
_PyStackRef temp = retval;
|
_PyStackRef temp = retval;
|
||||||
stack_pointer += -1;
|
stack_pointer += -1;
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
|
@ -7364,7 +7358,7 @@
|
||||||
v = stack_pointer[-1];
|
v = stack_pointer[-1];
|
||||||
PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver);
|
PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver);
|
||||||
PyObject *retval_o;
|
PyObject *retval_o;
|
||||||
assert(frame != &entry_frame);
|
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
|
||||||
if ((tstate->interp->eval_frame == NULL) &&
|
if ((tstate->interp->eval_frame == NULL) &&
|
||||||
(Py_TYPE(receiver_o) == &PyGen_Type || Py_TYPE(receiver_o) == &PyCoro_Type) &&
|
(Py_TYPE(receiver_o) == &PyGen_Type || Py_TYPE(receiver_o) == &PyCoro_Type) &&
|
||||||
((PyGenObject *)receiver_o)->gi_frame_state < FRAME_EXECUTING)
|
((PyGenObject *)receiver_o)->gi_frame_state < FRAME_EXECUTING)
|
||||||
|
@ -8486,9 +8480,7 @@
|
||||||
// NOTE: It's important that YIELD_VALUE never raises an exception!
|
// NOTE: It's important that YIELD_VALUE never raises an exception!
|
||||||
// The compiler treats any exception raised here as a failed close()
|
// The compiler treats any exception raised here as a failed close()
|
||||||
// or throw() call.
|
// or throw() call.
|
||||||
#if TIER_ONE
|
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
|
||||||
assert(frame != &entry_frame);
|
|
||||||
#endif
|
|
||||||
frame->instr_ptr++;
|
frame->instr_ptr++;
|
||||||
PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame);
|
PyGenObject *gen = _PyGen_GetGeneratorFromFrame(frame);
|
||||||
assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1);
|
assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1);
|
||||||
|
|
|
@ -1946,7 +1946,7 @@ instrument_all_executing_code_objects(PyInterpreterState *interp) {
|
||||||
while (ts) {
|
while (ts) {
|
||||||
_PyInterpreterFrame *frame = ts->current_frame;
|
_PyInterpreterFrame *frame = ts->current_frame;
|
||||||
while (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)) {
|
if (instrument_lock_held(_PyFrame_GetCode(frame), interp)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -890,7 +890,7 @@ done:
|
||||||
static void
|
static void
|
||||||
dump_frame(int fd, _PyInterpreterFrame *frame)
|
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);
|
PyCodeObject *code =_PyFrame_GetCode(frame);
|
||||||
PUTS(fd, " File ");
|
PUTS(fd, " File ");
|
||||||
|
@ -965,7 +965,7 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header)
|
||||||
|
|
||||||
unsigned int depth = 0;
|
unsigned int depth = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
if (frame->owner == FRAME_OWNED_BY_CSTACK) {
|
if (frame->owner == FRAME_OWNED_BY_INTERPRETER) {
|
||||||
/* Trampoline frame */
|
/* Trampoline frame */
|
||||||
frame = frame->previous;
|
frame = frame->previous;
|
||||||
if (frame == NULL) {
|
if (frame == NULL) {
|
||||||
|
@ -973,7 +973,7 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Can't have more than one shim frame in a row */
|
/* 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) {
|
if (MAX_FRAME_DEPTH <= depth) {
|
||||||
|
|
|
@ -99,7 +99,7 @@ Py_TPFLAGS_BASE_EXC_SUBCLASS = (1 << 30)
|
||||||
Py_TPFLAGS_TYPE_SUBCLASS = (1 << 31)
|
Py_TPFLAGS_TYPE_SUBCLASS = (1 << 31)
|
||||||
|
|
||||||
#From pycore_frame.h
|
#From pycore_frame.h
|
||||||
FRAME_OWNED_BY_CSTACK = 3
|
FRAME_OWNED_BY_INTERPRETER = 3
|
||||||
|
|
||||||
MAX_OUTPUT_LEN=1024
|
MAX_OUTPUT_LEN=1024
|
||||||
|
|
||||||
|
@ -1113,7 +1113,7 @@ class PyFramePtr:
|
||||||
return int(instr_ptr - first_instr)
|
return int(instr_ptr - first_instr)
|
||||||
|
|
||||||
def is_shim(self):
|
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):
|
def previous(self):
|
||||||
return self._f_special("previous", PyFramePtr)
|
return self._f_special("previous", PyFramePtr)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue