1 #ifndef Py_INTERNAL_FRAME_H
2 #define Py_INTERNAL_FRAME_H
3 #ifdef __cplusplus
4 extern "C" {
5 #endif
6
7 #ifndef Py_BUILD_CORE
8 # error "this header requires Py_BUILD_CORE define"
9 #endif
10
11 #include <stdbool.h>
12 #include <stddef.h> // offsetof()
13 #include "pycore_code.h" // STATS
14
15 /* See Objects/frame_layout.md for an explanation of the frame stack
16 * including explanation of the PyFrameObject and _PyInterpreterFrame
17 * structs. */
18
19
20 struct _frame {
21 PyObject_HEAD
22 PyFrameObject *f_back; /* previous frame, or NULL */
23 struct _PyInterpreterFrame *f_frame; /* points to the frame data */
24 PyObject *f_trace; /* Trace function */
25 int f_lineno; /* Current line number. Only valid if non-zero */
26 char f_trace_lines; /* Emit per-line trace events? */
27 char f_trace_opcodes; /* Emit per-opcode trace events? */
28 PyObject *f_extra_locals; /* Dict for locals set by users using f_locals, could be NULL */
29 /* This is purely for backwards compatibility for PyEval_GetLocals.
30 PyEval_GetLocals requires a borrowed reference so the actual reference
31 is stored here */
32 PyObject *f_locals_cache;
33 /* The frame data, if this frame object owns the frame */
34 PyObject *_f_frame_data[1];
35 };
36
37 extern PyFrameObject* _PyFrame_New_NoTrack(PyCodeObject *code);
38
39
40 /* other API */
41
42 typedef enum _framestate {
43 FRAME_CREATED = -3,
44 FRAME_SUSPENDED = -2,
45 FRAME_SUSPENDED_YIELD_FROM = -1,
46 FRAME_EXECUTING = 0,
47 FRAME_COMPLETED = 1,
48 FRAME_CLEARED = 4
49 } PyFrameState;
50
51 #define FRAME_STATE_SUSPENDED(S) ((S) == FRAME_SUSPENDED || (S) == FRAME_SUSPENDED_YIELD_FROM)
52 #define FRAME_STATE_FINISHED(S) ((S) >= FRAME_COMPLETED)
53
54 enum _frameowner {
55 FRAME_OWNED_BY_THREAD = 0,
56 FRAME_OWNED_BY_GENERATOR = 1,
57 FRAME_OWNED_BY_FRAME_OBJECT = 2,
58 FRAME_OWNED_BY_CSTACK = 3,
59 };
60
61 typedef struct _PyInterpreterFrame {
62 PyObject *f_executable; /* Strong reference (code object or None) */
63 struct _PyInterpreterFrame *previous;
64 PyObject *f_funcobj; /* Strong reference. Only valid if not on C stack */
65 PyObject *f_globals; /* Borrowed reference. Only valid if not on C stack */
66 PyObject *f_builtins; /* Borrowed reference. Only valid if not on C stack */
67 PyObject *f_locals; /* Strong reference, may be NULL. Only valid if not on C stack */
68 PyFrameObject *frame_obj; /* Strong reference, may be NULL. Only valid if not on C stack */
69 _Py_CODEUNIT *instr_ptr; /* Instruction currently executing (or about to begin) */
70 int stacktop; /* Offset of TOS from localsplus */
71 uint16_t return_offset; /* Only relevant during a function call */
72 char owner;
73 /* Locals and stack */
74 PyObject *localsplus[1];
75 } _PyInterpreterFrame;
76
77 #define _PyInterpreterFrame_LASTI(IF) \
78 ((int)((IF)->instr_ptr - _PyCode_CODE(_PyFrame_GetCode(IF))))
79
_PyFrame_GetCode(_PyInterpreterFrame * f)80 static inline PyCodeObject *_PyFrame_GetCode(_PyInterpreterFrame *f) {
81 assert(PyCode_Check(f->f_executable));
82 return (PyCodeObject *)f->f_executable;
83 }
84
_PyFrame_Stackbase(_PyInterpreterFrame * f)85 static inline PyObject **_PyFrame_Stackbase(_PyInterpreterFrame *f) {
86 return f->localsplus + _PyFrame_GetCode(f)->co_nlocalsplus;
87 }
88
_PyFrame_StackPeek(_PyInterpreterFrame * f)89 static inline PyObject *_PyFrame_StackPeek(_PyInterpreterFrame *f) {
90 assert(f->stacktop > _PyFrame_GetCode(f)->co_nlocalsplus);
91 assert(f->localsplus[f->stacktop-1] != NULL);
92 return f->localsplus[f->stacktop-1];
93 }
94
_PyFrame_StackPop(_PyInterpreterFrame * f)95 static inline PyObject *_PyFrame_StackPop(_PyInterpreterFrame *f) {
96 assert(f->stacktop > _PyFrame_GetCode(f)->co_nlocalsplus);
97 f->stacktop--;
98 return f->localsplus[f->stacktop];
99 }
100
_PyFrame_StackPush(_PyInterpreterFrame * f,PyObject * value)101 static inline void _PyFrame_StackPush(_PyInterpreterFrame *f, PyObject *value) {
102 f->localsplus[f->stacktop] = value;
103 f->stacktop++;
104 }
105
106 #define FRAME_SPECIALS_SIZE ((int)((sizeof(_PyInterpreterFrame)-1)/sizeof(PyObject *)))
107
108 static inline int
_PyFrame_NumSlotsForCodeObject(PyCodeObject * code)109 _PyFrame_NumSlotsForCodeObject(PyCodeObject *code)
110 {
111 /* This function needs to remain in sync with the calculation of
112 * co_framesize in Tools/build/deepfreeze.py */
113 assert(code->co_framesize >= FRAME_SPECIALS_SIZE);
114 return code->co_framesize - FRAME_SPECIALS_SIZE;
115 }
116
_PyFrame_Copy(_PyInterpreterFrame * src,_PyInterpreterFrame * dest)117 static inline void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest)
118 {
119 assert(src->stacktop >= _PyFrame_GetCode(src)->co_nlocalsplus);
120 *dest = *src;
121 for (int i = 1; i < src->stacktop; i++) {
122 dest->localsplus[i] = src->localsplus[i];
123 }
124 // Don't leave a dangling pointer to the old frame when creating generators
125 // and coroutines:
126 dest->previous = NULL;
127 }
128
129 /* Consumes reference to func and locals.
130 Does not initialize frame->previous, which happens
131 when frame is linked into the frame stack.
132 */
133 static inline void
_PyFrame_Initialize(_PyInterpreterFrame * frame,PyFunctionObject * func,PyObject * locals,PyCodeObject * code,int null_locals_from)134 _PyFrame_Initialize(
135 _PyInterpreterFrame *frame, PyFunctionObject *func,
136 PyObject *locals, PyCodeObject *code, int null_locals_from)
137 {
138 frame->f_funcobj = (PyObject *)func;
139 frame->f_executable = Py_NewRef(code);
140 frame->f_builtins = func->func_builtins;
141 frame->f_globals = func->func_globals;
142 frame->f_locals = locals;
143 frame->stacktop = code->co_nlocalsplus;
144 frame->frame_obj = NULL;
145 frame->instr_ptr = _PyCode_CODE(code);
146 frame->return_offset = 0;
147 frame->owner = FRAME_OWNED_BY_THREAD;
148
149 for (int i = null_locals_from; i < code->co_nlocalsplus; i++) {
150 frame->localsplus[i] = NULL;
151 }
152 }
153
154 /* Gets the pointer to the locals array
155 * that precedes this frame.
156 */
157 static inline PyObject**
_PyFrame_GetLocalsArray(_PyInterpreterFrame * frame)158 _PyFrame_GetLocalsArray(_PyInterpreterFrame *frame)
159 {
160 return frame->localsplus;
161 }
162
163 /* Fetches the stack pointer, and sets stacktop to -1.
164 Having stacktop <= 0 ensures that invalid
165 values are not visible to the cycle GC.
166 We choose -1 rather than 0 to assist debugging. */
167 static inline PyObject**
_PyFrame_GetStackPointer(_PyInterpreterFrame * frame)168 _PyFrame_GetStackPointer(_PyInterpreterFrame *frame)
169 {
170 PyObject **sp = frame->localsplus + frame->stacktop;
171 frame->stacktop = -1;
172 return sp;
173 }
174
175 static inline void
_PyFrame_SetStackPointer(_PyInterpreterFrame * frame,PyObject ** stack_pointer)176 _PyFrame_SetStackPointer(_PyInterpreterFrame *frame, PyObject **stack_pointer)
177 {
178 frame->stacktop = (int)(stack_pointer - frame->localsplus);
179 }
180
181 /* Determine whether a frame is incomplete.
182 * A frame is incomplete if it is part way through
183 * creating cell objects or a generator or coroutine.
184 *
185 * Frames on the frame stack are incomplete until the
186 * first RESUME instruction.
187 * Frames owned by a generator are always complete.
188 */
189 static inline bool
_PyFrame_IsIncomplete(_PyInterpreterFrame * frame)190 _PyFrame_IsIncomplete(_PyInterpreterFrame *frame)
191 {
192 if (frame->owner == FRAME_OWNED_BY_CSTACK) {
193 return true;
194 }
195 return frame->owner != FRAME_OWNED_BY_GENERATOR &&
196 frame->instr_ptr < _PyCode_CODE(_PyFrame_GetCode(frame)) + _PyFrame_GetCode(frame)->_co_firsttraceable;
197 }
198
199 static inline _PyInterpreterFrame *
_PyFrame_GetFirstComplete(_PyInterpreterFrame * frame)200 _PyFrame_GetFirstComplete(_PyInterpreterFrame *frame)
201 {
202 while (frame && _PyFrame_IsIncomplete(frame)) {
203 frame = frame->previous;
204 }
205 return frame;
206 }
207
208 static inline _PyInterpreterFrame *
_PyThreadState_GetFrame(PyThreadState * tstate)209 _PyThreadState_GetFrame(PyThreadState *tstate)
210 {
211 return _PyFrame_GetFirstComplete(tstate->current_frame);
212 }
213
214 /* For use by _PyFrame_GetFrameObject
215 Do not call directly. */
216 PyFrameObject *
217 _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame);
218
219 /* Gets the PyFrameObject for this frame, lazily
220 * creating it if necessary.
221 * Returns a borrowed reference */
222 static inline PyFrameObject *
_PyFrame_GetFrameObject(_PyInterpreterFrame * frame)223 _PyFrame_GetFrameObject(_PyInterpreterFrame *frame)
224 {
225
226 assert(!_PyFrame_IsIncomplete(frame));
227 PyFrameObject *res = frame->frame_obj;
228 if (res != NULL) {
229 return res;
230 }
231 return _PyFrame_MakeAndSetFrameObject(frame);
232 }
233
234 void
235 _PyFrame_ClearLocals(_PyInterpreterFrame *frame);
236
237 /* Clears all references in the frame.
238 * If take is non-zero, then the _PyInterpreterFrame frame
239 * may be transferred to the frame object it references
240 * instead of being cleared. Either way
241 * the caller no longer owns the references
242 * in the frame.
243 * take should be set to 1 for heap allocated
244 * frames like the ones in generators and coroutines.
245 */
246 void
247 _PyFrame_ClearExceptCode(_PyInterpreterFrame * frame);
248
249 int
250 _PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg);
251
252 bool
253 _PyFrame_HasHiddenLocals(_PyInterpreterFrame *frame);
254
255 PyObject *
256 _PyFrame_GetLocals(_PyInterpreterFrame *frame);
257
258 static inline bool
_PyThreadState_HasStackSpace(PyThreadState * tstate,int size)259 _PyThreadState_HasStackSpace(PyThreadState *tstate, int size)
260 {
261 assert(
262 (tstate->datastack_top == NULL && tstate->datastack_limit == NULL)
263 ||
264 (tstate->datastack_top != NULL && tstate->datastack_limit != NULL)
265 );
266 return tstate->datastack_top != NULL &&
267 size < tstate->datastack_limit - tstate->datastack_top;
268 }
269
270 extern _PyInterpreterFrame *
271 _PyThreadState_PushFrame(PyThreadState *tstate, size_t size);
272
273 PyAPI_FUNC(void) _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame *frame);
274
275 /* Pushes a frame without checking for space.
276 * Must be guarded by _PyThreadState_HasStackSpace()
277 * Consumes reference to func. */
278 static inline _PyInterpreterFrame *
_PyFrame_PushUnchecked(PyThreadState * tstate,PyFunctionObject * func,int null_locals_from)279 _PyFrame_PushUnchecked(PyThreadState *tstate, PyFunctionObject *func, int null_locals_from)
280 {
281 CALL_STAT_INC(frames_pushed);
282 PyCodeObject *code = (PyCodeObject *)func->func_code;
283 _PyInterpreterFrame *new_frame = (_PyInterpreterFrame *)tstate->datastack_top;
284 tstate->datastack_top += code->co_framesize;
285 assert(tstate->datastack_top < tstate->datastack_limit);
286 _PyFrame_Initialize(new_frame, func, NULL, code, null_locals_from);
287 return new_frame;
288 }
289
290 /* Pushes a trampoline frame without checking for space.
291 * Must be guarded by _PyThreadState_HasStackSpace() */
292 static inline _PyInterpreterFrame *
_PyFrame_PushTrampolineUnchecked(PyThreadState * tstate,PyCodeObject * code,int stackdepth)293 _PyFrame_PushTrampolineUnchecked(PyThreadState *tstate, PyCodeObject *code, int stackdepth)
294 {
295 CALL_STAT_INC(frames_pushed);
296 _PyInterpreterFrame *frame = (_PyInterpreterFrame *)tstate->datastack_top;
297 tstate->datastack_top += code->co_framesize;
298 assert(tstate->datastack_top < tstate->datastack_limit);
299 frame->f_funcobj = Py_None;
300 frame->f_executable = Py_NewRef(code);
301 #ifdef Py_DEBUG
302 frame->f_builtins = NULL;
303 frame->f_globals = NULL;
304 #endif
305 frame->f_locals = NULL;
306 frame->stacktop = code->co_nlocalsplus + stackdepth;
307 frame->frame_obj = NULL;
308 frame->instr_ptr = _PyCode_CODE(code);
309 frame->owner = FRAME_OWNED_BY_THREAD;
310 frame->return_offset = 0;
311 return frame;
312 }
313
314 static inline
_PyFrame_GetGenerator(_PyInterpreterFrame * frame)315 PyGenObject *_PyFrame_GetGenerator(_PyInterpreterFrame *frame)
316 {
317 assert(frame->owner == FRAME_OWNED_BY_GENERATOR);
318 size_t offset_in_gen = offsetof(PyGenObject, gi_iframe);
319 return (PyGenObject *)(((char *)frame) - offset_in_gen);
320 }
321
322 PyAPI_FUNC(_PyInterpreterFrame *)
323 _PyEvalFramePushAndInit(PyThreadState *tstate, PyFunctionObject *func,
324 PyObject *locals, PyObject* const* args,
325 size_t argcount, PyObject *kwnames);
326
327 #ifdef __cplusplus
328 }
329 #endif
330 #endif /* !Py_INTERNAL_FRAME_H */
331