https://github.com/python/cpython/commit/c87b5b2cb665b6bc413bc3a13cc2d70da14dfd66
commit: c87b5b2cb665b6bc413bc3a13cc2d70da14dfd66
branch: main
author: Mark Shannon <m...@hotpy.org>
committer: markshannon <m...@hotpy.org>
date: 2025-06-11T15:52:25+01:00
summary:

GH-135379: Remove types from stack items in code generator. (GH-135384)

* Make casts explicit in the instruction definitions

files:
A Misc/NEWS.d/next/Tools-Demos/2025-06-11-12-14-06.gh-issue-135379.25ttXq.rst
M Include/internal/pycore_stackref.h
M Lib/test/test_generated_cases.py
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h
M Tools/cases_generator/analyzer.py
M Tools/cases_generator/generators_common.py
M Tools/cases_generator/optimizer_generator.py
M Tools/cases_generator/parsing.py
M Tools/cases_generator/stack.py

diff --git a/Include/internal/pycore_stackref.h 
b/Include/internal/pycore_stackref.h
index 8791476725289c..10e7199269eb40 100644
--- a/Include/internal/pycore_stackref.h
+++ b/Include/internal/pycore_stackref.h
@@ -264,6 +264,32 @@ PyStackRef_IsNullOrInt(_PyStackRef ref);
 
 static const _PyStackRef PyStackRef_ERROR = { .bits = Py_TAG_INVALID };
 
