bpo-44590: Lazily allocate frame objects (GH-27077)

* Convert "specials" array to InterpreterFrame struct, adding f_lasti, f_state and other non-debug FrameObject fields to it.

* Refactor, calls pushing the call to the interpreter upward toward _PyEval_Vector.

* Compute f_back when on thread stack, only filling in value when frame object outlives stack invocation.

* Move ownership of InterpreterFrame in generator from frame object to generator object.

* Do not create frame objects for Python calls.

* Do not create frame objects for generators.
This commit is contained in:
Mark Shannon 2021-07-26 11:22:16 +01:00 committed by GitHub
parent 0363a4014d
commit ae0a2b7562
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
27 changed files with 1037 additions and 619 deletions

View file

@ -7,6 +7,7 @@
#include "pycore_atomic.h" // _Py_atomic_int
#include "pycore_call.h" // _PyObject_Call()
#include "pycore_ceval.h" // _PyEval_SignalReceived()
#include "pycore_frame.h"
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_pyerrors.h" // _PyErr_SetString()
#include "pycore_pylifecycle.h" // NSIG
@ -1786,11 +1787,7 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate)
*/
_Py_atomic_store(&is_tripped, 0);
PyObject *frame = (PyObject *)tstate->frame;
if (!frame) {
frame = Py_None;
}
InterpreterFrame *frame = tstate->frame;
signal_state_t *state = &signal_global_state;
for (int i = 1; i < NSIG; i++) {
if (!_Py_atomic_load_relaxed(&Handlers[i].tripped)) {
@ -1821,8 +1818,16 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate)
PyErr_WriteUnraisable(Py_None);
continue;
}
PyObject *arglist = Py_BuildValue("(iO)", i, frame);
PyObject *arglist = NULL;
if (frame == NULL) {
arglist = Py_BuildValue("(iO)", i, Py_None);
}
else {
PyFrameObject *f = _PyFrame_GetFrameObject(frame);
if (f != NULL) {
arglist = Py_BuildValue("(iO)", i, f);
}
}
PyObject *result;
if (arglist) {
result = _PyObject_Call(tstate, func, arglist, NULL);