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