+/* Wrap a pointer in a stack ref.
+ * The resulting stack reference is not safe and should only be used
+ * in the interpreter to pass values from one uop to another.
+ * The GC should never see one of these stack refs. */
+static inline _PyStackRef
+PyStackRef_Wrap(void *ptr)
+{
+    assert(ptr != NULL);
+#ifdef Py_DEBUG
+    return (_PyStackRef){ .bits = ((uintptr_t)ptr) | Py_TAG_INVALID };
+#else
+    return (_PyStackRef){ .bits = (uintptr_t)ptr };
+#endif
+}
+
+static inline void *
+PyStackRef_Unwrap(_PyStackRef ref)
+{
+#ifdef Py_DEBUG
+    assert ((ref.bits & Py_TAG_BITS) == Py_TAG_INVALID);
+    return (void *)(ref.bits & ~Py_TAG_BITS);
+#else
+    return (void *)(ref.bits);
+#endif
+}
+
 static inline bool
 PyStackRef_IsError(_PyStackRef ref)
 {
diff --git a/Lib/test/test_generated_cases.py b/Lib/test/test_generated_cases.py
index 37046d8e1c02b7..6411e4318b6c3a 100644
--- a/Lib/test/test_generated_cases.py
+++ b/Lib/test/test_generated_cases.py
@@ -56,14 +56,14 @@ class TestEffects(unittest.TestCase):
     def test_effect_sizes(self):
         stack = Stack()
         inputs = [
-            x := StackItem("x", None, "1"),
-            y := StackItem("y", None, "oparg"),
-            z := StackItem("z", None, "oparg*2"),
+            x := StackItem("x", "1"),
+            y := StackItem("y", "oparg"),
+            z := StackItem("z", "oparg*2"),
         ]
         outputs = [
-            StackItem("x", None, "1"),
-            StackItem("b", None, "oparg*4"),
-            StackItem("c", None, "1"),
+            StackItem("x", "1"),
+            StackItem("b", "oparg*4"),
+            StackItem("c", "1"),
         ]
         null = CWriter.null()
         stack.pop(z, null)
@@ -1103,32 +1103,6 @@ def test_array_of_one(self):
         """
         self.run_cases_test(input, output)
 
-    def test_pointer_to_stackref(self):
-        input = """
-        inst(OP, (arg: _PyStackRef * -- out)) {
-            out = *arg;
-            DEAD(arg);
-        }
-        """
-        output = """
-        TARGET(OP) {
-            #if Py_TAIL_CALL_INTERP
-            int opcode = OP;
-            (void)(opcode);
-            #endif
-            frame->instr_ptr = next_instr;
-            next_instr += 1;
-            INSTRUCTION_STATS(OP);
-            _PyStackRef *arg;
-            _PyStackRef out;
-            arg = (_PyStackRef *)stack_pointer[-1].bits;
-            out = *arg;
-            stack_pointer[-1] = out;
-            DISPATCH();
-        }
-        """
-        self.run_cases_test(input, output)
-
     def test_unused_cached_value(self):
         input = """
         op(FIRST, (arg1 -- out)) {
diff --git 
a/Misc/NEWS.d/next/Tools-Demos/2025-06-11-12-14-06.gh-issue-135379.25ttXq.rst 
b/Misc/NEWS.d/next/Tools-Demos/2025-06-11-12-14-06.gh-issue-135379.25ttXq.rst
new file mode 100644
index 00000000000000..25599a865b7246
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Tools-Demos/2025-06-11-12-14-06.gh-issue-135379.25ttXq.rst
@@ -0,0 +1,4 @@
+The cases generator no longer accepts type annotations on stack items.
+Conversions to non-default types are now done explictly in bytecodes.c and
+optimizer_bytecodes.c. This will simplify code generation for top-of-stack
+caching and other future features.
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index c4b13da5db41d8..032e76f72af42c 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -985,12 +985,13 @@ dummy_func(
             STAT_INC(BINARY_OP, hit);
         }
 
-        op(_BINARY_OP_SUBSCR_INIT_CALL, (container, sub, getitem -- new_frame: 
_PyInterpreterFrame* )) {
-            new_frame = _PyFrame_PushUnchecked(tstate, getitem, 2, frame);
-            new_frame->localsplus[0] = container;
-            new_frame->localsplus[1] = sub;
+        op(_BINARY_OP_SUBSCR_INIT_CALL, (container, sub, getitem -- 
new_frame)) {
+            _PyInterpreterFrame* pushed_frame = _PyFrame_PushUnchecked(tstate, 
getitem, 2, frame);
+            pushed_frame->localsplus[0] = container;
+            pushed_frame->localsplus[1] = sub;
             INPUTS_DEAD();
             frame->return_offset = INSTRUCTION_SIZE;
+            new_frame = PyStackRef_Wrap(pushed_frame);
         }
 
         macro(BINARY_OP_SUBSCR_GETITEM) =
@@ -1296,20 +1297,21 @@ dummy_func(
 
         macro(SEND) = _SPECIALIZE_SEND + _SEND;
 
-        op(_SEND_GEN_FRAME, (receiver, v -- receiver, gen_frame: 
_PyInterpreterFrame *)) {
+        op(_SEND_GEN_FRAME, (receiver, v -- receiver, gen_frame)) {
             PyGenObject *gen = (PyGenObject 
*)PyStackRef_AsPyObjectBorrow(receiver);
             DEOPT_IF(Py_TYPE(gen) != &PyGen_Type && Py_TYPE(gen) != 
&PyCoro_Type);
             DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING);
             STAT_INC(SEND, hit);
-            gen_frame = &gen->gi_iframe;
-            _PyFrame_StackPush(gen_frame, PyStackRef_MakeHeapSafe(v));
+            _PyInterpreterFrame *pushed_frame = &gen->gi_iframe;
+            _PyFrame_StackPush(pushed_frame, PyStackRef_MakeHeapSafe(v));
             DEAD(v);
             gen->gi_frame_state = FRAME_EXECUTING;
             gen->gi_exc_state.previous_item = tstate->exc_info;
             tstate->exc_info = &gen->gi_exc_state;
             assert(INSTRUCTION_SIZE + oparg <= UINT16_MAX);
             frame->return_offset = (uint16_t)(INSTRUCTION_SIZE + oparg);
-            gen_frame->previous = frame;
+            pushed_frame->previous = frame;
+            gen_frame = PyStackRef_Wrap(pushed_frame);
         }
 
         macro(SEND_GEN) =
@@ -2463,7 +2465,7 @@ dummy_func(
             _LOAD_ATTR_CLASS +
             _PUSH_NULL_CONDITIONAL;
 
-        op(_LOAD_ATTR_PROPERTY_FRAME, (fget/4, owner -- new_frame: 
_PyInterpreterFrame *)) {
+        op(_LOAD_ATTR_PROPERTY_FRAME, (fget/4, owner -- new_frame)) {
             assert((oparg & 1) == 0);
             assert(Py_IS_TYPE(fget, &PyFunction_Type));
             PyFunctionObject *f = (PyFunctionObject *)fget;
@@ -2473,9 +2475,10 @@ dummy_func(
             DEOPT_IF(code->co_argcount != 1);
             DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, 
code->co_framesize));
             STAT_INC(LOAD_ATTR, hit);
-            new_frame = _PyFrame_PushUnchecked(tstate, 
PyStackRef_FromPyObjectNew(fget), 1, frame);
-            new_frame->localsplus[0] = owner;
+            _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, 
PyStackRef_FromPyObjectNew(fget), 1, frame);
+            pushed_frame->localsplus[0] = owner;
             DEAD(owner);
+            new_frame = PyStackRef_Wrap(pushed_frame);
         }
 
         macro(LOAD_ATTR_PROPERTY) =
@@ -3344,7 +3347,7 @@ dummy_func(
             _ITER_JUMP_RANGE +
             _ITER_NEXT_RANGE;
 
-        op(_FOR_ITER_GEN_FRAME, (iter, null -- iter, null, gen_frame: 
_PyInterpreterFrame*)) {
+        op(_FOR_ITER_GEN_FRAME, (iter, null -- iter, null, gen_frame)) {
             PyGenObject *gen = (PyGenObject 
*)PyStackRef_AsPyObjectBorrow(iter);
             DEOPT_IF(Py_TYPE(gen) != &PyGen_Type);
 #ifdef Py_GIL_DISABLED
@@ -3356,14 +3359,15 @@ dummy_func(
 #endif
             DEOPT_IF(gen->gi_frame_state >= FRAME_EXECUTING);
             STAT_INC(FOR_ITER, hit);
-            gen_frame = &gen->gi_iframe;
-            _PyFrame_StackPush(gen_frame, PyStackRef_None);
+            _PyInterpreterFrame *pushed_frame = &gen->gi_iframe;
+            _PyFrame_StackPush(pushed_frame, PyStackRef_None);
             gen->gi_frame_state = FRAME_EXECUTING;
             gen->gi_exc_state.previous_item = tstate->exc_info;
             tstate->exc_info = &gen->gi_exc_state;
-            gen_frame->previous = frame;
+            pushed_frame->previous = frame;
             // oparg is the return offset from the next instruction.
             frame->return_offset = (uint16_t)(INSTRUCTION_SIZE + oparg);
+            gen_frame = PyStackRef_Wrap(pushed_frame);
         }
 
         macro(FOR_ITER_GEN) =
@@ -3715,7 +3719,7 @@ dummy_func(
         macro(CALL) = _SPECIALIZE_CALL + unused/2 + _MAYBE_EXPAND_METHOD + 
_DO_CALL + _CHECK_PERIODIC;
         macro(INSTRUMENTED_CALL) = unused/3 + _MAYBE_EXPAND_METHOD + 
_MONITOR_CALL + _DO_CALL + _CHECK_PERIODIC;
 
-        op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- 
new_frame: _PyInterpreterFrame*)) {
+        op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- 
new_frame)) {
             PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
 
             // oparg counts all of the args, but *not* self:
@@ -3737,7 +3741,7 @@ dummy_func(
             if (temp == NULL) {
                 ERROR_NO_POP();
             }
-            new_frame = temp;
+            new_frame = PyStackRef_Wrap(temp);
         }
 
         op(_CHECK_FUNCTION_VERSION, (func_version/2, callable, unused, 
unused[oparg] -- callable, unused, unused[oparg])) {
@@ -3874,27 +3878,26 @@ dummy_func(
             DEOPT_IF(tstate->py_recursion_remaining <= 1);
         }
 
-        replicate(5) pure op(_INIT_CALL_PY_EXACT_ARGS, (callable, 
self_or_null, args[oparg] -- new_frame: _PyInterpreterFrame*)) {
+        replicate(5) pure op(_INIT_CALL_PY_EXACT_ARGS, (callable, 
self_or_null, args[oparg] -- new_frame)) {
             int has_self = !PyStackRef_IsNull(self_or_null);
             STAT_INC(CALL, hit);
-            new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + 
has_self, frame);
-            _PyStackRef *first_non_self_local = new_frame->localsplus + 
has_self;
-            new_frame->localsplus[0] = self_or_null;
+            _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, 
callable, oparg + has_self, frame);
+            _PyStackRef *first_non_self_local = pushed_frame->localsplus + 
has_self;
+            pushed_frame->localsplus[0] = self_or_null;
             for (int i = 0; i < oparg; i++) {
                 first_non_self_local[i] = args[i];
             }
             INPUTS_DEAD();
+            new_frame = PyStackRef_Wrap(pushed_frame);
         }
 
-        op(_PUSH_FRAME, (new_frame: _PyInterpreterFrame* -- )) {
-            // Write it out explicitly because it's subtly different.
-            // Eventually this should be the only occurrence of this code.
+        op(_PUSH_FRAME, (new_frame -- )) {
             assert(tstate->interp->eval_frame == NULL);
-            _PyInterpreterFrame *temp = new_frame;
+            _PyInterpreterFrame *temp = PyStackRef_Unwrap(new_frame);
             DEAD(new_frame);
             SYNC_SP();
             _PyFrame_SetStackPointer(frame, stack_pointer);
-            assert(new_frame->previous == frame || 
new_frame->previous->previous == frame);
+            assert(temp->previous == frame || temp->previous->previous == 
frame);
             CALL_STAT_INC(inlined_py_calls);
             frame = tstate->current_frame = temp;
             tstate->py_recursion_remaining--;
@@ -4046,7 +4049,7 @@ dummy_func(
             PyStackRef_CLOSE(temp);
         }
 
-        op(_CREATE_INIT_FRAME, (init, self, args[oparg] -- init_frame: 
_PyInterpreterFrame *)) {
+        op(_CREATE_INIT_FRAME, (init, self, args[oparg] -- init_frame)) {
             _PyInterpreterFrame *shim = _PyFrame_PushTrampolineUnchecked(
                 tstate, (PyCodeObject *)&_Py_InitCleanup, 1, frame);
             assert(_PyFrame_GetBytecode(shim)[0].op.code == EXIT_INIT_CHECK);
@@ -4063,12 +4066,12 @@ dummy_func(
                 _PyEval_FrameClearAndPop(tstate, shim);
                 ERROR_NO_POP();
             }
-            init_frame = temp;
             frame->return_offset = 1 + INLINE_CACHE_ENTRIES_CALL;
             /* Account for pushing the extra frame.
              * We don't check recursion depth here,
              * as it will be checked after start_frame */
             tstate->py_recursion_remaining--;
+            init_frame = PyStackRef_Wrap(temp);
         }
 
         macro(CALL_ALLOC_AND_ENTER_INIT) =
@@ -4594,7 +4597,7 @@ dummy_func(
             res = PyStackRef_FromPyObjectSteal(res_o);
         }
 
-        op(_PY_FRAME_KW, (callable, self_or_null, args[oparg], kwnames -- 
new_frame: _PyInterpreterFrame*)) {
+        op(_PY_FRAME_KW, (callable, self_or_null, args[oparg], kwnames -- 
new_frame)) {
             PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
 
             // oparg counts all of the args, but *not* self:
@@ -4621,7 +4624,7 @@ dummy_func(
             DEAD(callable);
             SYNC_SP();
             ERROR_IF(temp == NULL);
-            new_frame = temp;
+            new_frame = PyStackRef_Wrap(temp);
         }
 
         op(_CHECK_FUNCTION_VERSION_KW, (func_version/2, callable, unused, 
unused[oparg], unused -- callable, unused, unused[oparg], unused)) {
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index d19605169d5e55..4f772f916d1152 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -1551,15 +1551,16 @@
             _PyStackRef getitem;
             _PyStackRef sub;
             _PyStackRef container;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef new_frame;
             getitem = stack_pointer[-1];
             sub = stack_pointer[-2];
             container = stack_pointer[-3];
-            new_frame = _PyFrame_PushUnchecked(tstate, getitem, 2, frame);
-            new_frame->localsplus[0] = container;
-            new_frame->localsplus[1] = sub;
+            _PyInterpreterFrame* pushed_frame = _PyFrame_PushUnchecked(tstate, 
getitem, 2, frame);
+            pushed_frame->localsplus[0] = container;
+            pushed_frame->localsplus[1] = sub;
             frame->return_offset = 6 ;
-            stack_pointer[-3].bits = (uintptr_t)new_frame;
+            new_frame = PyStackRef_Wrap(pushed_frame);
+            stack_pointer[-3] = new_frame;
             stack_pointer += -2;
             assert(WITHIN_STACK_BOUNDS());
             break;
@@ -1907,7 +1908,7 @@
         case _SEND_GEN_FRAME: {
             _PyStackRef v;
             _PyStackRef receiver;
-            _PyInterpreterFrame *gen_frame;
+            _PyStackRef gen_frame;
             oparg = CURRENT_OPARG();
             v = stack_pointer[-1];
             receiver = stack_pointer[-2];
@@ -1921,15 +1922,16 @@
                 JUMP_TO_JUMP_TARGET();
             }
             STAT_INC(SEND, hit);
-            gen_frame = &gen->gi_iframe;
-            _PyFrame_StackPush(gen_frame, PyStackRef_MakeHeapSafe(v));
+            _PyInterpreterFrame *pushed_frame = &gen->gi_iframe;
+            _PyFrame_StackPush(pushed_frame, PyStackRef_MakeHeapSafe(v));
             gen->gi_frame_state = FRAME_EXECUTING;
             gen->gi_exc_state.previous_item = tstate->exc_info;
             tstate->exc_info = &gen->gi_exc_state;
             assert( 2 + oparg <= UINT16_MAX);
             frame->return_offset = (uint16_t)( 2 + oparg);
-            gen_frame->previous = frame;
-            stack_pointer[-1].bits = (uintptr_t)gen_frame;
+            pushed_frame->previous = frame;
+            gen_frame = PyStackRef_Wrap(pushed_frame);
+            stack_pointer[-1] = gen_frame;
             break;
         }
 
@@ -3471,7 +3473,7 @@
 
         case _LOAD_ATTR_PROPERTY_FRAME: {
             _PyStackRef owner;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef new_frame;
             oparg = CURRENT_OPARG();
             owner = stack_pointer[-1];
             PyObject *fget = (PyObject *)CURRENT_OPERAND0();
@@ -3496,9 +3498,10 @@
                 JUMP_TO_JUMP_TARGET();
             }
             STAT_INC(LOAD_ATTR, hit);
-            new_frame = _PyFrame_PushUnchecked(tstate, 
PyStackRef_FromPyObjectNew(fget), 1, frame);
-            new_frame->localsplus[0] = owner;
-            stack_pointer[-1].bits = (uintptr_t)new_frame;
+            _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, 
PyStackRef_FromPyObjectNew(fget), 1, frame);
+            pushed_frame->localsplus[0] = owner;
+            new_frame = PyStackRef_Wrap(pushed_frame);
+            stack_pointer[-1] = new_frame;
             break;
         }
 
@@ -4467,7 +4470,7 @@
 
         case _FOR_ITER_GEN_FRAME: {
             _PyStackRef iter;
-            _PyInterpreterFrame *gen_frame;
+            _PyStackRef gen_frame;
             oparg = CURRENT_OPARG();
             iter = stack_pointer[-2];
             PyGenObject *gen = (PyGenObject 
*)PyStackRef_AsPyObjectBorrow(iter);
@@ -4487,14 +4490,15 @@
                 JUMP_TO_JUMP_TARGET();
             }
             STAT_INC(FOR_ITER, hit);
-            gen_frame = &gen->gi_iframe;
-            _PyFrame_StackPush(gen_frame, PyStackRef_None);
+            _PyInterpreterFrame *pushed_frame = &gen->gi_iframe;
+            _PyFrame_StackPush(pushed_frame, PyStackRef_None);
             gen->gi_frame_state = FRAME_EXECUTING;
             gen->gi_exc_state.previous_item = tstate->exc_info;
             tstate->exc_info = &gen->gi_exc_state;
-            gen_frame->previous = frame;
+            pushed_frame->previous = frame;
             frame->return_offset = (uint16_t)( 2 + oparg);
-            stack_pointer[0].bits = (uintptr_t)gen_frame;
+            gen_frame = PyStackRef_Wrap(pushed_frame);
+            stack_pointer[0] = gen_frame;
             stack_pointer += 1;
             assert(WITHIN_STACK_BOUNDS());
             break;
@@ -4775,7 +4779,7 @@
             _PyStackRef *args;
             _PyStackRef self_or_null;
             _PyStackRef callable;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef new_frame;
             oparg = CURRENT_OPARG();
             args = &stack_pointer[-oparg];
             self_or_null = stack_pointer[-1 - oparg];
@@ -4800,8 +4804,8 @@
             if (temp == NULL) {
                 JUMP_TO_ERROR();
             }
-            new_frame = temp;
-            stack_pointer[0].bits = (uintptr_t)new_frame;
+            new_frame = PyStackRef_Wrap(temp);
+            stack_pointer[0] = new_frame;
             stack_pointer += 1;
             assert(WITHIN_STACK_BOUNDS());
             break;
@@ -5067,7 +5071,7 @@
             _PyStackRef *args;
             _PyStackRef self_or_null;
             _PyStackRef callable;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef new_frame;
             oparg = 0;
             assert(oparg == CURRENT_OPARG());
             args = &stack_pointer[-oparg];
@@ -5075,13 +5079,14 @@
             callable = stack_pointer[-2 - oparg];
             int has_self = !PyStackRef_IsNull(self_or_null);
             STAT_INC(CALL, hit);
-            new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + 
has_self, frame);
-            _PyStackRef *first_non_self_local = new_frame->localsplus + 
has_self;
-            new_frame->localsplus[0] = self_or_null;
+            _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, 
callable, oparg + has_self, frame);
+            _PyStackRef *first_non_self_local = pushed_frame->localsplus + 
has_self;
+            pushed_frame->localsplus[0] = self_or_null;
             for (int i = 0; i < oparg; i++) {
                 first_non_self_local[i] = args[i];
             }
-            stack_pointer[-2 - oparg].bits = (uintptr_t)new_frame;
+            new_frame = PyStackRef_Wrap(pushed_frame);
+            stack_pointer[-2 - oparg] = new_frame;
             stack_pointer += -1 - oparg;
             assert(WITHIN_STACK_BOUNDS());
             break;
@@ -5091,7 +5096,7 @@
             _PyStackRef *args;
             _PyStackRef self_or_null;
             _PyStackRef callable;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef new_frame;
             oparg = 1;
             assert(oparg == CURRENT_OPARG());
             args = &stack_pointer[-oparg];
@@ -5099,13 +5104,14 @@
             callable = stack_pointer[-2 - oparg];
             int has_self = !PyStackRef_IsNull(self_or_null);
             STAT_INC(CALL, hit);
-            new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + 
has_self, frame);
-            _PyStackRef *first_non_self_local = new_frame->localsplus + 
has_self;
-            new_frame->localsplus[0] = self_or_null;
+            _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, 
callable, oparg + has_self, frame);
+            _PyStackRef *first_non_self_local = pushed_frame->localsplus + 
has_self;
+            pushed_frame->localsplus[0] = self_or_null;
             for (int i = 0; i < oparg; i++) {
                 first_non_self_local[i] = args[i];
             }
-            stack_pointer[-2 - oparg].bits = (uintptr_t)new_frame;
+            new_frame = PyStackRef_Wrap(pushed_frame);
+            stack_pointer[-2 - oparg] = new_frame;
             stack_pointer += -1 - oparg;
             assert(WITHIN_STACK_BOUNDS());
             break;
@@ -5115,7 +5121,7 @@
             _PyStackRef *args;
             _PyStackRef self_or_null;
             _PyStackRef callable;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef new_frame;
             oparg = 2;
             assert(oparg == CURRENT_OPARG());
             args = &stack_pointer[-oparg];
@@ -5123,13 +5129,14 @@
             callable = stack_pointer[-2 - oparg];
             int has_self = !PyStackRef_IsNull(self_or_null);
             STAT_INC(CALL, hit);
-            new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + 
has_self, frame);
-            _PyStackRef *first_non_self_local = new_frame->localsplus + 
has_self;
-            new_frame->localsplus[0] = self_or_null;
+            _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, 
callable, oparg + has_self, frame);
+            _PyStackRef *first_non_self_local = pushed_frame->localsplus + 
has_self;
+            pushed_frame->localsplus[0] = self_or_null;
             for (int i = 0; i < oparg; i++) {
                 first_non_self_local[i] = args[i];
             }
-            stack_pointer[-2 - oparg].bits = (uintptr_t)new_frame;
+            new_frame = PyStackRef_Wrap(pushed_frame);
+            stack_pointer[-2 - oparg] = new_frame;
             stack_pointer += -1 - oparg;
             assert(WITHIN_STACK_BOUNDS());
             break;
@@ -5139,7 +5146,7 @@
             _PyStackRef *args;
             _PyStackRef self_or_null;
             _PyStackRef callable;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef new_frame;
             oparg = 3;
             assert(oparg == CURRENT_OPARG());
             args = &stack_pointer[-oparg];
@@ -5147,13 +5154,14 @@
             callable = stack_pointer[-2 - oparg];
             int has_self = !PyStackRef_IsNull(self_or_null);
             STAT_INC(CALL, hit);
-            new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + 
has_self, frame);
-            _PyStackRef *first_non_self_local = new_frame->localsplus + 
has_self;
-            new_frame->localsplus[0] = self_or_null;
+            _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, 
callable, oparg + has_self, frame);
+            _PyStackRef *first_non_self_local = pushed_frame->localsplus + 
has_self;
+            pushed_frame->localsplus[0] = self_or_null;
             for (int i = 0; i < oparg; i++) {
                 first_non_self_local[i] = args[i];
             }
-            stack_pointer[-2 - oparg].bits = (uintptr_t)new_frame;
+            new_frame = PyStackRef_Wrap(pushed_frame);
+            stack_pointer[-2 - oparg] = new_frame;
             stack_pointer += -1 - oparg;
             assert(WITHIN_STACK_BOUNDS());
             break;
@@ -5163,7 +5171,7 @@
             _PyStackRef *args;
             _PyStackRef self_or_null;
             _PyStackRef callable;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef new_frame;
             oparg = 4;
             assert(oparg == CURRENT_OPARG());
             args = &stack_pointer[-oparg];
@@ -5171,13 +5179,14 @@
             callable = stack_pointer[-2 - oparg];
             int has_self = !PyStackRef_IsNull(self_or_null);
             STAT_INC(CALL, hit);
-            new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + 
has_self, frame);
-            _PyStackRef *first_non_self_local = new_frame->localsplus + 
has_self;
-            new_frame->localsplus[0] = self_or_null;
+            _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, 
callable, oparg + has_self, frame);
+            _PyStackRef *first_non_self_local = pushed_frame->localsplus + 
has_self;
+            pushed_frame->localsplus[0] = self_or_null;
             for (int i = 0; i < oparg; i++) {
                 first_non_self_local[i] = args[i];
             }
