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
0012
0013
0014
0015
0016 struct _frame {
0017 PyObject_HEAD
0018 PyFrameObject *f_back;
0019 struct _PyInterpreterFrame *f_frame;
0020 PyObject *f_trace;
0021 int f_lineno;
0022 char f_trace_lines;
0023 char f_trace_opcodes;
0024 char f_fast_as_locals;
0025
0026 PyObject *_f_frame_data[1];
0027 };
0028
0029 extern PyFrameObject* _PyFrame_New_NoTrack(PyCodeObject *code);
0030
0031
0032
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;
0053 struct _PyInterpreterFrame *previous;
0054 PyObject *f_funcobj;
0055 PyObject *f_globals;
0056 PyObject *f_builtins;
0057 PyObject *f_locals;
0058 PyFrameObject *frame_obj;
0059
0060
0061
0062
0063 _Py_CODEUNIT *prev_instr;
0064 int stacktop;
0065
0066
0067
0068
0069
0070
0071 uint16_t return_offset;
0072 char owner;
0073
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
0107
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
0115
0116
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
0140
0141
0142 static inline PyObject**
0143 _PyFrame_GetLocalsArray(_PyInterpreterFrame *frame)
0144 {
0145 return frame->localsplus;
0146 }
0147
0148
0149
0150
0151
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
0167
0168
0169
0170
0171
0172
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
0197
0198 PyFrameObject *
0199 _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame);
0200
0201
0202
0203
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
0217
0218
0219
0220
0221
0222
0223
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
0258
0259
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