GH-96421: Insert shim frame on entry to interpreter (GH-96319)

* Adds EXIT_INTERPRETER instruction to exit PyEval_EvalDefault()

* Simplifies RETURN_VALUE, YIELD_VALUE and RETURN_GENERATOR instructions as they no longer need to check for entry frames.
This commit is contained in:
Mark Shannon 2022-11-10 04:34:57 -08:00 committed by GitHub
parent dbf2faf579
commit 1e197e63e2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 450 additions and 346 deletions

View file

@ -2264,3 +2264,78 @@ _PyStaticCode_Init(PyCodeObject *co)
_PyCode_Quicken(co);
return 0;
}
#define MAX_CODE_UNITS_PER_LOC_ENTRY 8
PyCodeObject *
_Py_MakeShimCode(const _PyShimCodeDef *codedef)
{
PyObject *name = NULL;
PyObject *co_code = NULL;
PyObject *lines = NULL;
PyCodeObject *codeobj = NULL;
uint8_t *loc_table = NULL;
name = _PyUnicode_FromASCII(codedef->cname, strlen(codedef->cname));
if (name == NULL) {
goto cleanup;
}
co_code = PyBytes_FromStringAndSize(
(const char *)codedef->code, codedef->codelen);
if (co_code == NULL) {
goto cleanup;
}
int code_units = codedef->codelen / sizeof(_Py_CODEUNIT);
int loc_entries = (code_units + MAX_CODE_UNITS_PER_LOC_ENTRY - 1) /
MAX_CODE_UNITS_PER_LOC_ENTRY;
loc_table = PyMem_Malloc(loc_entries);
if (loc_table == NULL) {
PyErr_NoMemory();
goto cleanup;
}
for (int i = 0; i < loc_entries-1; i++) {
loc_table[i] = 0x80 | (PY_CODE_LOCATION_INFO_NONE << 3) | 7;
code_units -= MAX_CODE_UNITS_PER_LOC_ENTRY;
}
assert(loc_entries > 0);
assert(code_units > 0 && code_units <= MAX_CODE_UNITS_PER_LOC_ENTRY);
loc_table[loc_entries-1] = 0x80 |
(PY_CODE_LOCATION_INFO_NONE << 3) | (code_units-1);
lines = PyBytes_FromStringAndSize((const char *)loc_table, loc_entries);
PyMem_Free(loc_table);
if (lines == NULL) {
goto cleanup;
}
_Py_DECLARE_STR(shim_name, "<shim>");
struct _PyCodeConstructor con = {
.filename = &_Py_STR(shim_name),
.name = name,
.qualname = name,
.flags = CO_NEWLOCALS | CO_OPTIMIZED,
.code = co_code,
.firstlineno = 1,
.linetable = lines,
.consts = (PyObject *)&_Py_SINGLETON(tuple_empty),
.names = (PyObject *)&_Py_SINGLETON(tuple_empty),
.localsplusnames = (PyObject *)&_Py_SINGLETON(tuple_empty),
.localspluskinds = (PyObject *)&_Py_SINGLETON(bytes_empty),
.argcount = 0,
.posonlyargcount = 0,
.kwonlyargcount = 0,
.stacksize = codedef->stacksize,
.exceptiontable = (PyObject *)&_Py_SINGLETON(bytes_empty),
};
codeobj = _PyCode_New(&con);
cleanup:
Py_XDECREF(name);
Py_XDECREF(co_code);
Py_XDECREF(lines);
return codeobj;
}