[Python-checkins] GH-98831: Modernize a ton of simpler instructions (#100545)

gvanrossum webhook-mailer at python.org
Tue Dec 27 20:11:09 EST 2022


https://github.com/python/cpython/commit/08e5594cf3d42391a48e0311f6b9393ec2e00e1e
commit: 08e5594cf3d42391a48e0311f6b9393ec2e00e1e
branch: main
author: Guido van Rossum <guido at python.org>
committer: gvanrossum <gvanrossum at gmail.com>
date: 2022-12-27T17:11:03-08:00
summary:

GH-98831: Modernize a ton of simpler instructions (#100545)

* load_const and load_fast aren't families for now
* Don't decref unmoved names
* Modernize GET_ANEXT
* Modernize GET_AWAITABLE
* Modernize ASYNC_GEN_WRAP
* Modernize YIELD_VALUE
* Modernize POP_EXCEPT (in more than one way)
* Modernize PREP_RERAISE_STAR
* Modernize LOAD_ASSERTION_ERROR
* Modernize LOAD_BUILD_CLASS
* Modernize STORE_NAME
* Modernize LOAD_NAME
* Modernize LOAD_CLASSDEREF
* Modernize LOAD_DEREF
* Modernize STORE_DEREF
* Modernize COPY_FREE_VARS (mark it as done)
* Modernize LIST_TO_TUPLE
* Modernize LIST_EXTEND
* Modernize SET_UPDATE
* Modernize SETUP_ANNOTATIONS
* Modernize DICT_UPDATE
* Modernize DICT_MERGE
* Modernize MAP_ADD
* Modernize IS_OP
* Modernize CONTAINS_OP
* Modernize CHECK_EXC_MATCH
* Modernize IMPORT_NAME
* Modernize IMPORT_STAR
* Modernize IMPORT_FROM
* Modernize JUMP_FORWARD (mark it as done)
* Modernize JUMP_BACKWARD (mark it as done)

files:
M Python/bytecodes.c
M Python/generated_cases.c.h
M Tools/cases_generator/generate_cases.py

diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index c0b625bd662c..e1c73ab6b32f 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -83,9 +83,11 @@ static PyObject *value, *value1, *value2, *left, *right, *res, *sum, *prod, *sub
 static PyObject *container, *start, *stop, *v, *lhs, *rhs;
 static PyObject *list, *tuple, *dict, *owner;
 static PyObject *exit_func, *lasti, *val, *retval, *obj, *iter;
+static PyObject *aiter, *awaitable, *iterable, *w, *exc_value, *bc;
+static PyObject *orig, *excs, *update, *b, *fromlist, *level, *from;
 static size_t jump;
 // Dummy variables for cache effects
-static _Py_CODEUNIT when_to_jump_mask, invert, counter, index, hint;
+static uint16_t when_to_jump_mask, invert, counter, index, hint;
 static uint32_t type_version;
 // Dummy opcode names for 'op' opcodes
 #define _COMPARE_OP_FLOAT 1003
@@ -638,12 +640,9 @@ dummy_func(
             }
         }
 
-        // stack effect: ( -- __0)
-        inst(GET_ANEXT) {
+        inst(GET_ANEXT, (aiter -- aiter, awaitable)) {
             unaryfunc getter = NULL;
             PyObject *next_iter = NULL;
-            PyObject *awaitable = NULL;
-            PyObject *aiter = TOP();
             PyTypeObject *type = Py_TYPE(aiter);
 
             if (PyAsyncGen_CheckExact(aiter)) {
@@ -685,20 +684,17 @@ dummy_func(
                 }
             }
 
-            PUSH(awaitable);
             PREDICT(LOAD_CONST);
         }
 
-        // stack effect: ( -- )
-        inst(GET_AWAITABLE) {
-            PyObject *iterable = TOP();
-            PyObject *iter = _PyCoro_GetAwaitableIter(iterable);
+        inst(GET_AWAITABLE, (iterable -- iter)) {
+            iter = _PyCoro_GetAwaitableIter(iterable);
 
             if (iter == NULL) {
                 format_awaitable_error(tstate, Py_TYPE(iterable), oparg);
             }
 
-            Py_DECREF(iterable);
+            DECREF_INPUTS();
 
             if (iter != NULL && PyCoro_CheckExact(iter)) {
                 PyObject *yf = _PyGen_yf((PyGenObject*)iter);
@@ -714,11 +710,7 @@ dummy_func(
                 }
             }
 
-            SET_TOP(iter); /* Even if it's NULL */
-
-            if (iter == NULL) {
-                goto error;
-            }
+            ERROR_IF(iter == NULL, error);
 
             PREDICT(LOAD_CONST);
         }
@@ -773,29 +765,22 @@ dummy_func(
             }
         }
 
-        // stack effect: ( -- )
-        inst(ASYNC_GEN_WRAP) {
-            PyObject *v = TOP();
+        inst(ASYNC_GEN_WRAP, (v -- w)) {
             assert(frame->f_code->co_flags & CO_ASYNC_GENERATOR);
-            PyObject *w = _PyAsyncGenValueWrapperNew(v);
-            if (w == NULL) {
-                goto error;
-            }
-            SET_TOP(w);
-            Py_DECREF(v);
+            w = _PyAsyncGenValueWrapperNew(v);
+            DECREF_INPUTS();
+            ERROR_IF(w == NULL, error);
         }
 
-        // stack effect: ( -- )
-        inst(YIELD_VALUE) {
+        inst(YIELD_VALUE, (retval --)) {
             // NOTE: It's important that YIELD_VALUE never raises an exception!
             // The compiler treats any exception raised here as a failed close()
             // or throw() call.
             assert(oparg == STACK_LEVEL());
             assert(frame != &entry_frame);
-            PyObject *retval = POP();
             PyGenObject *gen = _PyFrame_GetGenerator(frame);
             gen->gi_frame_state = FRAME_SUSPENDED;
-            _PyFrame_SetStackPointer(frame, stack_pointer);
+            _PyFrame_SetStackPointer(frame, stack_pointer - 1);
             TRACE_FUNCTION_EXIT();
             DTRACE_FUNCTION_EXIT();
             tstate->exc_info = gen->gi_exc_state.previous_item;
@@ -809,12 +794,9 @@ dummy_func(
             goto resume_frame;
         }
 
-        // stack effect: (__0 -- )
-        inst(POP_EXCEPT) {
+        inst(POP_EXCEPT, (exc_value -- )) {
             _PyErr_StackItem *exc_info = tstate->exc_info;
-            PyObject *value = exc_info->exc_value;
-            exc_info->exc_value = POP();
-            Py_XDECREF(value);
+            Py_XSETREF(exc_info->exc_value, exc_value);
         }
 
         // stack effect: (__0 -- )
@@ -839,21 +821,13 @@ dummy_func(
             goto exception_unwind;
         }
 
-        // stack effect: (__0 -- )
-        inst(PREP_RERAISE_STAR) {
-            PyObject *excs = POP();
+        inst(PREP_RERAISE_STAR, (orig, excs -- val)) {
             assert(PyList_Check(excs));
-            PyObject *orig = POP();
-
-            PyObject *val = _PyExc_PrepReraiseStar(orig, excs);
-            Py_DECREF(excs);
-            Py_DECREF(orig);
 
-            if (val == NULL) {
-                goto error;
-            }
+            val = _PyExc_PrepReraiseStar(orig, excs);
+            DECREF_INPUTS();
 
-            PUSH(val);
+            ERROR_IF(val == NULL, error);
         }
 
         // stack effect: (__0, __1 -- )
@@ -934,16 +908,11 @@ dummy_func(
             }
         }
 
-
-        // stack effect: ( -- __0)
-        inst(LOAD_ASSERTION_ERROR) {
-            PyObject *value = PyExc_AssertionError;
-            PUSH(Py_NewRef(value));
+        inst(LOAD_ASSERTION_ERROR, ( -- value)) {
+            value = Py_NewRef(PyExc_AssertionError);
         }
 
-        // stack effect: ( -- __0)
-        inst(LOAD_BUILD_CLASS) {
-            PyObject *bc;
+        inst(LOAD_BUILD_CLASS, ( -- bc)) {
             if (PyDict_CheckExact(BUILTINS())) {
                 bc = _PyDict_GetItemWithError(BUILTINS(),
                                               &_Py_ID(__build_class__));
@@ -952,7 +921,7 @@ dummy_func(
                         _PyErr_SetString(tstate, PyExc_NameError,
                                          "__build_class__ not found");
                     }
-                    goto error;
+                    ERROR_IF(true, error);
                 }
                 Py_INCREF(bc);
             }
@@ -962,31 +931,27 @@ dummy_func(
                     if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError))
                         _PyErr_SetString(tstate, PyExc_NameError,
                                          "__build_class__ not found");
-                    goto error;
+                    ERROR_IF(true, error);
                 }
             }
-            PUSH(bc);
         }
 
-        // stack effect: (__0 -- )
-        inst(STORE_NAME) {
+        inst(STORE_NAME, (v -- )) {
             PyObject *name = GETITEM(names, oparg);
-            PyObject *v = POP();
             PyObject *ns = LOCALS();
             int err;
             if (ns == NULL) {
                 _PyErr_Format(tstate, PyExc_SystemError,
                               "no locals found when storing %R", name);
-                Py_DECREF(v);
-                goto error;
+                DECREF_INPUTS();
+                ERROR_IF(true, error);
             }
             if (PyDict_CheckExact(ns))
                 err = PyDict_SetItem(ns, name, v);
             else
                 err = PyObject_SetItem(ns, name, v);
-            Py_DECREF(v);
-            if (err != 0)
-                goto error;
+            DECREF_INPUTS();
+            ERROR_IF(err, error);
         }
 
         inst(DELETE_NAME, (--)) {
@@ -1139,11 +1104,9 @@ dummy_func(
             }
         }
 
-        // stack effect: ( -- __0)
-        inst(LOAD_NAME) {
+        inst(LOAD_NAME, ( -- v)) {
             PyObject *name = GETITEM(names, oparg);
             PyObject *locals = LOCALS();
-            PyObject *v;
             if (locals == NULL) {
                 _PyErr_Format(tstate, PyExc_SystemError,
                               "no locals when loading %R", name);
@@ -1200,7 +1163,6 @@ dummy_func(
                     }
                 }
             }
-            PUSH(v);
         }
 
         // error: LOAD_GLOBAL has irregular stack effect
@@ -1339,9 +1301,8 @@ dummy_func(
             Py_DECREF(oldobj);
         }
 
-        // stack effect: ( -- __0)
-        inst(LOAD_CLASSDEREF) {
-            PyObject *name, *value, *locals = LOCALS();
+        inst(LOAD_CLASSDEREF, ( -- value)) {
+            PyObject *name, *locals = LOCALS();
             assert(locals);
             assert(oparg >= 0 && oparg < frame->f_code->co_nlocalsplus);
             name = PyTuple_GET_ITEM(frame->f_code->co_localsplusnames, oparg);
@@ -1372,31 +1333,26 @@ dummy_func(
                 }
                 Py_INCREF(value);
             }
-            PUSH(value);
         }
 
-        // stack effect: ( -- __0)
-        inst(LOAD_DEREF) {
+        inst(LOAD_DEREF, ( -- value)) {
             PyObject *cell = GETLOCAL(oparg);
-            PyObject *value = PyCell_GET(cell);
+            value = PyCell_GET(cell);
             if (value == NULL) {
                 format_exc_unbound(tstate, frame->f_code, oparg);
-                goto error;
+                ERROR_IF(true, error);
             }
-            PUSH(Py_NewRef(value));
+            Py_INCREF(value);
         }
 
-        // stack effect: (__0 -- )
-        inst(STORE_DEREF) {
-            PyObject *v = POP();
+        inst(STORE_DEREF, (v --)) {
             PyObject *cell = GETLOCAL(oparg);
             PyObject *oldobj = PyCell_GET(cell);
             PyCell_SET(cell, v);
             Py_XDECREF(oldobj);
         }
 
-        // stack effect: ( -- )
-        inst(COPY_FREE_VARS) {
+        inst(COPY_FREE_VARS, (--)) {
             /* Copy closure variables to free variables */
             PyCodeObject *co = frame->f_code;
             assert(PyFunction_Check(frame->f_funcobj));
@@ -1444,21 +1400,14 @@ dummy_func(
             PUSH(list);
         }
 
-        // stack effect: ( -- )
-        inst(LIST_TO_TUPLE) {
-            PyObject *list = POP();
-            PyObject *tuple = PyList_AsTuple(list);
-            Py_DECREF(list);
-            if (tuple == NULL) {
-                goto error;
-            }
-            PUSH(tuple);
+        inst(LIST_TO_TUPLE, (list -- tuple)) {
+            tuple = PyList_AsTuple(list);
+            DECREF_INPUTS();
+            ERROR_IF(tuple == NULL, error);
         }
 
-        // stack effect: (__0 -- )
-        inst(LIST_EXTEND) {
-            PyObject *iterable = POP();
-            PyObject *list = PEEK(oparg);
+        inst(LIST_EXTEND, (iterable -- )) {
+            PyObject *list = PEEK(oparg + 1);  // iterable is still on the stack
             PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable);
             if (none_val == NULL) {
                 if (_PyErr_ExceptionMatches(tstate, PyExc_TypeError) &&
@@ -1469,22 +1418,18 @@ dummy_func(
                           "Value after * must be an iterable, not %.200s",
                           Py_TYPE(iterable)->tp_name);
                 }
-                Py_DECREF(iterable);
-                goto error;
+                DECREF_INPUTS();
+                ERROR_IF(true, error);
             }
             Py_DECREF(none_val);
-            Py_DECREF(iterable);
+            DECREF_INPUTS();
         }
 
-        // stack effect: (__0 -- )
-        inst(SET_UPDATE) {
-            PyObject *iterable = POP();
-            PyObject *set = PEEK(oparg);
+        inst(SET_UPDATE, (iterable --)) {
+            PyObject *set = PEEK(oparg + 1);  // iterable is still on the stack
             int err = _PySet_Update(set, iterable);
-            Py_DECREF(iterable);
-            if (err < 0) {
-                goto error;
-            }
+            DECREF_INPUTS();
+            ERROR_IF(err < 0, error);
         }
 
         // stack effect: (__array[oparg] -- __0)
@@ -1524,54 +1469,41 @@ dummy_func(
             PUSH(map);
         }
 
-        // stack effect: ( -- )
-        inst(SETUP_ANNOTATIONS) {
+        inst(SETUP_ANNOTATIONS, (--)) {
             int err;
             PyObject *ann_dict;
             if (LOCALS() == NULL) {
                 _PyErr_Format(tstate, PyExc_SystemError,
                               "no locals found when setting up annotations");
-                goto error;
+                ERROR_IF(true, error);
             }
             /* check if __annotations__ in locals()... */
             if (PyDict_CheckExact(LOCALS())) {
                 ann_dict = _PyDict_GetItemWithError(LOCALS(),
                                                     &_Py_ID(__annotations__));
                 if (ann_dict == NULL) {
-                    if (_PyErr_Occurred(tstate)) {
-                        goto error;
-                    }
+                    ERROR_IF(_PyErr_Occurred(tstate), error);
                     /* ...if not, create a new one */
                     ann_dict = PyDict_New();
-                    if (ann_dict == NULL) {
-                        goto error;
-                    }
+                    ERROR_IF(ann_dict == NULL, error);
                     err = PyDict_SetItem(LOCALS(), &_Py_ID(__annotations__),
                                          ann_dict);
                     Py_DECREF(ann_dict);
-                    if (err != 0) {
-                        goto error;
-                    }
+                    ERROR_IF(err, error);
                 }
             }
             else {
                 /* do the same if locals() is not a dict */
                 ann_dict = PyObject_GetItem(LOCALS(), &_Py_ID(__annotations__));
                 if (ann_dict == NULL) {
-                    if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
-                        goto error;
-                    }
+                    ERROR_IF(!_PyErr_ExceptionMatches(tstate, PyExc_KeyError), error);
                     _PyErr_Clear(tstate);
                     ann_dict = PyDict_New();
-                    if (ann_dict == NULL) {
-                        goto error;
-                    }
+                    ERROR_IF(ann_dict == NULL, error);
                     err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__),
                                            ann_dict);
                     Py_DECREF(ann_dict);
-                    if (err != 0) {
-                        goto error;
-                    }
+                    ERROR_IF(err, error);
                 }
                 else {
                     Py_DECREF(ann_dict);
@@ -1603,48 +1535,38 @@ dummy_func(
             PUSH(map);
         }
 
-        // stack effect: (__0 -- )
-        inst(DICT_UPDATE) {
-            PyObject *update = POP();
-            PyObject *dict = PEEK(oparg);
+        inst(DICT_UPDATE, (update --)) {
+            PyObject *dict = PEEK(oparg + 1);  // update is still on the stack
             if (PyDict_Update(dict, update) < 0) {
                 if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) {
                     _PyErr_Format(tstate, PyExc_TypeError,
                                     "'%.200s' object is not a mapping",
                                     Py_TYPE(update)->tp_name);
                 }
-                Py_DECREF(update);
-                goto error;
+                DECREF_INPUTS();
+                ERROR_IF(true, error);
             }
-            Py_DECREF(update);
+            DECREF_INPUTS();
         }
 
-        // stack effect: (__0 -- )
-        inst(DICT_MERGE) {
-            PyObject *update = POP();
-            PyObject *dict = PEEK(oparg);
+        inst(DICT_MERGE, (update --)) {
+            PyObject *dict = PEEK(oparg + 1);  // update is still on the stack
 
             if (_PyDict_MergeEx(dict, update, 2) < 0) {
-                format_kwargs_error(tstate, PEEK(2 + oparg), update);
-                Py_DECREF(update);
-                goto error;
+                format_kwargs_error(tstate, PEEK(3 + oparg), update);
+                DECREF_INPUTS();
+                ERROR_IF(true, error);
             }
-            Py_DECREF(update);
+            DECREF_INPUTS();
             PREDICT(CALL_FUNCTION_EX);
         }
 
-        // stack effect: (__0, __1 -- )
-        inst(MAP_ADD) {
-            PyObject *value = TOP();
-            PyObject *key = SECOND();
-            PyObject *map;
-            STACK_SHRINK(2);
-            map = PEEK(oparg);                      /* dict */
-            assert(PyDict_CheckExact(map));
-            /* map[key] = value */
-            if (_PyDict_SetItem_Take2((PyDictObject *)map, key, value) != 0) {
-                goto error;
-            }
+        inst(MAP_ADD, (key, value --)) {
+            PyObject *dict = PEEK(oparg + 2);  // key, value are still on the stack
+            assert(PyDict_CheckExact(dict));
+            /* dict[key] = value */
+            // Do not DECREF INPUTS because the function steals the references
+            ERROR_IF(_PyDict_SetItem_Take2((PyDictObject *)dict, key, value) != 0, error);
             PREDICT(JUMP_BACKWARD);
         }
 
@@ -2073,29 +1995,17 @@ dummy_func(
         }
         super(COMPARE_OP_STR_JUMP) = _COMPARE_OP_STR + _JUMP_IF;
 
-        // stack effect: (__0 -- )
-        inst(IS_OP) {
-            PyObject *right = POP();
-            PyObject *left = TOP();
+        inst(IS_OP, (left, right -- b)) {
             int res = Py_Is(left, right) ^ oparg;
-            PyObject *b = res ? Py_True : Py_False;
-            SET_TOP(Py_NewRef(b));
-            Py_DECREF(left);
-            Py_DECREF(right);
+            DECREF_INPUTS();
+            b = Py_NewRef(res ? Py_True : Py_False);
         }
 
-        // stack effect: (__0 -- )
-        inst(CONTAINS_OP) {
-            PyObject *right = POP();
-            PyObject *left = POP();
+        inst(CONTAINS_OP, (left, right -- b)) {
             int res = PySequence_Contains(right, left);
-            Py_DECREF(left);
-            Py_DECREF(right);
-            if (res < 0) {
-                goto error;
-            }
-            PyObject *b = (res^oparg) ? Py_True : Py_False;
-            PUSH(Py_NewRef(b));
+            DECREF_INPUTS();
+            ERROR_IF(res < 0, error);
+            b = Py_NewRef((res^oparg) ? Py_True : Py_False);
         }
 
         // stack effect: ( -- )
@@ -2139,76 +2049,57 @@ dummy_func(
             }
         }
 
-        // stack effect: ( -- )
-        inst(CHECK_EXC_MATCH) {
-            PyObject *right = POP();
-            PyObject *left = TOP();
+        inst(CHECK_EXC_MATCH, (left, right -- left, b)) {
             assert(PyExceptionInstance_Check(left));
             if (check_except_type_valid(tstate, right) < 0) {
-                 Py_DECREF(right);
-                 goto error;
+                 DECREF_INPUTS();
+                 ERROR_IF(true, error);
             }
 
             int res = PyErr_GivenExceptionMatches(left, right);
-            Py_DECREF(right);
-            PUSH(Py_NewRef(res ? Py_True : Py_False));
+            DECREF_INPUTS();
+            b = Py_NewRef(res ? Py_True : Py_False);
         }
 
-        // stack effect: (__0 -- )
-        inst(IMPORT_NAME) {
+         inst(IMPORT_NAME, (level, fromlist -- res)) {
             PyObject *name = GETITEM(names, oparg);
-            PyObject *fromlist = POP();
-            PyObject *level = TOP();
-            PyObject *res;
             res = import_name(tstate, frame, name, fromlist, level);
-            Py_DECREF(level);
-            Py_DECREF(fromlist);
-            SET_TOP(res);
-            if (res == NULL)
-                goto error;
+            DECREF_INPUTS();
+            ERROR_IF(res == NULL, error);
         }
 
-        // stack effect: (__0 -- )
-        inst(IMPORT_STAR) {
-            PyObject *from = POP(), *locals;
+        inst(IMPORT_STAR, (from --)) {
+            PyObject *locals;
             int err;
             if (_PyFrame_FastToLocalsWithError(frame) < 0) {
-                Py_DECREF(from);
-                goto error;
+                DECREF_INPUTS();
+                ERROR_IF(true, error);
             }
 
             locals = LOCALS();
             if (locals == NULL) {
                 _PyErr_SetString(tstate, PyExc_SystemError,
                                  "no locals found during 'import *'");
-                Py_DECREF(from);
-                goto error;
+                DECREF_INPUTS();
+                ERROR_IF(true, error);
             }
             err = import_all_from(tstate, locals, from);
             _PyFrame_LocalsToFast(frame, 0);
-            Py_DECREF(from);
-            if (err != 0)
-                goto error;
+            DECREF_INPUTS();
+            ERROR_IF(err, error);
         }
 
-        // stack effect: ( -- __0)
-        inst(IMPORT_FROM) {
+        inst(IMPORT_FROM, (from -- from, res)) {
             PyObject *name = GETITEM(names, oparg);
-            PyObject *from = TOP();
-            PyObject *res;
             res = import_from(tstate, from, name);
-            PUSH(res);
-            if (res == NULL)
-                goto error;
+            ERROR_IF(res == NULL, error);
         }
 
-        // stack effect: ( -- )
-        inst(JUMP_FORWARD) {
+        inst(JUMP_FORWARD, (--)) {
             JUMPBY(oparg);
         }
 
-        // stack effect: ( -- )
-        inst(JUMP_BACKWARD) {
+        inst(JUMP_BACKWARD, (--)) {
             assert(oparg < INSTR_OFFSET());
             JUMPBY(-oparg);
             CHECK_EVAL_BREAKER();
@@ -3631,8 +3522,6 @@ family(load_attr) = {
     LOAD_ATTR_PROPERTY, LOAD_ATTR_SLOT, LOAD_ATTR_WITH_HINT,
     LOAD_ATTR_METHOD_LAZY_DICT, LOAD_ATTR_METHOD_NO_DICT, LOAD_ATTR_METHOD_WITH_DICT,
     LOAD_ATTR_METHOD_WITH_VALUES };
-family(load_const) = { LOAD_CONST, LOAD_CONST__LOAD_FAST };
-family(load_fast) = { LOAD_FAST, LOAD_FAST__LOAD_CONST, LOAD_FAST__LOAD_FAST };
 family(load_global) = {
     LOAD_GLOBAL, LOAD_GLOBAL_BUILTIN,
     LOAD_GLOBAL_MODULE };
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 42b7ca086705..1179bdfc696c 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -795,10 +795,10 @@
         }
 
         TARGET(GET_ANEXT) {
+            PyObject *aiter = PEEK(1);
+            PyObject *awaitable;
             unaryfunc getter = NULL;
             PyObject *next_iter = NULL;
-            PyObject *awaitable = NULL;
-            PyObject *aiter = TOP();
             PyTypeObject *type = Py_TYPE(aiter);
 
             if (PyAsyncGen_CheckExact(aiter)) {
@@ -840,15 +840,17 @@
                 }
             }
 
-            PUSH(awaitable);
+            STACK_GROW(1);
+            POKE(1, awaitable);
             PREDICT(LOAD_CONST);
             DISPATCH();
         }
 
         TARGET(GET_AWAITABLE) {
             PREDICTED(GET_AWAITABLE);
-            PyObject *iterable = TOP();
-            PyObject *iter = _PyCoro_GetAwaitableIter(iterable);
+            PyObject *iterable = PEEK(1);
+            PyObject *iter;
+            iter = _PyCoro_GetAwaitableIter(iterable);
 
             if (iter == NULL) {
                 format_awaitable_error(tstate, Py_TYPE(iterable), oparg);
@@ -870,12 +872,9 @@
                 }
             }
 
-            SET_TOP(iter); /* Even if it's NULL */
-
-            if (iter == NULL) {
-                goto error;
-            }
+            if (iter == NULL) goto pop_1_error;
 
+            POKE(1, iter);
             PREDICT(LOAD_CONST);
             DISPATCH();
         }
@@ -931,27 +930,26 @@
         }
 
         TARGET(ASYNC_GEN_WRAP) {
-            PyObject *v = TOP();
+            PyObject *v = PEEK(1);
+            PyObject *w;
             assert(frame->f_code->co_flags & CO_ASYNC_GENERATOR);
-            PyObject *w = _PyAsyncGenValueWrapperNew(v);
-            if (w == NULL) {
-                goto error;
-            }
-            SET_TOP(w);
+            w = _PyAsyncGenValueWrapperNew(v);
             Py_DECREF(v);
+            if (w == NULL) goto pop_1_error;
+            POKE(1, w);
             DISPATCH();
         }
 
         TARGET(YIELD_VALUE) {
+            PyObject *retval = PEEK(1);
             // NOTE: It's important that YIELD_VALUE never raises an exception!
             // The compiler treats any exception raised here as a failed close()
             // or throw() call.
             assert(oparg == STACK_LEVEL());
             assert(frame != &entry_frame);
-            PyObject *retval = POP();
             PyGenObject *gen = _PyFrame_GetGenerator(frame);
             gen->gi_frame_state = FRAME_SUSPENDED;
-            _PyFrame_SetStackPointer(frame, stack_pointer);
+            _PyFrame_SetStackPointer(frame, stack_pointer - 1);
             TRACE_FUNCTION_EXIT();
             DTRACE_FUNCTION_EXIT();
             tstate->exc_info = gen->gi_exc_state.previous_item;
@@ -966,10 +964,10 @@
         }
 
         TARGET(POP_EXCEPT) {
+            PyObject *exc_value = PEEK(1);
             _PyErr_StackItem *exc_info = tstate->exc_info;
-            PyObject *value = exc_info->exc_value;
-            exc_info->exc_value = POP();
-            Py_XDECREF(value);
+            Py_XSETREF(exc_info->exc_value, exc_value);
+            STACK_SHRINK(1);
             DISPATCH();
         }
 
@@ -995,19 +993,18 @@
         }
 
         TARGET(PREP_RERAISE_STAR) {
-            PyObject *excs = POP();
+            PyObject *excs = PEEK(1);
+            PyObject *orig = PEEK(2);
+            PyObject *val;
             assert(PyList_Check(excs));
-            PyObject *orig = POP();
 
-            PyObject *val = _PyExc_PrepReraiseStar(orig, excs);
-            Py_DECREF(excs);
+            val = _PyExc_PrepReraiseStar(orig, excs);
             Py_DECREF(orig);
+            Py_DECREF(excs);
 
-            if (val == NULL) {
-                goto error;
-            }
-
-            PUSH(val);
+            if (val == NULL) goto pop_2_error;
+            STACK_SHRINK(1);
+            POKE(1, val);
             DISPATCH();
         }
 
@@ -1091,8 +1088,10 @@
         }
 
         TARGET(LOAD_ASSERTION_ERROR) {
-            PyObject *value = PyExc_AssertionError;
-            PUSH(Py_NewRef(value));
+            PyObject *value;
+            value = Py_NewRef(PyExc_AssertionError);
+            STACK_GROW(1);
+            POKE(1, value);
             DISPATCH();
         }
 
@@ -1106,7 +1105,7 @@
                         _PyErr_SetString(tstate, PyExc_NameError,
                                          "__build_class__ not found");
                     }
-                    goto error;
+                    if (true) goto error;
                 }
                 Py_INCREF(bc);
             }
@@ -1116,31 +1115,32 @@
                     if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError))
                         _PyErr_SetString(tstate, PyExc_NameError,
                                          "__build_class__ not found");
-                    goto error;
+                    if (true) goto error;
                 }
             }
-            PUSH(bc);
+            STACK_GROW(1);
+            POKE(1, bc);
             DISPATCH();
         }
 
         TARGET(STORE_NAME) {
+            PyObject *v = PEEK(1);
             PyObject *name = GETITEM(names, oparg);
-            PyObject *v = POP();
             PyObject *ns = LOCALS();
             int err;
             if (ns == NULL) {
                 _PyErr_Format(tstate, PyExc_SystemError,
                               "no locals found when storing %R", name);
                 Py_DECREF(v);
-                goto error;
+                if (true) goto pop_1_error;
             }
             if (PyDict_CheckExact(ns))
                 err = PyDict_SetItem(ns, name, v);
             else
                 err = PyObject_SetItem(ns, name, v);
             Py_DECREF(v);
-            if (err != 0)
-                goto error;
+            if (err) goto pop_1_error;
+            STACK_SHRINK(1);
             DISPATCH();
         }
 
@@ -1304,9 +1304,9 @@
         }
 
         TARGET(LOAD_NAME) {
+            PyObject *v;
             PyObject *name = GETITEM(names, oparg);
             PyObject *locals = LOCALS();
-            PyObject *v;
             if (locals == NULL) {
                 _PyErr_Format(tstate, PyExc_SystemError,
                               "no locals when loading %R", name);
@@ -1363,7 +1363,8 @@
                     }
                 }
             }
-            PUSH(v);
+            STACK_GROW(1);
+            POKE(1, v);
             DISPATCH();
         }
 
@@ -1508,7 +1509,8 @@
         }
 
         TARGET(LOAD_CLASSDEREF) {
-            PyObject *name, *value, *locals = LOCALS();
+            PyObject *value;
+            PyObject *name, *locals = LOCALS();
             assert(locals);
             assert(oparg >= 0 && oparg < frame->f_code->co_nlocalsplus);
             name = PyTuple_GET_ITEM(frame->f_code->co_localsplusnames, oparg);
@@ -1539,27 +1541,32 @@
                 }
                 Py_INCREF(value);
             }
-            PUSH(value);
+            STACK_GROW(1);
+            POKE(1, value);
             DISPATCH();
         }
 
         TARGET(LOAD_DEREF) {
+            PyObject *value;
             PyObject *cell = GETLOCAL(oparg);
-            PyObject *value = PyCell_GET(cell);
+            value = PyCell_GET(cell);
             if (value == NULL) {
                 format_exc_unbound(tstate, frame->f_code, oparg);
-                goto error;
+                if (true) goto error;
             }
-            PUSH(Py_NewRef(value));
+            Py_INCREF(value);
+            STACK_GROW(1);
+            POKE(1, value);
             DISPATCH();
         }
 
         TARGET(STORE_DEREF) {
-            PyObject *v = POP();
+            PyObject *v = PEEK(1);
             PyObject *cell = GETLOCAL(oparg);
             PyObject *oldobj = PyCell_GET(cell);
             PyCell_SET(cell, v);
             Py_XDECREF(oldobj);
+            STACK_SHRINK(1);
             DISPATCH();
         }
 
@@ -1613,19 +1620,18 @@
         }
 
         TARGET(LIST_TO_TUPLE) {
-            PyObject *list = POP();
-            PyObject *tuple = PyList_AsTuple(list);
+            PyObject *list = PEEK(1);
+            PyObject *tuple;
+            tuple = PyList_AsTuple(list);
             Py_DECREF(list);
-            if (tuple == NULL) {
-                goto error;
-            }
-            PUSH(tuple);
+            if (tuple == NULL) goto pop_1_error;
+            POKE(1, tuple);
             DISPATCH();
         }
 
         TARGET(LIST_EXTEND) {
-            PyObject *iterable = POP();
-            PyObject *list = PEEK(oparg);
+            PyObject *iterable = PEEK(1);
+            PyObject *list = PEEK(oparg + 1);  // iterable is still on the stack
             PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable);
             if (none_val == NULL) {
                 if (_PyErr_ExceptionMatches(tstate, PyExc_TypeError) &&
@@ -1637,21 +1643,21 @@
                           Py_TYPE(iterable)->tp_name);
                 }
                 Py_DECREF(iterable);
-                goto error;
+                if (true) goto pop_1_error;
             }
             Py_DECREF(none_val);
             Py_DECREF(iterable);
