• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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