17db96d56Sopenharmony_ci#ifndef Py_INTERNAL_FRAME_H 27db96d56Sopenharmony_ci#define Py_INTERNAL_FRAME_H 37db96d56Sopenharmony_ci#ifdef __cplusplus 47db96d56Sopenharmony_ciextern "C" { 57db96d56Sopenharmony_ci#endif 67db96d56Sopenharmony_ci 77db96d56Sopenharmony_ci#include <stdbool.h> 87db96d56Sopenharmony_ci#include <stddef.h> 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ci/* See Objects/frame_layout.md for an explanation of the frame stack 117db96d56Sopenharmony_ci * including explanation of the PyFrameObject and _PyInterpreterFrame 127db96d56Sopenharmony_ci * structs. */ 137db96d56Sopenharmony_ci 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_cistruct _frame { 167db96d56Sopenharmony_ci PyObject_HEAD 177db96d56Sopenharmony_ci PyFrameObject *f_back; /* previous frame, or NULL */ 187db96d56Sopenharmony_ci struct _PyInterpreterFrame *f_frame; /* points to the frame data */ 197db96d56Sopenharmony_ci PyObject *f_trace; /* Trace function */ 207db96d56Sopenharmony_ci int f_lineno; /* Current line number. Only valid if non-zero */ 217db96d56Sopenharmony_ci char f_trace_lines; /* Emit per-line trace events? */ 227db96d56Sopenharmony_ci char f_trace_opcodes; /* Emit per-opcode trace events? */ 237db96d56Sopenharmony_ci char f_fast_as_locals; /* Have the fast locals of this frame been converted to a dict? */ 247db96d56Sopenharmony_ci /* The frame data, if this frame object owns the frame */ 257db96d56Sopenharmony_ci PyObject *_f_frame_data[1]; 267db96d56Sopenharmony_ci}; 277db96d56Sopenharmony_ci 287db96d56Sopenharmony_ciextern PyFrameObject* _PyFrame_New_NoTrack(PyCodeObject *code); 297db96d56Sopenharmony_ci 307db96d56Sopenharmony_ci 317db96d56Sopenharmony_ci/* other API */ 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_citypedef enum _framestate { 347db96d56Sopenharmony_ci FRAME_CREATED = -2, 357db96d56Sopenharmony_ci FRAME_SUSPENDED = -1, 367db96d56Sopenharmony_ci FRAME_EXECUTING = 0, 377db96d56Sopenharmony_ci FRAME_COMPLETED = 1, 387db96d56Sopenharmony_ci FRAME_CLEARED = 4 397db96d56Sopenharmony_ci} PyFrameState; 407db96d56Sopenharmony_ci 417db96d56Sopenharmony_cienum _frameowner { 427db96d56Sopenharmony_ci FRAME_OWNED_BY_THREAD = 0, 437db96d56Sopenharmony_ci FRAME_OWNED_BY_GENERATOR = 1, 447db96d56Sopenharmony_ci FRAME_OWNED_BY_FRAME_OBJECT = 2 457db96d56Sopenharmony_ci}; 467db96d56Sopenharmony_ci 477db96d56Sopenharmony_citypedef struct _PyInterpreterFrame { 487db96d56Sopenharmony_ci /* "Specials" section */ 497db96d56Sopenharmony_ci PyFunctionObject *f_func; /* Strong reference */ 507db96d56Sopenharmony_ci PyObject *f_globals; /* Borrowed reference */ 517db96d56Sopenharmony_ci PyObject *f_builtins; /* Borrowed reference */ 527db96d56Sopenharmony_ci PyObject *f_locals; /* Strong reference, may be NULL */ 537db96d56Sopenharmony_ci PyCodeObject *f_code; /* Strong reference */ 547db96d56Sopenharmony_ci PyFrameObject *frame_obj; /* Strong reference, may be NULL */ 557db96d56Sopenharmony_ci /* Linkage section */ 567db96d56Sopenharmony_ci struct _PyInterpreterFrame *previous; 577db96d56Sopenharmony_ci // NOTE: This is not necessarily the last instruction started in the given 587db96d56Sopenharmony_ci // frame. Rather, it is the code unit *prior to* the *next* instruction. For 597db96d56Sopenharmony_ci // example, it may be an inline CACHE entry, an instruction we just jumped 607db96d56Sopenharmony_ci // over, or (in the case of a newly-created frame) a totally invalid value: 617db96d56Sopenharmony_ci _Py_CODEUNIT *prev_instr; 627db96d56Sopenharmony_ci int stacktop; /* Offset of TOS from localsplus */ 637db96d56Sopenharmony_ci bool is_entry; // Whether this is the "root" frame for the current _PyCFrame. 647db96d56Sopenharmony_ci char owner; 657db96d56Sopenharmony_ci /* Locals and stack */ 667db96d56Sopenharmony_ci PyObject *localsplus[1]; 677db96d56Sopenharmony_ci} _PyInterpreterFrame; 687db96d56Sopenharmony_ci 697db96d56Sopenharmony_ci#define _PyInterpreterFrame_LASTI(IF) \ 707db96d56Sopenharmony_ci ((int)((IF)->prev_instr - _PyCode_CODE((IF)->f_code))) 717db96d56Sopenharmony_ci 727db96d56Sopenharmony_cistatic inline PyObject **_PyFrame_Stackbase(_PyInterpreterFrame *f) { 737db96d56Sopenharmony_ci return f->localsplus + f->f_code->co_nlocalsplus; 747db96d56Sopenharmony_ci} 757db96d56Sopenharmony_ci 767db96d56Sopenharmony_cistatic inline PyObject *_PyFrame_StackPeek(_PyInterpreterFrame *f) { 777db96d56Sopenharmony_ci assert(f->stacktop > f->f_code->co_nlocalsplus); 787db96d56Sopenharmony_ci assert(f->localsplus[f->stacktop-1] != NULL); 797db96d56Sopenharmony_ci return f->localsplus[f->stacktop-1]; 807db96d56Sopenharmony_ci} 817db96d56Sopenharmony_ci 827db96d56Sopenharmony_cistatic inline PyObject *_PyFrame_StackPop(_PyInterpreterFrame *f) { 837db96d56Sopenharmony_ci assert(f->stacktop > f->f_code->co_nlocalsplus); 847db96d56Sopenharmony_ci f->stacktop--; 857db96d56Sopenharmony_ci return f->localsplus[f->stacktop]; 867db96d56Sopenharmony_ci} 877db96d56Sopenharmony_ci 887db96d56Sopenharmony_cistatic inline void _PyFrame_StackPush(_PyInterpreterFrame *f, PyObject *value) { 897db96d56Sopenharmony_ci f->localsplus[f->stacktop] = value; 907db96d56Sopenharmony_ci f->stacktop++; 917db96d56Sopenharmony_ci} 927db96d56Sopenharmony_ci 937db96d56Sopenharmony_ci#define FRAME_SPECIALS_SIZE ((sizeof(_PyInterpreterFrame)-1)/sizeof(PyObject *)) 947db96d56Sopenharmony_ci 957db96d56Sopenharmony_civoid _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest); 967db96d56Sopenharmony_ci 977db96d56Sopenharmony_ci/* Consumes reference to func and locals. 987db96d56Sopenharmony_ci Does not initialize frame->previous, which happens 997db96d56Sopenharmony_ci when frame is linked into the frame stack. 1007db96d56Sopenharmony_ci */ 1017db96d56Sopenharmony_cistatic inline void 1027db96d56Sopenharmony_ci_PyFrame_InitializeSpecials( 1037db96d56Sopenharmony_ci _PyInterpreterFrame *frame, PyFunctionObject *func, 1047db96d56Sopenharmony_ci PyObject *locals, int nlocalsplus) 1057db96d56Sopenharmony_ci{ 1067db96d56Sopenharmony_ci frame->f_func = func; 1077db96d56Sopenharmony_ci frame->f_code = (PyCodeObject *)Py_NewRef(func->func_code); 1087db96d56Sopenharmony_ci frame->f_builtins = func->func_builtins; 1097db96d56Sopenharmony_ci frame->f_globals = func->func_globals; 1107db96d56Sopenharmony_ci frame->f_locals = Py_XNewRef(locals); 1117db96d56Sopenharmony_ci frame->stacktop = nlocalsplus; 1127db96d56Sopenharmony_ci frame->frame_obj = NULL; 1137db96d56Sopenharmony_ci frame->prev_instr = _PyCode_CODE(frame->f_code) - 1; 1147db96d56Sopenharmony_ci frame->is_entry = false; 1157db96d56Sopenharmony_ci frame->owner = FRAME_OWNED_BY_THREAD; 1167db96d56Sopenharmony_ci} 1177db96d56Sopenharmony_ci 1187db96d56Sopenharmony_ci/* Gets the pointer to the locals array 1197db96d56Sopenharmony_ci * that precedes this frame. 1207db96d56Sopenharmony_ci */ 1217db96d56Sopenharmony_cistatic inline PyObject** 1227db96d56Sopenharmony_ci_PyFrame_GetLocalsArray(_PyInterpreterFrame *frame) 1237db96d56Sopenharmony_ci{ 1247db96d56Sopenharmony_ci return frame->localsplus; 1257db96d56Sopenharmony_ci} 1267db96d56Sopenharmony_ci 1277db96d56Sopenharmony_cistatic inline PyObject** 1287db96d56Sopenharmony_ci_PyFrame_GetStackPointer(_PyInterpreterFrame *frame) 1297db96d56Sopenharmony_ci{ 1307db96d56Sopenharmony_ci return frame->localsplus+frame->stacktop; 1317db96d56Sopenharmony_ci} 1327db96d56Sopenharmony_ci 1337db96d56Sopenharmony_cistatic inline void 1347db96d56Sopenharmony_ci_PyFrame_SetStackPointer(_PyInterpreterFrame *frame, PyObject **stack_pointer) 1357db96d56Sopenharmony_ci{ 1367db96d56Sopenharmony_ci frame->stacktop = (int)(stack_pointer - frame->localsplus); 1377db96d56Sopenharmony_ci} 1387db96d56Sopenharmony_ci 1397db96d56Sopenharmony_ci/* Determine whether a frame is incomplete. 1407db96d56Sopenharmony_ci * A frame is incomplete if it is part way through 1417db96d56Sopenharmony_ci * creating cell objects or a generator or coroutine. 1427db96d56Sopenharmony_ci * 1437db96d56Sopenharmony_ci * Frames on the frame stack are incomplete until the 1447db96d56Sopenharmony_ci * first RESUME instruction. 1457db96d56Sopenharmony_ci * Frames owned by a generator are always complete. 1467db96d56Sopenharmony_ci */ 1477db96d56Sopenharmony_cistatic inline bool 1487db96d56Sopenharmony_ci_PyFrame_IsIncomplete(_PyInterpreterFrame *frame) 1497db96d56Sopenharmony_ci{ 1507db96d56Sopenharmony_ci return frame->owner != FRAME_OWNED_BY_GENERATOR && 1517db96d56Sopenharmony_ci frame->prev_instr < _PyCode_CODE(frame->f_code) + frame->f_code->_co_firsttraceable; 1527db96d56Sopenharmony_ci} 1537db96d56Sopenharmony_ci 1547db96d56Sopenharmony_ci/* For use by _PyFrame_GetFrameObject 1557db96d56Sopenharmony_ci Do not call directly. */ 1567db96d56Sopenharmony_ciPyFrameObject * 1577db96d56Sopenharmony_ci_PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame); 1587db96d56Sopenharmony_ci 1597db96d56Sopenharmony_ci/* Gets the PyFrameObject for this frame, lazily 1607db96d56Sopenharmony_ci * creating it if necessary. 1617db96d56Sopenharmony_ci * Returns a borrowed referennce */ 1627db96d56Sopenharmony_cistatic inline PyFrameObject * 1637db96d56Sopenharmony_ci_PyFrame_GetFrameObject(_PyInterpreterFrame *frame) 1647db96d56Sopenharmony_ci{ 1657db96d56Sopenharmony_ci 1667db96d56Sopenharmony_ci assert(!_PyFrame_IsIncomplete(frame)); 1677db96d56Sopenharmony_ci PyFrameObject *res = frame->frame_obj; 1687db96d56Sopenharmony_ci if (res != NULL) { 1697db96d56Sopenharmony_ci return res; 1707db96d56Sopenharmony_ci } 1717db96d56Sopenharmony_ci return _PyFrame_MakeAndSetFrameObject(frame); 1727db96d56Sopenharmony_ci} 1737db96d56Sopenharmony_ci 1747db96d56Sopenharmony_ci/* Clears all references in the frame. 1757db96d56Sopenharmony_ci * If take is non-zero, then the _PyInterpreterFrame frame 1767db96d56Sopenharmony_ci * may be transferred to the frame object it references 1777db96d56Sopenharmony_ci * instead of being cleared. Either way 1787db96d56Sopenharmony_ci * the caller no longer owns the references 1797db96d56Sopenharmony_ci * in the frame. 1807db96d56Sopenharmony_ci * take should be set to 1 for heap allocated 1817db96d56Sopenharmony_ci * frames like the ones in generators and coroutines. 1827db96d56Sopenharmony_ci */ 1837db96d56Sopenharmony_civoid 1847db96d56Sopenharmony_ci_PyFrame_Clear(_PyInterpreterFrame * frame); 1857db96d56Sopenharmony_ci 1867db96d56Sopenharmony_ciint 1877db96d56Sopenharmony_ci_PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg); 1887db96d56Sopenharmony_ci 1897db96d56Sopenharmony_ciint 1907db96d56Sopenharmony_ci_PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame); 1917db96d56Sopenharmony_ci 1927db96d56Sopenharmony_civoid 1937db96d56Sopenharmony_ci_PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear); 1947db96d56Sopenharmony_ci 1957db96d56Sopenharmony_ciextern _PyInterpreterFrame * 1967db96d56Sopenharmony_ci_PyThreadState_BumpFramePointerSlow(PyThreadState *tstate, size_t size); 1977db96d56Sopenharmony_ci 1987db96d56Sopenharmony_cistatic inline bool 1997db96d56Sopenharmony_ci_PyThreadState_HasStackSpace(PyThreadState *tstate, size_t size) 2007db96d56Sopenharmony_ci{ 2017db96d56Sopenharmony_ci assert( 2027db96d56Sopenharmony_ci (tstate->datastack_top == NULL && tstate->datastack_limit == NULL) 2037db96d56Sopenharmony_ci || 2047db96d56Sopenharmony_ci (tstate->datastack_top != NULL && tstate->datastack_limit != NULL) 2057db96d56Sopenharmony_ci ); 2067db96d56Sopenharmony_ci return tstate->datastack_top != NULL && 2077db96d56Sopenharmony_ci size < (size_t)(tstate->datastack_limit - tstate->datastack_top); 2087db96d56Sopenharmony_ci} 2097db96d56Sopenharmony_ci 2107db96d56Sopenharmony_cistatic inline _PyInterpreterFrame * 2117db96d56Sopenharmony_ci_PyThreadState_BumpFramePointer(PyThreadState *tstate, size_t size) 2127db96d56Sopenharmony_ci{ 2137db96d56Sopenharmony_ci if (_PyThreadState_HasStackSpace(tstate, size)) { 2147db96d56Sopenharmony_ci _PyInterpreterFrame *res = (_PyInterpreterFrame *)tstate->datastack_top; 2157db96d56Sopenharmony_ci tstate->datastack_top += size; 2167db96d56Sopenharmony_ci return res; 2177db96d56Sopenharmony_ci } 2187db96d56Sopenharmony_ci return _PyThreadState_BumpFramePointerSlow(tstate, size); 2197db96d56Sopenharmony_ci} 2207db96d56Sopenharmony_ci 2217db96d56Sopenharmony_civoid _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame *frame); 2227db96d56Sopenharmony_ci 2237db96d56Sopenharmony_ci/* Consume reference to func */ 2247db96d56Sopenharmony_ci_PyInterpreterFrame * 2257db96d56Sopenharmony_ci_PyFrame_Push(PyThreadState *tstate, PyFunctionObject *func); 2267db96d56Sopenharmony_ci 2277db96d56Sopenharmony_ciint _PyInterpreterFrame_GetLine(_PyInterpreterFrame *frame); 2287db96d56Sopenharmony_ci 2297db96d56Sopenharmony_cistatic inline 2307db96d56Sopenharmony_ciPyGenObject *_PyFrame_GetGenerator(_PyInterpreterFrame *frame) 2317db96d56Sopenharmony_ci{ 2327db96d56Sopenharmony_ci assert(frame->owner == FRAME_OWNED_BY_GENERATOR); 2337db96d56Sopenharmony_ci size_t offset_in_gen = offsetof(PyGenObject, gi_iframe); 2347db96d56Sopenharmony_ci return (PyGenObject *)(((char *)frame) - offset_in_gen); 2357db96d56Sopenharmony_ci} 2367db96d56Sopenharmony_ci 2377db96d56Sopenharmony_ci#ifdef __cplusplus 2387db96d56Sopenharmony_ci} 2397db96d56Sopenharmony_ci#endif 2407db96d56Sopenharmony_ci#endif /* !Py_INTERNAL_FRAME_H */ 241