1
+ /* See InternalDocs/frames.md for an explanation of the frame stack
2
+ * including explanation of the PyFrameObject and _PyInterpreterFrame
3
+ * structs. */
4
+
1
5
#ifndef Py_INTERNAL_FRAME_H
2
6
#define Py_INTERNAL_FRAME_H
3
7
#ifdef __cplusplus
@@ -8,17 +12,8 @@ extern "C" {
8
12
# error "this header requires Py_BUILD_CORE define"
9
13
#endif
10
14
11
- #include <stdbool.h>
12
- #include <stddef.h> // offsetof()
13
- #include "pycore_code.h" // STATS
14
- #include "pycore_stackref.h" // _PyStackRef
15
- #include "pycore_stats.h"
16
15
#include "pycore_typedefs.h" // _PyInterpreterFrame
17
16
18
- /* See InternalDocs/frames.md for an explanation of the frame stack
19
- * including explanation of the PyFrameObject and _PyInterpreterFrame
20
- * structs. */
21
-
22
17
23
18
struct _frame {
24
19
PyObject_HEAD
@@ -54,360 +49,6 @@ typedef enum _framestate {
54
49
#define FRAME_STATE_SUSPENDED (S ) ((S) == FRAME_SUSPENDED || (S) == FRAME_SUSPENDED_YIELD_FROM)
55
50
#define FRAME_STATE_FINISHED (S ) ((S) >= FRAME_COMPLETED)
56
51
57
- enum _frameowner {
58
- FRAME_OWNED_BY_THREAD = 0 ,
59
- FRAME_OWNED_BY_GENERATOR = 1 ,
60
- FRAME_OWNED_BY_FRAME_OBJECT = 2 ,
61
- FRAME_OWNED_BY_INTERPRETER = 3 ,
62
- FRAME_OWNED_BY_CSTACK = 4 ,
63
- };
64
-
65
- struct _PyInterpreterFrame {
66
- _PyStackRef f_executable ; /* Deferred or strong reference (code object or None) */
67
- struct _PyInterpreterFrame * previous ;
68
- _PyStackRef f_funcobj ; /* Deferred or strong reference. Only valid if not on C stack */
69
- PyObject * f_globals ; /* Borrowed reference. Only valid if not on C stack */
70
- PyObject * f_builtins ; /* Borrowed reference. Only valid if not on C stack */
71
- PyObject * f_locals ; /* Strong reference, may be NULL. Only valid if not on C stack */
72
- PyFrameObject * frame_obj ; /* Strong reference, may be NULL. Only valid if not on C stack */
73
- _Py_CODEUNIT * instr_ptr ; /* Instruction currently executing (or about to begin) */
74
- _PyStackRef * stackpointer ;
75
- #ifdef Py_GIL_DISABLED
76
- /* Index of thread-local bytecode containing instr_ptr. */
77
- int32_t tlbc_index ;
78
- #endif
79
- uint16_t return_offset ; /* Only relevant during a function call */
80
- char owner ;
81
- #ifdef Py_DEBUG
82
- uint8_t visited :1 ;
83
- uint8_t lltrace :7 ;
84
- #else
85
- uint8_t visited ;
86
- #endif
87
- /* Locals and stack */
88
- _PyStackRef localsplus [1 ];
89
- };
90
-
91
- #define _PyInterpreterFrame_LASTI (IF ) \
92
- ((int)((IF)->instr_ptr - _PyFrame_GetBytecode((IF))))
93
-
94
- static inline PyCodeObject * _PyFrame_GetCode (_PyInterpreterFrame * f ) {
95
- PyObject * executable = PyStackRef_AsPyObjectBorrow (f -> f_executable );
96
- assert (PyCode_Check (executable ));
97
- return (PyCodeObject * )executable ;
98
- }
99
-
100
- static inline _Py_CODEUNIT *
101
- _PyFrame_GetBytecode (_PyInterpreterFrame * f )
102
- {
103
- #ifdef Py_GIL_DISABLED
104
- PyCodeObject * co = _PyFrame_GetCode (f );
105
- _PyCodeArray * tlbc = _PyCode_GetTLBCArray (co );
106
- assert (f -> tlbc_index >= 0 && f -> tlbc_index < tlbc -> size );
107
- return (_Py_CODEUNIT * )tlbc -> entries [f -> tlbc_index ];
108
- #else
109
- return _PyCode_CODE (_PyFrame_GetCode (f ));
110
- #endif
111
- }
112
-
113
- static inline PyFunctionObject * _PyFrame_GetFunction (_PyInterpreterFrame * f ) {
114
- PyObject * func = PyStackRef_AsPyObjectBorrow (f -> f_funcobj );
115
- assert (PyFunction_Check (func ));
116
- return (PyFunctionObject * )func ;
117
- }
118
-
119
- static inline _PyStackRef * _PyFrame_Stackbase (_PyInterpreterFrame * f ) {
120
- return (f -> localsplus + _PyFrame_GetCode (f )-> co_nlocalsplus );
121
- }
122
-
123
- static inline _PyStackRef _PyFrame_StackPeek (_PyInterpreterFrame * f ) {
124
- assert (f -> stackpointer > f -> localsplus + _PyFrame_GetCode (f )-> co_nlocalsplus );
125
- assert (!PyStackRef_IsNull (f -> stackpointer [-1 ]));
126
- return f -> stackpointer [-1 ];
127
- }
128
-
129
- static inline _PyStackRef _PyFrame_StackPop (_PyInterpreterFrame * f ) {
130
- assert (f -> stackpointer > f -> localsplus + _PyFrame_GetCode (f )-> co_nlocalsplus );
131
- f -> stackpointer -- ;
132
- return * f -> stackpointer ;
133
- }
134
-
135
- static inline void _PyFrame_StackPush (_PyInterpreterFrame * f , _PyStackRef value ) {
136
- * f -> stackpointer = value ;
137
- f -> stackpointer ++ ;
138
- }
139
-
140
- #define FRAME_SPECIALS_SIZE ((int)((sizeof(_PyInterpreterFrame)-1)/sizeof(PyObject *)))
141
-
142
- static inline int
143
- _PyFrame_NumSlotsForCodeObject (PyCodeObject * code )
144
- {
145
- /* This function needs to remain in sync with the calculation of
146
- * co_framesize in Tools/build/deepfreeze.py */
147
- assert (code -> co_framesize >= FRAME_SPECIALS_SIZE );
148
- return code -> co_framesize - FRAME_SPECIALS_SIZE ;
149
- }
150
-
151
- static inline void _PyFrame_Copy (_PyInterpreterFrame * src , _PyInterpreterFrame * dest )
152
- {
153
- dest -> f_executable = PyStackRef_MakeHeapSafe (src -> f_executable );
154
- // Don't leave a dangling pointer to the old frame when creating generators
155
- // and coroutines:
156
- dest -> previous = NULL ;
157
- dest -> f_funcobj = PyStackRef_MakeHeapSafe (src -> f_funcobj );
158
- dest -> f_globals = src -> f_globals ;
159
- dest -> f_builtins = src -> f_builtins ;
160
- dest -> f_locals = src -> f_locals ;
161
- dest -> frame_obj = src -> frame_obj ;
162
- dest -> instr_ptr = src -> instr_ptr ;
163
- #ifdef Py_GIL_DISABLED
164
- dest -> tlbc_index = src -> tlbc_index ;
165
- #endif
166
- assert (src -> stackpointer != NULL );
167
- int stacktop = (int )(src -> stackpointer - src -> localsplus );
168
- assert (stacktop >= 0 );
169
- dest -> stackpointer = dest -> localsplus + stacktop ;
170
- for (int i = 0 ; i < stacktop ; i ++ ) {
171
- dest -> localsplus [i ] = PyStackRef_MakeHeapSafe (src -> localsplus [i ]);
172
- }
173
- }
174
-
175
- #ifdef Py_GIL_DISABLED
176
- static inline void
177
- _PyFrame_InitializeTLBC (PyThreadState * tstate , _PyInterpreterFrame * frame ,
178
- PyCodeObject * code )
179
- {
180
- _Py_CODEUNIT * tlbc = _PyCode_GetTLBCFast (tstate , code );
181
- if (tlbc == NULL ) {
182
- // No thread-local bytecode exists for this thread yet; use the main
183
- // thread's copy, deferring thread-local bytecode creation to the
184
- // execution of RESUME.
185
- frame -> instr_ptr = _PyCode_CODE (code );
186
- frame -> tlbc_index = 0 ;
187
- }
188
- else {
189
- frame -> instr_ptr = tlbc ;
190
- frame -> tlbc_index = ((_PyThreadStateImpl * )tstate )-> tlbc_index ;
191
- }
192
- }
193
- #endif
194
-
195
- /* Consumes reference to func and locals.
196
- Does not initialize frame->previous, which happens
197
- when frame is linked into the frame stack.
198
- */
199
- static inline void
200
- _PyFrame_Initialize (
201
- PyThreadState * tstate , _PyInterpreterFrame * frame , _PyStackRef func ,
202
- PyObject * locals , PyCodeObject * code , int null_locals_from , _PyInterpreterFrame * previous )
203
- {
204
- frame -> previous = previous ;
205
- frame -> f_funcobj = func ;
206
- frame -> f_executable = PyStackRef_FromPyObjectNew (code );
207
- PyFunctionObject * func_obj = (PyFunctionObject * )PyStackRef_AsPyObjectBorrow (func );
208
- frame -> f_builtins = func_obj -> func_builtins ;
209
- frame -> f_globals = func_obj -> func_globals ;
210
- frame -> f_locals = locals ;
211
- frame -> stackpointer = frame -> localsplus + code -> co_nlocalsplus ;
212
- frame -> frame_obj = NULL ;
213
- #ifdef Py_GIL_DISABLED
214
- _PyFrame_InitializeTLBC (tstate , frame , code );
215
- #else
216
- (void )tstate ;
217
- frame -> instr_ptr = _PyCode_CODE (code );
218
- #endif
219
- frame -> return_offset = 0 ;
220
- frame -> owner = FRAME_OWNED_BY_THREAD ;
221
- frame -> visited = 0 ;
222
- #ifdef Py_DEBUG
223
- frame -> lltrace = 0 ;
224
- #endif
225
-
226
- for (int i = null_locals_from ; i < code -> co_nlocalsplus ; i ++ ) {
227
- frame -> localsplus [i ] = PyStackRef_NULL ;
228
- }
229
- }
230
-
231
- /* Gets the pointer to the locals array
232
- * that precedes this frame.
233
- */
234
- static inline _PyStackRef *
235
- _PyFrame_GetLocalsArray (_PyInterpreterFrame * frame )
236
- {
237
- return frame -> localsplus ;
238
- }
239
-
240
- /* Fetches the stack pointer, and sets stackpointer to NULL.
241
- Having stackpointer == NULL ensures that invalid
242
- values are not visible to the cycle GC. */
243
- static inline _PyStackRef *
244
- _PyFrame_GetStackPointer (_PyInterpreterFrame * frame )
245
- {
246
- assert (frame -> stackpointer != NULL );
247
- _PyStackRef * sp = frame -> stackpointer ;
248
- frame -> stackpointer = NULL ;
249
- return sp ;
250
- }
251
-
252
- static inline void
253
- _PyFrame_SetStackPointer (_PyInterpreterFrame * frame , _PyStackRef * stack_pointer )
254
- {
255
- assert (frame -> stackpointer == NULL );
256
- frame -> stackpointer = stack_pointer ;
257
- }
258
-
259
- /* Determine whether a frame is incomplete.
260
- * A frame is incomplete if it is part way through
261
- * creating cell objects or a generator or coroutine.
262
- *
263
- * Frames on the frame stack are incomplete until the
264
- * first RESUME instruction.
265
- * Frames owned by a generator are always complete.
266
- */
267
- static inline bool
268
- _PyFrame_IsIncomplete (_PyInterpreterFrame * frame )
269
- {
270
- if (frame -> owner >= FRAME_OWNED_BY_INTERPRETER ) {
271
- return true;
272
- }
273
- return frame -> owner != FRAME_OWNED_BY_GENERATOR &&
274
- frame -> instr_ptr < _PyFrame_GetBytecode (frame ) +
275
- _PyFrame_GetCode (frame )-> _co_firsttraceable ;
276
- }
277
-
278
- static inline _PyInterpreterFrame *
279
- _PyFrame_GetFirstComplete (_PyInterpreterFrame * frame )
280
- {
281
- while (frame && _PyFrame_IsIncomplete (frame )) {
282
- frame = frame -> previous ;
283
- }
284
- return frame ;
285
- }
286
-
287
- static inline _PyInterpreterFrame *
288
- _PyThreadState_GetFrame (PyThreadState * tstate )
289
- {
290
- return _PyFrame_GetFirstComplete (tstate -> current_frame );
291
- }
292
-
293
- /* For use by _PyFrame_GetFrameObject
294
- Do not call directly. */
295
- PyFrameObject *
296
- _PyFrame_MakeAndSetFrameObject (_PyInterpreterFrame * frame );
297
-
298
- /* Gets the PyFrameObject for this frame, lazily
299
- * creating it if necessary.
300
- * Returns a borrowed reference */
301
- static inline PyFrameObject *
302
- _PyFrame_GetFrameObject (_PyInterpreterFrame * frame )
303
- {
304
-
305
- assert (!_PyFrame_IsIncomplete (frame ));
306
- PyFrameObject * res = frame -> frame_obj ;
307
- if (res != NULL ) {
308
- return res ;
309
- }
310
- return _PyFrame_MakeAndSetFrameObject (frame );
311
- }
312
-
313
- void
314
- _PyFrame_ClearLocals (_PyInterpreterFrame * frame );
315
-
316
- /* Clears all references in the frame.
317
- * If take is non-zero, then the _PyInterpreterFrame frame
318
- * may be transferred to the frame object it references
319
- * instead of being cleared. Either way
320
- * the caller no longer owns the references
321
- * in the frame.
322
- * take should be set to 1 for heap allocated
323
- * frames like the ones in generators and coroutines.
324
- */
325
- void
326
- _PyFrame_ClearExceptCode (_PyInterpreterFrame * frame );
327
-
328
- int
329
- _PyFrame_Traverse (_PyInterpreterFrame * frame , visitproc visit , void * arg );
330
-
331
- bool
332
- _PyFrame_HasHiddenLocals (_PyInterpreterFrame * frame );
333
-
334
- PyObject *
335
- _PyFrame_GetLocals (_PyInterpreterFrame * frame );
336
-
337
- static inline bool
338
- _PyThreadState_HasStackSpace (PyThreadState * tstate , int size )
339
- {
340
- assert (
341
- (tstate -> datastack_top == NULL && tstate -> datastack_limit == NULL )
342
- ||
343
- (tstate -> datastack_top != NULL && tstate -> datastack_limit != NULL )
344
- );
345
- return tstate -> datastack_top != NULL &&
346
- size < tstate -> datastack_limit - tstate -> datastack_top ;
347
- }
348
-
349
- extern _PyInterpreterFrame *
350
- _PyThreadState_PushFrame (PyThreadState * tstate , size_t size );
351
-
352
- PyAPI_FUNC (void ) _PyThreadState_PopFrame (PyThreadState * tstate , _PyInterpreterFrame * frame );
353
-
354
- /* Pushes a frame without checking for space.
355
- * Must be guarded by _PyThreadState_HasStackSpace()
356
- * Consumes reference to func. */
357
- static inline _PyInterpreterFrame *
358
- _PyFrame_PushUnchecked (PyThreadState * tstate , _PyStackRef func , int null_locals_from , _PyInterpreterFrame * previous )
359
- {
360
- CALL_STAT_INC (frames_pushed );
361
- PyFunctionObject * func_obj = (PyFunctionObject * )PyStackRef_AsPyObjectBorrow (func );
362
- PyCodeObject * code = (PyCodeObject * )func_obj -> func_code ;
363
- _PyInterpreterFrame * new_frame = (_PyInterpreterFrame * )tstate -> datastack_top ;
364
- tstate -> datastack_top += code -> co_framesize ;
365
- assert (tstate -> datastack_top < tstate -> datastack_limit );
366
- _PyFrame_Initialize (tstate , new_frame , func , NULL , code , null_locals_from ,
367
- previous );
368
- return new_frame ;
369
- }
370
-
371
- /* Pushes a trampoline frame without checking for space.
372
- * Must be guarded by _PyThreadState_HasStackSpace() */
373
- static inline _PyInterpreterFrame *
374
- _PyFrame_PushTrampolineUnchecked (PyThreadState * tstate , PyCodeObject * code , int stackdepth , _PyInterpreterFrame * previous )
375
- {
376
- CALL_STAT_INC (frames_pushed );
377
- _PyInterpreterFrame * frame = (_PyInterpreterFrame * )tstate -> datastack_top ;
378
- tstate -> datastack_top += code -> co_framesize ;
379
- assert (tstate -> datastack_top < tstate -> datastack_limit );
380
- frame -> previous = previous ;
381
- frame -> f_funcobj = PyStackRef_None ;
382
- frame -> f_executable = PyStackRef_FromPyObjectNew (code );
383
- #ifdef Py_DEBUG
384
- frame -> f_builtins = NULL ;
385
- frame -> f_globals = NULL ;
386
- #endif
387
- frame -> f_locals = NULL ;
388
- assert (stackdepth <= code -> co_stacksize );
389
- frame -> stackpointer = frame -> localsplus + code -> co_nlocalsplus + stackdepth ;
390
- frame -> frame_obj = NULL ;
391
- #ifdef Py_GIL_DISABLED
392
- _PyFrame_InitializeTLBC (tstate , frame , code );
393
- #else
394
- frame -> instr_ptr = _PyCode_CODE (code );
395
- #endif
396
- frame -> owner = FRAME_OWNED_BY_THREAD ;
397
- frame -> visited = 0 ;
398
- #ifdef Py_DEBUG
399
- frame -> lltrace = 0 ;
400
- #endif
401
- frame -> return_offset = 0 ;
402
- return frame ;
403
- }
404
-
405
- PyAPI_FUNC (_PyInterpreterFrame * )
406
- _PyEvalFramePushAndInit (PyThreadState * tstate , _PyStackRef func ,
407
- PyObject * locals , _PyStackRef const * args ,
408
- size_t argcount , PyObject * kwnames ,
409
- _PyInterpreterFrame * previous );
410
-
411
52
#ifdef __cplusplus
412
53
}
413
54
#endif
0 commit comments