bpo-40941: Unify implicit and explicit state in the frame and generator objects into a single value. (GH-20803)
* Merge gen and frame state variables into one.
* Replace stack pointer with depth in PyFrameObject. Makes code easier to read and saves a word of memory.
diff --git a/Include/cpython/frameobject.h b/Include/cpython/frameobject.h
index c76fbe0..63240b5 100644
--- a/Include/cpython/frameobject.h
+++ b/Include/cpython/frameobject.h
@@ -4,6 +4,21 @@
# error "this header file must not be included directly"
#endif
+/* These values are chosen so that the inline functions below all
+ * compare f_state to zero.
+ */
+enum _framestate {
+ FRAME_CREATED = -2,
+ FRAME_SUSPENDED = -1,
+ FRAME_EXECUTING = 0,
+ FRAME_RETURNED = 1,
+ FRAME_UNWINDING = 2,
+ FRAME_RAISED = 3,
+ FRAME_CLEARED = 4
+};
+
+typedef signed char PyFrameState;
+
typedef struct {
int b_type; /* what kind of block this is */
int b_handler; /* where to jump to find handler */
@@ -18,11 +33,8 @@
PyObject *f_globals; /* global symbol table (PyDictObject) */
PyObject *f_locals; /* local symbol table (any mapping) */
PyObject **f_valuestack; /* points after the last local */
- /* Next free slot in f_valuestack. Frame creation sets to f_valuestack.
- Frame evaluation usually NULLs it, but a frame that yields sets it
- to the current stack top. */
- PyObject **f_stacktop;
PyObject *f_trace; /* Trace function */
+ int f_stackdepth; /* Depth of value stack */
char f_trace_lines; /* Emit per-line trace events? */
char f_trace_opcodes; /* Emit per-opcode trace events? */
@@ -37,11 +49,22 @@
bytecode index. */
int f_lineno; /* Current line number */
int f_iblock; /* index in f_blockstack */
- char f_executing; /* whether the frame is still executing */
+ PyFrameState f_state; /* What state the frame is in */
PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */
PyObject *f_localsplus[1]; /* locals+stack, dynamically sized */
};
+static inline int _PyFrame_IsRunnable(struct _frame *f) {
+ return f->f_state < FRAME_EXECUTING;
+}
+
+static inline int _PyFrame_IsExecuting(struct _frame *f) {
+ return f->f_state == FRAME_EXECUTING;
+}
+
+static inline int _PyFrameHasCompleted(struct _frame *f) {
+ return f->f_state > FRAME_EXECUTING;
+}
/* Standard object interface */