#ifndef Py_INTERNAL_FRAME_H
#define Py_INTERNAL_FRAME_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stddef.h>
#include "pycore_code.h"
struct _frame {
PyObject_HEAD
PyFrameObject *f_back;
struct _PyInterpreterFrame *f_frame;
PyObject *f_trace;
int f_lineno;
char f_trace_lines;
char f_trace_opcodes;
char f_fast_as_locals;
PyObject *_f_frame_data[1];
};
extern PyFrameObject* _PyFrame_New_NoTrack(PyCodeObject *code);
typedef enum _framestate {
FRAME_CREATED = -2,
FRAME_SUSPENDED = -1,
FRAME_EXECUTING = 0,
FRAME_COMPLETED = 1,
FRAME_CLEARED = 4
} PyFrameState;
enum _frameowner {
FRAME_OWNED_BY_THREAD = 0,
FRAME_OWNED_BY_GENERATOR = 1,
FRAME_OWNED_BY_FRAME_OBJECT = 2,
FRAME_OWNED_BY_CSTACK = 3,
};
typedef struct _PyInterpreterFrame {
PyObject *f_executable;
struct _PyInterpreterFrame *previous;
PyObject *f_funcobj;
PyObject *f_globals;
PyObject *f_builtins;
PyObject *f_locals;
PyFrameObject *frame_obj;
_Py_CODEUNIT *prev_instr;
int stacktop;
uint16_t return_offset;
char owner;
PyObject *localsplus[1];
} _PyInterpreterFrame;
#define _PyInterpreterFrame_LASTI(IF) \
((int)((IF)->prev_instr - _PyCode_CODE(_PyFrame_GetCode(IF))))
static inline PyCodeObject *_PyFrame_GetCode(_PyInterpreterFrame *f) {
assert(PyCode_Check(f->f_executable));
return (PyCodeObject *)f->f_executable;
}
static inline PyObject **_PyFrame_Stackbase(_PyInterpreterFrame *f) {
return f->localsplus + _PyFrame_GetCode(f)->co_nlocalsplus;
}
static inline PyObject *_PyFrame_StackPeek(_PyInterpreterFrame *f) {
assert(f->stacktop > _PyFrame_GetCode(f)->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 > _PyFrame_GetCode(f)->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++;
}
#define FRAME_SPECIALS_SIZE ((int)((sizeof(_PyInterpreterFrame)-1)/sizeof(PyObject *)))
static inline int
_PyFrame_NumSlotsForCodeObject(PyCodeObject *code)
{
assert(code->co_framesize >= FRAME_SPECIALS_SIZE);
return code->co_framesize - FRAME_SPECIALS_SIZE;
}
void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest);
static inline void
_PyFrame_Initialize(
_PyInterpreterFrame *frame, PyFunctionObject *func,
PyObject *locals, PyCodeObject *code, int null_locals_from)
{
frame->f_funcobj = (PyObject *)func;
frame->f_executable = Py_NewRef(code);
frame->f_builtins = func->func_builtins;
frame->f_globals = func->func_globals;
frame->f_locals = locals;
frame->stacktop = code->co_nlocalsplus;
frame->frame_obj = NULL;
frame->prev_instr = _PyCode_CODE(code) - 1;
frame->return_offset = 0;
frame->owner = FRAME_OWNED_BY_THREAD;
for (int i = null_locals_from; i < code->co_nlocalsplus; i++) {
frame->localsplus[i] = NULL;
}
}
static inline PyObject**
_PyFrame_GetLocalsArray(_PyInterpreterFrame *frame)
{
return frame->localsplus;
}
static inline PyObject**
_PyFrame_GetStackPointer(_PyInterpreterFrame *frame)
{
PyObject **sp = frame->localsplus + frame->stacktop;
frame->stacktop = -1;
return sp;
}
static inline void
_PyFrame_SetStackPointer(_PyInterpreterFrame *frame, PyObject **stack_pointer)
{
frame->stacktop = (int)(stack_pointer - frame->localsplus);
}
static inline bool
_PyFrame_IsIncomplete(_PyInterpreterFrame *frame)
{
if (frame->owner == FRAME_OWNED_BY_CSTACK) {
return true;
}
return frame->owner != FRAME_OWNED_BY_GENERATOR &&
frame->prev_instr < _PyCode_CODE(_PyFrame_GetCode(frame)) + _PyFrame_GetCode(frame)->_co_firsttraceable;
}
static inline _PyInterpreterFrame *
_PyFrame_GetFirstComplete(_PyInterpreterFrame *frame)
{
while (frame && _PyFrame_IsIncomplete(frame)) {
frame = frame->previous;
}
return frame;
}
static inline _PyInterpreterFrame *
_PyThreadState_GetFrame(PyThreadState *tstate)
{
return _PyFrame_GetFirstComplete(tstate->cframe->current_frame);
}
PyFrameObject *
_PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame);
static inline PyFrameObject *
_PyFrame_GetFrameObject(_PyInterpreterFrame *frame)
{
assert(!_PyFrame_IsIncomplete(frame));
PyFrameObject *res = frame->frame_obj;
if (res != NULL) {
return res;
}
return _PyFrame_MakeAndSetFrameObject(frame);
}
void
_PyFrame_ClearExceptCode(_PyInterpreterFrame * frame);
int
_PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg);
int
_PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame);
void
_PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear);
static inline bool
_PyThreadState_HasStackSpace(PyThreadState *tstate, int size)
{
assert(
(tstate->datastack_top == NULL && tstate->datastack_limit == NULL)
||
(tstate->datastack_top != NULL && tstate->datastack_limit != NULL)
);
return tstate->datastack_top != NULL &&
size < tstate->datastack_limit - tstate->datastack_top;
}
extern _PyInterpreterFrame *
_PyThreadState_PushFrame(PyThreadState *tstate, size_t size);
void _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame *frame);
static inline _PyInterpreterFrame *
_PyFrame_PushUnchecked(PyThreadState *tstate, PyFunctionObject *func, int null_locals_from)
{
CALL_STAT_INC(frames_pushed);
PyCodeObject *code = (PyCodeObject *)func->func_code;
_PyInterpreterFrame *new_frame = (_PyInterpreterFrame *)tstate->datastack_top;
tstate->datastack_top += code->co_framesize;
assert(tstate->datastack_top < tstate->datastack_limit);
_PyFrame_Initialize(new_frame, func, NULL, code, null_locals_from);
return new_frame;
}
static inline _PyInterpreterFrame *
_PyFrame_PushTrampolineUnchecked(PyThreadState *tstate, PyCodeObject *code, int stackdepth, int prev_instr)
{
CALL_STAT_INC(frames_pushed);
_PyInterpreterFrame *frame = (_PyInterpreterFrame *)tstate->datastack_top;
tstate->datastack_top += code->co_framesize;
assert(tstate->datastack_top < tstate->datastack_limit);
frame->f_funcobj = Py_None;
frame->f_executable = Py_NewRef(code);
#ifdef Py_DEBUG
frame->f_builtins = NULL;
frame->f_globals = NULL;
#endif
frame->f_locals = NULL;
frame->stacktop = code->co_nlocalsplus + stackdepth;
frame->frame_obj = NULL;
frame->prev_instr = _PyCode_CODE(code) + prev_instr;
frame->owner = FRAME_OWNED_BY_THREAD;
frame->return_offset = 0;
return frame;
}
static inline
PyGenObject *_PyFrame_GetGenerator(_PyInterpreterFrame *frame)
{
assert(frame->owner == FRAME_OWNED_BY_GENERATOR);
size_t offset_in_gen = offsetof(PyGenObject, gi_iframe);
return (PyGenObject *)(((char *)frame) - offset_in_gen);
}
#define PY_EXECUTABLE_KIND_SKIP 0
#define PY_EXECUTABLE_KIND_PY_FUNCTION 1
#define PY_EXECUTABLE_KIND_BUILTIN_FUNCTION 3
#define PY_EXECUTABLE_KIND_METHOD_DESCRIPTOR 4
#define PY_EXECUTABLE_KINDS 5
PyAPI_DATA(const PyTypeObject *) const PyUnstable_ExecutableKinds[PY_EXECUTABLE_KINDS+1];
#ifdef __cplusplus
}
#endif
#endif