+            STACK_SHRINK(1);
             DISPATCH();
         }
 
         TARGET(SET_UPDATE) {
-            PyObject *iterable = POP();
-            PyObject *set = PEEK(oparg);
+            PyObject *iterable = PEEK(1);
+            PyObject *set = PEEK(oparg + 1);  // iterable is still on the stack
             int err = _PySet_Update(set, iterable);
             Py_DECREF(iterable);
-            if (err < 0) {
-                goto error;
-            }
+            if (err < 0) goto pop_1_error;
+            STACK_SHRINK(1);
             DISPATCH();
         }
 
@@ -1698,47 +1704,35 @@
             if (LOCALS() == NULL) {
                 _PyErr_Format(tstate, PyExc_SystemError,
                               "no locals found when setting up annotations");
-                goto error;
+                if (true) goto error;
             }
             /* check if __annotations__ in locals()... */
             if (PyDict_CheckExact(LOCALS())) {
                 ann_dict = _PyDict_GetItemWithError(LOCALS(),
                                                     &_Py_ID(__annotations__));
                 if (ann_dict == NULL) {
-                    if (_PyErr_Occurred(tstate)) {
-                        goto error;
-                    }
+                    if (_PyErr_Occurred(tstate)) goto error;
                     /* ...if not, create a new one */
                     ann_dict = PyDict_New();
-                    if (ann_dict == NULL) {
-                        goto error;
-                    }
+                    if (ann_dict == NULL) goto error;
                     err = PyDict_SetItem(LOCALS(), &_Py_ID(__annotations__),
                                          ann_dict);
                     Py_DECREF(ann_dict);
-                    if (err != 0) {
-                        goto error;
-                    }
+                    if (err) goto error;
                 }
             }
             else {
                 /* do the same if locals() is not a dict */
                 ann_dict = PyObject_GetItem(LOCALS(), &_Py_ID(__annotations__));
                 if (ann_dict == NULL) {
-                    if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
-                        goto error;
-                    }
+                    if (!_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) goto error;
                     _PyErr_Clear(tstate);
                     ann_dict = PyDict_New();
-                    if (ann_dict == NULL) {
-                        goto error;
-                    }
+                    if (ann_dict == NULL) goto error;
                     err = PyObject_SetItem(LOCALS(), &_Py_ID(__annotations__),
                                            ann_dict);
                     Py_DECREF(ann_dict);
-                    if (err != 0) {
-                        goto error;
-                    }
+                    if (err) goto error;
                 }
                 else {
                     Py_DECREF(ann_dict);
@@ -1772,8 +1766,8 @@
         }
 
         TARGET(DICT_UPDATE) {
-            PyObject *update = POP();
-            PyObject *dict = PEEK(oparg);
+            PyObject *update = PEEK(1);
+            PyObject *dict = PEEK(oparg + 1);  // update is still on the stack
             if (PyDict_Update(dict, update) < 0) {
                 if (_PyErr_ExceptionMatches(tstate, PyExc_AttributeError)) {
                     _PyErr_Format(tstate, PyExc_TypeError,
@@ -1781,37 +1775,37 @@
                                     Py_TYPE(update)->tp_name);
                 }
                 Py_DECREF(update);
-                goto error;
+                if (true) goto pop_1_error;
             }
             Py_DECREF(update);
+            STACK_SHRINK(1);
             DISPATCH();
         }
 
         TARGET(DICT_MERGE) {
-            PyObject *update = POP();
-            PyObject *dict = PEEK(oparg);
+            PyObject *update = PEEK(1);
+            PyObject *dict = PEEK(oparg + 1);  // update is still on the stack
 
             if (_PyDict_MergeEx(dict, update, 2) < 0) {
-                format_kwargs_error(tstate, PEEK(2 + oparg), update);
+                format_kwargs_error(tstate, PEEK(3 + oparg), update);
                 Py_DECREF(update);
-                goto error;
+                if (true) goto pop_1_error;
             }
             Py_DECREF(update);
+            STACK_SHRINK(1);
             PREDICT(CALL_FUNCTION_EX);
             DISPATCH();
         }
 
         TARGET(MAP_ADD) {
-            PyObject *value = TOP();
-            PyObject *key = SECOND();
-            PyObject *map;
+            PyObject *value = PEEK(1);
+            PyObject *key = PEEK(2);
+            PyObject *dict = PEEK(oparg + 2);  // key, value are still on the stack
+            assert(PyDict_CheckExact(dict));
+            /* dict[key] = value */
+            // Do not DECREF INPUTS because the function steals the references
+            if (_PyDict_SetItem_Take2((PyDictObject *)dict, key, value) != 0) goto pop_2_error;
             STACK_SHRINK(2);
-            map = PEEK(oparg);                      /* dict */
-            assert(PyDict_CheckExact(map));
-            /* map[key] = value */
-            if (_PyDict_SetItem_Take2((PyDictObject *)map, key, value) != 0) {
-                goto error;
-            }
             PREDICT(JUMP_BACKWARD);
             DISPATCH();
         }
