|
4 | 4 | extern "C" { |
5 | 5 | #endif |
6 | 6 |
|
7 | | -enum { |
8 | | - FRAME_SPECIALS_GLOBALS_OFFSET = 0, |
9 | | - FRAME_SPECIALS_BUILTINS_OFFSET = 1, |
10 | | - FRAME_SPECIALS_LOCALS_OFFSET = 2, |
11 | | - FRAME_SPECIALS_CODE_OFFSET = 3, |
12 | | - FRAME_SPECIALS_SIZE = 4 |
| 7 | +/* These values are chosen so that the inline functions below all |
| 8 | + * compare f_state to zero. |
| 9 | + */ |
| 10 | +enum _framestate { |
| 11 | + FRAME_CREATED = -2, |
| 12 | + FRAME_SUSPENDED = -1, |
| 13 | + FRAME_EXECUTING = 0, |
| 14 | + FRAME_RETURNED = 1, |
| 15 | + FRAME_UNWINDING = 2, |
| 16 | + FRAME_RAISED = 3, |
| 17 | + FRAME_CLEARED = 4 |
13 | 18 | }; |
14 | 19 |
|
15 | | -static inline PyObject ** |
16 | | -_PyFrame_Specials(PyFrameObject *f) { |
17 | | - return &f->f_valuestack[-FRAME_SPECIALS_SIZE]; |
| 20 | +typedef signed char PyFrameState; |
| 21 | + |
| 22 | +typedef struct _interpreter_frame { |
| 23 | + PyObject *f_globals; |
| 24 | + PyObject *f_builtins; |
| 25 | + PyObject *f_locals; |
| 26 | + PyCodeObject *f_code; |
| 27 | + PyFrameObject *frame_obj; |
| 28 | + /* Borrowed reference to a generator, or NULL */ |
| 29 | + PyObject *generator; |
| 30 | + struct _interpreter_frame *previous; |
| 31 | + int f_lasti; /* Last instruction if called */ |
| 32 | + int stackdepth; /* Depth of value stack */ |
| 33 | + int nlocalsplus; |
| 34 | + PyFrameState f_state; /* What state the frame is in */ |
| 35 | + PyObject *stack[1]; |
| 36 | +} InterpreterFrame; |
| 37 | + |
| 38 | +static inline int _PyFrame_IsRunnable(InterpreterFrame *f) { |
| 39 | + return f->f_state < FRAME_EXECUTING; |
| 40 | +} |
| 41 | + |
| 42 | +static inline int _PyFrame_IsExecuting(InterpreterFrame *f) { |
| 43 | + return f->f_state == FRAME_EXECUTING; |
18 | 44 | } |
19 | 45 |
|
20 | | -/* Returns a *borrowed* reference. */ |
21 | | -static inline PyObject * |
22 | | -_PyFrame_GetGlobals(PyFrameObject *f) |
| 46 | +static inline int _PyFrameHasCompleted(InterpreterFrame *f) { |
| 47 | + return f->f_state > FRAME_EXECUTING; |
| 48 | +} |
| 49 | + |
| 50 | +#define FRAME_SPECIALS_SIZE ((sizeof(InterpreterFrame)-1)/sizeof(PyObject *)) |
| 51 | + |
| 52 | +InterpreterFrame * |
| 53 | +_PyInterpreterFrame_HeapAlloc(PyFrameConstructor *con, PyObject *locals); |
| 54 | + |
| 55 | +static inline void |
| 56 | +_PyFrame_InitializeSpecials( |
| 57 | + InterpreterFrame *frame, PyFrameConstructor *con, |
| 58 | + PyObject *locals, int nlocalsplus) |
23 | 59 | { |
24 | | - return _PyFrame_Specials(f)[FRAME_SPECIALS_GLOBALS_OFFSET]; |
| 60 | + frame->f_code = (PyCodeObject *)Py_NewRef(con->fc_code); |
| 61 | + frame->f_builtins = Py_NewRef(con->fc_builtins); |
| 62 | + frame->f_globals = Py_NewRef(con->fc_globals); |
| 63 | + frame->f_locals = Py_XNewRef(locals); |
| 64 | + frame->nlocalsplus = nlocalsplus; |
| 65 | + frame->stackdepth = 0; |
| 66 | + frame->frame_obj = NULL; |
| 67 | + frame->generator = NULL; |
| 68 | + frame->f_lasti = -1; |
| 69 | + frame->f_state = FRAME_CREATED; |
25 | 70 | } |
26 | 71 |
|
27 | | -/* Returns a *borrowed* reference. */ |
28 | | -static inline PyObject * |
29 | | -_PyFrame_GetBuiltins(PyFrameObject *f) |
| 72 | +/* Gets the pointer to the locals array |
| 73 | + * that precedes this frame. |
| 74 | + */ |
| 75 | +static inline PyObject** |
| 76 | +_PyFrame_GetLocalsArray(InterpreterFrame *frame) |
30 | 77 | { |
31 | | - return _PyFrame_Specials(f)[FRAME_SPECIALS_BUILTINS_OFFSET]; |
| 78 | + return ((PyObject **)frame) - frame->nlocalsplus; |
32 | 79 | } |
33 | 80 |
|
34 | | -/* Returns a *borrowed* reference. */ |
35 | | -static inline PyCodeObject * |
36 | | -_PyFrame_GetCode(PyFrameObject *f) |
| 81 | +/* For use by _PyFrame_GetFrameObject |
| 82 | + Do not call directly. */ |
| 83 | +PyFrameObject * |
| 84 | +_PyFrame_MakeAndSetFrameObject(InterpreterFrame *frame); |
| 85 | + |
| 86 | +/* Gets the PyFrameObject for this frame, lazily |
| 87 | + * creating it if necessary. |
| 88 | + * Returns a borrowed referennce */ |
| 89 | +static inline PyFrameObject * |
| 90 | +_PyFrame_GetFrameObject(InterpreterFrame *frame) |
37 | 91 | { |
38 | | - return (PyCodeObject *)_PyFrame_Specials(f)[FRAME_SPECIALS_CODE_OFFSET]; |
| 92 | + PyFrameObject *res = frame->frame_obj; |
| 93 | + if (res != NULL) { |
| 94 | + return res; |
| 95 | + } |
| 96 | + return _PyFrame_MakeAndSetFrameObject(frame); |
39 | 97 | } |
40 | 98 |
|
41 | | -int _PyFrame_TakeLocals(PyFrameObject *f); |
| 99 | +/* Clears all references in the frame. |
| 100 | + * If take is non-zero, then the InterpreterFrame frame |
| 101 | + * may be transfered to the frame object it references |
| 102 | + * instead of being cleared. Either way |
| 103 | + * the caller no longer owns the references |
| 104 | + * in the frame. |
| 105 | + * take should be set to 1 for heap allocated |
| 106 | + * frames like the ones in generators and coroutines. |
| 107 | + */ |
| 108 | +int |
| 109 | +_PyFrame_Clear(InterpreterFrame * frame, int take); |
| 110 | + |
| 111 | +int |
| 112 | +_PyFrame_Traverse(InterpreterFrame *frame, visitproc visit, void *arg); |
| 113 | + |
| 114 | +int |
| 115 | +_PyFrame_FastToLocalsWithError(InterpreterFrame *frame); |
| 116 | + |
| 117 | +void |
| 118 | +_PyFrame_LocalsToFast(InterpreterFrame *frame, int clear); |
| 119 | + |
| 120 | +InterpreterFrame *_PyThreadState_PushFrame( |
| 121 | + PyThreadState *tstate, PyFrameConstructor *con, PyObject *locals); |
| 122 | + |
| 123 | +void _PyThreadState_PopFrame(PyThreadState *tstate, InterpreterFrame *frame); |
42 | 124 |
|
43 | 125 | #ifdef __cplusplus |
44 | 126 | } |
|
0 commit comments