• 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 #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