Skip to content

Commit d740f45

Browse files
committed
Assorted fixups
1 parent d21fd88 commit d740f45

File tree

6 files changed

+63
-11
lines changed

6 files changed

+63
-11
lines changed

Include/cpython/frameobject.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@ PyAPI_FUNC(int) _PyFrame_IsEntryFrame(PyFrameObject *frame);
2828
PyAPI_FUNC(int) PyFrame_FastToLocalsWithError(PyFrameObject *f);
2929
PyAPI_FUNC(void) PyFrame_FastToLocals(PyFrameObject *);
3030

31+
typedef struct PyExtensionFrame {
32+
void *opaque[4];
33+
} PyExtensionFrame;
34+
35+
PyAPI_FUNC(int) Py_PushExtensionFrame(PyThreadState *tstate, PyExtensionFrame *frame, PyObject *codelike);
36+
37+
/* Returns a new reference to the codelike object */
38+
PyAPI_FUNC(void) Py_PopExtensionFrame(PyThreadState *tstate, PyExtensionFrame *frame);
39+
3140

3241
typedef struct {
3342
PyObject_HEAD

Include/internal/pycore_frame.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ enum _frameowner {
5858
FRAME_OWNED_BY_GENERATOR = 1,
5959
FRAME_OWNED_BY_FRAME_OBJECT = 2,
6060
FRAME_OWNED_BY_INTERPRETER = 3,
61-
FRAME_OWNED_BY_CSTACK = 4,
61+
FRAME_OWNED_BY_EXTENSION = 4,
62+
FRAME_OWNED_BY_CSTACK = 5,
6263
};
6364

6465
struct _PyFrameCore {
@@ -93,10 +94,18 @@ typedef struct _PyInterpreterFrame {
9394
_PyStackRef localsplus[1];
9495
} _PyInterpreterFrame;
9596

97+
typedef struct _PyExtensionFrame {
98+
_PyStackRef f_executable; /* A "code like" object */
99+
union _PyVMFrame *previous;
100+
char owner;
101+
void *extension_data;
102+
} _PyExtensionFrame;
103+
96104

97105
typedef union _PyVMFrame {
98106
struct _PyFrameCore core;
99107
_PyInterpreterFrame iframe;
108+
_PyExtensionFrame eframe;
100109
} _PyVMFrame;
101110

102111
#define _PyInterpreterFrame_LASTI(IF) \
@@ -366,6 +375,24 @@ _PyThreadState_HasStackSpace(PyThreadState *tstate, int size)
366375
size < tstate->datastack_limit - tstate->datastack_top;
367376
}
368377

378+
static inline void
379+
_Py_PushNonPythonFrame(PyThreadState *tstate, struct _PyFrameCore *frame, PyObject *callable, enum _frameowner owner)
380+
{
381+
frame->owner = owner;
382+
frame->f_executable = PyStackRef_FromPyObjectNew(callable);
383+
frame->previous = tstate->current_frame;
384+
tstate->current_frame = (_PyVMFrame *)frame;
385+
}
386+
387+
static inline void
388+
_Py_PopNonPythonFrame(PyThreadState *tstate, struct _PyFrameCore *frame)
389+
{
390+
assert(tstate->current_frame == (_PyVMFrame *)frame);
391+
_PyStackRef codelike = frame->f_executable;
392+
tstate->current_frame = frame->previous;
393+
PyStackRef_CLOSE(codelike);
394+
}
395+
369396
extern _PyInterpreterFrame *
370397
_PyThreadState_PushFrame(PyThreadState *tstate, size_t size);
371398

Modules/_testexternalinspection.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,8 +1265,8 @@ parse_async_frame_object(
12651265
return -1;
12661266
}
12671267

1268-
if (owner == FRAME_OWNED_BY_CSTACK || owner == FRAME_OWNED_BY_INTERPRETER) {
1269-
return 0; // C frame
1268+
if (owner >= FRAME_OWNED_BY_INTERPRETER) {
1269+
return 0; // Non-Python frame
12701270
}
12711271

12721272
if (owner != FRAME_OWNED_BY_GENERATOR

Objects/genobject.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -962,11 +962,11 @@ _Py_MakeCoro(PyFunctionObject *func)
962962
if (origin_depth == 0) {
963963
((PyCoroObject *)coro)->cr_origin_or_finalizer = NULL;
964964
} else {
965-
_PyInterpreterFrame *frame = tstate->current_frame;
965+
_PyVMFrame *frame = tstate->current_frame;
966966
assert(frame);
967-
assert(_PyFrame_IsIncomplete(frame));
968-
frame = _PyFrame_GetFirstComplete(frame->previous);
969-
PyObject *cr_origin = compute_cr_origin(origin_depth, frame);
967+
assert(_PyVMFrame_IsIncomplete(frame));
968+
_PyInterpreterFrame *iframe = _PyFrame_GetFirstComplete(frame->core.previous);
969+
PyObject *cr_origin = compute_cr_origin(origin_depth, iframe);
970970
((PyCoroObject *)coro)->cr_origin_or_finalizer = cr_origin;
971971
if (!cr_origin) {
972972
Py_DECREF(coro);

Objects/typevarobject.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,14 +384,15 @@ make_union(PyObject *self, PyObject *other)
384384
static PyObject *
385385
caller(void)
386386
{
387-
_PyInterpreterFrame *f = _PyThreadState_GET()->current_frame;
387+
_PyVMFrame *f = _PyThreadState_GET()->current_frame;
388388
if (f == NULL) {
389389
Py_RETURN_NONE;
390390
}
391-
if (f == NULL || PyStackRef_IsNull(f->f_funcobj)) {
391+
_PyInterpreterFrame *frame = _PyFrame_GetFirstComplete(f);
392+
if (frame == NULL || PyStackRef_IsNull(frame->f_funcobj)) {
392393
Py_RETURN_NONE;
393394
}
394-
PyObject *r = PyFunction_GetModule(PyStackRef_AsPyObjectBorrow(f->f_funcobj));
395+
PyObject *r = PyFunction_GetModule(PyStackRef_AsPyObjectBorrow(frame->f_funcobj));
395396
if (!r) {
396397
PyErr_Clear();
397398
Py_RETURN_NONE;

Python/frame.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ _PyFrame_ClearExceptCode(_PyInterpreterFrame *frame)
110110
_PyGen_GetGeneratorFromFrame(frame)->gi_frame_state == FRAME_CLEARED);
111111
// GH-99729: Clearing this frame can expose the stack (via finalizers). It's
112112
// crucial that this frame has been unlinked, and is no longer visible:
113-
assert(_PyThreadState_GET()->current_frame != frame);
113+
assert(_PyThreadState_GET()->current_frame != (_PyVMFrame *)frame);
114114
if (frame->frame_obj) {
115115
PyFrameObject *f = frame->frame_obj;
116116
frame->frame_obj = NULL;
@@ -153,3 +153,18 @@ const PyTypeObject *const PyUnstable_ExecutableKinds[PyUnstable_EXECUTABLE_KINDS
153153
[PyUnstable_EXECUTABLE_KIND_METHOD_DESCRIPTOR] = &PyMethodDescr_Type,
154154
[PyUnstable_EXECUTABLE_KINDS] = NULL,
155155
};
156+
157+
int
158+
Py_PushExtensionFrame(PyThreadState *tstate, PyExtensionFrame *frame, PyObject *codelike)
159+
{
160+
assert(sizeof(PyExtensionFrame) >= sizeof(struct _PyFrameCore));
161+
_Py_PushNonPythonFrame(tstate, (struct _PyFrameCore *)frame, codelike, FRAME_OWNED_BY_EXTENSION);
162+
return 0;
163+
}
164+
165+
void
166+
Py_PopExtensionFrame(PyThreadState *tstate, PyExtensionFrame *frame)
167+
{
168+
assert(((struct _PyFrameCore *)frame)->owner == FRAME_OWNED_BY_EXTENSION);
169+
_Py_PopNonPythonFrame(tstate, (struct _PyFrameCore *)frame);
170+
}

0 commit comments

Comments
 (0)