-            stack_pointer[-2 - oparg].bits = (uintptr_t)new_frame;
+            new_frame = PyStackRef_Wrap(pushed_frame);
+            stack_pointer[-2 - oparg] = new_frame;
             stack_pointer += -1 - oparg;
             assert(WITHIN_STACK_BOUNDS());
             break;
@@ -5187,34 +5196,35 @@
             _PyStackRef *args;
             _PyStackRef self_or_null;
             _PyStackRef callable;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef new_frame;
             oparg = CURRENT_OPARG();
             args = &stack_pointer[-oparg];
             self_or_null = stack_pointer[-1 - oparg];
             callable = stack_pointer[-2 - oparg];
             int has_self = !PyStackRef_IsNull(self_or_null);
             STAT_INC(CALL, hit);
-            new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + 
has_self, frame);
-            _PyStackRef *first_non_self_local = new_frame->localsplus + 
has_self;
-            new_frame->localsplus[0] = self_or_null;
+            _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, 
callable, oparg + has_self, frame);
+            _PyStackRef *first_non_self_local = pushed_frame->localsplus + 
has_self;
+            pushed_frame->localsplus[0] = self_or_null;
             for (int i = 0; i < oparg; i++) {
                 first_non_self_local[i] = args[i];
             }
-            stack_pointer[-2 - oparg].bits = (uintptr_t)new_frame;
+            new_frame = PyStackRef_Wrap(pushed_frame);
+            stack_pointer[-2 - oparg] = new_frame;
             stack_pointer += -1 - oparg;
             assert(WITHIN_STACK_BOUNDS());
             break;
         }
 
         case _PUSH_FRAME: {
-            _PyInterpreterFrame *new_frame;
-            new_frame = (_PyInterpreterFrame *)stack_pointer[-1].bits;
+            _PyStackRef new_frame;
+            new_frame = stack_pointer[-1];
             assert(tstate->interp->eval_frame == NULL);
-            _PyInterpreterFrame *temp = new_frame;
+            _PyInterpreterFrame *temp = PyStackRef_Unwrap(new_frame);
             stack_pointer += -1;
             assert(WITHIN_STACK_BOUNDS());
             _PyFrame_SetStackPointer(frame, stack_pointer);
-            assert(new_frame->previous == frame || 
new_frame->previous->previous == frame);
+            assert(temp->previous == frame || temp->previous->previous == 
frame);
             CALL_STAT_INC(inlined_py_calls);
             frame = tstate->current_frame = temp;
             tstate->py_recursion_remaining--;
@@ -5429,7 +5439,7 @@
             _PyStackRef *args;
             _PyStackRef self;
             _PyStackRef init;
-            _PyInterpreterFrame *init_frame;
+            _PyStackRef init_frame;
             oparg = CURRENT_OPARG();
             args = &stack_pointer[-oparg];
             self = stack_pointer[-1 - oparg];
@@ -5453,10 +5463,10 @@
                 stack_pointer = _PyFrame_GetStackPointer(frame);
                 JUMP_TO_ERROR();
             }