@@ -2312,27 +2306,29 @@
         }
 
         TARGET(IS_OP) {
-            PyObject *right = POP();
-            PyObject *left = TOP();
+            PyObject *right = PEEK(1);
+            PyObject *left = PEEK(2);
+            PyObject *b;
             int res = Py_Is(left, right) ^ oparg;
-            PyObject *b = res ? Py_True : Py_False;
-            SET_TOP(Py_NewRef(b));
             Py_DECREF(left);
             Py_DECREF(right);
+            b = Py_NewRef(res ? Py_True : Py_False);
+            STACK_SHRINK(1);
+            POKE(1, b);
             DISPATCH();
         }
 
         TARGET(CONTAINS_OP) {
-            PyObject *right = POP();
-            PyObject *left = POP();
+            PyObject *right = PEEK(1);
+            PyObject *left = PEEK(2);
+            PyObject *b;
             int res = PySequence_Contains(right, left);
             Py_DECREF(left);
             Py_DECREF(right);
-            if (res < 0) {
-                goto error;
-            }
-            PyObject *b = (res^oparg) ? Py_True : Py_False;
-            PUSH(Py_NewRef(b));
+            if (res < 0) goto pop_2_error;
+            b = Py_NewRef((res^oparg) ? Py_True : Py_False);
+            STACK_SHRINK(1);
+            POKE(1, b);
             DISPATCH();
         }
 
