Skip to content

Commit 7f5348a

Browse files
committed
Get entry frame shim working.
1 parent cf78d2b commit 7f5348a

File tree

18 files changed

+167
-81
lines changed

18 files changed

+167
-81
lines changed

Include/internal/pycore_code.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,9 @@ _PyCode_LineNumberFromArray(PyCodeObject *co, int index)
510510
}
511511
}
512512

513+
extern PyCodeObject *
514+
_Py_MakeTrampoline(const char *code, int codelen, const char *cname);
515+
513516

514517
#ifdef __cplusplus
515518
}

Include/internal/pycore_frame.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ typedef enum _framestate {
4242
enum _frameowner {
4343
FRAME_OWNED_BY_THREAD = 0,
4444
FRAME_OWNED_BY_GENERATOR = 1,
45-
FRAME_OWNED_BY_FRAME_OBJECT = 2
45+
FRAME_OWNED_BY_FRAME_OBJECT = 2,
46+
FRAME_OWNED_BY_CSTACK = 3,
4647
};
4748

4849
typedef struct _PyInterpreterFrame {
@@ -60,9 +61,9 @@ typedef struct _PyInterpreterFrame {
6061
// example, it may be an inline CACHE entry, an instruction we just jumped
6162
// over, or (in the case of a newly-created frame) a totally invalid value:
6263
_Py_CODEUNIT *prev_instr;
63-
int stacktop; /* Offset of TOS from localsplus */
64-
bool is_entry; // Whether this is the "root" frame for the current _PyCFrame.
65-
char owner;
64+
int stacktop; /* Offset of TOS from localsplus */
65+
int yield_offset: 28;
66+
int owner: 4;
6667
/* Locals and stack */
6768
PyObject *localsplus[1];
6869
} _PyInterpreterFrame;
@@ -109,7 +110,6 @@ _PyFrame_InitializeSpecials(
109110
frame->stacktop = code->co_nlocalsplus;
110111
frame->frame_obj = NULL;
111112
frame->prev_instr = _PyCode_CODE(code) - 1;
112-
frame->is_entry = false;
113113
frame->owner = FRAME_OWNED_BY_THREAD;
114114
}
115115

Include/internal/pycore_interp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ struct _is {
175175
struct ast_state ast;
176176
struct types_state types;
177177
struct callable_cache callable_cache;
178+
PyCodeObject *interpreter_trampoline;
178179

179180
/* The following fields are here to avoid allocation during init.
180181
The data is exposed through PyInterpreterState pointer fields.

Include/internal/pycore_opcode.h

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

Include/opcode.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/opcode.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def pseudo_op(name, op, real_ops):
7777
def_op('CACHE', 0)
7878
def_op('POP_TOP', 1)
7979
def_op('PUSH_NULL', 2)
80-
def_op('INTEPRETER_EXIT', 3)
80+
def_op('INTERPRETER_EXIT', 3)
8181

8282
def_op('NOP', 9)
8383
def_op('UNARY_POSITIVE', 10)

Modules/_tracemalloc.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,9 @@ traceback_get_frames(traceback_t *traceback)
411411
}
412412

413413
_PyInterpreterFrame *back = pyframe->previous;
414+
if (back && back->owner == FRAME_OWNED_BY_CSTACK) {
415+
back = back->previous;
416+
}
414417
pyframe = back;
415418
}
416419
}

Objects/codeobject.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2221,3 +2221,57 @@ _PyStaticCode_InternStrings(PyCodeObject *co)
22212221
}
22222222
return 0;
22232223
}
2224+
2225+
PyCodeObject *
2226+
_Py_MakeTrampoline(const char *code, int codelen, const char *cname)
2227+
{
2228+
PyObject *name = NULL;
2229+
PyObject *co_code = NULL;
2230+
PyObject *lines = NULL;
2231+
PyCodeObject *codeobj = NULL;
2232+
2233+
name = _PyUnicode_FromASCII(cname, strlen(cname));
2234+
if (name == NULL) {
2235+
goto cleanup;
2236+
}
2237+
co_code = PyBytes_FromStringAndSize(code, codelen);
2238+
if (co_code == NULL) {
2239+
goto cleanup;
2240+
}
2241+
const char loc[2] = { 0x80 | (PY_CODE_LOCATION_INFO_NO_COLUMNS << 3) | 3, 0 };
2242+
lines = PyBytes_FromStringAndSize(loc, 2);
2243+
if (lines == NULL) {
2244+
goto cleanup;
2245+
}
2246+
struct _PyCodeConstructor con = {
2247+
.filename = &_Py_STR(empty),
2248+
.name = name,
2249+
.qualname = name,
2250+
.flags = CO_NEWLOCALS | CO_OPTIMIZED,
2251+
2252+
.code = co_code,
2253+
.firstlineno = 1,
2254+
.linetable = lines,
2255+
2256+
.consts = (PyObject *)&_Py_SINGLETON(tuple_empty),
2257+
.names = (PyObject *)&_Py_SINGLETON(tuple_empty),
2258+
2259+
.localsplusnames = (PyObject *)&_Py_SINGLETON(tuple_empty),
2260+
.localspluskinds = (PyObject *)&_Py_SINGLETON(bytes_empty),
2261+
2262+
.argcount = 0,
2263+
.posonlyargcount = 0,
2264+
.kwonlyargcount = 0,
2265+
2266+
.stacksize = 2,
2267+
2268+
.exceptiontable = (PyObject *)&_Py_SINGLETON(bytes_empty),
2269+
};
2270+
2271+
codeobj = _PyCode_New(&con);
2272+
cleanup:
2273+
Py_XDECREF(name);
2274+
Py_XDECREF(co_code);
2275+
Py_XDECREF(lines);
2276+
return codeobj;
2277+
}

Objects/frameobject.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,14 +1339,18 @@ PyFrame_LocalsToFast(PyFrameObject *f, int clear)
13391339
}
13401340
}
13411341

1342-
13431342
int _PyFrame_IsEntryFrame(PyFrameObject *frame)
13441343
{
13451344
assert(frame != NULL);
1346-
return frame->f_frame->is_entry;
1345+
_PyInterpreterFrame *f = frame->f_frame;
1346+
assert(f->owner == FRAME_OWNED_BY_FRAME_OBJECT ||
1347+
f->owner == FRAME_OWNED_BY_GENERATOR);
1348+
if (f->previous == NULL) {
1349+
return 0;
1350+
}
1351+
return f->previous->owner == FRAME_OWNED_BY_CSTACK;
13471352
}
13481353

1349-
13501354
PyCodeObject *
13511355
PyFrame_GetCode(PyFrameObject *frame)
13521356
{

Objects/genobject.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult,
208208
Py_INCREF(result);
209209
_PyFrame_StackPush(frame, result);
210210

211+
_PyInterpreterFrame *prev = tstate->cframe->current_frame;
211212
frame->previous = tstate->cframe->current_frame;
212213

213214
gen->gi_exc_state.previous_item = tstate->exc_info;
@@ -227,7 +228,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult,
227228
tstate->exc_info = gen->gi_exc_state.previous_item;
228229
gen->gi_exc_state.previous_item = NULL;
229230

230-
assert(tstate->cframe->current_frame == frame->previous);
231+
assert(tstate->cframe->current_frame == prev);
231232
/* Don't keep the reference to previous any longer than necessary. It
232233
* may keep a chain of frames alive or it could create a reference
233234
* cycle. */
@@ -273,7 +274,6 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult,
273274
_PyErr_ClearExcState(&gen->gi_exc_state);
274275

275276
gen->gi_frame_state = FRAME_CLEARED;
276-
_PyFrame_Clear(frame);
277277
*presult = result;
278278
return result ? PYGEN_RETURN : PYGEN_ERROR;
279279
}

0 commit comments

Comments
 (0)