Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:06:43

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