@@ -2378,40 +2374,43 @@
         }
 
         TARGET(CHECK_EXC_MATCH) {
-            PyObject *right = POP();
-            PyObject *left = TOP();
+            PyObject *right = PEEK(1);
+            PyObject *left = PEEK(2);
+            PyObject *b;
             assert(PyExceptionInstance_Check(left));
             if (check_except_type_valid(tstate, right) < 0) {
                  Py_DECREF(right);
-                 goto error;
+                 if (true) goto pop_1_error;
             }
 
             int res = PyErr_GivenExceptionMatches(left, right);
             Py_DECREF(right);
-            PUSH(Py_NewRef(res ? Py_True : Py_False));
+            b = Py_NewRef(res ? Py_True : Py_False);
+            POKE(1, b);
             DISPATCH();
         }
 
         TARGET(IMPORT_NAME) {
-            PyObject *name = GETITEM(names, oparg);
-            PyObject *fromlist = POP();
-            PyObject *level = TOP();
+            PyObject *fromlist = PEEK(1);
+            PyObject *level = PEEK(2);
             PyObject *res;
+            PyObject *name = GETITEM(names, oparg);
             res = import_name(tstate, frame, name, fromlist, level);
             Py_DECREF(level);
             Py_DECREF(fromlist);
-            SET_TOP(res);
-            if (res == NULL)
-                goto error;
+            if (res == NULL) goto pop_2_error;
+            STACK_SHRINK(1);
+            POKE(1, res);
             DISPATCH();
         }
 
         TARGET(IMPORT_STAR) {
-            PyObject *from = POP(), *locals;
+            PyObject *from = PEEK(1);
+            PyObject *locals;
             int err;
             if (_PyFrame_FastToLocalsWithError(frame) < 0) {
                 Py_DECREF(from);
-                goto error;
+                if (true) goto pop_1_error;
             }
 
             locals = LOCALS();
@@ -2419,24 +2418,24 @@
                 _PyErr_SetString(tstate, PyExc_SystemError,
                                  "no locals found during 'import *'");
                 Py_DECREF(from);
-                goto error;
+                if (true) goto pop_1_error;
             }
             err = import_all_from(tstate, locals, from);
             _PyFrame_LocalsToFast(frame, 0);
             Py_DECREF(from);