-            init_frame = temp;
             frame->return_offset = 1 + INLINE_CACHE_ENTRIES_CALL;
             tstate->py_recursion_remaining--;
-            stack_pointer[0].bits = (uintptr_t)init_frame;
+            init_frame = PyStackRef_Wrap(temp);
+            stack_pointer[0] = init_frame;
             stack_pointer += 1;
             assert(WITHIN_STACK_BOUNDS());
             break;
@@ -6309,7 +6319,7 @@
             _PyStackRef *args;
             _PyStackRef self_or_null;
             _PyStackRef callable;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef new_frame;
             oparg = CURRENT_OPARG();
             kwnames = stack_pointer[-1];
             args = &stack_pointer[-1 - oparg];
@@ -6343,8 +6353,8 @@
             if (temp == NULL) {
                 JUMP_TO_ERROR();
             }
-            new_frame = temp;
-            stack_pointer[0].bits = (uintptr_t)new_frame;
+            new_frame = PyStackRef_Wrap(temp);
+            stack_pointer[0] = new_frame;
             stack_pointer += 1;
             assert(WITHIN_STACK_BOUNDS());
             break;
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index c8825df3ade5a5..5ac519bb1b6093 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -604,7 +604,7 @@
             _PyStackRef container;
             _PyStackRef getitem;
             _PyStackRef sub;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef new_frame;
             /* Skip 5 cache entries */
             // _CHECK_PEP_523
             {
@@ -650,19 +650,20 @@
             // _BINARY_OP_SUBSCR_INIT_CALL
             {
                 sub = stack_pointer[-1];
-                new_frame = _PyFrame_PushUnchecked(tstate, getitem, 2, frame);
-                new_frame->localsplus[0] = container;
-                new_frame->localsplus[1] = sub;
+                _PyInterpreterFrame* pushed_frame = 
_PyFrame_PushUnchecked(tstate, getitem, 2, frame);
+                pushed_frame->localsplus[0] = container;
+                pushed_frame->localsplus[1] = sub;
                 frame->return_offset = 6 ;
+                new_frame = PyStackRef_Wrap(pushed_frame);
             }
             // _PUSH_FRAME
             {
                 assert(tstate->interp->eval_frame == NULL);
-                _PyInterpreterFrame *temp = new_frame;
+                _PyInterpreterFrame *temp = PyStackRef_Unwrap(new_frame);
                 stack_pointer += -2;
                 assert(WITHIN_STACK_BOUNDS());
                 _PyFrame_SetStackPointer(frame, stack_pointer);
-                assert(new_frame->previous == frame || 
new_frame->previous->previous == frame);
+                assert(temp->previous == frame || temp->previous->previous == 
frame);
                 CALL_STAT_INC(inlined_py_calls);
                 frame = tstate->current_frame = temp;
                 tstate->py_recursion_remaining--;
@@ -1708,8 +1709,8 @@
             _PyStackRef init;
             _PyStackRef self;
             _PyStackRef *args;
-            _PyInterpreterFrame *init_frame;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef init_frame;
+            _PyStackRef new_frame;
             /* Skip 1 cache entry */
             // _CHECK_PEP_523
             {
@@ -1792,17 +1793,17 @@
                     stack_pointer = _PyFrame_GetStackPointer(frame);
                     JUMP_TO_LABEL(error);
                 }
-                init_frame = temp;
                 frame->return_offset = 1 + INLINE_CACHE_ENTRIES_CALL;
                 tstate->py_recursion_remaining--;
+                init_frame = PyStackRef_Wrap(temp);
             }
             // _PUSH_FRAME
             {
                 new_frame = init_frame;
                 assert(tstate->interp->eval_frame == NULL);
-                _PyInterpreterFrame *temp = new_frame;
+                _PyInterpreterFrame *temp = PyStackRef_Unwrap(new_frame);
                 _PyFrame_SetStackPointer(frame, stack_pointer);
-                assert(new_frame->previous == frame || 
new_frame->previous->previous == frame);
+                assert(temp->previous == frame || temp->previous->previous == 
frame);
                 CALL_STAT_INC(inlined_py_calls);
                 frame = tstate->current_frame = temp;
                 tstate->py_recursion_remaining--;
@@ -1828,7 +1829,7 @@
             _PyStackRef null;
             _PyStackRef self_or_null;
             _PyStackRef *args;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef new_frame;
             /* Skip 1 cache entry */
             // _CHECK_PEP_523
             {
@@ -1921,12 +1922,13 @@
                 args = &stack_pointer[-oparg];
                 int has_self = !PyStackRef_IsNull(self_or_null);
                 STAT_INC(CALL, hit);
-                new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + 
has_self, frame);
-                _PyStackRef *first_non_self_local = new_frame->localsplus + 
has_self;
-                new_frame->localsplus[0] = self_or_null;
+                _PyInterpreterFrame *pushed_frame = 
_PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame);
+                _PyStackRef *first_non_self_local = pushed_frame->localsplus + 
has_self;
+                pushed_frame->localsplus[0] = self_or_null;
                 for (int i = 0; i < oparg; i++) {
                     first_non_self_local[i] = args[i];
                 }
+                new_frame = PyStackRef_Wrap(pushed_frame);
             }
             // _SAVE_RETURN_OFFSET
             {
@@ -1940,11 +1942,11 @@
             // _PUSH_FRAME
             {
                 assert(tstate->interp->eval_frame == NULL);
-                _PyInterpreterFrame *temp = new_frame;
+                _PyInterpreterFrame *temp = PyStackRef_Unwrap(new_frame);
                 stack_pointer += -2 - oparg;
                 assert(WITHIN_STACK_BOUNDS());
                 _PyFrame_SetStackPointer(frame, stack_pointer);
-                assert(new_frame->previous == frame || 
new_frame->previous->previous == frame);
+                assert(temp->previous == frame || temp->previous->previous == 
frame);
                 CALL_STAT_INC(inlined_py_calls);
                 frame = tstate->current_frame = temp;
                 tstate->py_recursion_remaining--;
@@ -1970,7 +1972,7 @@
             _PyStackRef null;
             _PyStackRef self_or_null;
             _PyStackRef *args;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef new_frame;
             /* Skip 1 cache entry */
             // _CHECK_PEP_523
             {
@@ -2056,7 +2058,7 @@
                 if (temp == NULL) {
                     JUMP_TO_LABEL(error);
                 }
-                new_frame = temp;
+                new_frame = PyStackRef_Wrap(temp);
             }
             // _SAVE_RETURN_OFFSET
             {
@@ -2070,9 +2072,9 @@
             // _PUSH_FRAME
             {
                 assert(tstate->interp->eval_frame == NULL);
-                _PyInterpreterFrame *temp = new_frame;
+                _PyInterpreterFrame *temp = PyStackRef_Unwrap(new_frame);
                 _PyFrame_SetStackPointer(frame, stack_pointer);
-                assert(new_frame->previous == frame || 
new_frame->previous->previous == frame);
+                assert(temp->previous == frame || temp->previous->previous == 
frame);
                 CALL_STAT_INC(inlined_py_calls);
                 frame = tstate->current_frame = temp;
                 tstate->py_recursion_remaining--;
@@ -3040,7 +3042,7 @@
             _PyStackRef self_or_null;
             _PyStackRef *args;
             _PyStackRef kwnames;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef new_frame;
             /* Skip 1 cache entry */
             // _CHECK_PEP_523
             {
@@ -3127,7 +3129,7 @@
                 if (temp == NULL) {
                     JUMP_TO_LABEL(error);
                 }
-                new_frame = temp;
+                new_frame = PyStackRef_Wrap(temp);
             }
             // _SAVE_RETURN_OFFSET
             {
@@ -3141,9 +3143,9 @@
             // _PUSH_FRAME
             {
                 assert(tstate->interp->eval_frame == NULL);
-                _PyInterpreterFrame *temp = new_frame;
+                _PyInterpreterFrame *temp = PyStackRef_Unwrap(new_frame);
                 _PyFrame_SetStackPointer(frame, stack_pointer);
-                assert(new_frame->previous == frame || 
new_frame->previous->previous == frame);
+                assert(temp->previous == frame || temp->previous->previous == 
frame);
                 CALL_STAT_INC(inlined_py_calls);
                 frame = tstate->current_frame = temp;
                 tstate->py_recursion_remaining--;
@@ -3304,7 +3306,7 @@
             _PyStackRef self_or_null;
             _PyStackRef *args;
             _PyStackRef kwnames;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef new_frame;
             /* Skip 1 cache entry */
             // _CHECK_PEP_523
             {
@@ -3364,7 +3366,7 @@
                 if (temp == NULL) {
                     JUMP_TO_LABEL(error);
                 }
-                new_frame = temp;
+                new_frame = PyStackRef_Wrap(temp);
             }
             // _SAVE_RETURN_OFFSET
             {
@@ -3378,9 +3380,9 @@
             // _PUSH_FRAME
             {
                 assert(tstate->interp->eval_frame == NULL);
-                _PyInterpreterFrame *temp = new_frame;
+                _PyInterpreterFrame *temp = PyStackRef_Unwrap(new_frame);
                 _PyFrame_SetStackPointer(frame, stack_pointer);
-                assert(new_frame->previous == frame || 
new_frame->previous->previous == frame);
+                assert(temp->previous == frame || temp->previous->previous == 
frame);
                 CALL_STAT_INC(inlined_py_calls);
                 frame = tstate->current_frame = temp;
                 tstate->py_recursion_remaining--;
@@ -4163,7 +4165,7 @@
             _PyStackRef callable;
             _PyStackRef self_or_null;
             _PyStackRef *args;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef new_frame;
             /* Skip 1 cache entry */
             // _CHECK_PEP_523
             {
@@ -4227,12 +4229,13 @@
                 args = &stack_pointer[-oparg];
                 int has_self = !PyStackRef_IsNull(self_or_null);
                 STAT_INC(CALL, hit);
-                new_frame = _PyFrame_PushUnchecked(tstate, callable, oparg + 
has_self, frame);
-                _PyStackRef *first_non_self_local = new_frame->localsplus + 
has_self;
-                new_frame->localsplus[0] = self_or_null;
+                _PyInterpreterFrame *pushed_frame = 
_PyFrame_PushUnchecked(tstate, callable, oparg + has_self, frame);
+                _PyStackRef *first_non_self_local = pushed_frame->localsplus + 
has_self;
+                pushed_frame->localsplus[0] = self_or_null;
                 for (int i = 0; i < oparg; i++) {
                     first_non_self_local[i] = args[i];
                 }
+                new_frame = PyStackRef_Wrap(pushed_frame);
             }
             // _SAVE_RETURN_OFFSET
             {
@@ -4246,11 +4249,11 @@
             // _PUSH_FRAME
             {
                 assert(tstate->interp->eval_frame == NULL);
-                _PyInterpreterFrame *temp = new_frame;
+                _PyInterpreterFrame *temp = PyStackRef_Unwrap(new_frame);
                 stack_pointer += -2 - oparg;
                 assert(WITHIN_STACK_BOUNDS());
                 _PyFrame_SetStackPointer(frame, stack_pointer);
-                assert(new_frame->previous == frame || 
new_frame->previous->previous == frame);
+                assert(temp->previous == frame || temp->previous->previous == 
frame);
                 CALL_STAT_INC(inlined_py_calls);
                 frame = tstate->current_frame = temp;
                 tstate->py_recursion_remaining--;
@@ -4275,7 +4278,7 @@
             _PyStackRef callable;
             _PyStackRef self_or_null;
             _PyStackRef *args;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef new_frame;
             /* Skip 1 cache entry */
             // _CHECK_PEP_523
             {
@@ -4334,7 +4337,7 @@
                 if (temp == NULL) {
                     JUMP_TO_LABEL(error);
                 }
-                new_frame = temp;
+                new_frame = PyStackRef_Wrap(temp);
             }
             // _SAVE_RETURN_OFFSET
             {
@@ -4348,9 +4351,9 @@
             // _PUSH_FRAME
             {
                 assert(tstate->interp->eval_frame == NULL);
-                _PyInterpreterFrame *temp = new_frame;
+                _PyInterpreterFrame *temp = PyStackRef_Unwrap(new_frame);
                 _PyFrame_SetStackPointer(frame, stack_pointer);
-                assert(new_frame->previous == frame || 
new_frame->previous->previous == frame);
+                assert(temp->previous == frame || temp->previous->previous == 
frame);
                 CALL_STAT_INC(inlined_py_calls);
                 frame = tstate->current_frame = temp;
                 tstate->py_recursion_remaining--;
@@ -5785,8 +5788,8 @@
             INSTRUCTION_STATS(FOR_ITER_GEN);
             static_assert(INLINE_CACHE_ENTRIES_FOR_ITER == 1, "incorrect cache 
size");
             _PyStackRef iter;
-            _PyInterpreterFrame *gen_frame;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef gen_frame;
+            _PyStackRef new_frame;
             /* Skip 1 cache entry */
             // _CHECK_PEP_523
             {
@@ -5818,21 +5821,22 @@
                     JUMP_TO_PREDICTED(FOR_ITER);
                 }
                 STAT_INC(FOR_ITER, hit);
-                gen_frame = &gen->gi_iframe;
-                _PyFrame_StackPush(gen_frame, PyStackRef_None);
+                _PyInterpreterFrame *pushed_frame = &gen->gi_iframe;
+                _PyFrame_StackPush(pushed_frame, PyStackRef_None);
                 gen->gi_frame_state = FRAME_EXECUTING;
                 gen->gi_exc_state.previous_item = tstate->exc_info;
                 tstate->exc_info = &gen->gi_exc_state;
-                gen_frame->previous = frame;
+                pushed_frame->previous = frame;
                 frame->return_offset = (uint16_t)( 2 + oparg);
+                gen_frame = PyStackRef_Wrap(pushed_frame);
             }
             // _PUSH_FRAME
             {
                 new_frame = gen_frame;
                 assert(tstate->interp->eval_frame == NULL);
-                _PyInterpreterFrame *temp = new_frame;
+                _PyInterpreterFrame *temp = PyStackRef_Unwrap(new_frame);
                 _PyFrame_SetStackPointer(frame, stack_pointer);
-                assert(new_frame->previous == frame || 
new_frame->previous->previous == frame);
+                assert(temp->previous == frame || temp->previous->previous == 
frame);
                 CALL_STAT_INC(inlined_py_calls);
                 frame = tstate->current_frame = temp;
                 tstate->py_recursion_remaining--;
@@ -8650,7 +8654,7 @@
             INSTRUCTION_STATS(LOAD_ATTR_PROPERTY);
             static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect 
cache size");
             _PyStackRef owner;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef new_frame;
             /* Skip 1 cache entry */
             // _CHECK_PEP_523
             {
@@ -8701,8 +8705,9 @@
                     JUMP_TO_PREDICTED(LOAD_ATTR);
                 }
                 STAT_INC(LOAD_ATTR, hit);
-                new_frame = _PyFrame_PushUnchecked(tstate, 
PyStackRef_FromPyObjectNew(fget), 1, frame);
-                new_frame->localsplus[0] = owner;
+                _PyInterpreterFrame *pushed_frame = 
_PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame);
+                pushed_frame->localsplus[0] = owner;
+                new_frame = PyStackRef_Wrap(pushed_frame);
             }
             // _SAVE_RETURN_OFFSET
             {
@@ -8716,11 +8721,11 @@
             // _PUSH_FRAME
             {
                 assert(tstate->interp->eval_frame == NULL);
-                _PyInterpreterFrame *temp = new_frame;
+                _PyInterpreterFrame *temp = PyStackRef_Unwrap(new_frame);
                 stack_pointer += -1;
                 assert(WITHIN_STACK_BOUNDS());
                 _PyFrame_SetStackPointer(frame, stack_pointer);
-                assert(new_frame->previous == frame || 
new_frame->previous->previous == frame);
+                assert(temp->previous == frame || temp->previous->previous == 
frame);
                 CALL_STAT_INC(inlined_py_calls);
                 frame = tstate->current_frame = temp;
                 tstate->py_recursion_remaining--;
@@ -10661,8 +10666,8 @@
             static_assert(INLINE_CACHE_ENTRIES_SEND == 1, "incorrect cache 
size");
             _PyStackRef receiver;
             _PyStackRef v;
-            _PyInterpreterFrame *gen_frame;
-            _PyInterpreterFrame *new_frame;
+            _PyStackRef gen_frame;
+            _PyStackRef new_frame;
             /* Skip 1 cache entry */
             // _CHECK_PEP_523
             {
@@ -10688,24 +10693,25 @@
                     JUMP_TO_PREDICTED(SEND);
                 }
                 STAT_INC(SEND, hit);
-                gen_frame = &gen->gi_iframe;
-                _PyFrame_StackPush(gen_frame, PyStackRef_MakeHeapSafe(v));
+                _PyInterpreterFrame *pushed_frame = &gen->gi_iframe;
+                _PyFrame_StackPush(pushed_frame, PyStackRef_MakeHeapSafe(v));
                 gen->gi_frame_state = FRAME_EXECUTING;
                 gen->gi_exc_state.previous_item = tstate->exc_info;
                 tstate->exc_info = &gen->gi_exc_state;
                 assert( 2 + oparg <= UINT16_MAX);
                 frame->return_offset = (uint16_t)( 2 + oparg);
-                gen_frame->previous = frame;
+                pushed_frame->previous = frame;
+                gen_frame = PyStackRef_Wrap(pushed_frame);
             }
             // _PUSH_FRAME
             {
                 new_frame = gen_frame;
                 assert(tstate->interp->eval_frame == NULL);
-                _PyInterpreterFrame *temp = new_frame;
+                _PyInterpreterFrame *temp = PyStackRef_Unwrap(new_frame);
                 stack_pointer += -1;
                 assert(WITHIN_STACK_BOUNDS());
                 _PyFrame_SetStackPointer(frame, stack_pointer);
-                assert(new_frame->previous == frame || 
new_frame->previous->previous == frame);
+                assert(temp->previous == frame || temp->previous->previous == 
frame);
                 CALL_STAT_INC(inlined_py_calls);
                 frame = tstate->current_frame = temp;
                 tstate->py_recursion_remaining--;
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index a9d5e92ca02a59..babd3e46b8d1da 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -373,7 +373,7 @@ dummy_func(void) {
         GETLOCAL(this_instr->operand0) = res;
     }
 
-    op(_BINARY_OP_SUBSCR_INIT_CALL, (container, sub, getitem  -- new_frame: 
_Py_UOpsAbstractFrame *)) {
+    op(_BINARY_OP_SUBSCR_INIT_CALL, (container, sub, getitem  -- new_frame)) {
         new_frame = NULL;
         ctx->done = true;
     }
@@ -697,7 +697,7 @@ dummy_func(void) {
         self = owner;
     }
 
-    op(_LOAD_ATTR_PROPERTY_FRAME, (fget/4, owner -- new_frame: 
_Py_UOpsAbstractFrame *)) {
+    op(_LOAD_ATTR_PROPERTY_FRAME, (fget/4, owner -- new_frame)) {
         (void)fget;
         new_frame = NULL;
         ctx->done = true;
@@ -735,7 +735,7 @@ dummy_func(void) {
         sym_set_type(callable, &PyMethod_Type);
     }
 
-    op(_INIT_CALL_PY_EXACT_ARGS, (callable, self_or_null, args[oparg] -- 
new_frame: _Py_UOpsAbstractFrame *)) {
+    op(_INIT_CALL_PY_EXACT_ARGS, (callable, self_or_null, args[oparg] -- 
new_frame)) {
         int argcount = oparg;
 
         PyCodeObject *co = NULL;
@@ -756,10 +756,9 @@ dummy_func(void) {
         }
 
         if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) {
-            new_frame = frame_new(ctx, co, 0, args, argcount);
+            new_frame = (JitOptSymbol *)frame_new(ctx, co, 0, args, argcount);
         } else {
-            new_frame = frame_new(ctx, co, 0, NULL, 0);
-
+            new_frame = (JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0);
         }
     }
 
@@ -769,7 +768,7 @@ dummy_func(void) {
         self_or_null = sym_new_not_null(ctx);
     }
 
-    op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- new_frame: 
_Py_UOpsAbstractFrame *)) {
+    op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- new_frame)) {
         PyCodeObject *co = NULL;
         assert((this_instr + 2)->opcode == _PUSH_FRAME);
         co = get_code_with_logging((this_instr + 2));
@@ -778,10 +777,10 @@ dummy_func(void) {
             break;
         }
 
-        new_frame = frame_new(ctx, co, 0, NULL, 0);
+        new_frame = (JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0);
     }
 
-    op(_PY_FRAME_KW, (callable, self_or_null, args[oparg], kwnames -- 
new_frame: _Py_UOpsAbstractFrame *)) {
+    op(_PY_FRAME_KW, (callable, self_or_null, args[oparg], kwnames -- 
new_frame)) {
         new_frame = NULL;
         ctx->done = true;
     }
@@ -793,7 +792,7 @@ dummy_func(void) {
         self_or_null = sym_new_not_null(ctx);
     }
 
-    op(_CREATE_INIT_FRAME, (init, self, args[oparg] -- init_frame: 
_Py_UOpsAbstractFrame *)) {
+    op(_CREATE_INIT_FRAME, (init, self, args[oparg] -- init_frame)) {
         init_frame = NULL;
         ctx->done = true;
     }
@@ -860,13 +859,13 @@ dummy_func(void) {
         }
     }
 
-    op(_FOR_ITER_GEN_FRAME, (unused, unused -- unused, unused, gen_frame: 
_Py_UOpsAbstractFrame*)) {
+    op(_FOR_ITER_GEN_FRAME, (unused, unused -- unused, unused, gen_frame)) {
         gen_frame = NULL;
         /* We are about to hit the end of the trace */
         ctx->done = true;
     }
 
-    op(_SEND_GEN_FRAME, (unused, unused -- unused, gen_frame: 
_Py_UOpsAbstractFrame *)) {
+    op(_SEND_GEN_FRAME, (unused, unused -- unused, gen_frame)) {
         gen_frame = NULL;
         // We are about to hit the end of the trace:
         ctx->done = true;
@@ -884,12 +883,12 @@ dummy_func(void) {
         Py_UNREACHABLE();
     }
 
-    op(_PUSH_FRAME, (new_frame: _Py_UOpsAbstractFrame * -- )) {
+    op(_PUSH_FRAME, (new_frame -- )) {
         SYNC_SP();
         ctx->frame->stack_pointer = stack_pointer;
-        ctx->frame = new_frame;
+        ctx->frame = (_Py_UOpsAbstractFrame *)new_frame;
         ctx->curr_frame_depth++;
-        stack_pointer = new_frame->stack_pointer;
+        stack_pointer = ctx->frame->stack_pointer;
         co = get_code(this_instr);
         if (co == NULL) {
             // should be about to _EXIT_TRACE anyway
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index 4780e492f61d74..adab110c5ced66 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -715,10 +715,10 @@
         }
 
         case _BINARY_OP_SUBSCR_INIT_CALL: {
-            _Py_UOpsAbstractFrame *new_frame;
+            JitOptSymbol *new_frame;
             new_frame = NULL;
             ctx->done = true;
-            stack_pointer[-3] = (JitOptSymbol *)new_frame;
+            stack_pointer[-3] = new_frame;
             stack_pointer += -2;
             assert(WITHIN_STACK_BOUNDS());
             break;
@@ -829,10 +829,10 @@
         /* _SEND is not a viable micro-op for tier 2 */
 
         case _SEND_GEN_FRAME: {
-            _Py_UOpsAbstractFrame *gen_frame;
+            JitOptSymbol *gen_frame;
             gen_frame = NULL;
             ctx->done = true;
-            stack_pointer[-1] = (JitOptSymbol *)gen_frame;
+            stack_pointer[-1] = gen_frame;
             break;
         }
 
@@ -1323,12 +1323,12 @@
         }
 
         case _LOAD_ATTR_PROPERTY_FRAME: {
-            _Py_UOpsAbstractFrame *new_frame;
+            JitOptSymbol *new_frame;
             PyObject *fget = (PyObject *)this_instr->operand0;
             (void)fget;
             new_frame = NULL;
             ctx->done = true;
-            stack_pointer[-1] = (JitOptSymbol *)new_frame;
+            stack_pointer[-1] = new_frame;
             break;
         }
 
@@ -1685,10 +1685,10 @@
         }
 
         case _FOR_ITER_GEN_FRAME: {
-            _Py_UOpsAbstractFrame *gen_frame;
+            JitOptSymbol *gen_frame;
             gen_frame = NULL;
             ctx->done = true;
-            stack_pointer[0] = (JitOptSymbol *)gen_frame;
+            stack_pointer[0] = gen_frame;
             stack_pointer += 1;
             assert(WITHIN_STACK_BOUNDS());
             break;
@@ -1857,7 +1857,7 @@
         /* _MONITOR_CALL is not a viable micro-op for tier 2 */
 
         case _PY_FRAME_GENERAL: {
-            _Py_UOpsAbstractFrame *new_frame;
+            JitOptSymbol *new_frame;
             PyCodeObject *co = NULL;
             assert((this_instr + 2)->opcode == _PUSH_FRAME);
             co = get_code_with_logging((this_instr + 2));
@@ -1865,8 +1865,8 @@
                 ctx->done = true;
                 break;
             }
-            new_frame = frame_new(ctx, co, 0, NULL, 0);
-            stack_pointer[-2 - oparg] = (JitOptSymbol *)new_frame;
+            new_frame = (JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0);
+            stack_pointer[-2 - oparg] = new_frame;
             stack_pointer += -1 - oparg;
             assert(WITHIN_STACK_BOUNDS());
             break;
@@ -1970,7 +1970,7 @@
         case _INIT_CALL_PY_EXACT_ARGS: {
             JitOptSymbol **args;
             JitOptSymbol *self_or_null;
-            _Py_UOpsAbstractFrame *new_frame;
+            JitOptSymbol *new_frame;
             args = &stack_pointer[-oparg];
             self_or_null = stack_pointer[-1 - oparg];
             int argcount = oparg;
@@ -1988,25 +1988,25 @@
                 argcount++;
             }
             if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) {
-                new_frame = frame_new(ctx, co, 0, args, argcount);
+                new_frame = (JitOptSymbol *)frame_new(ctx, co, 0, args, 
argcount);
             } else {
-                new_frame = frame_new(ctx, co, 0, NULL, 0);
+                new_frame = (JitOptSymbol *)frame_new(ctx, co, 0, NULL, 0);
             }
-            stack_pointer[-2 - oparg] = (JitOptSymbol *)new_frame;
+            stack_pointer[-2 - oparg] = new_frame;
             stack_pointer += -1 - oparg;
             assert(WITHIN_STACK_BOUNDS());
             break;
         }
 
         case _PUSH_FRAME: {
-            _Py_UOpsAbstractFrame *new_frame;
-            new_frame = (_Py_UOpsAbstractFrame *)stack_pointer[-1];
+            JitOptSymbol *new_frame;
+            new_frame = stack_pointer[-1];
             stack_pointer += -1;
             assert(WITHIN_STACK_BOUNDS());
             ctx->frame->stack_pointer = stack_pointer;
-            ctx->frame = new_frame;
+            ctx->frame = (_Py_UOpsAbstractFrame *)new_frame;
             ctx->curr_frame_depth++;
-            stack_pointer = new_frame->stack_pointer;
+            stack_pointer = ctx->frame->stack_pointer;
             co = get_code(this_instr);
             if (co == NULL) {
                 ctx->done = true;
@@ -2159,10 +2159,10 @@
         }
 
         case _CREATE_INIT_FRAME: {
-            _Py_UOpsAbstractFrame *init_frame;
+            JitOptSymbol *init_frame;
             init_frame = NULL;
             ctx->done = true;
-            stack_pointer[-2 - oparg] = (JitOptSymbol *)init_frame;
+            stack_pointer[-2 - oparg] = init_frame;
             stack_pointer += -1 - oparg;
             assert(WITHIN_STACK_BOUNDS());
             break;
@@ -2326,10 +2326,10 @@
         /* _DO_CALL_KW is not a viable micro-op for tier 2 */
 
         case _PY_FRAME_KW: {
-            _Py_UOpsAbstractFrame *new_frame;
+            JitOptSymbol *new_frame;
             new_frame = NULL;
             ctx->done = true;
-            stack_pointer[-3 - oparg] = (JitOptSymbol *)new_frame;
+            stack_pointer[-3 - oparg] = new_frame;
             stack_pointer += -2 - oparg;
             assert(WITHIN_STACK_BOUNDS());
             break;
diff --git a/Tools/cases_generator/analyzer.py 
b/Tools/cases_generator/analyzer.py
index 1447f365336d82..fca9b29f9ebc2e 100644
--- a/Tools/cases_generator/analyzer.py
+++ b/Tools/cases_generator/analyzer.py
@@ -135,15 +135,13 @@ def size(self) -> int:
 @dataclass
 class StackItem:
     name: str
-    type: str | None
     size: str
     peek: bool = False
     used: bool = False
 
     def __str__(self) -> str:
         size = f"[{self.size}]" if self.size else ""
-        type = "" if self.type is None else f"{self.type} "
-        return f"{type}{self.name}{size} {self.peek}"
+        return f"{self.name}{size} {self.peek}"
 
     def is_array(self) -> bool:
         return self.size != ""
@@ -345,7 +343,7 @@ def override_error(
 def convert_stack_item(
     item: parser.StackEffect, replace_op_arg_1: str | None
 ) -> StackItem:
-    return StackItem(item.name, item.type, item.size)
+    return StackItem(item.name, item.size)
 
 def check_unused(stack: list[StackItem], input_names: dict[str, lexer.Token]) 
-> None:
     "Unused items cannot be on the stack above used, non-peek items"
@@ -683,6 +681,8 @@ def has_error_without_pop(op: parser.CodeDef) -> bool:
     "PyStackRef_IsNullOrInt",
     "PyStackRef_IsError",
     "PyStackRef_IsValid",
+    "PyStackRef_Wrap",
+    "PyStackRef_Unwrap",
 )
 
 
@@ -811,7 +811,7 @@ def stack_effect_only_peeks(instr: parser.InstDef) -> bool:
     if len(stack_inputs) == 0:
         return False
     return all(
-        (s.name == other.name and s.type == other.type and s.size == 
other.size)
+        (s.name == other.name and s.size == other.size)
         for s, other in zip(stack_inputs, instr.outputs)
     )
 
diff --git a/Tools/cases_generator/generators_common.py 
b/Tools/cases_generator/generators_common.py
index 02f9a952754e66..47de205c0e9120 100644
--- a/Tools/cases_generator/generators_common.py
+++ b/Tools/cases_generator/generators_common.py
@@ -56,9 +56,7 @@ def root_relative_path(filename: str) -> str:
 
 
 def type_and_null(var: StackItem) -> tuple[str, str]:
-    if var.type:
-        return var.type, "NULL"
-    elif var.is_array():
+    if var.is_array():
         return "_PyStackRef *", "NULL"
     else:
         return "_PyStackRef", "PyStackRef_NULL"
diff --git a/Tools/cases_generator/optimizer_generator.py 
b/Tools/cases_generator/optimizer_generator.py
index fda022a44e59cc..75805dbd7f37f4 100644
--- a/Tools/cases_generator/optimizer_generator.py
+++ b/Tools/cases_generator/optimizer_generator.py
@@ -73,8 +73,6 @@ def validate_uop(override: Uop, uop: Uop) -> None:
 def type_name(var: StackItem) -> str:
     if var.is_array():
         return "JitOptSymbol **"
-    if var.type:
-        return var.type
     return "JitOptSymbol *"
 
 
@@ -230,7 +228,7 @@ def generate_abstract_interpreter(
             declare_variables(override, out, skip_inputs=False)
         else:
             declare_variables(uop, out, skip_inputs=True)
-        stack = Stack(extract_bits=False, cast_type="JitOptSymbol *")
+        stack = Stack()
         write_uop(override, uop, out, stack, debug, skip_inputs=(override is 
None))
         out.start_line()
         out.emit("break;\n")
diff --git a/Tools/cases_generator/parsing.py b/Tools/cases_generator/parsing.py
index 9c9b0053a5928b..a6dac48187525d 100644
--- a/Tools/cases_generator/parsing.py
+++ b/Tools/cases_generator/parsing.py
@@ -247,12 +247,11 @@ def accept(self, visitor: Visitor) -> None:
 @dataclass
 class StackEffect(Node):
     name: str = field(compare=False)  # __eq__ only uses type, cond, size
-    type: str = ""  # Optional `:type`
     size: str = ""  # Optional `[size]`
     # Note: size cannot be combined with type or cond
 
     def __repr__(self) -> str:
-        items = [self.name, self.type, self.size]
+        items = [self.name, self.size]
         while items and items[-1] == "":
             del items[-1]
         return f"StackEffect({', '.join(repr(item) for item in items)})"
@@ -463,20 +462,13 @@ def stack_effect(self) -> StackEffect | None:
         # IDENTIFIER [':' IDENTIFIER [TIMES]] ['if' '(' expression ')']
         # | IDENTIFIER '[' expression ']'
         if tkn := self.expect(lx.IDENTIFIER):
-            type_text = ""
-            if self.expect(lx.COLON):
-                type_text = self.require(lx.IDENTIFIER).text.strip()
-                if self.expect(lx.TIMES):
-                    type_text += " *"
             size_text = ""
             if self.expect(lx.LBRACKET):
-                if type_text:
-                    raise self.make_syntax_error("Unexpected [")
                 if not (size := self.expression()):
                     raise self.make_syntax_error("Expected expression")
                 self.require(lx.RBRACKET)
                 size_text = size.text.strip()
-            return StackEffect(tkn.text, type_text, size_text)
+            return StackEffect(tkn.text, size_text)
         return None
 
     @contextual
diff --git a/Tools/cases_generator/stack.py b/Tools/cases_generator/stack.py
index df168afa88888c..3a0e7e5d0d5636 100644
--- a/Tools/cases_generator/stack.py
+++ b/Tools/cases_generator/stack.py
@@ -168,7 +168,7 @@ def from_memory(defn: StackItem, offset: PointerOffset) -> 
"Local":
 
     @staticmethod
     def register(name: str) -> "Local":
-        item = StackItem(name, None, "", False, True)
+        item = StackItem(name, "", False, True)
         return Local(item, None, True)
 
     def kill(self) -> None:
@@ -216,13 +216,11 @@ def array_or_scalar(var: StackItem | Local) -> str:
     return "array" if var.is_array() else "scalar"
 
 class Stack:
-    def __init__(self, extract_bits: bool=True, cast_type: str = "uintptr_t") 
-> None:
+    def __init__(self) -> None:
         self.base_offset = PointerOffset.zero()
         self.physical_sp = PointerOffset.zero()
         self.logical_sp = PointerOffset.zero()
         self.variables: list[Local] = []
-        self.extract_bits = extract_bits
-        self.cast_type = cast_type
 
     def drop(self, var: StackItem, check_liveness: bool) -> None:
         self.logical_sp = self.logical_sp.pop(var)
@@ -268,10 +266,8 @@ def pop(self, var: StackItem, out: CWriter) -> Local:
         self.base_offset = self.logical_sp
         if var.name in UNUSED or not var.used:
             return Local.unused(var, self.base_offset)
-        cast = f"({var.type})" if (not indirect and var.type) else ""
-        bits = ".bits" if cast and self.extract_bits else ""
         c_offset = (self.base_offset - self.physical_sp).to_c()
-        assign = f"{var.name} = 
{cast}{indirect}stack_pointer[{c_offset}]{bits};\n"
+        assign = f"{var.name} = {indirect}stack_pointer[{c_offset}];\n"
         out.emit(assign)
         self._print(out)
         return Local.from_memory(var, self.base_offset)
@@ -292,12 +288,8 @@ def _do_emit(
         out: CWriter,
         var: StackItem,
         stack_offset: PointerOffset,
-        cast_type: str,
-        extract_bits: bool,
     ) -> None:
-        cast = f"({cast_type})" if var.type else ""
-        bits = ".bits" if cast and extract_bits else ""
-        out.emit(f"stack_pointer[{stack_offset.to_c()}]{bits} = 
{cast}{var.name};\n")
+        out.emit(f"stack_pointer[{stack_offset.to_c()}] = {var.name};\n")
 
     def _save_physical_sp(self, out: CWriter) -> None:
         if self.physical_sp != self.logical_sp:
@@ -320,7 +312,7 @@ def save_variables(self, out: CWriter) -> None:
                 self._print(out)
                 var.memory_offset = var_offset
                 stack_offset = var_offset - self.physical_sp
-                Stack._do_emit(out, var.item, stack_offset, self.cast_type, 
self.extract_bits)
+                Stack._do_emit(out, var.item, stack_offset)
                 self._print(out)
             var_offset = var_offset.push(var.item)
 
@@ -350,7 +342,7 @@ def _print(self, out: CWriter) -> None:
             out.emit(self.as_comment() + "\n")
 
     def copy(self) -> "Stack":
-        other = Stack(self.extract_bits, self.cast_type)
+        other = Stack()
         other.base_offset = self.base_offset
         other.physical_sp = self.physical_sp
         other.logical_sp = self.logical_sp

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: arch...@mail-archive.com

Reply via email to