Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-19 09:50:46

0001 #ifndef Py_INTERNAL_FRAME_H
0002 #define Py_INTERNAL_FRAME_H
0003 #ifdef __cplusplus
0004 extern "C" {
0005 #endif
0006 
0007 #ifndef Py_BUILD_CORE
0008 #  error "this header requires Py_BUILD_CORE define"
0009 #endif
0010 
0011 #include <stdbool.h>
0012 #include <stddef.h>               // offsetof()
0013 #include "pycore_code.h"          // STATS
0014 
0015 /* See Objects/frame_layout.md for an explanation of the frame stack
0016  * including explanation of the PyFrameObject and _PyInterpreterFrame
0017  * structs. */
0018 
0019 
0020 struct _frame {
0021     PyObject_HEAD
0022     PyFrameObject *f_back;      /* previous frame, or NULL */
0023     struct _PyInterpreterFrame *f_frame; /* points to the frame data */
0024     PyObject *f_trace;          /* Trace function */
0025     int f_lineno;               /* Current line number. Only valid if non-zero */
0026     char f_trace_lines;         /* Emit per-line trace events? */
0027     char f_trace_opcodes;       /* Emit per-opcode trace events? */
0028     PyObject *f_extra_locals;   /* Dict for locals set by users using f_locals, could be NULL */
0029     /* This is purely for backwards compatibility for PyEval_GetLocals.
0030        PyEval_GetLocals requires a borrowed reference so the actual reference
0031        is stored here */
0032     PyObject *f_locals_cache;
0033     /* The frame data, if this frame object owns the frame */
0034     PyObject *_f_frame_data[1];
0035 };
0036 
0037 extern PyFrameObject* _PyFrame_New_NoTrack(PyCodeObject *code);
0038 
0039 
0040 /* other API */
0041 
0042 typedef enum _framestate {
0043     FRAME_CREATED = -3,
0044     FRAME_SUSPENDED = -2,
0045     FRAME_SUSPENDED_YIELD_FROM = -1,
0046     FRAME_EXECUTING = 0,
0047     FRAME_COMPLETED = 1,
0048     FRAME_CLEARED = 4
0049 } PyFrameState;
0050 
0051 #define FRAME_STATE_SUSPENDED(S) ((S) == FRAME_SUSPENDED || (S) == FRAME_SUSPENDED_YIELD_FROM)
0052 #define FRAME_STATE_FINISHED(S) ((S) >= FRAME_COMPLETED)
0053 
0054 enum _frameowner {
0055     FRAME_OWNED_BY_THREAD = 0,
0056     FRAME_OWNED_BY_GENERATOR = 1,
0057     FRAME_OWNED_BY_FRAME_OBJECT = 2,
0058     FRAME_OWNED_BY_CSTACK = 3,
0059 };
0060 
0061 typedef struct _PyInterpreterFrame {
0062     PyObject *f_executable; /* Strong reference (code object or None) */
0063     struct _PyInterpreterFrame *previous;
0064     PyObject *f_funcobj; /* Strong reference. Only valid if not on C stack */
0065     PyObject *f_globals; /* Borrowed reference. Only valid if not on C stack */
0066     PyObject *f_builtins; /* Borrowed reference. Only valid if not on C stack */
0067     PyObject *f_locals; /* Strong reference, may be NULL. Only valid if not on C stack */
0068     PyFrameObject *frame_obj; /* Strong reference, may be NULL. Only valid if not on C stack */
0069     _Py_CODEUNIT *instr_ptr; /* Instruction currently executing (or about to begin) */
0070     int stacktop;  /* Offset of TOS from localsplus  */
0071     uint16_t return_offset;  /* Only relevant during a function call */
0072     char owner;
0073     /* Locals and stack */
0074     PyObject *localsplus[1];
0075 } _PyInterpreterFrame;
0076 
0077 #define _PyInterpreterFrame_LASTI(IF) \
0078     ((int)((IF)->instr_ptr - _PyCode_CODE(_PyFrame_GetCode(IF))))
0079 
0080 static inline PyCodeObject *_PyFrame_GetCode(_PyInterpreterFrame *f) {
0081     assert(PyCode_Check(f->f_executable));
0082     return (PyCodeObject *)f->f_executable;
0083 }
0084 
0085 static inline PyObject **_PyFrame_Stackbase(_PyInterpreterFrame *f) {
0086     return f->localsplus + _PyFrame_GetCode(f)->co_nlocalsplus;
0087 }
0088 
0089 static inline PyObject *_PyFrame_StackPeek(_PyInterpreterFrame *f) {
0090     assert(f->stacktop > _PyFrame_GetCode(f)->co_nlocalsplus);
0091     assert(f->localsplus[f->stacktop-1] != NULL);
0092     return f->localsplus[f->stacktop-1];
0093 }
0094 
0095 static inline PyObject *_PyFrame_StackPop(_PyInterpreterFrame *f) {
0096     assert(f->stacktop > _PyFrame_GetCode(f)->co_nlocalsplus);
0097     f->stacktop--;
0098     return f->localsplus[f->stacktop];
0099 }
0100 
0101 static inline void _PyFrame_StackPush(_PyInterpreterFrame *f, PyObject *value) {
0102     f->localsplus[f->stacktop] = value;
0103     f->stacktop++;
0104 }
0105 
0106 #define FRAME_SPECIALS_SIZE ((int)((sizeof(_PyInterpreterFrame)-1)/sizeof(PyObject *)))
0107 
0108 static inline int
0109 _PyFrame_NumSlotsForCodeObject(PyCodeObject *code)
0110 {
0111     /* This function needs to remain in sync with the calculation of
0112      * co_framesize in Tools/build/deepfreeze.py */
0113     assert(code->co_framesize >= FRAME_SPECIALS_SIZE);
0114     return code->co_framesize - FRAME_SPECIALS_SIZE;
0115 }
0116 
0117 static inline void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest)
0118 {
0119     assert(src->stacktop >= _PyFrame_GetCode(src)->co_nlocalsplus);
0120     *dest = *src;
0121     for (int i = 1; i < src->stacktop; i++) {
0122         dest->localsplus[i] = src->localsplus[i];
0123     }
0124     // Don't leave a dangling pointer to the old frame when creating generators
0125     // and coroutines:
0126     dest->previous = NULL;
0127 }
0128 
0129 /* Consumes reference to func and locals.
0130    Does not initialize frame->previous, which happens
0131    when frame is linked into the frame stack.
0132  */
0133 static inline void
0134 _PyFrame_Initialize(
0135     _PyInterpreterFrame *frame, PyFunctionObject *func,
0136     PyObject *locals, PyCodeObject *code, int null_locals_from)
0137 {
0138     frame->f_funcobj = (PyObject *)func;
0139     frame->f_executable = Py_NewRef(code);
0140     frame->f_builtins = func->func_builtins;
0141     frame->f_globals = func->func_globals;
0142     frame->f_locals = locals;
0143     frame->stacktop = code->co_nlocalsplus;
0144     frame->frame_obj = NULL;
0145     frame->instr_ptr = _PyCode_CODE(code);
0146     frame->return_offset = 0;
0147     frame->owner = FRAME_OWNED_BY_THREAD;
0148 
0149     for (int i = null_locals_from; i < code->co_nlocalsplus; i++) {
0150         frame->localsplus[i] = NULL;
0151     }
0152 }
0153 
0154 /* Gets the pointer to the locals array
0155  * that precedes this frame.
0156  */
0157 static inline PyObject**
0158 _PyFrame_GetLocalsArray(_PyInterpreterFrame *frame)
0159 {
0160     return frame->localsplus;
0161 }
0162 
0163 /* Fetches the stack pointer, and sets stacktop to -1.
0164    Having stacktop <= 0 ensures that invalid
0165    values are not visible to the cycle GC.
0166    We choose -1 rather than 0 to assist debugging. */
0167 static inline PyObject**
0168 _PyFrame_GetStackPointer(_PyInterpreterFrame *frame)
0169 {
0170     PyObject **sp = frame->localsplus + frame->stacktop;
0171     frame->stacktop = -1;
0172     return sp;
0173 }
0174 
0175 static inline void
0176 _PyFrame_SetStackPointer(_PyInterpreterFrame *frame, PyObject **stack_pointer)
0177 {
0178     frame->stacktop = (int)(stack_pointer - frame->localsplus);
0179 }
0180 
0181 /* Determine whether a frame is incomplete.
0182  * A frame is incomplete if it is part way through
0183  * creating cell objects or a generator or coroutine.
0184  *
0185  * Frames on the frame stack are incomplete until the
0186  * first RESUME instruction.
0187  * Frames owned by a generator are always complete.
0188  */
0189 static inline bool
0190 _PyFrame_IsIncomplete(_PyInterpreterFrame *frame)
0191 {
0192     if (frame->owner == FRAME_OWNED_BY_CSTACK) {
0193         return true;
0194     }
0195     return frame->owner != FRAME_OWNED_BY_GENERATOR &&
0196         frame->instr_ptr < _PyCode_CODE(_PyFrame_GetCode(frame)) + _PyFrame_GetCode(frame)->_co_firsttraceable;
0197 }
0198 
0199 static inline _PyInterpreterFrame *
0200 _PyFrame_GetFirstComplete(_PyInterpreterFrame *frame)
0201 {
0202     while (frame && _PyFrame_IsIncomplete(frame)) {
0203         frame = frame->previous;
0204     }
0205     return frame;
0206 }
0207 
0208 static inline _PyInterpreterFrame *
0209 _PyThreadState_GetFrame(PyThreadState *tstate)
0210 {
0211     return _PyFrame_GetFirstComplete(tstate->current_frame);
0212 }
0213 
0214 /* For use by _PyFrame_GetFrameObject
0215   Do not call directly. */
0216 PyFrameObject *
0217 _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame);
0218 
0219 /* Gets the PyFrameObject for this frame, lazily
0220  * creating it if necessary.
0221  * Returns a borrowed reference */
0222 static inline PyFrameObject *
0223 _PyFrame_GetFrameObject(_PyInterpreterFrame *frame)
0224 {
0225 
0226     assert(!_PyFrame_IsIncomplete(frame));
0227     PyFrameObject *res =  frame->frame_obj;
0228     if (res != NULL) {
0229         return res;
0230     }
0231     return _PyFrame_MakeAndSetFrameObject(frame);
0232 }
0233 
0234 void
0235 _PyFrame_ClearLocals(_PyInterpreterFrame *frame);
0236 
0237 /* Clears all references in the frame.
0238  * If take is non-zero, then the _PyInterpreterFrame frame
0239  * may be transferred to the frame object it references
0240  * instead of being cleared. Either way
0241  * the caller no longer owns the references
0242  * in the frame.
0243  * take should  be set to 1 for heap allocated
0244  * frames like the ones in generators and coroutines.
0245  */
0246 void
0247 _PyFrame_ClearExceptCode(_PyInterpreterFrame * frame);
0248 
0249 int
0250 _PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg);
0251 
0252 bool
0253 _PyFrame_HasHiddenLocals(_PyInterpreterFrame *frame);
0254 
0255 PyObject *
0256 _PyFrame_GetLocals(_PyInterpreterFrame *frame);
0257 
0258 static inline bool
0259 _PyThreadState_HasStackSpace(PyThreadState *tstate, int size)
0260 {
0261     assert(
0262         (tstate->datastack_top == NULL && tstate->datastack_limit == NULL)
0263         ||
0264         (tstate->datastack_top != NULL && tstate->datastack_limit != NULL)
0265     );
0266     return tstate->datastack_top != NULL &&
0267         size < tstate->datastack_limit - tstate->datastack_top;
0268 }
0269 
0270 extern _PyInterpreterFrame *
0271 _PyThreadState_PushFrame(PyThreadState *tstate, size_t size);
0272 
0273 PyAPI_FUNC(void) _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame *frame);
0274 
0275 /* Pushes a frame without checking for space.
0276  * Must be guarded by _PyThreadState_HasStackSpace()
0277  * Consumes reference to func. */
0278 static inline _PyInterpreterFrame *
0279 _PyFrame_PushUnchecked(PyThreadState *tstate, PyFunctionObject *func, int null_locals_from)
0280 {
0281     CALL_STAT_INC(frames_pushed);
0282     PyCodeObject *code = (PyCodeObject *)func->func_code;
0283     _PyInterpreterFrame *new_frame = (_PyInterpreterFrame *)tstate->datastack_top;
0284     tstate->datastack_top += code->co_framesize;
0285     assert(tstate->datastack_top < tstate->datastack_limit);
0286     _PyFrame_Initialize(new_frame, func, NULL, code, null_locals_from);
0287     return new_frame;
0288 }
0289 
0290 /* Pushes a trampoline frame without checking for space.
0291  * Must be guarded by _PyThreadState_HasStackSpace() */
0292 static inline _PyInterpreterFrame *
0293 _PyFrame_PushTrampolineUnchecked(PyThreadState *tstate, PyCodeObject *code, int stackdepth)
0294 {
0295     CALL_STAT_INC(frames_pushed);
0296     _PyInterpreterFrame *frame = (_PyInterpreterFrame *)tstate->datastack_top;
0297     tstate->datastack_top += code->co_framesize;
0298     assert(tstate->datastack_top < tstate->datastack_limit);
0299     frame->f_funcobj = Py_None;
0300     frame->f_executable = Py_NewRef(code);
0301 #ifdef Py_DEBUG
0302     frame->f_builtins = NULL;
0303     frame->f_globals = NULL;
0304 #endif
0305     frame->f_locals = NULL;
0306     frame->stacktop = code->co_nlocalsplus + stackdepth;
0307     frame->frame_obj = NULL;
0308     frame->instr_ptr = _PyCode_CODE(code);
0309     frame->owner = FRAME_OWNED_BY_THREAD;
0310     frame->return_offset = 0;
0311     return frame;
0312 }
0313 
0314 static inline
0315 PyGenObject *_PyFrame_GetGenerator(_PyInterpreterFrame *frame)
0316 {
0317     assert(frame->owner == FRAME_OWNED_BY_GENERATOR);
0318     size_t offset_in_gen = offsetof(PyGenObject, gi_iframe);
0319     return (PyGenObject *)(((char *)frame) - offset_in_gen);
0320 }
0321 
0322 PyAPI_FUNC(_PyInterpreterFrame *)
0323 _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
0324                         PyObject *locals, PyObject* const* args,
0325                         size_t argcount, PyObject *kwnames);
0326 
0327 #ifdef __cplusplus
0328 }
0329 #endif
0330 #endif /* !Py_INTERNAL_FRAME_H */