-            if (err != 0)
-                goto error;
+            if (err) goto pop_1_error;
+            STACK_SHRINK(1);
             DISPATCH();
         }
 
         TARGET(IMPORT_FROM) {
-            PyObject *name = GETITEM(names, oparg);
-            PyObject *from = TOP();
+            PyObject *from = PEEK(1);
             PyObject *res;
+            PyObject *name = GETITEM(names, oparg);
             res = import_from(tstate, from, name);
-            PUSH(res);
-            if (res == NULL)
-                goto error;
+            if (res == NULL) goto error;
+            STACK_GROW(1);
+            POKE(1, res);
             DISPATCH();
         }
 
diff --git a/Tools/cases_generator/generate_cases.py b/Tools/cases_generator/generate_cases.py
index 85a7c6098e0b..5eed74c5e147 100644
--- a/Tools/cases_generator/generate_cases.py
+++ b/Tools/cases_generator/generate_cases.py
@@ -125,6 +125,7 @@ class Instruction:
     # Set later
     family: parser.Family | None = None
     predicted: bool = False
+    unmoved_names: frozenset[str] = frozenset()
 
     def __init__(self, inst: parser.InstDef):
         self.inst = inst
@@ -141,6 +142,13 @@ def __init__(self, inst: parser.InstDef):
             effect for effect in inst.inputs if isinstance(effect, StackEffect)
         ]
         self.output_effects = inst.outputs  # For consistency/completeness
