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
0016
0017
0018
0019
0020 struct _frame {
0021 PyObject_HEAD
0022 PyFrameObject *f_back;
0023 struct _PyInterpreterFrame *f_frame;
0024 PyObject *f_trace;
0025 int f_lineno;
0026 char f_trace_lines;
0027 char f_trace_opcodes;
0028 PyObject *f_extra_locals;
0029
0030
0031
0032 PyObject *f_locals_cache;
0033
0034 PyObject *_f_frame_data[1];
0035 };
0036
0037 extern PyFrameObject* _PyFrame_New_NoTrack(PyCodeObject *code);
0038
0039
0040
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;
0063 struct _PyInterpreterFrame *previous;
0064 PyObject *f_funcobj;
0065 PyObject *f_globals;
0066 PyObject *f_builtins;
0067 PyObject *f_locals;
0068 PyFrameObject *frame_obj;
0069 _Py_CODEUNIT *instr_ptr;
0070 int stacktop;
0071 uint16_t return_offset;
0072 char owner;
0073
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
0112
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
0125
0126 dest->previous = NULL;
0127 }
0128
0129
0130
0131
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
0155
0156
0157 static inline PyObject**
0158 _PyFrame_GetLocalsArray(_PyInterpreterFrame *frame)
0159 {
0160 return frame->localsplus;
0161 }
0162
0163
0164
0165
0166
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
0182
0183
0184
0185
0186
0187
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
0215
0216 PyFrameObject *
0217 _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame);
0218
0219
0220
0221
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
0238
0239
0240
0241
0242
0243
0244
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
0276
0277
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
0291
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