1 #ifndef Py_INTERNAL_FRAME_H
2 #define Py_INTERNAL_FRAME_H
3 #ifdef __cplusplus
4 extern "C" {
5 #endif
6
7 #include <stdbool.h>
8 #include <stddef.h>
9
10 /* See Objects/frame_layout.md for an explanation of the frame stack
11 * including explanation of the PyFrameObject and _PyInterpreterFrame
12 * structs. */
13
14
15 struct _frame {
16 PyObject_HEAD
17 PyFrameObject *f_back; /* previous frame, or NULL */
18 struct _PyInterpreterFrame *f_frame; /* points to the frame data */
19 PyObject *f_trace; /* Trace function */
20 int f_lineno; /* Current line number. Only valid if non-zero */
21 char f_trace_lines; /* Emit per-line trace events? */
22 char f_trace_opcodes; /* Emit per-opcode trace events? */
23 char f_fast_as_locals; /* Have the fast locals of this frame been converted to a dict? */
24 /* The frame data, if this frame object owns the frame */
25 PyObject *_f_frame_data[1];
26 };
27
28 extern PyFrameObject* _PyFrame_New_NoTrack(PyCodeObject *code);
29
30
31 /* other API */
32
33 typedef enum _framestate {
34 FRAME_CREATED = -2,
35 FRAME_SUSPENDED = -1,
36 FRAME_EXECUTING = 0,
37 FRAME_COMPLETED = 1,
38 FRAME_CLEARED = 4
39 } PyFrameState;
40
41 enum _frameowner {
42 FRAME_OWNED_BY_THREAD = 0,
43 FRAME_OWNED_BY_GENERATOR = 1,
44 FRAME_OWNED_BY_FRAME_OBJECT = 2
45 };
46
47 typedef struct _PyInterpreterFrame {
48 /* "Specials" section */
49 PyFunctionObject *f_func; /* Strong reference */
50 PyObject *f_globals; /* Borrowed reference */
51 PyObject *f_builtins; /* Borrowed reference */
52 PyObject *f_locals; /* Strong reference, may be NULL */
53 PyCodeObject *f_code; /* Strong reference */
54 PyFrameObject *frame_obj; /* Strong reference, may be NULL */
55 /* Linkage section */
56 struct _PyInterpreterFrame *previous;
57 // NOTE: This is not necessarily the last instruction started in the given
58 // frame. Rather, it is the code unit *prior to* the *next* instruction. For
59 // example, it may be an inline CACHE entry, an instruction we just jumped
60 // over, or (in the case of a newly-created frame) a totally invalid value:
61 _Py_CODEUNIT *prev_instr;
62 int stacktop; /* Offset of TOS from localsplus */
63 bool is_entry; // Whether this is the "root" frame for the current _PyCFrame.
64 char owner;
65 /* Locals and stack */
66 PyObject *localsplus[1];
67 } _PyInterpreterFrame;
68
69 #define _PyInterpreterFrame_LASTI(IF) \
70 ((int)((IF)->prev_instr - _PyCode_CODE((IF)->f_code)))
71
_PyFrame_Stackbase(_PyInterpreterFrame * f)72 static inline PyObject **_PyFrame_Stackbase(_PyInterpreterFrame *f) {
73 return f->localsplus + f->f_code->co_nlocalsplus;
74 }
75
_PyFrame_StackPeek(_PyInterpreterFrame * f)76 static inline PyObject *_PyFrame_StackPeek(_PyInterpreterFrame *f) {
77 assert(f->stacktop > f->f_code->co_nlocalsplus);
78 assert(f->localsplus[f->stacktop-1] != NULL);
79 return f->localsplus[f->stacktop-1];
80 }
81
_PyFrame_StackPop(_PyInterpreterFrame * f)82 static inline PyObject *_PyFrame_StackPop(_PyInterpreterFrame *f) {
83 assert(f->stacktop > f->f_code->co_nlocalsplus);
84 f->stacktop--;
85 return f->localsplus[f->stacktop];
86 }
87
_PyFrame_StackPush(_PyInterpreterFrame * f,PyObject * value)88 static inline void _PyFrame_StackPush(_PyInterpreterFrame *f, PyObject *value) {
89 f->localsplus[f->stacktop] = value;
90 f->stacktop++;
91 }
92
93 #define FRAME_SPECIALS_SIZE ((sizeof(_PyInterpreterFrame)-1)/sizeof(PyObject *))
94
95 void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *dest);
96
97 /* Consumes reference to func and locals.
98 Does not initialize frame->previous, which happens
99 when frame is linked into the frame stack.
100 */
101 static inline void
_PyFrame_InitializeSpecials(_PyInterpreterFrame * frame,PyFunctionObject * func,PyObject * locals,int nlocalsplus)102 _PyFrame_InitializeSpecials(
103 _PyInterpreterFrame *frame, PyFunctionObject *func,
104 PyObject *locals, int nlocalsplus)
105 {
106 frame->f_func = func;
107 frame->f_code = (PyCodeObject *)Py_NewRef(func->func_code);
108 frame->f_builtins = func->func_builtins;
109 frame->f_globals = func->func_globals;
110 frame->f_locals = Py_XNewRef(locals);
111 frame->stacktop = nlocalsplus;
112 frame->frame_obj = NULL;
113 frame->prev_instr = _PyCode_CODE(frame->f_code) - 1;
114 frame->is_entry = false;
115 frame->owner = FRAME_OWNED_BY_THREAD;
116 }
117
118 /* Gets the pointer to the locals array
119 * that precedes this frame.
120 */
121 static inline PyObject**
_PyFrame_GetLocalsArray(_PyInterpreterFrame * frame)122 _PyFrame_GetLocalsArray(_PyInterpreterFrame *frame)
123 {
124 return frame->localsplus;
125 }
126
127 static inline PyObject**
_PyFrame_GetStackPointer(_PyInterpreterFrame * frame)128 _PyFrame_GetStackPointer(_PyInterpreterFrame *frame)
129 {
130 return frame->localsplus+frame->stacktop;
131 }
132
133 static inline void
_PyFrame_SetStackPointer(_PyInterpreterFrame * frame,PyObject ** stack_pointer)134 _PyFrame_SetStackPointer(_PyInterpreterFrame *frame, PyObject **stack_pointer)
135 {
136 frame->stacktop = (int)(stack_pointer - frame->localsplus);
137 }
138
139 /* Determine whether a frame is incomplete.
140 * A frame is incomplete if it is part way through
141 * creating cell objects or a generator or coroutine.
142 *
143 * Frames on the frame stack are incomplete until the
144 * first RESUME instruction.
145 * Frames owned by a generator are always complete.
146 */
147 static inline bool
_PyFrame_IsIncomplete(_PyInterpreterFrame * frame)148 _PyFrame_IsIncomplete(_PyInterpreterFrame *frame)
149 {
150 return frame->owner != FRAME_OWNED_BY_GENERATOR &&
151 frame->prev_instr < _PyCode_CODE(frame->f_code) + frame->f_code->_co_firsttraceable;
152 }
153
154 /* For use by _PyFrame_GetFrameObject
155 Do not call directly. */
156 PyFrameObject *
157 _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame);
158
159 /* Gets the PyFrameObject for this frame, lazily
160 * creating it if necessary.
161 * Returns a borrowed referennce */
162 static inline PyFrameObject *
_PyFrame_GetFrameObject(_PyInterpreterFrame * frame)163 _PyFrame_GetFrameObject(_PyInterpreterFrame *frame)
164 {
165
166 assert(!_PyFrame_IsIncomplete(frame));
167 PyFrameObject *res = frame->frame_obj;
168 if (res != NULL) {
169 return res;
170 }
171 return _PyFrame_MakeAndSetFrameObject(frame);
172 }
173
174 /* Clears all references in the frame.
175 * If take is non-zero, then the _PyInterpreterFrame frame
176 * may be transferred to the frame object it references
177 * instead of being cleared. Either way
178 * the caller no longer owns the references
179 * in the frame.
180 * take should be set to 1 for heap allocated
181 * frames like the ones in generators and coroutines.
182 */
183 void
184 _PyFrame_Clear(_PyInterpreterFrame * frame);
185
186 int
187 _PyFrame_Traverse(_PyInterpreterFrame *frame, visitproc visit, void *arg);
188
189 int
190 _PyFrame_FastToLocalsWithError(_PyInterpreterFrame *frame);
191
192 void
193 _PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear);
194
195 extern _PyInterpreterFrame *
196 _PyThreadState_BumpFramePointerSlow(PyThreadState *tstate, size_t size);
197
198 static inline bool
_PyThreadState_HasStackSpace(PyThreadState * tstate,size_t size)199 _PyThreadState_HasStackSpace(PyThreadState *tstate, size_t size)
200 {
201 assert(
202 (tstate->datastack_top == NULL && tstate->datastack_limit == NULL)
203 ||
204 (tstate->datastack_top != NULL && tstate->datastack_limit != NULL)
205 );
206 return tstate->datastack_top != NULL &&
207 size < (size_t)(tstate->datastack_limit - tstate->datastack_top);
208 }
209
210 static inline _PyInterpreterFrame *
_PyThreadState_BumpFramePointer(PyThreadState * tstate,size_t size)211 _PyThreadState_BumpFramePointer(PyThreadState *tstate, size_t size)
212 {
213 if (_PyThreadState_HasStackSpace(tstate, size)) {
214 _PyInterpreterFrame *res = (_PyInterpreterFrame *)tstate->datastack_top;
215 tstate->datastack_top += size;
216 return res;
217 }
218 return _PyThreadState_BumpFramePointerSlow(tstate, size);
219 }
220
221 void _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame *frame);
222
223 /* Consume reference to func */
224 _PyInterpreterFrame *
225 _PyFrame_Push(PyThreadState *tstate, PyFunctionObject *func);
226
227 int _PyInterpreterFrame_GetLine(_PyInterpreterFrame *frame);
228
229 static inline
_PyFrame_GetGenerator(_PyInterpreterFrame * frame)230 PyGenObject *_PyFrame_GetGenerator(_PyInterpreterFrame *frame)
231 {
232 assert(frame->owner == FRAME_OWNED_BY_GENERATOR);
233 size_t offset_in_gen = offsetof(PyGenObject, gi_iframe);
234 return (PyGenObject *)(((char *)frame) - offset_in_gen);
235 }
236
237 #ifdef __cplusplus
238 }
239 #endif
240 #endif /* !Py_INTERNAL_FRAME_H */
241