+        unmoved_names: set[str] = set()
+        for ieffect, oeffect in zip(self.input_effects, self.output_effects):
+            if ieffect.name == oeffect.name:
+                unmoved_names.add(ieffect.name)
+            else:
+                break
+        self.unmoved_names = frozenset(unmoved_names)
 
     def write(self, out: Formatter) -> None:
         """Write one instruction, sans prologue and epilogue."""
@@ -175,12 +183,8 @@ def write(self, out: Formatter) -> None:
         out.stack_adjust(diff)
 
         # Write output stack effect assignments
-        unmoved_names: set[str] = set()
-        for ieffect, oeffect in zip(self.input_effects, self.output_effects):
-            if ieffect.name == oeffect.name:
-                unmoved_names.add(ieffect.name)
         for i, oeffect in enumerate(reversed(self.output_effects), 1):
-            if oeffect.name not in unmoved_names:
+            if oeffect.name not in self.unmoved_names:
                 dst = StackEffect(f"PEEK({i})", "")
                 out.assign(dst, oeffect)
 
@@ -235,7 +239,8 @@ def write_body(self, out: Formatter, dedent: int, cache_adjust: int = 0) -> None
             elif m := re.match(r"(\s*)DECREF_INPUTS\(\);\s*$", line):
                 space = m.group(1)
                 for ieff in self.input_effects:
-                    out.write_raw(f"{extra}{space}Py_DECREF({ieff.name});\n")
+                    if ieff.name not in self.unmoved_names:
+                        out.write_raw(f"{extra}{space}Py_DECREF({ieff.name});\n")
             else:
                 out.write_raw(extra + line)
 
@@ -533,7 +538,7 @@ def stack_analysis(
     ) -> tuple[list[StackEffect], int]:
         """Analyze a super-instruction or macro.
 
-        Print an error if there's a cache effect (which we don't support yet).
+        Ignore cache effects.
 
         Return the list of variable names and the initial stack pointer.
         """



More information about the Python-checkins mailing list