diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 8ab68546630309..03bed6ccb07e09 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -919,8 +919,8 @@ Porting to Python 3.11 #if PY_VERSION_HEX < 0x030900B1 static inline PyCodeObject* PyFrame_GetCode(PyFrameObject *frame) { - Py_INCREF(frame->f_code); - return frame->f_code; + Py_INCREF(frame->code); + return frame->code; } #endif diff --git a/Include/cpython/ceval.h b/Include/cpython/ceval.h index 5a904bd3f08e90..eb30bfaa923eba 100644 --- a/Include/cpython/ceval.h +++ b/Include/cpython/ceval.h @@ -22,7 +22,7 @@ PyAPI_FUNC(PyObject *) _PyEval_GetBuiltinId(_Py_Identifier *); flag was set, else return 0. */ PyAPI_FUNC(int) PyEval_MergeCompilerFlags(PyCompilerFlags *cf); -PyAPI_FUNC(PyObject *) _PyEval_EvalFrameDefault(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc); +PyAPI_FUNC(PyObject *) _PyEval_EvalFrameDefault(PyThreadState *tstate, struct _Py_framedata *fdata, int exc); PyAPI_FUNC(void) _PyEval_SetSwitchInterval(unsigned long microseconds); PyAPI_FUNC(unsigned long) _PyEval_GetSwitchInterval(void); diff --git a/Include/cpython/genobject.h b/Include/cpython/genobject.h index b485ac6183e2ee..a206d3be62c09a 100644 --- a/Include/cpython/genobject.h +++ b/Include/cpython/genobject.h @@ -28,7 +28,7 @@ extern "C" { char prefix##_running_async; \ /* The frame */ \ char prefix##_frame_valid; \ - PyObject *prefix##_iframe[1]; + void *prefix##_fdata[1]; typedef struct { /* The gi_ prefix is intended to remind of generator-iterator. */ diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index 26d6f7576e524f..5edff06d63282d 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -48,7 +48,7 @@ typedef struct _PyCFrame { */ int use_tracing; /* Pointer to the currently executing frame (it can be NULL) */ - struct _PyInterpreterFrame *current_frame; + struct _Py_framedata *current_frame; struct _PyCFrame *previous; } _PyCFrame; @@ -260,7 +260,7 @@ PyAPI_FUNC(void) PyThreadState_DeleteCurrent(void); /* Frame evaluation API */ -typedef PyObject* (*_PyFrameEvalFunction)(PyThreadState *tstate, struct _PyInterpreterFrame *, int); +typedef PyObject* (*_PyFrameEvalFunction)(PyThreadState *tstate, struct _Py_framedata *, int); PyAPI_FUNC(_PyFrameEvalFunction) _PyInterpreterState_GetEvalFrameFunc( PyInterpreterState *interp); diff --git a/Include/internal/pycore_ceval.h b/Include/internal/pycore_ceval.h index 70178e38650cf5..d65056f07d325c 100644 --- a/Include/internal/pycore_ceval.h +++ b/Include/internal/pycore_ceval.h @@ -47,12 +47,12 @@ extern PyObject *_PyEval_BuiltinsFromGlobals( static inline PyObject* -_PyEval_EvalFrame(PyThreadState *tstate, struct _PyInterpreterFrame *frame, int throwflag) +_PyEval_EvalFrame(PyThreadState *tstate, struct _Py_framedata *fdata, int throwflag) { if (tstate->interp->eval_frame == NULL) { - return _PyEval_EvalFrameDefault(tstate, frame, throwflag); + return _PyEval_EvalFrameDefault(tstate, fdata, throwflag); } - return tstate->interp->eval_frame(tstate, frame, throwflag); + return tstate->interp->eval_frame(tstate, fdata, throwflag); } extern PyObject * @@ -116,7 +116,7 @@ static inline void _Py_LeaveRecursiveCall_inline(void) { #define Py_LeaveRecursiveCall() _Py_LeaveRecursiveCall_inline() -struct _PyInterpreterFrame *_PyEval_GetFrame(void); +struct _Py_framedata *_PyEval_GetFrame(void); PyObject *_Py_MakeCoro(PyFunctionObject *func); diff --git a/Include/internal/pycore_frame.h b/Include/internal/pycore_frame.h index 207983dcc22d7c..496c15498b3577 100644 --- a/Include/internal/pycore_frame.h +++ b/Include/internal/pycore_frame.h @@ -6,17 +6,60 @@ extern "C" { #include +/* Starting in CPython 3.11, CPython separates the frame state between the + * full frame objects exposed by the Python and C runtime state introspection + * APIs, and internal lighter weight frame data structs, which are simple C + * structures owned by either the interpreter eval loop (while executing + * ordinary functions), by a generator or coroutine object (for frames that + * are able to be suspended), or by their corresponding full frame object (if + * a state instrospection API has been invoked and the full frame object has + * taken responsibility for the lifecycle of the frame data storage). + * + * This split storage eliminates a lot of allocation and deallocation of full + * Python objects during code execution, providing a significant speed gain + * over the previous approach of using full Python objects for both + * introspection and code execution. + * + * Field naming conventions: + * + * * full frame object fields have an "f_*" prefix + * * frame data struct fields have no prefix + * + * Local variable and function argument naming conventions: + * + * * "frame", "f", and "frameobj" are used for full frame objects + * * Exception: "current_frame" in the thread state cframe struct is a frame data struct + * * "fdata" is used for frame data structs + * + * Function/macro naming conventions: + * + * * "PyFrame_*" functions accept a full frame object + * * "_PyFrame_*" functions accept either a full frame object or a frame + * data struct. Check the specific function signatures for details. + * * Other public C API functions that relate to frames only accept full + * frame objects + * * Other private C API functions that relate to frames may accept either a + * full frame object or a frame data struct. Check the specific function + * signatures for details + * + * Function return types: + * * Public C API functions will only ever return full frame objects + * * Private C API functions with an underscore prefix may return frame + * data structs instead + */ + + struct _frame { PyObject_HEAD PyFrameObject *f_back; /* previous frame, or NULL */ - struct _PyInterpreterFrame *f_frame; /* points to the frame data */ + struct _Py_framedata *f_fdata; /* points to the frame data */ PyObject *f_trace; /* Trace function */ int f_lineno; /* Current line number. Only valid if non-zero */ char f_trace_lines; /* Emit per-line trace events? */ char f_trace_opcodes; /* Emit per-opcode trace events? */ char f_owns_frame; /* This frame owns the frame */ /* The frame data, if this frame object owns the frame */ - PyObject *_f_frame_data[1]; + struct _Py_framedata *_f_owned_fdata[1]; }; extern PyFrameObject* _PyFrame_New_NoTrack(PyCodeObject *code); @@ -29,7 +72,8 @@ extern void _PyFrame_Fini(PyInterpreterState *interp); /* other API */ /* These values are chosen so that the inline functions below all - * compare f_state to zero. + * compare fdata->state to zero while keeping the property that most + * state transitions move to a higher value frame state. */ enum _framestate { FRAME_CREATED = -2, @@ -44,146 +88,146 @@ enum _framestate { typedef signed char PyFrameState; /* - frame->f_lasti refers to the index of the last instruction, + frame->lasti refers to the index of the last instruction, unless it's -1 in which case next_instr should be first_instr. */ -typedef struct _PyInterpreterFrame { - PyFunctionObject *f_func; /* Strong reference */ - PyObject *f_globals; /* Borrowed reference */ - PyObject *f_builtins; /* Borrowed reference */ - PyObject *f_locals; /* Strong reference, may be NULL */ - PyCodeObject *f_code; /* Strong reference */ +typedef struct _Py_framedata { + PyFunctionObject *func; /* Strong reference */ + PyObject *globals; /* Borrowed reference */ + PyObject *builtins; /* Borrowed reference */ + PyObject *locals; /* Strong reference, may be NULL */ + PyCodeObject *code; /* Strong reference */ PyFrameObject *frame_obj; /* Strong reference, may be NULL */ - struct _PyInterpreterFrame *previous; - int f_lasti; /* Last instruction if called */ + struct _Py_framedata *previous; + int lasti; /* Last instruction if called */ int stacktop; /* Offset of TOS from localsplus */ - PyFrameState f_state; /* What state the frame is in */ + PyFrameState state; /* What state the frame is in */ bool is_entry; // Whether this is the "root" frame for the current _PyCFrame. bool is_generator; PyObject *localsplus[1]; -} _PyInterpreterFrame; +} _Py_framedata; -static inline int _PyFrame_IsRunnable(_PyInterpreterFrame *f) { - return f->f_state < FRAME_EXECUTING; +static inline int _PyFrame_IsRunnable(_Py_framedata *f) { + return f->state < FRAME_EXECUTING; } -static inline int _PyFrame_IsExecuting(_PyInterpreterFrame *f) { - return f->f_state == FRAME_EXECUTING; +static inline int _PyFrame_IsExecuting(_Py_framedata *f) { + return f->state == FRAME_EXECUTING; } -static inline int _PyFrameHasCompleted(_PyInterpreterFrame *f) { - return f->f_state > FRAME_EXECUTING; +static inline int _PyFrameHasCompleted(_Py_framedata *f) { + return f->state > FRAME_EXECUTING; } -static inline PyObject **_PyFrame_Stackbase(_PyInterpreterFrame *f) { - return f->localsplus + f->f_code->co_nlocalsplus; +static inline PyObject **_PyFrame_Stackbase(_Py_framedata *f) { + return f->localsplus + f->code->co_nlocalsplus; } -static inline PyObject *_PyFrame_StackPeek(_PyInterpreterFrame *f) { - assert(f->stacktop > f->f_code->co_nlocalsplus); +static inline PyObject *_PyFrame_StackPeek(_Py_framedata *f) { + assert(f->stacktop > f->code->co_nlocalsplus); assert(f->localsplus[f->stacktop-1] != NULL); return f->localsplus[f->stacktop-1]; } -static inline PyObject *_PyFrame_StackPop(_PyInterpreterFrame *f) { - assert(f->stacktop > f->f_code->co_nlocalsplus); +static inline PyObject *_PyFrame_StackPop(_Py_framedata *f) { + assert(f->stacktop > f->code->co_nlocalsplus); f->stacktop--; return f->localsplus[f->stacktop]; } -static inline void _PyFrame_StackPush(_PyInterpreterFrame *f, PyObject *value) { - f->localsplus[f->stacktop] = value; - f->stacktop++; +static inline void _PyFrame_StackPush(_Py_framedata *fdata, PyObject *value) { + fdata->localsplus[fdata->stacktop] = value; + fdata->stacktop++; } -#define FRAME_SPECIALS_SIZE ((sizeof(_PyInterpreterFrame)-1)/sizeof(PyObject *)) +#define FRAME_SPECIALS_SIZE ((sizeof(_Py_framedata)-1)/sizeof(PyObject *)) -void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest); +void _PyFrame_Copy(_Py_framedata *src, _Py_framedata *dest); /* Consumes reference to func */ static inline void _PyFrame_InitializeSpecials( - _PyInterpreterFrame *frame, PyFunctionObject *func, + _Py_framedata *fdata, PyFunctionObject *func, PyObject *locals, int nlocalsplus) { - frame->f_func = func; - frame->f_code = (PyCodeObject *)Py_NewRef(func->func_code); - frame->f_builtins = func->func_builtins; - frame->f_globals = func->func_globals; - frame->f_locals = Py_XNewRef(locals); - frame->stacktop = nlocalsplus; - frame->frame_obj = NULL; - frame->f_lasti = -1; - frame->f_state = FRAME_CREATED; - frame->is_entry = false; - frame->is_generator = false; + fdata->func = func; + fdata->code = (PyCodeObject *)Py_NewRef(func->func_code); + fdata->builtins = func->func_builtins; + fdata->globals = func->func_globals; + fdata->locals = Py_XNewRef(locals); + fdata->stacktop = nlocalsplus; + fdata->frame_obj = NULL; + fdata->lasti = -1; + fdata->state = FRAME_CREATED; + fdata->is_entry = false; + fdata->is_generator = false; } /* Gets the pointer to the locals array * that precedes this frame. */ static inline PyObject** -_PyFrame_GetLocalsArray(_PyInterpreterFrame *frame) +_PyFrame_GetLocalsArray(_Py_framedata *fdata) { - return frame->localsplus; + return fdata->localsplus; } static inline PyObject** -_PyFrame_GetStackPointer(_PyInterpreterFrame *frame) +_PyFrame_GetStackPointer(_Py_framedata *fdata) { - return frame->localsplus+frame->stacktop; + return fdata->localsplus+fdata->stacktop; } static inline void -_PyFrame_SetStackPointer(_PyInterpreterFrame *frame, PyObject **stack_pointer) +_PyFrame_SetStackPointer(_Py_framedata *fdata, PyObject **stack_pointer) { - frame->stacktop = (int)(stack_pointer - frame->localsplus); + fdata->stacktop = (int)(stack_pointer - fdata->localsplus); } /* For use by _PyFrame_GetFrameObject Do not call directly. */ PyFrameObject * -_PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame); +_PyFrame_MakeAndSetFrameObject(_Py_framedata *fdata); /* Gets the PyFrameObject for this frame, lazily * creating it if necessary. * Returns a borrowed referennce */ static inline PyFrameObject * -_PyFrame_GetFrameObject(_PyInterpreterFrame *frame) +_PyFrame_GetFrameObject(_Py_framedata *fdata) { - PyFrameObject *res = frame->frame_obj; + PyFrameObject *res = fdata->frame_obj; if (res != NULL) { return res; } - return _PyFrame_MakeAndSetFrameObject(frame); + return _PyFrame_MakeAndSetFrameObject(fdata); } /* Clears all references in the frame. - * If take is non-zero, then the _PyInterpreterFrame frame - * may be transferred to the frame object it references + * If take is non-zero, then the frame data + * may be transfered to the frame object it references * instead of being cleared. Either way * the caller no longer owns the references * in the frame. - * take should be set to 1 for heap allocated + * take should be set to 1 for heap allocated * frames like the ones in generators and coroutines. */ void -_PyFrame_Clear(_PyInterpreterFrame * frame); +_PyFrame_Clear(_Py_framedata * fdata); int -_PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg); +_PyFrame_Traverse(_Py_framedata *fdata, visitproc visit, void *arg); int -_PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame); +_PyFrame_FastToLocalsWithError(_Py_framedata *fdata); void -_PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear); +_PyFrame_LocalsToFast(_Py_framedata *fdata, int clear); -extern _PyInterpreterFrame * +extern _Py_framedata * _PyThreadState_BumpFramePointerSlow(PyThreadState *tstate, size_t size); -static inline _PyInterpreterFrame * +static inline _Py_framedata * _PyThreadState_BumpFramePointer(PyThreadState *tstate, size_t size) { PyObject **base = tstate->datastack_top; @@ -192,16 +236,16 @@ _PyThreadState_BumpFramePointer(PyThreadState *tstate, size_t size) assert(tstate->datastack_limit); if (top < tstate->datastack_limit) { tstate->datastack_top = top; - return (_PyInterpreterFrame *)base; + return (_Py_framedata *)base; } } return _PyThreadState_BumpFramePointerSlow(tstate, size); } -void _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame *frame); +void _PyThreadState_PopFrame(PyThreadState *tstate, _Py_framedata *fdata); /* Consume reference to func */ -_PyInterpreterFrame * +_Py_framedata * _PyFrame_Push(PyThreadState *tstate, PyFunctionObject *func); #ifdef __cplusplus diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-08-01-18-18-51.bpo-44800.TCsfH3.rst b/Misc/NEWS.d/next/Core and Builtins/2021-08-01-18-18-51.bpo-44800.TCsfH3.rst new file mode 100644 index 00000000000000..25f56ae4e11058 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-08-01-18-18-51.bpo-44800.TCsfH3.rst @@ -0,0 +1,8 @@ +Refactored internal APIs for the new lazy frame object creation to more +consistently distinguish between the full ``PyFrameObject`` Python object +implementation that is still used in the Python and C runtime state +introspection APIs (function prefix ``PyFrame``, field prefix ``f_``, typical +variable names ``frame`` and ``f``) and the new ``_Py_framedata`` internal +frame data storage (C structs with no intrinsic instance lifecycle management) +that is now used for code execution (function prefix ``_Py_framedata``, no +field prefix, typical variable name ``fdata``). diff --git a/Misc/gdbinit b/Misc/gdbinit index e8f62ba6476423..ef8985d61f4a20 100644 --- a/Misc/gdbinit +++ b/Misc/gdbinit @@ -37,14 +37,14 @@ end define pylocals set $_i = 0 - while $_i < f->f_code->co_nlocals - if f->f_localsplus + $_i != 0 - set $_names = f->f_code->co_varnames - set $_name = PyUnicode_AsUTF8(PyTuple_GetItem($_names, $_i)) - printf "%s:\n", $_name - pyo f->f_localsplus[$_i] - end - set $_i = $_i + 1 + while $_i < f->f_fdata->code->co_nlocals + if _PyFrame_GetLocalsArray(f->f_fdata) + $_i != 0 + set $_names = f->f_fdata->code->co_varnames + set $_name = PyUnicode_AsUTF8(PyTuple_GetItem($_names, $_i)) + printf "%s:\n", $_name + pyo _PyFrame_GetLocalsArray(f->f_fdata)[$_i] + end + set $_i = $_i + 1 end end document pylocals @@ -55,8 +55,8 @@ end # command language define lineno set $__continue = 1 - set $__co = f->f_code - set $__lasti = f->f_lasti + set $__co = f->f_fdata->code + set $__lasti = f->f_fdata->lasti set $__sz = ((PyVarObject *)$__co->co_lnotab)->ob_size/2 set $__p = (unsigned char *)((PyBytesObject *)$__co->co_lnotab)->ob_sval set $__li = $__co->co_firstlineno @@ -66,7 +66,7 @@ define lineno set $__ad = $__ad + *$__p set $__p = $__p + 1 if ($__ad > $__lasti) - set $__continue = 0 + set $__continue = 0 else set $__li = $__li + *$__p set $__p = $__p + 1 @@ -84,8 +84,8 @@ document pyframev end define pyframe - set $__fn = PyUnicode_AsUTF8(f->f_code->co_filename) - set $__n = PyUnicode_AsUTF8(f->f_code->co_name) + set $__fn = PyUnicode_AsUTF8(f->f_fdata->code->co_filename) + set $__n = PyUnicode_AsUTF8(f->f_fdata->code->co_name) printf "%s (", $__fn lineno printf "): %s\n", $__n @@ -134,6 +134,10 @@ end # the interpreter you may will have to change the functions you compare with # $pc. +# Python 3.11 TODO: once all the interpreter optimisation changes settle down, +# revisit the checks in these example hooks, as the correct symbols to look for +# are likely to have changed. + define pystack while $pc < Py_Main || $pc > Py_GetArgcArgv if $pc > PyEval_EvalFrameEx && $pc < _PyEval_EvalFrameDefault diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c index 738d54530c9674..a22bee4a7e407e 100644 --- a/Modules/_tracemalloc.c +++ b/Modules/_tracemalloc.c @@ -305,16 +305,16 @@ hashtable_compare_traceback(const void *key1, const void *key2) static void -tracemalloc_get_frame(_PyInterpreterFrame *pyframe, frame_t *frame) +tracemalloc_get_frame(_Py_framedata *pyframe, frame_t *frame) { frame->filename = &_Py_STR(anon_unknown); - int lineno = PyCode_Addr2Line(pyframe->f_code, pyframe->f_lasti*sizeof(_Py_CODEUNIT)); + int lineno = PyCode_Addr2Line(pyframe->code, pyframe->lasti*sizeof(_Py_CODEUNIT)); if (lineno < 0) { lineno = 0; } frame->lineno = (unsigned int)lineno; - PyObject *filename = pyframe->f_code->co_filename; + PyObject *filename = pyframe->code->co_filename; if (filename == NULL) { #ifdef TRACE_DEBUG @@ -399,7 +399,7 @@ traceback_get_frames(traceback_t *traceback) return; } - _PyInterpreterFrame *pyframe = tstate->cframe->current_frame; + _Py_framedata *pyframe = tstate->cframe->current_frame; for (; pyframe != NULL;) { if (traceback->nframe < _Py_tracemalloc_config.max_nframe) { tracemalloc_get_frame(pyframe, &traceback->frames[traceback->nframe]); @@ -410,7 +410,7 @@ traceback_get_frames(traceback_t *traceback) traceback->total_nframe++; } - _PyInterpreterFrame *back = pyframe->previous; + _Py_framedata *back = pyframe->previous; pyframe = back; } } diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c index 846b24d5efa9a6..1bc45b0aaf21d4 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_xxsubinterpretersmodule.c @@ -1839,12 +1839,12 @@ _is_running(PyInterpreterState *interp) } assert(!PyErr_Occurred()); - _PyInterpreterFrame *frame = tstate->cframe->current_frame; - if (frame == NULL) { + _Py_framedata *fdata = tstate->cframe->current_frame; + if (fdata == NULL) { return 0; } - int executing = _PyFrame_IsExecuting(frame); + int executing = _PyFrame_IsExecuting(fdata); return executing; } diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 9566263a0dd87e..53253a4e92eb90 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -8,7 +8,7 @@ #include "pycore_call.h" // _PyObject_Call() #include "pycore_ceval.h" // _PyEval_SignalReceived() #include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH -#include "pycore_frame.h" // _PyInterpreterFrame +#include "pycore_frame.h" // _Py_framedata #include "pycore_moduleobject.h" // _PyModule_GetState() #include "pycore_pyerrors.h" // _PyErr_SetString() #include "pycore_pylifecycle.h" // NSIG @@ -1817,7 +1817,7 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate) */ _Py_atomic_store(&is_tripped, 0); - _PyInterpreterFrame *frame = tstate->cframe->current_frame; + _Py_framedata *fdata = tstate->cframe->current_frame; signal_state_t *state = &signal_global_state; for (int i = 1; i < NSIG; i++) { if (!_Py_atomic_load_relaxed(&Handlers[i].tripped)) { @@ -1850,11 +1850,11 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate) continue; } PyObject *arglist = NULL; - if (frame == NULL) { + if (fdata == NULL) { arglist = Py_BuildValue("(iO)", i, Py_None); } else { - PyFrameObject *f = _PyFrame_GetFrameObject(frame); + PyFrameObject *f = _PyFrame_GetFrameObject(fdata); if (f != NULL) { arglist = Py_BuildValue("(iO)", i, f); } diff --git a/Objects/frameobject.c b/Objects/frameobject.c index eb7fdb30cd75e6..42169ac0390466 100644 --- a/Objects/frameobject.c +++ b/Objects/frameobject.c @@ -26,7 +26,7 @@ frame_getlocals(PyFrameObject *f, void *closure) { if (PyFrame_FastToLocalsWithError(f) < 0) return NULL; - PyObject *locals = f->f_frame->f_locals; + PyObject *locals = f->f_fdata->locals; Py_INCREF(locals); return locals; } @@ -39,7 +39,7 @@ PyFrame_GetLineNumber(PyFrameObject *f) return f->f_lineno; } else { - return PyCode_Addr2Line(f->f_frame->f_code, f->f_frame->f_lasti*sizeof(_Py_CODEUNIT)); + return PyCode_Addr2Line(f->f_fdata->code, f->f_fdata->lasti*sizeof(_Py_CODEUNIT)); } } @@ -58,16 +58,16 @@ frame_getlineno(PyFrameObject *f, void *closure) static PyObject * frame_getlasti(PyFrameObject *f, void *closure) { - if (f->f_frame->f_lasti < 0) { + if (f->f_fdata->lasti < 0) { return PyLong_FromLong(-1); } - return PyLong_FromLong(f->f_frame->f_lasti*sizeof(_Py_CODEUNIT)); + return PyLong_FromLong(f->f_fdata->lasti*sizeof(_Py_CODEUNIT)); } static PyObject * frame_getglobals(PyFrameObject *f, void *closure) { - PyObject *globals = f->f_frame->f_globals; + PyObject *globals = f->f_fdata->globals; if (globals == NULL) { globals = Py_None; } @@ -78,7 +78,7 @@ frame_getglobals(PyFrameObject *f, void *closure) static PyObject * frame_getbuiltins(PyFrameObject *f, void *closure) { - PyObject *builtins = f->f_frame->f_builtins; + PyObject *builtins = f->f_fdata->builtins; if (builtins == NULL) { builtins = Py_None; } @@ -402,7 +402,7 @@ first_line_not_before(int *lines, int len, int line) static void frame_stack_pop(PyFrameObject *f) { - PyObject *v = _PyFrame_StackPop(f->f_frame); + PyObject *v = _PyFrame_StackPop(f->f_fdata); Py_DECREF(v); } @@ -442,7 +442,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore * In addition, jumps are forbidden when not tracing, * as this is a debugging feature. */ - switch(f->f_frame->f_state) { + switch(f->f_fdata->state) { case FRAME_CREATED: PyErr_Format(PyExc_ValueError, "can't jump from the 'call' trace event of a new frame"); @@ -484,7 +484,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore } new_lineno = (int)l_new_lineno; - if (new_lineno < f->f_frame->f_code->co_firstlineno) { + if (new_lineno < f->f_fdata->code->co_firstlineno) { PyErr_Format(PyExc_ValueError, "line %d comes before the current code block", new_lineno); @@ -493,8 +493,8 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore /* PyCode_NewWithPosOnlyArgs limits co_code to be under INT_MAX so this * should never overflow. */ - int len = (int)(PyBytes_GET_SIZE(f->f_frame->f_code->co_code) / sizeof(_Py_CODEUNIT)); - int *lines = marklines(f->f_frame->f_code, len); + int len = (int)(PyBytes_GET_SIZE(f->f_fdata->code->co_code) / sizeof(_Py_CODEUNIT)); + int *lines = marklines(f->f_fdata->code, len); if (lines == NULL) { return -1; } @@ -508,7 +508,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore return -1; } - int64_t *stacks = mark_stacks(f->f_frame->f_code, len); + int64_t *stacks = mark_stacks(f->f_fdata->code, len); if (stacks == NULL) { PyMem_Free(lines); return -1; @@ -516,7 +516,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore int64_t best_stack = OVERFLOWED; int best_addr = -1; - int64_t start_stack = stacks[f->f_frame->f_lasti]; + int64_t start_stack = stacks[f->f_fdata->lasti]; int err = -1; const char *msg = "cannot find bytecode for specified line"; for (int i = 0; i < len; i++) { @@ -550,7 +550,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore return -1; } /* Unwind block stack. */ - if (f->f_frame->f_state == FRAME_SUSPENDED) { + if (f->f_fdata->state == FRAME_SUSPENDED) { /* Account for value popped by yield */ start_stack = pop_value(start_stack); } @@ -560,7 +560,7 @@ frame_setlineno(PyFrameObject *f, PyObject* p_new_lineno, void *Py_UNUSED(ignore } /* Finally set the new lasti and return OK. */ f->f_lineno = 0; - f->f_frame->f_lasti = best_addr; + f->f_fdata->lasti = best_addr; return 0; } @@ -617,7 +617,7 @@ frame_dealloc(PyFrameObject *f) { /* It is the responsibility of the owning generator/coroutine * to have cleared the generator pointer */ - assert(!f->f_frame->is_generator); + assert(!f->f_fdata->is_generator); if (_PyObject_GC_IS_TRACKED(f)) { _PyObject_GC_UNTRACK(f); @@ -629,15 +629,15 @@ frame_dealloc(PyFrameObject *f) /* Kill all local variables including specials, if we own them */ if (f->f_owns_frame) { f->f_owns_frame = 0; - assert(f->f_frame == (_PyInterpreterFrame *)f->_f_frame_data); - _PyInterpreterFrame *frame = (_PyInterpreterFrame *)f->_f_frame_data; + assert(f->f_fdata == (_Py_framedata *)f->_f_owned_fdata); + _Py_framedata *fdata = (_Py_framedata *)f->_f_owned_fdata; /* Don't clear code object until the end */ - co = frame->f_code; - frame->f_code = NULL; - Py_CLEAR(frame->f_func); - Py_CLEAR(frame->f_locals); - PyObject **locals = _PyFrame_GetLocalsArray(frame); - for (int i = 0; i < frame->stacktop; i++) { + co = fdata->code; + fdata->code = NULL; + Py_CLEAR(fdata->func); + Py_CLEAR(fdata->locals); + PyObject **locals = _PyFrame_GetLocalsArray(fdata); + for (int i = 0; i < fdata->stacktop; i++) { Py_CLEAR(locals[i]); } } @@ -656,8 +656,8 @@ frame_traverse(PyFrameObject *f, visitproc visit, void *arg) if (f->f_owns_frame == 0) { return 0; } - assert(f->f_frame->frame_obj == NULL); - return _PyFrame_Traverse(f->f_frame, visit, arg); + assert(f->f_fdata->frame_obj == NULL); + return _PyFrame_Traverse(f->f_fdata, visit, arg); } static int @@ -668,32 +668,32 @@ frame_tp_clear(PyFrameObject *f) * frame may also point to this frame, believe itself to still be * active, and try cleaning up this frame again. */ - f->f_frame->f_state = FRAME_CLEARED; + f->f_fdata->state = FRAME_CLEARED; Py_CLEAR(f->f_trace); /* locals and stack */ - PyObject **locals = _PyFrame_GetLocalsArray(f->f_frame); - assert(f->f_frame->stacktop >= 0); - for (int i = 0; i < f->f_frame->stacktop; i++) { + PyObject **locals = _PyFrame_GetLocalsArray(f->f_fdata); + assert(f->f_fdata->stacktop >= 0); + for (int i = 0; i < f->f_fdata->stacktop; i++) { Py_CLEAR(locals[i]); } - f->f_frame->stacktop = 0; + f->f_fdata->stacktop = 0; return 0; } static PyObject * frame_clear(PyFrameObject *f, PyObject *Py_UNUSED(ignored)) { - if (_PyFrame_IsExecuting(f->f_frame)) { + if (_PyFrame_IsExecuting(f->f_fdata)) { PyErr_SetString(PyExc_RuntimeError, "cannot clear an executing frame"); return NULL; } - if (f->f_frame->is_generator) { + if (f->f_fdata->is_generator) { assert(!f->f_owns_frame); - size_t offset_in_gen = offsetof(PyGenObject, gi_iframe); - PyObject *gen = (PyObject *)(((char *)f->f_frame) - offset_in_gen); + size_t offset_in_gen = offsetof(PyGenObject, gi_fdata); + PyObject *gen = (PyObject *)(((char *)f->f_fdata) - offset_in_gen); _PyGen_Finalize(gen); } (void)frame_tp_clear(f); @@ -707,8 +707,8 @@ static PyObject * frame_sizeof(PyFrameObject *f, PyObject *Py_UNUSED(ignored)) { Py_ssize_t res; - res = offsetof(PyFrameObject, _f_frame_data) + offsetof(_PyInterpreterFrame, localsplus); - PyCodeObject *code = f->f_frame->f_code; + res = offsetof(PyFrameObject, _f_owned_fdata) + offsetof(_Py_framedata, localsplus); + PyCodeObject *code = f->f_fdata->code; res += (code->co_nlocalsplus+code->co_stacksize) * sizeof(PyObject *); return PyLong_FromSsize_t(res); } @@ -720,7 +720,7 @@ static PyObject * frame_repr(PyFrameObject *f) { int lineno = PyFrame_GetLineNumber(f); - PyCodeObject *code = f->f_frame->f_code; + PyCodeObject *code = f->f_fdata->code; return PyUnicode_FromFormat( "", f, code->co_filename, lineno, code->co_name); @@ -737,8 +737,8 @@ static PyMethodDef frame_methods[] = { PyTypeObject PyFrame_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "frame", - offsetof(PyFrameObject, _f_frame_data) + - offsetof(_PyInterpreterFrame, localsplus), + offsetof(PyFrameObject, _f_owned_fdata) + + offsetof(_Py_framedata, localsplus), sizeof(PyObject *), (destructor)frame_dealloc, /* tp_dealloc */ 0, /* tp_vectorcall_offset */ @@ -771,14 +771,14 @@ PyTypeObject PyFrame_Type = { }; static void -init_frame(_PyInterpreterFrame *frame, PyFunctionObject *func, PyObject *locals) +init_frame(_Py_framedata *fdata, PyFunctionObject *func, PyObject *locals) { /* _PyFrame_InitializeSpecials consumes reference to func */ Py_INCREF(func); PyCodeObject *code = (PyCodeObject *)func->func_code; - _PyFrame_InitializeSpecials(frame, func, locals, code->co_nlocalsplus); + _PyFrame_InitializeSpecials(fdata, func, locals, code->co_nlocalsplus); for (Py_ssize_t i = 0; i < code->co_nlocalsplus; i++) { - frame->localsplus[i] = NULL; + fdata->localsplus[i] = NULL; } } @@ -827,8 +827,8 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, Py_DECREF(func); return NULL; } - init_frame((_PyInterpreterFrame *)f->_f_frame_data, func, locals); - f->f_frame = (_PyInterpreterFrame *)f->_f_frame_data; + init_frame((_Py_framedata *)f->_f_owned_fdata, func, locals); + f->f_fdata = (_Py_framedata *)f->_f_owned_fdata; f->f_owns_frame = 1; Py_DECREF(func); _PyObject_GC_TRACK(f); @@ -836,11 +836,11 @@ PyFrame_New(PyThreadState *tstate, PyCodeObject *code, } static int -_PyFrame_OpAlreadyRan(_PyInterpreterFrame *frame, int opcode, int oparg) +_PyFrame_OpAlreadyRan(_Py_framedata *fdata, int opcode, int oparg) { const _Py_CODEUNIT *code = - (const _Py_CODEUNIT *)PyBytes_AS_STRING(frame->f_code->co_code); - for (int i = 0; i < frame->f_lasti; i++) { + (const _Py_CODEUNIT *)PyBytes_AS_STRING(fdata->code->co_code); + for (int i = 0; i < fdata->lasti; i++) { if (_Py_OPCODE(code[i]) == opcode && _Py_OPARG(code[i]) == oparg) { return 1; } @@ -849,30 +849,30 @@ _PyFrame_OpAlreadyRan(_PyInterpreterFrame *frame, int opcode, int oparg) } int -_PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame) { - /* Merge fast locals into f->f_locals */ +_PyFrame_FastToLocalsWithError(_Py_framedata *fdata) { + /* Merge fast locals into f->locals */ PyObject *locals; PyObject **fast; PyCodeObject *co; - locals = frame->f_locals; + locals = fdata->locals; if (locals == NULL) { - locals = frame->f_locals = PyDict_New(); + locals = fdata->locals = PyDict_New(); if (locals == NULL) return -1; } - co = frame->f_code; - fast = _PyFrame_GetLocalsArray(frame); - if (frame->f_lasti < 0 && _Py_OPCODE(co->co_firstinstr[0]) == COPY_FREE_VARS) { + co = fdata->code; + fast = _PyFrame_GetLocalsArray(fdata); + if (fdata->lasti < 0 && _Py_OPCODE(co->co_firstinstr[0]) == COPY_FREE_VARS) { /* Free vars have not been initialized -- Do that */ - PyCodeObject *co = frame->f_code; - PyObject *closure = frame->f_func->func_closure; + PyCodeObject *co = fdata->code; + PyObject *closure = fdata->func->func_closure; int offset = co->co_nlocals + co->co_nplaincellvars; for (int i = 0; i < co->co_nfreevars; ++i) { PyObject *o = PyTuple_GET_ITEM(closure, i); Py_INCREF(o); - frame->localsplus[offset + i] = o; + fdata->localsplus[offset + i] = o; } - frame->f_lasti = 0; + fdata->lasti = 0; } for (int i = 0; i < co->co_nlocalsplus; i++) { _PyLocals_Kind kind = _PyLocals_GetKind(co->co_localspluskinds, i); @@ -891,7 +891,7 @@ _PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame) { PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i); PyObject *value = fast[i]; - if (frame->f_state != FRAME_CLEARED) { + if (fdata->state != FRAME_CLEARED) { if (kind & CO_FAST_FREE) { // The cell was set by COPY_FREE_VARS. assert(value != NULL && PyCell_Check(value)); @@ -904,7 +904,7 @@ _PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame) { // run yet. if (value != NULL) { if (PyCell_Check(value) && - _PyFrame_OpAlreadyRan(frame, MAKE_CELL, i)) { + _PyFrame_OpAlreadyRan(fdata, MAKE_CELL, i)) { // (likely) MAKE_CELL must have executed already. value = PyCell_GET(value); } @@ -944,7 +944,7 @@ PyFrame_FastToLocalsWithError(PyFrameObject *f) PyErr_BadInternalCall(); return -1; } - return _PyFrame_FastToLocalsWithError(f->f_frame); + return _PyFrame_FastToLocalsWithError(f->f_fdata); } void @@ -960,18 +960,18 @@ PyFrame_FastToLocals(PyFrameObject *f) } void -_PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear) +_PyFrame_LocalsToFast(_Py_framedata *fdata, int clear) { /* Merge locals into fast locals */ PyObject *locals; PyObject **fast; PyObject *error_type, *error_value, *error_traceback; PyCodeObject *co; - locals = frame->f_locals; + locals = fdata->locals; if (locals == NULL) return; - fast = _PyFrame_GetLocalsArray(frame); - co = frame->f_code; + fast = _PyFrame_GetLocalsArray(fdata); + co = fdata->code; PyErr_Fetch(&error_type, &error_value, &error_traceback); for (int i = 0; i < co->co_nlocalsplus; i++) { @@ -1001,7 +1001,7 @@ _PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear) else if (kind & CO_FAST_CELL && oldvalue != NULL) { /* Same test as in PyFrame_FastToLocals() above. */ if (PyCell_Check(oldvalue) && - _PyFrame_OpAlreadyRan(frame, MAKE_CELL, i)) { + _PyFrame_OpAlreadyRan(fdata, MAKE_CELL, i)) { // (likely) MAKE_CELL must have executed already. cell = oldvalue; } @@ -1028,10 +1028,10 @@ _PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear) void PyFrame_LocalsToFast(PyFrameObject *f, int clear) { - if (f == NULL || f->f_frame->f_state == FRAME_CLEARED) { + if (f == NULL || f->f_fdata->state == FRAME_CLEARED) { return; } - _PyFrame_LocalsToFast(f->f_frame, clear); + _PyFrame_LocalsToFast(f->f_fdata, clear); } void @@ -1050,7 +1050,7 @@ PyCodeObject * PyFrame_GetCode(PyFrameObject *frame) { assert(frame != NULL); - PyCodeObject *code = frame->f_frame->f_code; + PyCodeObject *code = frame->f_fdata->code; assert(code != NULL); Py_INCREF(code); return code; @@ -1062,8 +1062,8 @@ PyFrame_GetBack(PyFrameObject *frame) { assert(frame != NULL); PyFrameObject *back = frame->f_back; - if (back == NULL && frame->f_frame->previous != NULL) { - back = _PyFrame_GetFrameObject(frame->f_frame->previous); + if (back == NULL && frame->f_fdata->previous != NULL) { + back = _PyFrame_GetFrameObject(frame->f_fdata->previous); } Py_XINCREF(back); return back; diff --git a/Objects/genobject.c b/Objects/genobject.c index 4fac0ce241c096..1dbd8c553b7478 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -7,7 +7,7 @@ #include "pycore_object.h" // _PyObject_GC_UNTRACK() #include "pycore_pyerrors.h" // _PyErr_ClearExcState() #include "pycore_pystate.h" // _PyThreadState_GET() -#include "pycore_frame.h" // _PyInterpreterFrame +#include "pycore_frame.h" // _Py_framedata #include "frameobject.h" // PyFrameObject #include "structmember.h" // PyMemberDef #include "opcode.h" // SEND @@ -36,9 +36,9 @@ gen_traverse(PyGenObject *gen, visitproc visit, void *arg) Py_VISIT(gen->gi_name); Py_VISIT(gen->gi_qualname); if (gen->gi_frame_valid) { - _PyInterpreterFrame *frame = (_PyInterpreterFrame *)(gen->gi_iframe); - assert(frame->frame_obj == NULL || frame->frame_obj->f_owns_frame == 0); - int err = _PyFrame_Traverse(frame, visit, arg); + _Py_framedata *fdata = (_Py_framedata *)(gen->gi_fdata); + assert(fdata->frame_obj == NULL || fdata->frame_obj->f_owns_frame == 0); + int err = _PyFrame_Traverse(fdata, visit, arg); if (err) { return err; } @@ -55,7 +55,7 @@ _PyGen_Finalize(PyObject *self) PyObject *res = NULL; PyObject *error_type, *error_value, *error_traceback; - if (gen->gi_frame_valid == 0 || _PyFrameHasCompleted((_PyInterpreterFrame *)gen->gi_iframe)) { + if (gen->gi_frame_valid == 0 || _PyFrameHasCompleted((_Py_framedata *)gen->gi_fdata)) { /* Generator isn't paused, so no need to close */ return; } @@ -87,7 +87,7 @@ _PyGen_Finalize(PyObject *self) issue a RuntimeWarning. */ if (gen->gi_code != NULL && ((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE && - ((_PyInterpreterFrame *)gen->gi_iframe)->f_state == FRAME_CREATED) + ((_Py_framedata *)gen->gi_fdata)->state == FRAME_CREATED) { _PyErr_WarnUnawaitedCoroutine((PyObject *)gen); } @@ -131,11 +131,11 @@ gen_dealloc(PyGenObject *gen) Py_CLEAR(((PyAsyncGenObject*)gen)->ag_origin_or_finalizer); } if (gen->gi_frame_valid) { - _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe; + _Py_framedata *fdata = (_Py_framedata *)gen->gi_fdata; gen->gi_frame_valid = 0; - frame->is_generator = false; - frame->previous = NULL; - _PyFrame_Clear(frame); + fdata->is_generator = false; + fdata->previous = NULL; + _PyFrame_Clear(fdata); } if (((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE) { Py_CLEAR(((PyCoroObject *)gen)->cr_origin_or_finalizer); @@ -152,11 +152,11 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, int exc, int closing) { PyThreadState *tstate = _PyThreadState_GET(); - _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe; + _Py_framedata *fdata = (_Py_framedata *)gen->gi_fdata; PyObject *result; *presult = NULL; - if (frame->f_state == FRAME_CREATED && arg && arg != Py_None) { + if (fdata->state == FRAME_CREATED && arg && arg != Py_None) { const char *msg = "can't send non-None value to a " "just-started generator"; if (PyCoro_CheckExact(gen)) { @@ -169,7 +169,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, PyErr_SetString(PyExc_TypeError, msg); return PYGEN_ERROR; } - if (gen->gi_frame_valid && _PyFrame_IsExecuting(frame)) { + if (gen->gi_frame_valid && _PyFrame_IsExecuting(fdata)) { const char *msg = "generator already executing"; if (PyCoro_CheckExact(gen)) { msg = "coroutine already executing"; @@ -180,7 +180,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, PyErr_SetString(PyExc_ValueError, msg); return PYGEN_ERROR; } - if (gen->gi_frame_valid == 0 || _PyFrameHasCompleted(frame)) { + if (gen->gi_frame_valid == 0 || _PyFrameHasCompleted(fdata)) { if (PyCoro_CheckExact(gen) && !closing) { /* `gen` is an exhausted coroutine: raise an error, except when called from gen_close(), which should @@ -200,13 +200,13 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, } assert(gen->gi_frame_valid); - assert(_PyFrame_IsRunnable(frame)); + assert(_PyFrame_IsRunnable(fdata)); /* Push arg onto the frame's value stack */ result = arg ? arg : Py_None; Py_INCREF(result); - _PyFrame_StackPush(frame, result); + _PyFrame_StackPush(fdata, result); - frame->previous = tstate->cframe->current_frame; + fdata->previous = tstate->cframe->current_frame; gen->gi_exc_state.previous_item = tstate->exc_info; tstate->exc_info = &gen->gi_exc_state; @@ -216,20 +216,20 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, _PyErr_ChainStackItem(NULL); } - result = _PyEval_EvalFrame(tstate, frame, exc); + result = _PyEval_EvalFrame(tstate, fdata, exc); tstate->exc_info = gen->gi_exc_state.previous_item; gen->gi_exc_state.previous_item = NULL; - assert(tstate->cframe->current_frame == frame->previous); + assert(tstate->cframe->current_frame == fdata->previous); /* Don't keep the reference to previous any longer than necessary. It * may keep a chain of frames alive or it could create a reference * cycle. */ - frame->previous = NULL; + fdata->previous = NULL; /* If the generator just returned (as opposed to yielding), signal * that the generator is exhausted. */ if (result) { - if (!_PyFrameHasCompleted(frame)) { + if (!_PyFrameHasCompleted(fdata)) { *presult = result; return PYGEN_NEXT; } @@ -265,9 +265,9 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult, /* first clean reference cycle through stored exception traceback */ _PyErr_ClearExcState(&gen->gi_exc_state); - frame->is_generator = false; + fdata->is_generator = false; gen->gi_frame_valid = 0; - _PyFrame_Clear(frame); + _PyFrame_Clear(fdata); *presult = result; return result ? PYGEN_RETURN : PYGEN_ERROR; } @@ -348,11 +348,11 @@ _PyGen_yf(PyGenObject *gen) PyObject *yf = NULL; if (gen->gi_frame_valid) { - _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe; + _Py_framedata *fdata = (_Py_framedata *)gen->gi_fdata; PyObject *bytecode = gen->gi_code->co_code; unsigned char *code = (unsigned char *)PyBytes_AS_STRING(bytecode); - if (frame->f_lasti < 1) { + if (fdata->lasti < 1) { /* Return immediately if the frame didn't start yet. SEND always come after LOAD_CONST: a code object should not start with SEND */ @@ -360,9 +360,9 @@ _PyGen_yf(PyGenObject *gen) return NULL; } - if (code[(frame->f_lasti-1)*sizeof(_Py_CODEUNIT)] != SEND || frame->stacktop < 0) + if (code[(fdata->lasti-1)*sizeof(_Py_CODEUNIT)] != SEND || fdata->stacktop < 0) return NULL; - yf = _PyFrame_StackPeek(frame); + yf = _PyFrame_StackPeek(fdata); Py_INCREF(yf); } @@ -377,11 +377,11 @@ gen_close(PyGenObject *gen, PyObject *args) int err = 0; if (yf) { - _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe; - PyFrameState state = frame->f_state; - frame->f_state = FRAME_EXECUTING; + _Py_framedata *fdata = (_Py_framedata *)gen->gi_fdata; + PyFrameState state = fdata->state; + fdata->state = FRAME_EXECUTING; err = gen_close_iter(yf); - frame->f_state = state; + fdata->state = state; Py_DECREF(yf); } if (err == 0) @@ -418,7 +418,7 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, PyObject *yf = _PyGen_yf(gen); if (yf) { - _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe; + _Py_framedata *fdata = (_Py_framedata *)gen->gi_fdata; PyObject *ret; int err; if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit) && @@ -428,10 +428,10 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, We have to allow some awaits to work it through, hence the `close_on_genexit` parameter here. */ - PyFrameState state = frame->f_state; - frame->f_state = FRAME_EXECUTING; + PyFrameState state = fdata->state; + fdata->state = FRAME_EXECUTING; err = gen_close_iter(yf); - frame->f_state = state; + fdata->state = state; Py_DECREF(yf); if (err < 0) return gen_send_ex(gen, Py_None, 1, 0); @@ -445,18 +445,18 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, will be reported correctly to the user. */ /* XXX We should probably be updating the current frame somewhere in ceval.c. */ - _PyInterpreterFrame *prev = tstate->cframe->current_frame; - frame->previous = prev; - tstate->cframe->current_frame = frame; + _Py_framedata *prev = tstate->cframe->current_frame; + fdata->previous = prev; + tstate->cframe->current_frame = fdata; /* Close the generator that we are currently iterating with 'yield from' or awaiting on with 'await'. */ - PyFrameState state = frame->f_state; - frame->f_state = FRAME_EXECUTING; + PyFrameState state = fdata->state; + fdata->state = FRAME_EXECUTING; ret = _gen_throw((PyGenObject *)yf, close_on_genexit, typ, val, tb); - frame->f_state = state; + fdata->state = state; tstate->cframe->current_frame = prev; - frame->previous = NULL; + fdata->previous = NULL; } else { /* `yf` is an iterator or a coroutine-like object. */ PyObject *meth; @@ -468,10 +468,10 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, Py_DECREF(yf); goto throw_here; } - PyFrameState state = frame->f_state; - frame->f_state = FRAME_EXECUTING; + PyFrameState state = fdata->state; + fdata->state = FRAME_EXECUTING; ret = PyObject_CallFunctionObjArgs(meth, typ, val, tb, NULL); - frame->f_state = state; + fdata->state = state; Py_DECREF(meth); } Py_DECREF(yf); @@ -479,18 +479,18 @@ _gen_throw(PyGenObject *gen, int close_on_genexit, PyObject *val; /* Pop subiterator from stack */ assert(gen->gi_frame_valid); - ret = _PyFrame_StackPop((_PyInterpreterFrame *)gen->gi_iframe); + ret = _PyFrame_StackPop((_Py_framedata *)gen->gi_fdata); assert(ret == yf); Py_DECREF(ret); /* Termination repetition of SEND loop */ - assert(frame->f_lasti >= 0); + assert(fdata->lasti >= 0); PyObject *bytecode = gen->gi_code->co_code; unsigned char *code = (unsigned char *)PyBytes_AS_STRING(bytecode); /* Backup to SEND */ - frame->f_lasti--; - assert(code[frame->f_lasti*sizeof(_Py_CODEUNIT)] == SEND); - int jump = code[frame->f_lasti*sizeof(_Py_CODEUNIT)+1]; - frame->f_lasti += jump; + fdata->lasti--; + assert(code[fdata->lasti*sizeof(_Py_CODEUNIT)] == SEND); + int jump = code[fdata->lasti*sizeof(_Py_CODEUNIT)+1]; + fdata->lasti += jump; if (_PyGen_FetchStopIterationValue(&val) == 0) { ret = gen_send(gen, val); Py_DECREF(val); @@ -757,7 +757,7 @@ gen_getrunning(PyGenObject *gen, void *Py_UNUSED(ignored)) if (gen->gi_frame_valid == 0) { Py_RETURN_FALSE; } - return PyBool_FromLong(_PyFrame_IsExecuting((_PyInterpreterFrame *)gen->gi_iframe)); + return PyBool_FromLong(_PyFrame_IsExecuting((_Py_framedata *)gen->gi_fdata)); } static PyObject * @@ -766,7 +766,7 @@ gen_getsuspended(PyGenObject *gen, void *Py_UNUSED(ignored)) if (gen->gi_frame_valid == 0) { Py_RETURN_FALSE; } - return PyBool_FromLong(((_PyInterpreterFrame *)gen->gi_iframe)->f_state == FRAME_SUSPENDED); + return PyBool_FromLong(((_Py_framedata *)gen->gi_fdata)->state == FRAME_SUSPENDED); } static PyObject * @@ -778,7 +778,7 @@ _gen_getframe(PyGenObject *gen, const char *const name) if (gen->gi_frame_valid == 0) { Py_RETURN_NONE; } - return _Py_XNewRef((PyObject *)_PyFrame_GetFrameObject((_PyInterpreterFrame *)gen->gi_iframe)); + return _Py_XNewRef((PyObject *)_PyFrame_GetFrameObject((_Py_framedata *)gen->gi_fdata)); } static PyObject * @@ -809,7 +809,7 @@ static PyObject * gen_sizeof(PyGenObject *gen, PyObject *Py_UNUSED(ignored)) { Py_ssize_t res; - res = offsetof(PyGenObject, gi_iframe) + offsetof(_PyInterpreterFrame, localsplus); + res = offsetof(PyGenObject, gi_fdata) + offsetof(_Py_framedata, localsplus); PyCodeObject *code = gen->gi_code; res += (code->co_nlocalsplus+code->co_stacksize) * sizeof(PyObject *); return PyLong_FromSsize_t(res); @@ -837,8 +837,8 @@ static PyAsyncMethods gen_as_async = { PyTypeObject PyGen_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "generator", /* tp_name */ - offsetof(PyGenObject, gi_iframe) + - offsetof(_PyInterpreterFrame, localsplus), /* tp_basicsize */ + offsetof(PyGenObject, gi_fdata) + + offsetof(_Py_framedata, localsplus), /* tp_basicsize */ sizeof(PyObject *), /* tp_itemsize */ /* methods */ (destructor)gen_dealloc, /* tp_dealloc */ @@ -912,7 +912,7 @@ make_gen(PyTypeObject *type, PyFunctionObject *func) } static PyObject * -compute_cr_origin(int origin_depth, _PyInterpreterFrame *current_frame); +compute_cr_origin(int origin_depth, _Py_framedata *current_frame); PyObject * _Py_MakeCoro(PyFunctionObject *func) @@ -961,7 +961,7 @@ static PyObject * gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f, PyObject *name, PyObject *qualname) { - PyCodeObject *code = f->f_frame->f_code; + PyCodeObject *code = f->f_fdata->code; int size = code->co_nlocalsplus + code->co_stacksize; PyGenObject *gen = PyObject_GC_NewVar(PyGenObject, type, size); if (gen == NULL) { @@ -969,15 +969,15 @@ gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f, return NULL; } /* Copy the frame */ - assert(f->f_frame->frame_obj == NULL); + assert(f->f_fdata->frame_obj == NULL); assert(f->f_owns_frame); - _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe; - _PyFrame_Copy((_PyInterpreterFrame *)f->_f_frame_data, frame); + _Py_framedata *fdata = (_Py_framedata *)gen->gi_fdata; + _PyFrame_Copy((_Py_framedata *)f->_f_owned_fdata, fdata); gen->gi_frame_valid = 1; - assert(frame->frame_obj == f); + assert(fdata->frame_obj == f); f->f_owns_frame = 0; - f->f_frame = frame; - frame->is_generator = true; + f->f_fdata = fdata; + fdata->is_generator = true; assert(PyObject_GC_IsTracked((PyObject *)f)); gen->gi_code = PyFrame_GetCode(f); Py_INCREF(gen->gi_code); @@ -1115,7 +1115,7 @@ cr_getsuspended(PyCoroObject *coro, void *Py_UNUSED(ignored)) if (coro->cr_frame_valid == 0) { Py_RETURN_FALSE; } - return PyBool_FromLong(((_PyInterpreterFrame *)coro->cr_iframe)->f_state == FRAME_SUSPENDED); + return PyBool_FromLong(((_Py_framedata *)coro->cr_fdata)->state == FRAME_SUSPENDED); } static PyObject * @@ -1124,7 +1124,7 @@ cr_getrunning(PyCoroObject *coro, void *Py_UNUSED(ignored)) if (coro->cr_frame_valid == 0) { Py_RETURN_FALSE; } - return PyBool_FromLong(_PyFrame_IsExecuting((_PyInterpreterFrame *)coro->cr_iframe)); + return PyBool_FromLong(_PyFrame_IsExecuting((_Py_framedata *)coro->cr_fdata)); } static PyObject * @@ -1182,8 +1182,8 @@ static PyAsyncMethods coro_as_async = { PyTypeObject PyCoro_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "coroutine", /* tp_name */ - offsetof(PyCoroObject, cr_iframe) + - offsetof(_PyInterpreterFrame, localsplus), /* tp_basicsize */ + offsetof(PyCoroObject, cr_fdata) + + offsetof(_Py_framedata, localsplus), /* tp_basicsize */ sizeof(PyObject *), /* tp_itemsize */ /* methods */ (destructor)gen_dealloc, /* tp_dealloc */ @@ -1322,13 +1322,13 @@ PyTypeObject _PyCoroWrapper_Type = { }; static PyObject * -compute_cr_origin(int origin_depth, _PyInterpreterFrame *current_frame) +compute_cr_origin(int origin_depth, _Py_framedata *current_frame) { - _PyInterpreterFrame *frame = current_frame; + _Py_framedata *fdata = current_frame; /* First count how many frames we have */ int frame_count = 0; - for (; frame && frame_count < origin_depth; ++frame_count) { - frame = frame->previous; + for (; fdata && frame_count < origin_depth; ++frame_count) { + fdata = fdata->previous; } /* Now collect them */ @@ -1336,19 +1336,19 @@ compute_cr_origin(int origin_depth, _PyInterpreterFrame *current_frame) if (cr_origin == NULL) { return NULL; } - frame = current_frame; + fdata = current_frame; for (int i = 0; i < frame_count; ++i) { - PyCodeObject *code = frame->f_code; + PyCodeObject *code = fdata->code; PyObject *frameinfo = Py_BuildValue("OiO", code->co_filename, - PyCode_Addr2Line(frame->f_code, frame->f_lasti*sizeof(_Py_CODEUNIT)), + PyCode_Addr2Line(fdata->code, fdata->lasti*sizeof(_Py_CODEUNIT)), code->co_name); if (!frameinfo) { Py_DECREF(cr_origin); return NULL; } PyTuple_SET_ITEM(cr_origin, i, frameinfo); - frame = frame->previous; + fdata = fdata->previous; } return cr_origin; @@ -1574,8 +1574,8 @@ static PyAsyncMethods async_gen_as_async = { PyTypeObject PyAsyncGen_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) "async_generator", /* tp_name */ - offsetof(PyAsyncGenObject, ag_iframe) + - offsetof(_PyInterpreterFrame, localsplus), /* tp_basicsize */ + offsetof(PyAsyncGenObject, ag_fdata) + + offsetof(_Py_framedata, localsplus), /* tp_basicsize */ sizeof(PyObject *), /* tp_itemsize */ /* methods */ (destructor)gen_dealloc, /* tp_dealloc */ @@ -2061,7 +2061,7 @@ static PyObject * async_gen_athrow_send(PyAsyncGenAThrow *o, PyObject *arg) { PyGenObject *gen = (PyGenObject*)o->agt_gen; - _PyInterpreterFrame *frame = (_PyInterpreterFrame *)gen->gi_iframe; + _Py_framedata *fdata = (_Py_framedata *)gen->gi_fdata; PyObject *retval; if (o->agt_state == AWAITABLE_STATE_CLOSED) { @@ -2071,7 +2071,7 @@ async_gen_athrow_send(PyAsyncGenAThrow *o, PyObject *arg) return NULL; } - if (gen->gi_frame_valid == 0 || _PyFrameHasCompleted(frame)) { + if (gen->gi_frame_valid == 0 || _PyFrameHasCompleted(fdata)) { o->agt_state = AWAITABLE_STATE_CLOSED; PyErr_SetNone(PyExc_StopIteration); return NULL; diff --git a/Objects/lnotab_notes.txt b/Objects/lnotab_notes.txt index 362b87a86a481f..75d028b58313f2 100644 --- a/Objects/lnotab_notes.txt +++ b/Objects/lnotab_notes.txt @@ -157,7 +157,7 @@ number of the current instruction changes. Re-computing the current line for every instruction is a little slow, though, so each time we compute the line number we save the bytecode indices where it's valid: - *instr_lb <= frame->f_lasti < *instr_ub + *instr_lb <= frame->lasti < *instr_ub is true so long as execution does not change lines. That is, *instr_lb holds the first bytecode index of the current line, and *instr_ub holds the first diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 78795150756130..5a2cf38144c8d0 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -12,7 +12,7 @@ #include "pycore_typeobject.h" // struct type_cache #include "pycore_unionobject.h" // _Py_union_type_or #include "frameobject.h" // PyFrameObject -#include "pycore_frame.h" // _PyInterpreterFrame +#include "pycore_frame.h" // _Py_framedata #include "opcode.h" // MAKE_CELL #include "structmember.h" // PyMemberDef @@ -8933,7 +8933,7 @@ super_descr_get(PyObject *self, PyObject *obj, PyObject *type) } static int -super_init_without_args(_PyInterpreterFrame *cframe, PyCodeObject *co, +super_init_without_args(_Py_framedata *fdata, PyCodeObject *co, PyTypeObject **type_p, PyObject **obj_p) { if (co->co_argcount == 0) { @@ -8942,13 +8942,13 @@ super_init_without_args(_PyInterpreterFrame *cframe, PyCodeObject *co, return -1; } - assert(cframe->f_code->co_nlocalsplus > 0); - PyObject *firstarg = _PyFrame_GetLocalsArray(cframe)[0]; + assert(fdata->code->co_nlocalsplus > 0); + PyObject *firstarg = _PyFrame_GetLocalsArray(fdata)[0]; // The first argument might be a cell. if (firstarg != NULL && (_PyLocals_GetKind(co->co_localspluskinds, 0) & CO_FAST_CELL)) { // "firstarg" is a cell here unless (very unlikely) super() // was called from the C-API before the first MAKE_CELL op. - if (cframe->f_lasti >= 0) { + if (fdata->lasti >= 0) { assert(_Py_OPCODE(*co->co_firstinstr) == MAKE_CELL || _Py_OPCODE(*co->co_firstinstr) == COPY_FREE_VARS); assert(PyCell_Check(firstarg)); firstarg = PyCell_GET(firstarg); @@ -8968,7 +8968,7 @@ super_init_without_args(_PyInterpreterFrame *cframe, PyCodeObject *co, PyObject *name = PyTuple_GET_ITEM(co->co_localsplusnames, i); assert(PyUnicode_Check(name)); if (_PyUnicode_Equal(name, &_Py_ID(__class__))) { - PyObject *cell = _PyFrame_GetLocalsArray(cframe)[i]; + PyObject *cell = _PyFrame_GetLocalsArray(fdata)[i]; if (cell == NULL || !PyCell_Check(cell)) { PyErr_SetString(PyExc_RuntimeError, "super(): bad __class__ cell"); @@ -9026,13 +9026,13 @@ super_init_impl(PyObject *self, PyTypeObject *type, PyObject *obj) { /* Call super(), without args -- fill in from __class__ and first local variable on the stack. */ PyThreadState *tstate = _PyThreadState_GET(); - _PyInterpreterFrame *cframe = tstate->cframe->current_frame; - if (cframe == NULL) { + _Py_framedata *fdata = tstate->cframe->current_frame; + if (fdata == NULL) { PyErr_SetString(PyExc_RuntimeError, "super(): no current frame"); return -1; } - int res = super_init_without_args(cframe, cframe->f_code, &type, &obj); + int res = super_init_without_args(fdata, fdata->code, &type, &obj); if (res < 0) { return -1; diff --git a/Python/_warnings.c b/Python/_warnings.c index be962e76cd8019..26760d36f30f83 100644 --- a/Python/_warnings.c +++ b/Python/_warnings.c @@ -848,8 +848,8 @@ setup_context(Py_ssize_t stack_level, PyObject **filename, int *lineno, *lineno = 1; } else { - globals = f->f_frame->f_globals; - *filename = f->f_frame->f_code->co_filename; + globals = f->f_fdata->globals; + *filename = f->f_fdata->code->co_filename; Py_INCREF(*filename); *lineno = PyFrame_GetLineNumber(f); Py_DECREF(f); diff --git a/Python/ceval.c b/Python/ceval.c index f7514796642196..66a044516a21db 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -59,33 +59,33 @@ static PyObject * do_call_core( #ifdef LLTRACE static int lltrace; static int prtrace(PyThreadState *, PyObject *, const char *); -static void lltrace_instruction(_PyInterpreterFrame *frame, int opcode, int oparg) +static void lltrace_instruction(_Py_framedata *fdata, int opcode, int oparg) { if (HAS_ARG(opcode)) { printf("%d: %d, %d\n", - frame->f_lasti, opcode, oparg); + fdata->lasti, opcode, oparg); } else { printf("%d: %d\n", - frame->f_lasti, opcode); + fdata->lasti, opcode); } } #endif static int call_trace(Py_tracefunc, PyObject *, - PyThreadState *, _PyInterpreterFrame *, + PyThreadState *, _Py_framedata *, int, PyObject *); static int call_trace_protected(Py_tracefunc, PyObject *, - PyThreadState *, _PyInterpreterFrame *, + PyThreadState *, _Py_framedata *, int, PyObject *); static void call_exc_trace(Py_tracefunc, PyObject *, - PyThreadState *, _PyInterpreterFrame *); + PyThreadState *, _Py_framedata *); static int maybe_call_line_trace(Py_tracefunc, PyObject *, - PyThreadState *, _PyInterpreterFrame *, int); -static void maybe_dtrace_line(_PyInterpreterFrame *, PyTraceInfo *, int); -static void dtrace_function_entry(_PyInterpreterFrame *); -static void dtrace_function_return(_PyInterpreterFrame *); + PyThreadState *, _Py_framedata *, int); +static void maybe_dtrace_line(_Py_framedata *, PyTraceInfo *, int); +static void dtrace_function_entry(_Py_framedata *); +static void dtrace_function_return(_Py_framedata *); -static PyObject * import_name(PyThreadState *, _PyInterpreterFrame *, +static PyObject * import_name(PyThreadState *, _Py_framedata *, PyObject *, PyObject *, PyObject *); static PyObject * import_from(PyThreadState *, PyObject *, PyObject *); static int import_all_from(PyThreadState *, PyObject *, PyObject *); @@ -97,12 +97,12 @@ static int check_except_star_type_valid(PyThreadState *tstate, PyObject* right); static void format_kwargs_error(PyThreadState *, PyObject *func, PyObject *kwargs); static void format_awaitable_error(PyThreadState *, PyTypeObject *, int); static int get_exception_handler(PyCodeObject *, int, int*, int*, int*); -static _PyInterpreterFrame * +static _Py_framedata * _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func, PyObject *locals, PyObject* const* args, size_t argcount, PyObject *kwnames); static void -_PyEvalFrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame *frame); +_PyEvalFrameClearAndPop(PyThreadState *tstate, _Py_framedata *fdata); #define NAME_ERROR_MSG \ "name '%.200s' is not defined" @@ -1111,14 +1111,14 @@ PyEval_EvalFrame(PyFrameObject *f) { /* Function kept for backward compatibility */ PyThreadState *tstate = _PyThreadState_GET(); - return _PyEval_EvalFrame(tstate, f->f_frame, 0); + return _PyEval_EvalFrame(tstate, f->f_fdata, 0); } PyObject * PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) { PyThreadState *tstate = _PyThreadState_GET(); - return _PyEval_EvalFrame(tstate, f->f_frame, throwflag); + return _PyEval_EvalFrame(tstate, f->f_fdata, throwflag); } @@ -1253,14 +1253,14 @@ eval_frame_handle_pending(PyThreadState *tstate) #ifdef Py_STATS #define INSTRUCTION_START(op) \ do { \ - frame->f_lasti = INSTR_OFFSET(); \ + fdata->lasti = INSTR_OFFSET(); \ next_instr++; \ OPCODE_EXE_INC(op); \ _py_stats.opcode_stats[lastopcode].pair_count[op]++; \ lastopcode = op; \ } while (0) #else -#define INSTRUCTION_START(op) frame->f_lasti = INSTR_OFFSET(); next_instr++ +#define INSTRUCTION_START(op) fdata->lasti = INSTR_OFFSET(); next_instr++ #endif #if USE_COMPUTED_GOTOS @@ -1273,7 +1273,7 @@ eval_frame_handle_pending(PyThreadState *tstate) /* PRE_DISPATCH_GOTO() does lltrace if enabled. Normally a no-op */ #ifdef LLTRACE -#define PRE_DISPATCH_GOTO() if (lltrace) { lltrace_instruction(frame, opcode, oparg); } +#define PRE_DISPATCH_GOTO() if (lltrace) { lltrace_instruction(fdata, opcode, oparg); } #else #define PRE_DISPATCH_GOTO() ((void)0) #endif @@ -1327,7 +1327,7 @@ eval_frame_handle_pending(PyThreadState *tstate) /* Get opcode and oparg from original instructions, not quickened form. */ #define TRACING_NEXTOPARG() do { \ - _Py_CODEUNIT word = ((_Py_CODEUNIT *)PyBytes_AS_STRING(frame->f_code->co_code))[INSTR_OFFSET()]; \ + _Py_CODEUNIT word = ((_Py_CODEUNIT *)PyBytes_AS_STRING(fdata->code->co_code))[INSTR_OFFSET()]; \ opcode = _Py_OPCODE(word); \ oparg = _Py_OPARG(word); \ } while (0) @@ -1381,7 +1381,7 @@ eval_frame_handle_pending(PyThreadState *tstate) /* The stack can grow at most MAXINT deep, as co_nlocals and co_stacksize are ints. */ -#define STACK_LEVEL() ((int)(stack_pointer - _PyFrame_Stackbase(frame))) +#define STACK_LEVEL() ((int)(stack_pointer - _PyFrame_Stackbase(fdata))) #define EMPTY() (STACK_LEVEL() == 0) #define TOP() (stack_pointer[-1]) #define SECOND() (stack_pointer[-2]) @@ -1397,20 +1397,20 @@ eval_frame_handle_pending(PyThreadState *tstate) #ifdef LLTRACE #define PUSH(v) { (void)(BASIC_PUSH(v), \ lltrace && prtrace(tstate, TOP(), "push")); \ - assert(STACK_LEVEL() <= frame->f_code->co_stacksize); } + assert(STACK_LEVEL() <= fdata->code->co_stacksize); } #define POP() ((void)(lltrace && prtrace(tstate, TOP(), "pop")), \ BASIC_POP()) #define STACK_GROW(n) do { \ assert(n >= 0); \ (void)(BASIC_STACKADJ(n), \ lltrace && prtrace(tstate, TOP(), "stackadj")); \ - assert(STACK_LEVEL() <= frame->f_code->co_stacksize); \ + assert(STACK_LEVEL() <= fdata->code->co_stacksize); \ } while (0) #define STACK_SHRINK(n) do { \ assert(n >= 0); \ (void)(lltrace && prtrace(tstate, TOP(), "stackadj")); \ (void)(BASIC_STACKADJ(-(n))); \ - assert(STACK_LEVEL() <= frame->f_code->co_stacksize); \ + assert(STACK_LEVEL() <= fdata->code->co_stacksize); \ } while (0) #else #define PUSH(v) BASIC_PUSH(v) @@ -1421,7 +1421,7 @@ eval_frame_handle_pending(PyThreadState *tstate) /* Local variable macros */ -#define GETLOCAL(i) (frame->localsplus[i]) +#define GETLOCAL(i) (fdata->localsplus[i]) /* The SETLOCAL() macro must not DECREF the local variable in-place and then store the new value; it must copy the old value to a temporary @@ -1441,9 +1441,9 @@ eval_frame_handle_pending(PyThreadState *tstate) #define UPDATE_PREV_INSTR_OPARG(instr, oparg) ((uint8_t*)(instr))[-1] = (oparg) -#define GLOBALS() frame->f_globals -#define BUILTINS() frame->f_builtins -#define LOCALS() frame->f_locals +#define GLOBALS() fdata->globals +#define BUILTINS() fdata->builtins +#define LOCALS() fdata->locals /* Shared opcode macros */ @@ -1465,7 +1465,7 @@ eval_frame_handle_pending(PyThreadState *tstate) #define TRACE_FUNCTION_EXIT() \ if (cframe.use_tracing) { \ - if (trace_function_exit(tstate, frame, retval)) { \ + if (trace_function_exit(tstate, fdata, retval)) { \ Py_DECREF(retval); \ goto exit_unwind; \ } \ @@ -1473,21 +1473,21 @@ eval_frame_handle_pending(PyThreadState *tstate) #define DTRACE_FUNCTION_EXIT() \ if (PyDTrace_FUNCTION_RETURN_ENABLED()) { \ - dtrace_function_return(frame); \ + dtrace_function_return(fdata); \ } #define TRACE_FUNCTION_UNWIND() \ if (cframe.use_tracing) { \ /* Since we are already unwinding, \ * we dont't care if this raises */ \ - trace_function_exit(tstate, frame, NULL); \ + trace_function_exit(tstate, fdata, NULL); \ } #define TRACE_FUNCTION_ENTRY() \ if (cframe.use_tracing) { \ - _PyFrame_SetStackPointer(frame, stack_pointer); \ - int err = trace_function_entry(tstate, frame); \ - stack_pointer = _PyFrame_GetStackPointer(frame); \ + _PyFrame_SetStackPointer(fdata, stack_pointer); \ + int err = trace_function_entry(tstate, fdata); \ + stack_pointer = _PyFrame_GetStackPointer(fdata); \ if (err) { \ goto error; \ } \ @@ -1495,21 +1495,21 @@ eval_frame_handle_pending(PyThreadState *tstate) #define TRACE_FUNCTION_THROW_ENTRY() \ if (cframe.use_tracing) { \ - assert(frame->stacktop >= 0); \ - if (trace_function_entry(tstate, frame)) { \ + assert(fdata->stacktop >= 0); \ + if (trace_function_entry(tstate, fdata)) { \ goto exit_unwind; \ } \ } #define DTRACE_FUNCTION_ENTRY() \ if (PyDTrace_FUNCTION_ENTRY_ENABLED()) { \ - dtrace_function_entry(frame); \ + dtrace_function_entry(fdata); \ } static int -trace_function_entry(PyThreadState *tstate, _PyInterpreterFrame *frame) +trace_function_entry(PyThreadState *tstate, _Py_framedata *fdata) { if (tstate->c_tracefunc != NULL) { /* tstate->c_tracefunc, if defined, is a @@ -1527,7 +1527,7 @@ trace_function_entry(PyThreadState *tstate, _PyInterpreterFrame *frame) whenever an exception is detected. */ if (call_trace_protected(tstate->c_tracefunc, tstate->c_traceobj, - tstate, frame, + tstate, fdata, PyTrace_CALL, Py_None)) { /* Trace function raised an error */ return -1; @@ -1538,7 +1538,7 @@ trace_function_entry(PyThreadState *tstate, _PyInterpreterFrame *frame) return itself and isn't called for "line" events */ if (call_trace_protected(tstate->c_profilefunc, tstate->c_profileobj, - tstate, frame, + tstate, fdata, PyTrace_CALL, Py_None)) { /* Profile function raised an error */ return -1; @@ -1548,17 +1548,17 @@ trace_function_entry(PyThreadState *tstate, _PyInterpreterFrame *frame) } static int -trace_function_exit(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *retval) +trace_function_exit(PyThreadState *tstate, _Py_framedata *fdata, PyObject *retval) { if (tstate->c_tracefunc) { if (call_trace_protected(tstate->c_tracefunc, tstate->c_traceobj, - tstate, frame, PyTrace_RETURN, retval)) { + tstate, fdata, PyTrace_RETURN, retval)) { return -1; } } if (tstate->c_profilefunc) { if (call_trace_protected(tstate->c_profilefunc, tstate->c_profileobj, - tstate, frame, PyTrace_RETURN, retval)) { + tstate, fdata, PyTrace_RETURN, retval)) { return -1; } } @@ -1575,11 +1575,11 @@ skip_backwards_over_extended_args(PyCodeObject *code, int offset) return offset; } -static _PyInterpreterFrame * -pop_frame(PyThreadState *tstate, _PyInterpreterFrame *frame) +static _Py_framedata * +pop_frame(PyThreadState *tstate, _Py_framedata *fdata) { - _PyInterpreterFrame *prev_frame = frame->previous; - _PyEvalFrameClearAndPop(tstate, frame); + _Py_framedata *prev_frame = fdata->previous; + _PyEvalFrameClearAndPop(tstate, fdata); return prev_frame; } @@ -1599,7 +1599,7 @@ is_method(PyObject **stack_pointer, int args) { (call_shape.kwnames == NULL ? 0 : ((int)PyTuple_GET_SIZE(call_shape.kwnames))) PyObject* _Py_HOT_FUNCTION -_PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag) +_PyEval_EvalFrameDefault(PyThreadState *tstate, _Py_framedata *fdata, int throwflag) { _Py_EnsureTstateNotNULL(tstate); CALL_STAT_INC(pyeval_calls); @@ -1629,10 +1629,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int cframe.previous = prev_cframe; tstate->cframe = &cframe; - frame->is_entry = true; + fdata->is_entry = true; /* Push frame */ - frame->previous = prev_cframe->current_frame; - cframe.current_frame = frame; + fdata->previous = prev_cframe->current_frame; + cframe.current_frame = fdata; /* support for generator.throw() */ if (throwflag) { @@ -1657,21 +1657,21 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int /* Sets the above local variables from the frame */ #define SET_LOCALS_FROM_FRAME() \ { \ - PyCodeObject *co = frame->f_code; \ + PyCodeObject *co = fdata->code; \ names = co->co_names; \ consts = co->co_consts; \ first_instr = co->co_firstinstr; \ } \ - assert(frame->f_lasti >= -1); \ - next_instr = first_instr + frame->f_lasti + 1; \ - stack_pointer = _PyFrame_GetStackPointer(frame); \ + assert(fdata->lasti >= -1); \ + next_instr = first_instr + fdata->lasti + 1; \ + stack_pointer = _PyFrame_GetStackPointer(fdata); \ /* Set stackdepth to -1. \ Update when returning or calling trace function. \ Having stackdepth <= 0 ensures that invalid \ values are not visible to the cycle GC. \ We choose -1 rather than 0 to assist debugging. \ */ \ - frame->stacktop = -1; + fdata->stacktop = -1; start_frame: @@ -1732,14 +1732,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(RESUME) { - int err = _Py_IncrementCountAndMaybeQuicken(frame->f_code); + int err = _Py_IncrementCountAndMaybeQuicken(fdata->code); if (err) { if (err < 0) { goto error; } /* Update first_instr and next_instr to point to newly quickened code */ int nexti = INSTR_OFFSET(); - first_instr = frame->f_code->co_firstinstr; + first_instr = fdata->code->co_firstinstr; next_instr = first_instr + nexti; } JUMP_TO_INSTRUCTION(RESUME_QUICK); @@ -1748,8 +1748,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TARGET(RESUME_QUICK) { PREDICTED(RESUME_QUICK); assert(tstate->cframe == &cframe); - assert(frame == cframe.current_frame); - frame->f_state = FRAME_EXECUTING; + assert(fdata == cframe.current_frame); + fdata->state = FRAME_EXECUTING; if (_Py_atomic_load_relaxed(eval_breaker) && oparg < 2) { goto handle_eval_breaker; } @@ -2209,24 +2209,24 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyCodeObject *code = (PyCodeObject *)getitem->func_code; size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE; assert(code->co_argcount == 2); - _PyInterpreterFrame *new_frame = _PyThreadState_BumpFramePointer(tstate, size); - if (new_frame == NULL) { + _Py_framedata *new_fdata = _PyThreadState_BumpFramePointer(tstate, size); + if (new_fdata == NULL) { goto error; } CALL_STAT_INC(frames_pushed); Py_INCREF(getitem); - _PyFrame_InitializeSpecials(new_frame, getitem, + _PyFrame_InitializeSpecials(new_fdata, getitem, NULL, code->co_nlocalsplus); STACK_SHRINK(2); - new_frame->localsplus[0] = container; - new_frame->localsplus[1] = sub; + new_fdata->localsplus[0] = container; + new_fdata->localsplus[1] = sub; for (int i = 2; i < code->co_nlocalsplus; i++) { - new_frame->localsplus[i] = NULL; + new_fdata->localsplus[i] = NULL; } - _PyFrame_SetStackPointer(frame, stack_pointer); - frame->f_lasti += INLINE_CACHE_ENTRIES_BINARY_SUBSCR; - new_frame->previous = frame; - frame = cframe.current_frame = new_frame; + _PyFrame_SetStackPointer(fdata, stack_pointer); + fdata->lasti += INLINE_CACHE_ENTRIES_BINARY_SUBSCR; + new_fdata->previous = fdata; + fdata = cframe.current_frame = new_fdata; CALL_STAT_INC(inlined_py_calls); goto start_frame; } @@ -2392,20 +2392,20 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TARGET(RETURN_VALUE) { PyObject *retval = POP(); assert(EMPTY()); - frame->f_state = FRAME_RETURNED; - _PyFrame_SetStackPointer(frame, stack_pointer); + fdata->state = FRAME_RETURNED; + _PyFrame_SetStackPointer(fdata, stack_pointer); TRACE_FUNCTION_EXIT(); DTRACE_FUNCTION_EXIT(); _Py_LeaveRecursiveCall(tstate); - if (!frame->is_entry) { - frame = cframe.current_frame = pop_frame(tstate, frame); - _PyFrame_StackPush(frame, retval); + if (!fdata->is_entry) { + fdata = cframe.current_frame = pop_frame(tstate, fdata); + _PyFrame_StackPush(fdata, retval); goto resume_frame; } /* Restore previous cframe and return. */ tstate->cframe = cframe.previous; tstate->cframe->use_tracing = cframe.use_tracing; - assert(tstate->cframe->current_frame == frame->previous); + assert(tstate->cframe->current_frame == fdata->previous); assert(!_PyErr_Occurred(tstate)); return retval; } @@ -2541,7 +2541,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(SEND) { - assert(frame->is_entry); + assert(fdata->is_entry); assert(STACK_LEVEL() >= 2); PyObject *v = POP(); PyObject *receiver = TOP(); @@ -2559,7 +2559,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (retval == NULL) { if (tstate->c_tracefunc != NULL && _PyErr_ExceptionMatches(tstate, PyExc_StopIteration)) - call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, tstate, frame); + call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, tstate, fdata); if (_PyGen_FetchStopIterationValue(&retval) == 0) { gen_status = PYGEN_RETURN; } @@ -2591,7 +2591,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TARGET(ASYNC_GEN_WRAP) { PyObject *v = TOP(); - assert(frame->f_code->co_flags & CO_ASYNC_GENERATOR); + assert(fdata->code->co_flags & CO_ASYNC_GENERATOR); PyObject *w = _PyAsyncGenValueWrapperNew(v); if (w == NULL) { goto error; @@ -2602,17 +2602,17 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(YIELD_VALUE) { - assert(frame->is_entry); + assert(fdata->is_entry); PyObject *retval = POP(); - frame->f_state = FRAME_SUSPENDED; - _PyFrame_SetStackPointer(frame, stack_pointer); + fdata->state = FRAME_SUSPENDED; + _PyFrame_SetStackPointer(fdata, stack_pointer); TRACE_FUNCTION_EXIT(); DTRACE_FUNCTION_EXIT(); _Py_LeaveRecursiveCall(tstate); /* Restore previous cframe and return. */ tstate->cframe = cframe.previous; tstate->cframe->use_tracing = cframe.use_tracing; - assert(tstate->cframe->current_frame == frame->previous); + assert(tstate->cframe->current_frame == fdata->previous); assert(!_PyErr_Occurred(tstate)); return retval; } @@ -2629,7 +2629,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int if (oparg) { PyObject *lasti = PEEK(oparg + 1); if (PyLong_Check(lasti)) { - frame->f_lasti = PyLong_AsLong(lasti); + fdata->lasti = PyLong_AsLong(lasti); assert(!_PyErr_Occurred(tstate)); } else { @@ -3093,15 +3093,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int Py_DECREF(oldobj); DISPATCH(); } - format_exc_unbound(tstate, frame->f_code, oparg); + format_exc_unbound(tstate, fdata->code, oparg); goto error; } TARGET(LOAD_CLASSDEREF) { PyObject *name, *value, *locals = LOCALS(); assert(locals); - assert(oparg >= 0 && oparg < frame->f_code->co_nlocalsplus); - name = PyTuple_GET_ITEM(frame->f_code->co_localsplusnames, oparg); + assert(oparg >= 0 && oparg < fdata->code->co_nlocalsplus); + name = PyTuple_GET_ITEM(fdata->code->co_localsplusnames, oparg); if (PyDict_CheckExact(locals)) { value = PyDict_GetItemWithError(locals, name); if (value != NULL) { @@ -3124,7 +3124,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyObject *cell = GETLOCAL(oparg); value = PyCell_GET(cell); if (value == NULL) { - format_exc_unbound(tstate, frame->f_code, oparg); + format_exc_unbound(tstate, fdata->code, oparg); goto error; } Py_INCREF(value); @@ -3137,7 +3137,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyObject *cell = GETLOCAL(oparg); PyObject *value = PyCell_GET(cell); if (value == NULL) { - format_exc_unbound(tstate, frame->f_code, oparg); + format_exc_unbound(tstate, fdata->code, oparg); goto error; } Py_INCREF(value); @@ -3156,14 +3156,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TARGET(COPY_FREE_VARS) { /* Copy closure variables to free variables */ - PyCodeObject *co = frame->f_code; - PyObject *closure = frame->f_func->func_closure; + PyCodeObject *co = fdata->code; + PyObject *closure = fdata->func->func_closure; int offset = co->co_nlocals + co->co_nplaincellvars; assert(oparg == co->co_nfreevars); for (int i = 0; i < oparg; ++i) { PyObject *o = PyTuple_GET_ITEM(closure, i); Py_INCREF(o); - frame->localsplus[offset + i] = o; + fdata->localsplus[offset + i] = o; } DISPATCH(); } @@ -3892,7 +3892,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyObject *fromlist = POP(); PyObject *level = TOP(); PyObject *res; - res = import_name(tstate, frame, name, fromlist, level); + res = import_name(tstate, fdata, name, fromlist, level); Py_DECREF(level); Py_DECREF(fromlist); SET_TOP(res); @@ -3904,7 +3904,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TARGET(IMPORT_STAR) { PyObject *from = POP(), *locals; int err; - if (_PyFrame_FastToLocalsWithError(frame) < 0) { + if (_PyFrame_FastToLocalsWithError(fdata) < 0) { Py_DECREF(from); goto error; } @@ -3917,7 +3917,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int goto error; } err = import_all_from(tstate, locals, from); - _PyFrame_LocalsToFast(frame, 0); + _PyFrame_LocalsToFast(fdata, 0); Py_DECREF(from); if (err != 0) goto error; @@ -4069,14 +4069,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TARGET(JUMP_ABSOLUTE) { PREDICTED(JUMP_ABSOLUTE); - int err = _Py_IncrementCountAndMaybeQuicken(frame->f_code); + int err = _Py_IncrementCountAndMaybeQuicken(fdata->code); if (err) { if (err < 0) { goto error; } /* Update first_instr and next_instr to point to newly quickened code */ int nexti = INSTR_OFFSET(); - first_instr = frame->f_code->co_firstinstr; + first_instr = fdata->code->co_firstinstr; next_instr = first_instr + nexti; } JUMP_TO_INSTRUCTION(JUMP_ABSOLUTE_QUICK); @@ -4088,7 +4088,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int * generator or coroutine, so we deliberately do not check it here. * (see bpo-30039). */ - frame->f_state = FRAME_EXECUTING; + fdata->state = FRAME_EXECUTING; JUMPTO(oparg); DISPATCH(); } @@ -4193,7 +4193,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyObject *iter; if (PyCoro_CheckExact(iterable)) { /* `iterable` is a coroutine */ - if (!(frame->f_code->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { + if (!(fdata->code->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) { /* and it is used in a 'yield from' expression of a regular generator. */ Py_DECREF(iterable); @@ -4237,7 +4237,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int goto error; } else if (tstate->c_tracefunc != NULL) { - call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, tstate, frame); + call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, tstate, fdata); } _PyErr_Clear(tstate); } @@ -4631,7 +4631,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(function))->co_flags; PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : PyFunction_GET_GLOBALS(function); STACK_SHRINK(total_args); - _PyInterpreterFrame *new_frame = _PyEvalFramePushAndInit( + _Py_framedata *new_fdata = _PyEvalFramePushAndInit( tstate, (PyFunctionObject *)function, locals, stack_pointer, positional_args, call_shape.kwnames ); @@ -4639,13 +4639,13 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int STACK_SHRINK(2-is_meth); // The frame has stolen all the arguments from the stack, // so there is no need to clean them up. - if (new_frame == NULL) { + if (new_fdata == NULL) { goto error; } - _PyFrame_SetStackPointer(frame, stack_pointer); - frame->f_lasti += INLINE_CACHE_ENTRIES_CALL; - new_frame->previous = frame; - cframe.current_frame = frame = new_frame; + _PyFrame_SetStackPointer(fdata, stack_pointer); + fdata->lasti += INLINE_CACHE_ENTRIES_CALL; + new_fdata->previous = fdata; + cframe.current_frame = fdata = new_fdata; CALL_STAT_INC(inlined_py_calls); goto start_frame; } @@ -4734,23 +4734,23 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int PyCodeObject *code = (PyCodeObject *)func->func_code; DEOPT_IF(code->co_argcount != argcount, CALL); STAT_INC(CALL, hit); - _PyInterpreterFrame *new_frame = _PyFrame_Push(tstate, func); - if (new_frame == NULL) { + _Py_framedata *new_fdata = _PyFrame_Push(tstate, func); + if (new_fdata == NULL) { goto error; } CALL_STAT_INC(inlined_py_calls); STACK_SHRINK(argcount); for (int i = 0; i < argcount; i++) { - new_frame->localsplus[i] = stack_pointer[i]; + new_fdata->localsplus[i] = stack_pointer[i]; } for (int i = argcount; i < code->co_nlocalsplus; i++) { - new_frame->localsplus[i] = NULL; + new_fdata->localsplus[i] = NULL; } STACK_SHRINK(2-is_meth); - _PyFrame_SetStackPointer(frame, stack_pointer); - frame->f_lasti += INLINE_CACHE_ENTRIES_CALL; - new_frame->previous = frame; - frame = cframe.current_frame = new_frame; + _PyFrame_SetStackPointer(fdata, stack_pointer); + fdata->lasti += INLINE_CACHE_ENTRIES_CALL; + new_fdata->previous = fdata; + fdata = cframe.current_frame = new_fdata; goto start_frame; } @@ -4768,29 +4768,29 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int int minargs = cache->min_args; DEOPT_IF(argcount < minargs, CALL); STAT_INC(CALL, hit); - _PyInterpreterFrame *new_frame = _PyFrame_Push(tstate, func); - if (new_frame == NULL) { + _Py_framedata *new_fdata = _PyFrame_Push(tstate, func); + if (new_fdata == NULL) { goto error; } CALL_STAT_INC(inlined_py_calls); STACK_SHRINK(argcount); for (int i = 0; i < argcount; i++) { - new_frame->localsplus[i] = stack_pointer[i]; + new_fdata->localsplus[i] = stack_pointer[i]; } for (int i = argcount; i < code->co_argcount; i++) { PyObject *def = PyTuple_GET_ITEM(func->func_defaults, i - minargs); Py_INCREF(def); - new_frame->localsplus[i] = def; + new_fdata->localsplus[i] = def; } for (int i = code->co_argcount; i < code->co_nlocalsplus; i++) { - new_frame->localsplus[i] = NULL; + new_fdata->localsplus[i] = NULL; } STACK_SHRINK(2-is_meth); - _PyFrame_SetStackPointer(frame, stack_pointer); - frame->f_lasti += INLINE_CACHE_ENTRIES_CALL; - new_frame->previous = frame; - frame = cframe.current_frame = new_frame; + _PyFrame_SetStackPointer(fdata, stack_pointer); + fdata->lasti += INLINE_CACHE_ENTRIES_CALL; + new_fdata->previous = fdata; + fdata = cframe.current_frame = new_fdata; goto start_frame; } @@ -5264,35 +5264,35 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int } TARGET(RETURN_GENERATOR) { - PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(frame->f_func); + PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(fdata->func); if (gen == NULL) { goto error; } assert(EMPTY()); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe; - _PyFrame_Copy(frame, gen_frame); - assert(frame->frame_obj == NULL); + _PyFrame_SetStackPointer(fdata, stack_pointer); + _Py_framedata *gen_fdata = (_Py_framedata *)gen->gi_fdata; + _PyFrame_Copy(fdata, gen_fdata); + assert(fdata->frame_obj == NULL); gen->gi_frame_valid = 1; - gen_frame->is_generator = true; - gen_frame->f_state = FRAME_CREATED; + gen_fdata->is_generator = true; + gen_fdata->state = FRAME_CREATED; _Py_LeaveRecursiveCall(tstate); - if (!frame->is_entry) { - _PyInterpreterFrame *prev = frame->previous; - _PyThreadState_PopFrame(tstate, frame); - frame = cframe.current_frame = prev; - _PyFrame_StackPush(frame, (PyObject *)gen); + if (!fdata->is_entry) { + _Py_framedata *prev = fdata->previous; + _PyThreadState_PopFrame(tstate, fdata); + fdata = cframe.current_frame = prev; + _PyFrame_StackPush(fdata, (PyObject *)gen); goto resume_frame; } /* Make sure that frame is in a valid state */ - frame->stacktop = 0; - frame->f_locals = NULL; - Py_INCREF(frame->f_func); - Py_INCREF(frame->f_code); + fdata->stacktop = 0; + fdata->locals = NULL; + Py_INCREF(fdata->func); + Py_INCREF(fdata->code); /* Restore previous cframe and return. */ tstate->cframe = cframe.previous; tstate->cframe->use_tracing = cframe.use_tracing; - assert(tstate->cframe->current_frame == frame->previous); + assert(tstate->cframe->current_frame == fdata->previous); assert(!_PyErr_Occurred(tstate)); return (PyObject *)gen; } @@ -5443,8 +5443,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int #else case DO_TRACING: { #endif - int instr_prev = skip_backwards_over_extended_args(frame->f_code, frame->f_lasti); - frame->f_lasti = INSTR_OFFSET(); + int instr_prev = skip_backwards_over_extended_args(fdata->code, fdata->lasti); + fdata->lasti = INSTR_OFFSET(); TRACING_NEXTOPARG(); if (opcode == RESUME) { if (oparg < 2) { @@ -5454,10 +5454,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int TRACE_FUNCTION_ENTRY(); DTRACE_FUNCTION_ENTRY(); } - else if (frame->f_state > FRAME_CREATED) { + else if (fdata->state > FRAME_CREATED) { /* line-by-line tracing support */ if (PyDTrace_LINE_ENABLED()) { - maybe_dtrace_line(frame, &tstate->trace_info, instr_prev); + maybe_dtrace_line(fdata, &tstate->trace_info, instr_prev); } if (cframe.use_tracing && @@ -5465,21 +5465,21 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int int err; /* see maybe_call_line_trace() for expository comments */ - _PyFrame_SetStackPointer(frame, stack_pointer); + _PyFrame_SetStackPointer(fdata, stack_pointer); err = maybe_call_line_trace(tstate->c_tracefunc, tstate->c_traceobj, - tstate, frame, instr_prev); + tstate, fdata, instr_prev); if (err) { /* trace function raised an exception */ next_instr++; goto error; } /* Reload possibly changed frame fields */ - JUMPTO(frame->f_lasti); + JUMPTO(fdata->lasti); - stack_pointer = _PyFrame_GetStackPointer(frame); - frame->stacktop = -1; + stack_pointer = _PyFrame_GetStackPointer(fdata); + fdata->stacktop = -1; } } TRACING_NEXTOPARG(); @@ -5495,7 +5495,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int #endif fprintf(stderr, "XXX lineno: %d, opcode: %d\n", - PyCode_Addr2Line(frame->f_code, frame->f_lasti*sizeof(_Py_CODEUNIT)), + PyCode_Addr2Line(fdata->code, fdata->lasti*sizeof(_Py_CODEUNIT)), opcode); _PyErr_SetString(tstate, PyExc_SystemError, "unknown opcode"); goto error; @@ -5550,7 +5550,7 @@ MISS_WITH_INLINE_CACHE(STORE_SUBSCR) { format_exc_check_arg(tstate, PyExc_UnboundLocalError, UNBOUNDLOCAL_ERROR_MSG, - PyTuple_GetItem(frame->f_code->co_localsplusnames, oparg) + PyTuple_GetItem(fdata->code->co_localsplusnames, oparg) ); goto error; } @@ -5568,50 +5568,50 @@ MISS_WITH_INLINE_CACHE(STORE_SUBSCR) #endif /* Log traceback info. */ - PyFrameObject *f = _PyFrame_GetFrameObject(frame); + PyFrameObject *f = _PyFrame_GetFrameObject(fdata); if (f != NULL) { PyTraceBack_Here(f); } if (tstate->c_tracefunc != NULL) { /* Make sure state is set to FRAME_UNWINDING for tracing */ - frame->f_state = FRAME_UNWINDING; + fdata->state = FRAME_UNWINDING; call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, - tstate, frame); + tstate, fdata); } exception_unwind: - frame->f_state = FRAME_UNWINDING; - /* We can't use frame->f_lasti here, as RERAISE may have set it */ + fdata->state = FRAME_UNWINDING; + /* We can't use fdata->lasti here, as RERAISE may have set it */ int offset = INSTR_OFFSET()-1; int level, handler, lasti; - if (get_exception_handler(frame->f_code, offset, &level, &handler, &lasti) == 0) { + if (get_exception_handler(fdata->code, offset, &level, &handler, &lasti) == 0) { // No handlers, so exit. assert(_PyErr_Occurred(tstate)); /* Pop remaining stack entries. */ - PyObject **stackbase = _PyFrame_Stackbase(frame); + PyObject **stackbase = _PyFrame_Stackbase(fdata); while (stack_pointer > stackbase) { PyObject *o = POP(); Py_XDECREF(o); } assert(STACK_LEVEL() == 0); - _PyFrame_SetStackPointer(frame, stack_pointer); - frame->f_state = FRAME_RAISED; + _PyFrame_SetStackPointer(fdata, stack_pointer); + fdata->state = FRAME_RAISED; TRACE_FUNCTION_UNWIND(); DTRACE_FUNCTION_EXIT(); goto exit_unwind; } assert(STACK_LEVEL() >= level); - PyObject **new_top = _PyFrame_Stackbase(frame) + level; + PyObject **new_top = _PyFrame_Stackbase(fdata) + level; while (stack_pointer > new_top) { PyObject *v = POP(); Py_XDECREF(v); } PyObject *exc, *val, *tb; if (lasti) { - PyObject *lasti = PyLong_FromLong(frame->f_lasti); + PyObject *lasti = PyLong_FromLong(fdata->lasti); if (lasti == NULL) { goto exception_unwind; } @@ -5632,21 +5632,21 @@ MISS_WITH_INLINE_CACHE(STORE_SUBSCR) PUSH(val); JUMPTO(handler); /* Resume normal execution */ - frame->f_state = FRAME_EXECUTING; + fdata->state = FRAME_EXECUTING; DISPATCH(); } exit_unwind: assert(_PyErr_Occurred(tstate)); _Py_LeaveRecursiveCall(tstate); - if (frame->is_entry) { + if (fdata->is_entry) { /* Restore previous cframe and exit */ tstate->cframe = cframe.previous; tstate->cframe->use_tracing = cframe.use_tracing; - assert(tstate->cframe->current_frame == frame->previous); + assert(tstate->cframe->current_frame == fdata->previous); return NULL; } - frame = cframe.current_frame = pop_frame(tstate, frame); + fdata = cframe.current_frame = pop_frame(tstate, fdata); resume_with_error: SET_LOCALS_FROM_FRAME(); @@ -6179,7 +6179,7 @@ initialize_locals(PyThreadState *tstate, PyFunctionObject *func, } /* Consumes references to func and all the args */ -static _PyInterpreterFrame * +static _Py_framedata * _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func, PyObject *locals, PyObject* const* args, size_t argcount, PyObject *kwnames) @@ -6187,20 +6187,20 @@ _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func, PyCodeObject * code = (PyCodeObject *)func->func_code; size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE; CALL_STAT_INC(frames_pushed); - _PyInterpreterFrame *frame = _PyThreadState_BumpFramePointer(tstate, size); - if (frame == NULL) { + _Py_framedata *fdata = _PyThreadState_BumpFramePointer(tstate, size); + if (fdata == NULL) { goto fail; } - _PyFrame_InitializeSpecials(frame, func, locals, code->co_nlocalsplus); - PyObject **localsarray = &frame->localsplus[0]; + _PyFrame_InitializeSpecials(fdata, func, locals, code->co_nlocalsplus); + PyObject **localsarray = &fdata->localsplus[0]; for (int i = 0; i < code->co_nlocalsplus; i++) { localsarray[i] = NULL; } if (initialize_locals(tstate, func, localsarray, args, argcount, kwnames)) { - _PyFrame_Clear(frame); + _PyFrame_Clear(fdata); return NULL; } - return frame; + return fdata; fail: /* Consume the references */ for (size_t i = 0; i < argcount; i++) { @@ -6217,13 +6217,13 @@ _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func, } static void -_PyEvalFrameClearAndPop(PyThreadState *tstate, _PyInterpreterFrame * frame) +_PyEvalFrameClearAndPop(PyThreadState *tstate, _Py_framedata * fdata) { tstate->recursion_remaining--; - assert(frame->frame_obj == NULL || frame->frame_obj->f_owns_frame == 0); - _PyFrame_Clear(frame); + assert(fdata->frame_obj == NULL || fdata->frame_obj->f_owns_frame == 0); + _PyFrame_Clear(fdata); tstate->recursion_remaining++; - _PyThreadState_PopFrame(tstate, frame); + _PyThreadState_PopFrame(tstate, fdata); } PyObject * @@ -6244,17 +6244,17 @@ _PyEval_Vector(PyThreadState *tstate, PyFunctionObject *func, Py_INCREF(args[i+argcount]); } } - _PyInterpreterFrame *frame = _PyEvalFramePushAndInit( + _Py_framedata *fdata = _PyEvalFramePushAndInit( tstate, func, locals, args, argcount, kwnames); - if (frame == NULL) { + if (fdata == NULL) { return NULL; } - PyObject *retval = _PyEval_EvalFrame(tstate, frame, 0); + PyObject *retval = _PyEval_EvalFrame(tstate, fdata, 0); assert( - _PyFrame_GetStackPointer(frame) == _PyFrame_Stackbase(frame) || - _PyFrame_GetStackPointer(frame) == frame->localsplus + _PyFrame_GetStackPointer(fdata) == _PyFrame_Stackbase(fdata) || + _PyFrame_GetStackPointer(fdata) == fdata->localsplus ); - _PyEvalFrameClearAndPop(tstate, frame); + _PyEvalFrameClearAndPop(tstate, fdata); return retval; } @@ -6613,7 +6613,7 @@ prtrace(PyThreadState *tstate, PyObject *v, const char *str) static void call_exc_trace(Py_tracefunc func, PyObject *self, PyThreadState *tstate, - _PyInterpreterFrame *f) + _Py_framedata *fdata) { PyObject *type, *value, *traceback, *orig_traceback, *arg; int err; @@ -6629,7 +6629,7 @@ call_exc_trace(Py_tracefunc func, PyObject *self, _PyErr_Restore(tstate, type, value, orig_traceback); return; } - err = call_trace(func, self, tstate, f, PyTrace_EXCEPTION, arg); + err = call_trace(func, self, tstate, fdata, PyTrace_EXCEPTION, arg); Py_DECREF(arg); if (err == 0) { _PyErr_Restore(tstate, type, value, orig_traceback); @@ -6643,13 +6643,13 @@ call_exc_trace(Py_tracefunc func, PyObject *self, static int call_trace_protected(Py_tracefunc func, PyObject *obj, - PyThreadState *tstate, _PyInterpreterFrame *frame, + PyThreadState *tstate, _Py_framedata *fdata, int what, PyObject *arg) { PyObject *type, *value, *traceback; int err; _PyErr_Fetch(tstate, &type, &value, &traceback); - err = call_trace(func, obj, tstate, frame, what, arg); + err = call_trace(func, obj, tstate, fdata, what, arg); if (err == 0) { _PyErr_Restore(tstate, type, value, traceback); @@ -6664,9 +6664,9 @@ call_trace_protected(Py_tracefunc func, PyObject *obj, } static void -initialize_trace_info(PyTraceInfo *trace_info, _PyInterpreterFrame *frame) +initialize_trace_info(PyTraceInfo *trace_info, _Py_framedata *fdata) { - PyCodeObject *code = frame->f_code; + PyCodeObject *code = fdata->code; if (trace_info->code != code) { trace_info->code = code; _PyCode_InitAddressRange(code, &trace_info->bounds); @@ -6675,7 +6675,7 @@ initialize_trace_info(PyTraceInfo *trace_info, _PyInterpreterFrame *frame) static int call_trace(Py_tracefunc func, PyObject *obj, - PyThreadState *tstate, _PyInterpreterFrame *frame, + PyThreadState *tstate, _Py_framedata *fdata, int what, PyObject *arg) { int result; @@ -6683,13 +6683,13 @@ call_trace(Py_tracefunc func, PyObject *obj, return 0; tstate->tracing++; _PyThreadState_PauseTracing(tstate); - PyFrameObject *f = _PyFrame_GetFrameObject(frame); + PyFrameObject *f = _PyFrame_GetFrameObject(fdata); if (f == NULL) { return -1; } - assert (frame->f_lasti >= 0); - initialize_trace_info(&tstate->trace_info, frame); - f->f_lineno = _PyCode_CheckLineNumber(frame->f_lasti*sizeof(_Py_CODEUNIT), &tstate->trace_info.bounds); + assert (fdata->lasti >= 0); + initialize_trace_info(&tstate->trace_info, fdata); + f->f_lineno = _PyCode_CheckLineNumber(fdata->lasti*sizeof(_Py_CODEUNIT), &tstate->trace_info.bounds); result = func(obj, f, what, arg); f->f_lineno = 0; _PyThreadState_ResumeTracing(tstate); @@ -6716,7 +6716,7 @@ _PyEval_CallTracing(PyObject *func, PyObject *args) /* See Objects/lnotab_notes.txt for a description of how tracing works. */ static int maybe_call_line_trace(Py_tracefunc func, PyObject *obj, - PyThreadState *tstate, _PyInterpreterFrame *frame, int instr_prev) + PyThreadState *tstate, _Py_framedata *fdata, int instr_prev) { int result = 0; @@ -6724,8 +6724,8 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj, represents a jump backwards, update the frame's line number and then call the trace function if we're tracing source lines. */ - initialize_trace_info(&tstate->trace_info, frame); - _Py_CODEUNIT prev = ((_Py_CODEUNIT *)PyBytes_AS_STRING(frame->f_code->co_code))[instr_prev]; + initialize_trace_info(&tstate->trace_info, fdata); + _Py_CODEUNIT prev = ((_Py_CODEUNIT *)PyBytes_AS_STRING(fdata->code->co_code))[instr_prev]; int lastline; if (_Py_OPCODE(prev) == RESUME && _Py_OPARG(prev) == 0) { lastline = -1; @@ -6733,23 +6733,23 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj, else { lastline = _PyCode_CheckLineNumber(instr_prev*sizeof(_Py_CODEUNIT), &tstate->trace_info.bounds); } - int line = _PyCode_CheckLineNumber(frame->f_lasti*sizeof(_Py_CODEUNIT), &tstate->trace_info.bounds); - PyFrameObject *f = _PyFrame_GetFrameObject(frame); + int line = _PyCode_CheckLineNumber(fdata->lasti*sizeof(_Py_CODEUNIT), &tstate->trace_info.bounds); + PyFrameObject *f = _PyFrame_GetFrameObject(fdata); if (f == NULL) { return -1; } if (line != -1 && f->f_trace_lines) { /* Trace backward edges (except in 'yield from') or if line number has changed */ int trace = line != lastline || - (frame->f_lasti < instr_prev && - _Py_OPCODE(frame->f_code->co_firstinstr[frame->f_lasti]) != SEND); + (fdata->lasti < instr_prev && + _Py_OPCODE(fdata->code->co_firstinstr[fdata->lasti]) != SEND); if (trace) { - result = call_trace(func, obj, tstate, frame, PyTrace_LINE, Py_None); + result = call_trace(func, obj, tstate, fdata, PyTrace_LINE, Py_None); } } /* Always emit an opcode event if we're tracing all opcodes. */ if (f->f_trace_opcodes) { - result = call_trace(func, obj, tstate, frame, PyTrace_OPCODE, Py_None); + result = call_trace(func, obj, tstate, fdata, PyTrace_OPCODE, Py_None); } return result; } @@ -6894,7 +6894,7 @@ _PyEval_GetAsyncGenFinalizer(void) return tstate->async_gen_finalizer; } -_PyInterpreterFrame * +_Py_framedata * _PyEval_GetFrame(void) { PyThreadState *tstate = _PyThreadState_GET(); @@ -6918,9 +6918,9 @@ PyEval_GetFrame(void) PyObject * _PyEval_GetBuiltins(PyThreadState *tstate) { - _PyInterpreterFrame *frame = tstate->cframe->current_frame; - if (frame != NULL) { - return frame->f_builtins; + _Py_framedata *fdata = tstate->cframe->current_frame; + if (fdata != NULL) { + return fdata->builtins; } return tstate->interp->builtins; } @@ -6957,17 +6957,17 @@ PyObject * PyEval_GetLocals(void) { PyThreadState *tstate = _PyThreadState_GET(); - _PyInterpreterFrame *current_frame = tstate->cframe->current_frame; - if (current_frame == NULL) { - _PyErr_SetString(tstate, PyExc_SystemError, "frame does not exist"); + _Py_framedata *fdata = tstate->cframe->current_frame; + if (fdata == NULL) { + _PyErr_SetString(tstate, PyExc_SystemError, "cannot get locals; frame data does not exist"); return NULL; } - if (_PyFrame_FastToLocalsWithError(current_frame) < 0) { + if (_PyFrame_FastToLocalsWithError(fdata) < 0) { return NULL; } - PyObject *locals = current_frame->f_locals; + PyObject *locals = fdata->locals; assert(locals != NULL); return locals; } @@ -6976,22 +6976,23 @@ PyObject * PyEval_GetGlobals(void) { PyThreadState *tstate = _PyThreadState_GET(); - _PyInterpreterFrame *current_frame = tstate->cframe->current_frame; - if (current_frame == NULL) { + _Py_framedata *fdata = tstate->cframe->current_frame; + if (fdata == NULL) { + _PyErr_SetString(tstate, PyExc_SystemError, "cannot get globals; frame data does not exist"); return NULL; } - return current_frame->f_globals; + return fdata->globals; } int PyEval_MergeCompilerFlags(PyCompilerFlags *cf) { PyThreadState *tstate = _PyThreadState_GET(); - _PyInterpreterFrame *current_frame = tstate->cframe->current_frame; + _Py_framedata *fdata = tstate->cframe->current_frame; int result = cf->cf_flags != 0; - if (current_frame != NULL) { - const int codeflags = current_frame->f_code->co_flags; + if (fdata != NULL) { + const int codeflags = fdata->code->co_flags; const int compilerflags = codeflags & PyCF_MASK; if (compilerflags) { result = 1; @@ -7191,20 +7192,20 @@ _PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi) } static PyObject * -import_name(PyThreadState *tstate, _PyInterpreterFrame *frame, +import_name(PyThreadState *tstate, _Py_framedata *fdata, PyObject *name, PyObject *fromlist, PyObject *level) { PyObject *import_func, *res; PyObject* stack[5]; - import_func = _PyDict_GetItemWithError(frame->f_builtins, &_Py_ID(__import__)); + import_func = _PyDict_GetItemWithError(fdata->builtins, &_Py_ID(__import__)); if (import_func == NULL) { if (!_PyErr_Occurred(tstate)) { _PyErr_SetString(tstate, PyExc_ImportError, "__import__ not found"); } return NULL; } - PyObject *locals = frame->f_locals; + PyObject *locals = fdata->locals; /* Fast path for not overloaded __import__. */ if (import_func == tstate->interp->import_func) { int ilevel = _PyLong_AsInt(level); @@ -7213,8 +7214,8 @@ import_name(PyThreadState *tstate, _PyInterpreterFrame *frame, } res = PyImport_ImportModuleLevelObject( name, - frame->f_globals, - locals == NULL ? Py_None :locals, + fdata->globals, + locals == NULL ? Py_None : locals, fromlist, ilevel); return res; @@ -7223,7 +7224,7 @@ import_name(PyThreadState *tstate, _PyInterpreterFrame *frame, Py_INCREF(import_func); stack[0] = name; - stack[1] = frame->f_globals; + stack[1] = fdata->globals; stack[2] = locals == NULL ? Py_None : locals; stack[3] = fromlist; stack[4] = level; @@ -7665,38 +7666,38 @@ _PyEval_RequestCodeExtraIndex(freefunc free) } static void -dtrace_function_entry(_PyInterpreterFrame *frame) +dtrace_function_entry(_Py_framedata *fdata) { const char *filename; const char *funcname; int lineno; - PyCodeObject *code = frame->f_code; + PyCodeObject *code = fdata->code; filename = PyUnicode_AsUTF8(code->co_filename); funcname = PyUnicode_AsUTF8(code->co_name); - lineno = PyCode_Addr2Line(frame->f_code, frame->f_lasti*sizeof(_Py_CODEUNIT)); + lineno = PyCode_Addr2Line(fdata->code, fdata->lasti*sizeof(_Py_CODEUNIT)); PyDTrace_FUNCTION_ENTRY(filename, funcname, lineno); } static void -dtrace_function_return(_PyInterpreterFrame *frame) +dtrace_function_return(_Py_framedata *fdata) { const char *filename; const char *funcname; int lineno; - PyCodeObject *code = frame->f_code; + PyCodeObject *code = fdata->code; filename = PyUnicode_AsUTF8(code->co_filename); funcname = PyUnicode_AsUTF8(code->co_name); - lineno = PyCode_Addr2Line(frame->f_code, frame->f_lasti*sizeof(_Py_CODEUNIT)); + lineno = PyCode_Addr2Line(fdata->code, fdata->lasti*sizeof(_Py_CODEUNIT)); PyDTrace_FUNCTION_RETURN(filename, funcname, lineno); } /* DTrace equivalent of maybe_call_line_trace. */ static void -maybe_dtrace_line(_PyInterpreterFrame *frame, +maybe_dtrace_line(_Py_framedata *fdata, PyTraceInfo *trace_info, int instr_prev) { @@ -7705,19 +7706,19 @@ maybe_dtrace_line(_PyInterpreterFrame *frame, /* If the last instruction executed isn't in the current instruction window, reset the window. */ - initialize_trace_info(trace_info, frame); + initialize_trace_info(trace_info, fdata); int lastline = _PyCode_CheckLineNumber(instr_prev*sizeof(_Py_CODEUNIT), &trace_info->bounds); - int line = _PyCode_CheckLineNumber(frame->f_lasti*sizeof(_Py_CODEUNIT), &trace_info->bounds); + int line = _PyCode_CheckLineNumber(fdata->lasti*sizeof(_Py_CODEUNIT), &trace_info->bounds); if (line != -1) { /* Trace backward edges or first instruction of a new line */ - if (frame->f_lasti < instr_prev || - (line != lastline && frame->f_lasti*sizeof(_Py_CODEUNIT) == (unsigned int)trace_info->bounds.ar_start)) + if (fdata->lasti < instr_prev || + (line != lastline && fdata->lasti*sizeof(_Py_CODEUNIT) == (unsigned int)trace_info->bounds.ar_start)) { - co_filename = PyUnicode_AsUTF8(frame->f_code->co_filename); + co_filename = PyUnicode_AsUTF8(fdata->code->co_filename); if (!co_filename) { co_filename = "?"; } - co_name = PyUnicode_AsUTF8(frame->f_code->co_name); + co_name = PyUnicode_AsUTF8(fdata->code->co_name); if (!co_name) { co_name = "?"; } diff --git a/Python/frame.c b/Python/frame.c index 20b4f81425bc8b..3513cfa05787d1 100644 --- a/Python/frame.c +++ b/Python/frame.c @@ -7,30 +7,30 @@ #include "opcode.h" int -_PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg) +_PyFrame_Traverse(_Py_framedata *fdata, visitproc visit, void *arg) { - Py_VISIT(frame->frame_obj); - Py_VISIT(frame->f_locals); - Py_VISIT(frame->f_func); - Py_VISIT(frame->f_code); + Py_VISIT(fdata->frame_obj); + Py_VISIT(fdata->locals); + Py_VISIT(fdata->func); + Py_VISIT(fdata->code); /* locals */ - PyObject **locals = _PyFrame_GetLocalsArray(frame); + PyObject **locals = _PyFrame_GetLocalsArray(fdata); int i = 0; /* locals and stack */ - for (; i stacktop; i++) { + for (; i stacktop; i++) { Py_VISIT(locals[i]); } return 0; } PyFrameObject * -_PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame) +_PyFrame_MakeAndSetFrameObject(_Py_framedata *fdata) { - assert(frame->frame_obj == NULL); + assert(fdata->frame_obj == NULL); PyObject *error_type, *error_value, *error_traceback; PyErr_Fetch(&error_type, &error_value, &error_traceback); - PyFrameObject *f = _PyFrame_New_NoTrack(frame->f_code); + PyFrameObject *f = _PyFrame_New_NoTrack(fdata->code); if (f == NULL) { Py_XDECREF(error_type); Py_XDECREF(error_value); @@ -38,35 +38,35 @@ _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame) } else { f->f_owns_frame = 0; - f->f_frame = frame; - frame->frame_obj = f; + f->f_fdata = fdata; + fdata->frame_obj = f; PyErr_Restore(error_type, error_value, error_traceback); } return f; } void -_PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest) +_PyFrame_Copy(_Py_framedata *src, _Py_framedata *dest) { - assert(src->stacktop >= src->f_code->co_nlocalsplus); + assert(src->stacktop >= src->code->co_nlocalsplus); Py_ssize_t size = ((char*)&src->localsplus[src->stacktop]) - (char *)src; memcpy(dest, src, size); } static void -take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame) +take_ownership(PyFrameObject *f, _Py_framedata *fdata) { assert(f->f_owns_frame == 0); - Py_ssize_t size = ((char*)&frame->localsplus[frame->stacktop]) - (char *)frame; - memcpy((_PyInterpreterFrame *)f->_f_frame_data, frame, size); - frame = (_PyInterpreterFrame *)f->_f_frame_data; + Py_ssize_t size = ((char*)&fdata->localsplus[fdata->stacktop]) - (char *)fdata; + memcpy((_Py_framedata *)f->_f_owned_fdata, fdata, size); + fdata = (_Py_framedata *)f->_f_owned_fdata; f->f_owns_frame = 1; - f->f_frame = frame; + f->f_fdata = fdata; assert(f->f_back == NULL); - if (frame->previous != NULL) { - /* Link PyFrameObjects.f_back and remove link through _PyInterpreterFrame.previous */ - PyFrameObject *back = _PyFrame_GetFrameObject(frame->previous); + if (fdata->previous != NULL) { + /* Link PyFrameObjects.f_back and remove link through _Py_framedata.previous */ + PyFrameObject *back = _PyFrame_GetFrameObject(fdata->previous); if (back == NULL) { /* Memory error here. */ assert(PyErr_ExceptionMatches(PyExc_MemoryError)); @@ -76,7 +76,7 @@ take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame) else { f->f_back = (PyFrameObject *)Py_NewRef(back); } - frame->previous = NULL; + fdata->previous = NULL; } if (!_PyObject_GC_IS_TRACKED((PyObject *)f)) { _PyObject_GC_TRACK((PyObject *)f); @@ -84,43 +84,43 @@ take_ownership(PyFrameObject *f, _PyInterpreterFrame *frame) } void -_PyFrame_Clear(_PyInterpreterFrame *frame) +_PyFrame_Clear(_Py_framedata *fdata) { /* It is the responsibility of the owning generator/coroutine * to have cleared the enclosing generator, if any. */ - assert(!frame->is_generator); - if (frame->frame_obj) { - PyFrameObject *f = frame->frame_obj; - frame->frame_obj = NULL; + assert(!fdata->is_generator); + if (fdata->frame_obj) { + PyFrameObject *f = fdata->frame_obj; + fdata->frame_obj = NULL; if (Py_REFCNT(f) > 1) { - take_ownership(f, frame); + take_ownership(f, fdata); Py_DECREF(f); return; } Py_DECREF(f); } - assert(frame->stacktop >= 0); - for (int i = 0; i < frame->stacktop; i++) { - Py_XDECREF(frame->localsplus[i]); + assert(fdata->stacktop >= 0); + for (int i = 0; i < fdata->stacktop; i++) { + Py_XDECREF(fdata->localsplus[i]); } - Py_XDECREF(frame->frame_obj); - Py_XDECREF(frame->f_locals); - Py_DECREF(frame->f_func); - Py_DECREF(frame->f_code); + Py_XDECREF(fdata->frame_obj); + Py_XDECREF(fdata->locals); + Py_DECREF(fdata->func); + Py_DECREF(fdata->code); } /* Consumes reference to func */ -_PyInterpreterFrame * +_Py_framedata * _PyFrame_Push(PyThreadState *tstate, PyFunctionObject *func) { PyCodeObject *code = (PyCodeObject *)func->func_code; size_t size = code->co_nlocalsplus + code->co_stacksize + FRAME_SPECIALS_SIZE; CALL_STAT_INC(frames_pushed); - _PyInterpreterFrame *new_frame = _PyThreadState_BumpFramePointer(tstate, size); - if (new_frame == NULL) { + _Py_framedata *new_fdata = _PyThreadState_BumpFramePointer(tstate, size); + if (new_fdata == NULL) { Py_DECREF(func); return NULL; } - _PyFrame_InitializeSpecials(new_frame, func, NULL, code->co_nlocalsplus); - return new_frame; + _PyFrame_InitializeSpecials(new_fdata, func, NULL, code->co_nlocalsplus); + return new_fdata; } diff --git a/Python/import.c b/Python/import.c index 982ec8cfe631a6..af908f50ec59c0 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1988,6 +1988,11 @@ PyImport_Import(PyObject *module_name) goto err; } else { + if (PyErr_Occurred()) { + // It's legitimate to have no Python frame and hence no globals + // if importing from C (e.g. during startup, or when embedded) + PyErr_Clear(); + } /* No globals -- use standard builtins, and fake globals */ builtins = PyImport_ImportModuleLevel("builtins", NULL, NULL, NULL, 0); diff --git a/Python/pystate.c b/Python/pystate.c index edf2f62431f3df..0458c706642b62 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1000,7 +1000,7 @@ PyThreadState_Clear(PyThreadState *tstate) /* bpo-20526: After the main thread calls _PyRuntimeState_SetFinalizing() in Py_FinalizeEx(), threads must exit when trying to take the GIL. If a thread exit in the middle of - _PyEval_EvalFrameDefault(), tstate->frame is not reset to its + _PyEval_EvalFrameDefault(), tstate->fdata is not reset to its previous value. It is more likely with daemon threads, but it can happen with regular threads if threading._shutdown() fails (ex: interrupted by CTRL+C). */ @@ -1410,15 +1410,15 @@ _PyThread_CurrentFrames(void) for (i = runtime->interpreters.head; i != NULL; i = i->next) { PyThreadState *t; for (t = i->threads.head; t != NULL; t = t->next) { - _PyInterpreterFrame *frame = t->cframe->current_frame; - if (frame == NULL) { + _Py_framedata *fdata = t->cframe->current_frame; + if (fdata == NULL) { continue; } PyObject *id = PyLong_FromUnsignedLong(t->thread_id); if (id == NULL) { goto fail; } - int stat = PyDict_SetItem(result, id, (PyObject *)_PyFrame_GetFrameObject(frame)); + int stat = PyDict_SetItem(result, id, (PyObject *)_PyFrame_GetFrameObject(fdata)); Py_DECREF(id); if (stat < 0) { goto fail; @@ -2197,7 +2197,7 @@ push_chunk(PyThreadState *tstate, int size) return res; } -_PyInterpreterFrame * +_Py_framedata * _PyThreadState_BumpFramePointerSlow(PyThreadState *tstate, size_t size) { assert(size < INT_MAX/sizeof(PyObject *)); @@ -2209,11 +2209,11 @@ _PyThreadState_BumpFramePointerSlow(PyThreadState *tstate, size_t size) else { tstate->datastack_top = top; } - return (_PyInterpreterFrame *)base; + return (_Py_framedata *)base; } void -_PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame * frame) +_PyThreadState_PopFrame(PyThreadState *tstate, _Py_framedata * frame) { assert(tstate->datastack_chunk); PyObject **base = (PyObject **)frame; diff --git a/Python/suggestions.c b/Python/suggestions.c index d9e69fa7e0db21..6d598e6cfb23df 100644 --- a/Python/suggestions.c +++ b/Python/suggestions.c @@ -240,7 +240,7 @@ offer_suggestions_for_name_error(PyNameErrorObject *exc) return suggestions; } - dir = PySequence_List(frame->f_frame->f_globals); + dir = PySequence_List(frame->f_fdata->globals); if (dir == NULL) { return NULL; } @@ -250,7 +250,7 @@ offer_suggestions_for_name_error(PyNameErrorObject *exc) return suggestions; } - dir = PySequence_List(frame->f_frame->f_builtins); + dir = PySequence_List(frame->f_fdata->builtins); if (dir == NULL) { return NULL; } diff --git a/Python/sysmodule.c b/Python/sysmodule.c index a97d0341ddcfd7..826e6967dc160b 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -18,7 +18,7 @@ Data members: #include "pycore_call.h" // _PyObject_CallNoArgs() #include "pycore_ceval.h" // _Py_RecursionLimitLowerWaterMark() #include "pycore_code.h" // _Py_QuickenedCount -#include "pycore_frame.h" // _PyInterpreterFrame +#include "pycore_frame.h" // _Py_framedata #include "pycore_initconfig.h" // _PyStatus_EXCEPTION() #include "pycore_namespace.h" // _PyNamespace_New() #include "pycore_object.h" // _PyObject_IS_GC() @@ -1807,22 +1807,22 @@ sys__getframe_impl(PyObject *module, int depth) /*[clinic end generated code: output=d438776c04d59804 input=c1be8a6464b11ee5]*/ { PyThreadState *tstate = _PyThreadState_GET(); - _PyInterpreterFrame *frame = tstate->cframe->current_frame; + _Py_framedata *fdata = tstate->cframe->current_frame; if (_PySys_Audit(tstate, "sys._getframe", NULL) < 0) { return NULL; } - while (depth > 0 && frame != NULL) { - frame = frame->previous; + while (depth > 0 && fdata != NULL) { + fdata = fdata->previous; --depth; } - if (frame == NULL) { + if (fdata == NULL) { _PyErr_SetString(tstate, PyExc_ValueError, "call stack is not deep enough"); return NULL; } - return _Py_XNewRef((PyObject *)_PyFrame_GetFrameObject(frame)); + return _Py_XNewRef((PyObject *)_PyFrame_GetFrameObject(fdata)); } /*[clinic input] diff --git a/Python/traceback.c b/Python/traceback.c index 6a721cf9097573..14a90dc0188d11 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -240,7 +240,7 @@ _PyTraceBack_FromFrame(PyObject *tb_next, PyFrameObject *frame) assert(tb_next == NULL || PyTraceBack_Check(tb_next)); assert(frame != NULL); - return tb_create_raw((PyTracebackObject *)tb_next, frame, frame->f_frame->f_lasti*sizeof(_Py_CODEUNIT), + return tb_create_raw((PyTracebackObject *)tb_next, frame, frame->f_fdata->lasti*sizeof(_Py_CODEUNIT), PyFrame_GetLineNumber(frame)); } @@ -791,7 +791,7 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen } int code_offset = tb->tb_lasti; - PyCodeObject* code = frame->f_frame->f_code; + PyCodeObject* code = frame->f_fdata->code; int start_line; int end_line; @@ -1167,9 +1167,9 @@ _Py_DumpASCII(int fd, PyObject *text) This function is signal safe. */ static void -dump_frame(int fd, _PyInterpreterFrame *frame) +dump_frame(int fd, _Py_framedata *fdata) { - PyCodeObject *code = frame->f_code; + PyCodeObject *code = fdata->code; PUTS(fd, " File "); if (code->co_filename != NULL && PyUnicode_Check(code->co_filename)) @@ -1181,7 +1181,7 @@ dump_frame(int fd, _PyInterpreterFrame *frame) PUTS(fd, "???"); } - int lineno = PyCode_Addr2Line(code, frame->f_lasti*sizeof(_Py_CODEUNIT)); + int lineno = PyCode_Addr2Line(code, fdata->lasti*sizeof(_Py_CODEUNIT)); PUTS(fd, ", line "); if (lineno >= 0) { _Py_DumpDecimal(fd, (size_t)lineno); @@ -1205,28 +1205,27 @@ dump_frame(int fd, _PyInterpreterFrame *frame) static void dump_traceback(int fd, PyThreadState *tstate, int write_header) { - _PyInterpreterFrame *frame; - unsigned int depth; + _Py_framedata *fdata; + unsigned int depth = 0; if (write_header) { PUTS(fd, "Stack (most recent call first):\n"); } - frame = tstate->cframe->current_frame; - if (frame == NULL) { - PUTS(fd, " \n"); + fdata = tstate->cframe->current_frame; + if (fdata == NULL) { + PUTS(fd, "\n"); return; } - depth = 0; while (1) { if (MAX_FRAME_DEPTH <= depth) { PUTS(fd, " ...\n"); break; } - dump_frame(fd, frame); - frame = frame->previous; - if (frame == NULL) { + dump_frame(fd, fdata); + fdata = fdata->previous; + if (fdata == NULL) { break; } depth++; diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py index 8b227e61082be7..4dc44d60131a38 100755 --- a/Tools/gdb/libpython.py +++ b/Tools/gdb/libpython.py @@ -914,7 +914,7 @@ def __init__(self, gdbval, cast_to=None): PyObjectPtr.__init__(self, gdbval, cast_to) if not self.is_optimized_out(): - self._frame = PyFramePtr(self.field('f_frame')) + self._fdata = _Py_framedataPtr(self.field('f_fdata')) def iter_locals(self): ''' @@ -923,7 +923,7 @@ def iter_locals(self): ''' if self.is_optimized_out(): return - return self._frame.iter_locals() + return self._fdata.iter_locals() def iter_globals(self): ''' @@ -932,7 +932,7 @@ def iter_globals(self): ''' if self.is_optimized_out(): return () - return self._frame.iter_globals() + return self._fdata.iter_globals() def iter_builtins(self): ''' @@ -941,19 +941,19 @@ def iter_builtins(self): ''' if self.is_optimized_out(): return () - return self._frame.iter_builtins() + return self._fdata.iter_builtins() def get_var_by_name(self, name): if self.is_optimized_out(): return None, None - return self._frame.get_var_by_name(name) + return self._fdata.get_var_by_name(name) def filename(self): '''Get the path of the current Python source file, as a string''' if self.is_optimized_out(): return FRAME_INFO_OPTIMIZED_OUT - return self._frame.filename() + return self._fdata.filename() def current_line_num(self): '''Get current line number as an integer (1-based) @@ -964,38 +964,38 @@ def current_line_num(self): ''' if self.is_optimized_out(): return None - return self._frame.current_line_num() + return self._fdata.current_line_num() def current_line(self): '''Get the text of the current source line as a string, with a trailing newline character''' if self.is_optimized_out(): return FRAME_INFO_OPTIMIZED_OUT - return self._frame.current_line() + return self._fdata.current_line() def write_repr(self, out, visited): if self.is_optimized_out(): out.write(FRAME_INFO_OPTIMIZED_OUT) return - return self._frame.write_repr(out, visited) + return self._fdata.write_repr(out, visited) def print_traceback(self): if self.is_optimized_out(): sys.stdout.write(' %s\n' % FRAME_INFO_OPTIMIZED_OUT) return - return self._frame.print_traceback() + return self._fdata.print_traceback() -class PyFramePtr: +class _Py_framedataPtr: def __init__(self, gdbval): self._gdbval = gdbval if not self.is_optimized_out(): - self.co = self._f_code() + self.co = self._code() self.co_name = self.co.pyop_field('co_name') self.co_filename = self.co.pyop_field('co_filename') - self.f_lasti = self._f_lasti() + self.lasti = self._lasti() self.co_nlocals = int_from_int(self.co.field('co_nlocals')) pnames = self.co.field('co_localsplusnames') self.co_localsplusnames = PyTupleObjectPtr.from_pyobject_ptr(pnames) @@ -1023,29 +1023,29 @@ def iter_locals(self): pyop_name = PyObjectPtr.from_pyobject_ptr(self.co_localsplusnames[i]) yield (pyop_name, pyop_value) - def _f_special(self, name, convert=PyObjectPtr.from_pyobject_ptr): + def _special(self, name, convert=PyObjectPtr.from_pyobject_ptr): return convert(self._gdbval[name]) - def _f_globals(self): - return self._f_special("f_globals") + def _globals(self): + return self._special("globals") - def _f_builtins(self): - return self._f_special("f_builtins") + def _builtins(self): + return self._special("builtins") - def _f_code(self): - return self._f_special("f_code", PyCodeObjectPtr.from_pyobject_ptr) + def _code(self): + return self._special("code", PyCodeObjectPtr.from_pyobject_ptr) - def _f_nlocalsplus(self): - return self._f_special("nlocalsplus", int_from_int) + def _nlocalsplus(self): + return self._special("nlocalsplus", int_from_int) - def _f_lasti(self): - return self._f_special("f_lasti", int_from_int) + def _lasti(self): + return self._special("lasti", int_from_int) def is_entry(self): - return self._f_special("is_entry", bool) + return self._special("is_entry", bool) def previous(self): - return self._f_special("previous", PyFramePtr) + return self._special("previous", _Py_framedataPtr) def iter_globals(self): ''' @@ -1055,7 +1055,7 @@ def iter_globals(self): if self.is_optimized_out(): return () - pyop_globals = self._f_globals() + pyop_globals = self._globals() return pyop_globals.iteritems() def iter_builtins(self): @@ -1066,7 +1066,7 @@ def iter_builtins(self): if self.is_optimized_out(): return () - pyop_builtins = self._f_builtins() + pyop_builtins = self._builtins() return pyop_builtins.iteritems() def get_var_by_name(self, name): @@ -1103,7 +1103,7 @@ def current_line_num(self): if self.is_optimized_out(): return None try: - return self.co.addr2line(self.f_lasti*2) + return self.co.addr2line(self.lasti*2) except Exception: # bpo-34989: addr2line() is a complex function, it can fail in many # ways. For example, it fails with a TypeError on "FakeRepr" if @@ -1793,16 +1793,16 @@ def is_gc_collect(self): def get_pyop(self): try: - frame = self._gdbframe.read_var('frame') - frame = PyFramePtr(frame) - if not frame.is_optimized_out(): - return frame + _gdbfdata = self._gdbframe.read_var('fdata') + fdata = _Py_framedataPtr(_gdbfdata) + if not fdata.is_optimized_out(): + return fdata cframe = self._gdbframe.read_var('cframe') if cframe is None: return None - frame = PyFramePtr(cframe["current_frame"]) - if frame and not frame.is_optimized_out(): - return frame + fdata = _Py_framedataPtr(cframe["current_frame"]) + if fdata and not fdata.is_optimized_out(): + return fdata return None except ValueError: return None