]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-111485: Factor out tier 2 code generation from the rest of the interpreter code...
authorMark Shannon <mark@hotpy.org>
Tue, 12 Dec 2023 12:12:17 +0000 (12:12 +0000)
committerGitHub <noreply@github.com>
Tue, 12 Dec 2023 12:12:17 +0000 (12:12 +0000)
14 files changed:
Include/internal/pycore_uop_ids.h
Include/opcode_ids.h
Makefile.pre.in
Python/bytecodes.c
Python/executor_cases.c.h
Python/generated_cases.c.h
Tools/cases_generator/analyzer.py
Tools/cases_generator/generate_cases.py
Tools/cases_generator/generators_common.py
Tools/cases_generator/opcode_id_generator.py
Tools/cases_generator/stack.py
Tools/cases_generator/tier1_generator.py
Tools/cases_generator/tier2_generator.py [new file with mode: 0644]
Tools/cases_generator/uop_id_generator.py

index 03e089953698c967aa8d7f18a3cc93777bc35222..c96ea51ae1acb6e0eaad0c7fcf6cc5ac84ab4b38 100644 (file)
@@ -1,6 +1,6 @@
 // This file is generated by Tools/cases_generator/uop_id_generator.py
 // from:
-//   ['./Python/bytecodes.c']
+//   Python/bytecodes.c
 // Do not edit!
 #ifndef Py_CORE_UOP_IDS_H
 #define Py_CORE_UOP_IDS_H
index 47f809e345f61c3531c4d67fb586ef192deffbde..e2e27ca00fd47bfac7347e02154a56043c9a0635 100644 (file)
@@ -1,6 +1,6 @@
 // This file is generated by Tools/cases_generator/opcode_id_generator.py
 // from:
-//   ['./Python/bytecodes.c']
+//   Python/bytecodes.c
 // Do not edit!
 
 #ifndef Py_OPCODE_IDS_H
index 4317c947aeb919219d43d4f0d0869a11d1e789de..5fb6ffc4e8f0cfc89aa995eeb2a464f4a489986a 100644 (file)
@@ -1589,7 +1589,6 @@ regen-cases:
                $(CASESFLAG) \
                -t $(srcdir)/Python/opcode_targets.h.new \
                -m $(srcdir)/Include/internal/pycore_opcode_metadata.h.new \
-               -e $(srcdir)/Python/executor_cases.c.h.new \
                -p $(srcdir)/Lib/_opcode_metadata.py.new \
                -a $(srcdir)/Python/abstract_interp_cases.c.h.new \
                $(srcdir)/Python/bytecodes.c
@@ -1599,6 +1598,8 @@ regen-cases:
            $(srcdir)/Tools/cases_generator/uop_id_generator.py -o $(srcdir)/Include/internal/pycore_uop_ids.h.new $(srcdir)/Python/bytecodes.c
        $(PYTHON_FOR_REGEN) \
            $(srcdir)/Tools/cases_generator/tier1_generator.py -o $(srcdir)/Python/generated_cases.c.h.new $(srcdir)/Python/bytecodes.c
+       $(PYTHON_FOR_REGEN) \
+           $(srcdir)/Tools/cases_generator/tier2_generator.py -o $(srcdir)/Python/executor_cases.c.h.new $(srcdir)/Python/bytecodes.c
        $(UPDATE_FILE) $(srcdir)/Python/generated_cases.c.h $(srcdir)/Python/generated_cases.c.h.new
        $(UPDATE_FILE) $(srcdir)/Include/opcode_ids.h $(srcdir)/Include/opcode_ids.h.new
        $(UPDATE_FILE) $(srcdir)/Include/internal/pycore_uop_ids.h $(srcdir)/Include/internal/pycore_uop_ids.h.new
index bcad8dcf0e7dabcb6b3b5b6fa65013dc6f38fc85..e0f373536ce67cd03b6f19c2919a8dd054038772 100644 (file)
@@ -3967,6 +3967,7 @@ dummy_func(
         }
 
         inst(EXTENDED_ARG, ( -- )) {
+            TIER_ONE_ONLY
             assert(oparg);
             opcode = next_instr->op.code;
             oparg = oparg << 8 | next_instr->op.arg;
@@ -3975,11 +3976,13 @@ dummy_func(
         }
 
         inst(CACHE, (--)) {
+            TIER_ONE_ONLY
             assert(0 && "Executing a cache.");
             Py_UNREACHABLE();
         }
 
         inst(RESERVED, (--)) {
+            TIER_ONE_ONLY
             assert(0 && "Executing RESERVED instruction.");
             Py_UNREACHABLE();
         }
index 974e3f28a411b876952a73c2c40dac5ffe1b28ab..9dda3c9a743258b0fba57dc0286809503358472d 100644 (file)
@@ -1,4 +1,4 @@
-// This file is generated by Tools/cases_generator/generate_cases.py
+// This file is generated by Tools/cases_generator/tier2_generator.py
 // from:
 //   Python/bytecodes.c
 // Do not edit!
 #endif
 #define TIER_TWO 2
 
-        case NOP: {
+        case _NOP: {
             break;
         }
 
-        case RESUME_CHECK: {
-#if defined(__EMSCRIPTEN__)
-            DEOPT_IF(_Py_emscripten_signal_clock == 0, RESUME);
+        case _RESUME_CHECK: {
+            #if defined(__EMSCRIPTEN__)
+            if (_Py_emscripten_signal_clock == 0) goto deoptimize;
             _Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING;
-#endif
+            #endif
             uintptr_t eval_breaker = _Py_atomic_load_uintptr_relaxed(&tstate->interp->ceval.eval_breaker);
             uintptr_t version = _PyFrame_GetCode(frame)->_co_instrumentation_version;
             assert((version & _PY_EVAL_EVENTS_MASK) == 0);
-            DEOPT_IF(eval_breaker != version, RESUME);
+            if (eval_breaker != version) goto deoptimize;
             break;
         }
 
-        case LOAD_FAST_CHECK: {
-            oparg = CURRENT_OPARG();
+        /* _INSTRUMENTED_RESUME is not a viable micro-op for tier 2 */
+
+        case _LOAD_FAST_CHECK: {
             PyObject *value;
+            oparg = CURRENT_OPARG();
             value = GETLOCAL(oparg);
             if (value == NULL) goto unbound_local_error_tier_two;
             Py_INCREF(value);
-            STACK_GROW(1);
-            stack_pointer[-1] = value;
+            stack_pointer[0] = value;
+            stack_pointer += 1;
             break;
         }
 
-        case LOAD_FAST: {
-            oparg = CURRENT_OPARG();
+        case _LOAD_FAST: {
             PyObject *value;
+            oparg = CURRENT_OPARG();
             value = GETLOCAL(oparg);
             assert(value != NULL);
             Py_INCREF(value);
-            STACK_GROW(1);
-            stack_pointer[-1] = value;
+            stack_pointer[0] = value;
+            stack_pointer += 1;
             break;
         }
 
-        case LOAD_FAST_AND_CLEAR: {
-            oparg = CURRENT_OPARG();
+        case _LOAD_FAST_AND_CLEAR: {
             PyObject *value;
+            oparg = CURRENT_OPARG();
             value = GETLOCAL(oparg);
             // do not use SETLOCAL here, it decrefs the old value
             GETLOCAL(oparg) = NULL;
-            STACK_GROW(1);
-            stack_pointer[-1] = value;
+            stack_pointer[0] = value;
+            stack_pointer += 1;
             break;
         }
 
-        case LOAD_CONST: {
-            oparg = CURRENT_OPARG();
+        case _LOAD_CONST: {
             PyObject *value;
+            oparg = CURRENT_OPARG();
             value = GETITEM(FRAME_CO_CONSTS, oparg);
             Py_INCREF(value);
-            STACK_GROW(1);
-            stack_pointer[-1] = value;
+            stack_pointer[0] = value;
+            stack_pointer += 1;
             break;
         }
 
-        case STORE_FAST: {
-            oparg = CURRENT_OPARG();
+        case _STORE_FAST: {
             PyObject *value;
+            oparg = CURRENT_OPARG();
             value = stack_pointer[-1];
             SETLOCAL(oparg, value);
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             break;
         }
 
-        case POP_TOP: {
+        case _POP_TOP: {
             PyObject *value;
             value = stack_pointer[-1];
             Py_DECREF(value);
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             break;
         }
 
-        case PUSH_NULL: {
+        case _PUSH_NULL: {
             PyObject *res;
             res = NULL;
-            STACK_GROW(1);
-            stack_pointer[-1] = res;
+            stack_pointer[0] = res;
+            stack_pointer += 1;
             break;
         }
 
-        case END_SEND: {
+        case _END_SEND: {
             PyObject *value;
             PyObject *receiver;
             value = stack_pointer[-1];
             receiver = stack_pointer[-2];
             Py_DECREF(receiver);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = value;
+            stack_pointer[-2] = value;
+            stack_pointer += -1;
             break;
         }
 
-        case UNARY_NEGATIVE: {
+        case _UNARY_NEGATIVE: {
             PyObject *value;
             PyObject *res;
             value = stack_pointer[-1];
             break;
         }
 
-        case UNARY_NOT: {
+        case _UNARY_NOT: {
             PyObject *value;
             PyObject *res;
             value = stack_pointer[-1];
             break;
         }
 
-        case TO_BOOL_BOOL: {
+        case _TO_BOOL_BOOL: {
             PyObject *value;
             value = stack_pointer[-1];
-            DEOPT_IF(!PyBool_Check(value), TO_BOOL);
+            if (!PyBool_Check(value)) goto deoptimize;
             STAT_INC(TO_BOOL, hit);
             break;
         }
 
-        case TO_BOOL_INT: {
+        case _TO_BOOL_INT: {
             PyObject *value;
             PyObject *res;
             value = stack_pointer[-1];
-            DEOPT_IF(!PyLong_CheckExact(value), TO_BOOL);
+            if (!PyLong_CheckExact(value)) goto deoptimize;
             STAT_INC(TO_BOOL, hit);
             if (_PyLong_IsZero((PyLongObject *)value)) {
                 assert(_Py_IsImmortal(value));
             break;
         }
 
-        case TO_BOOL_LIST: {
+        case _TO_BOOL_LIST: {
             PyObject *value;
             PyObject *res;
             value = stack_pointer[-1];
-            DEOPT_IF(!PyList_CheckExact(value), TO_BOOL);
+            if (!PyList_CheckExact(value)) goto deoptimize;
             STAT_INC(TO_BOOL, hit);
             res = Py_SIZE(value) ? Py_True : Py_False;
             Py_DECREF(value);
             break;
         }
 
-        case TO_BOOL_NONE: {
+        case _TO_BOOL_NONE: {
             PyObject *value;
             PyObject *res;
             value = stack_pointer[-1];
             // This one is a bit weird, because we expect *some* failures:
-            DEOPT_IF(!Py_IsNone(value), TO_BOOL);
+            if (!Py_IsNone(value)) goto deoptimize;
             STAT_INC(TO_BOOL, hit);
             res = Py_False;
             stack_pointer[-1] = res;
             break;
         }
 
-        case TO_BOOL_STR: {
+        case _TO_BOOL_STR: {
             PyObject *value;
             PyObject *res;
             value = stack_pointer[-1];
-            DEOPT_IF(!PyUnicode_CheckExact(value), TO_BOOL);
+            if (!PyUnicode_CheckExact(value)) goto deoptimize;
             STAT_INC(TO_BOOL, hit);
             if (value == &_Py_STR(empty)) {
                 assert(_Py_IsImmortal(value));
             break;
         }
 
-        case TO_BOOL_ALWAYS_TRUE: {
+        case _TO_BOOL_ALWAYS_TRUE: {
             PyObject *value;
             PyObject *res;
             value = stack_pointer[-1];
             uint32_t version = (uint32_t)CURRENT_OPERAND();
             // This one is a bit weird, because we expect *some* failures:
             assert(version);
-            DEOPT_IF(Py_TYPE(value)->tp_version_tag != version, TO_BOOL);
+            if (Py_TYPE(value)->tp_version_tag != version) goto deoptimize;
             STAT_INC(TO_BOOL, hit);
             Py_DECREF(value);
             res = Py_True;
             break;
         }
 
-        case UNARY_INVERT: {
+        case _UNARY_INVERT: {
             PyObject *value;
             PyObject *res;
             value = stack_pointer[-1];
             PyObject *left;
             right = stack_pointer[-1];
             left = stack_pointer[-2];
-            DEOPT_IF(!PyLong_CheckExact(left), _GUARD_BOTH_INT);
-            DEOPT_IF(!PyLong_CheckExact(right), _GUARD_BOTH_INT);
+            if (!PyLong_CheckExact(left)) goto deoptimize;
+            if (!PyLong_CheckExact(right)) goto deoptimize;
             break;
         }
 
             _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
             _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
             if (res == NULL) goto pop_2_error_tier_two;
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             break;
         }
 
             _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
             _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
             if (res == NULL) goto pop_2_error_tier_two;
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             break;
         }
 
             _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
             _Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
             if (res == NULL) goto pop_2_error_tier_two;
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             break;
         }
 
             PyObject *left;
             right = stack_pointer[-1];
             left = stack_pointer[-2];
-            DEOPT_IF(!PyFloat_CheckExact(left), _GUARD_BOTH_FLOAT);
-            DEOPT_IF(!PyFloat_CheckExact(right), _GUARD_BOTH_FLOAT);
+            if (!PyFloat_CheckExact(left)) goto deoptimize;
+            if (!PyFloat_CheckExact(right)) goto deoptimize;
             break;
         }
 
             left = stack_pointer[-2];
             STAT_INC(BINARY_OP, hit);
             double dres =
-                ((PyFloatObject *)left)->ob_fval *
-                ((PyFloatObject *)right)->ob_fval;
+            ((PyFloatObject *)left)->ob_fval *
+            ((PyFloatObject *)right)->ob_fval;
             DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             break;
         }
 
             left = stack_pointer[-2];
             STAT_INC(BINARY_OP, hit);
             double dres =
-                ((PyFloatObject *)left)->ob_fval +
-                ((PyFloatObject *)right)->ob_fval;
+            ((PyFloatObject *)left)->ob_fval +
+            ((PyFloatObject *)right)->ob_fval;
             DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             break;
         }
 
             left = stack_pointer[-2];
             STAT_INC(BINARY_OP, hit);
             double dres =
-                ((PyFloatObject *)left)->ob_fval -
-                ((PyFloatObject *)right)->ob_fval;
+            ((PyFloatObject *)left)->ob_fval -
+            ((PyFloatObject *)right)->ob_fval;
             DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             break;
         }
 
             PyObject *left;
             right = stack_pointer[-1];
             left = stack_pointer[-2];
-            DEOPT_IF(!PyUnicode_CheckExact(left), _GUARD_BOTH_UNICODE);
-            DEOPT_IF(!PyUnicode_CheckExact(right), _GUARD_BOTH_UNICODE);
+            if (!PyUnicode_CheckExact(left)) goto deoptimize;
+            if (!PyUnicode_CheckExact(right)) goto deoptimize;
             break;
         }
 
             _Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);
             _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
             if (res == NULL) goto pop_2_error_tier_two;
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
+            break;
+        }
+
+        case _BINARY_OP_INPLACE_ADD_UNICODE: {
+            PyObject *right;
+            PyObject *left;
+            right = stack_pointer[-1];
+            left = stack_pointer[-2];
+            assert(next_instr->op.code == STORE_FAST);
+            PyObject **target_local = &GETLOCAL(next_instr->op.arg);
+            if (*target_local != left) goto deoptimize;
+            STAT_INC(BINARY_OP, hit);
+            /* Handle `left = left + right` or `left += right` for str.
+             *
+             * When possible, extend `left` in place rather than
+             * allocating a new PyUnicodeObject. This attempts to avoid
+             * quadratic behavior when one neglects to use str.join().
+             *
+             * If `left` has only two references remaining (one from
+             * the stack, one in the locals), DECREFing `left` leaves
+             * only the locals reference, so PyUnicode_Append knows
+             * that the string is safe to mutate.
+             */
+            assert(Py_REFCNT(left) >= 2);
+            _Py_DECREF_NO_DEALLOC(left);
+            PyUnicode_Append(target_local, right);
+            _Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
+            if (*target_local == NULL) goto pop_2_error_tier_two;
+            // The STORE_FAST is already done.
+            assert(next_instr->op.code == STORE_FAST);
+            SKIP_OVER(1);
+            stack_pointer += -2;
             break;
         }
 
             Py_DECREF(container);
             Py_DECREF(sub);
             if (res == NULL) goto pop_2_error_tier_two;
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             break;
         }
 
-        case BINARY_SLICE: {
+        case _BINARY_SLICE: {
             PyObject *stop;
             PyObject *start;
             PyObject *container;
             }
             Py_DECREF(container);
             if (res == NULL) goto pop_3_error_tier_two;
-            STACK_SHRINK(2);
-            stack_pointer[-1] = res;
+            stack_pointer[-3] = res;
+            stack_pointer += -2;
             break;
         }
 
-        case STORE_SLICE: {
+        case _STORE_SLICE: {
             PyObject *stop;
             PyObject *start;
             PyObject *container;
             Py_DECREF(v);
             Py_DECREF(container);
             if (err) goto pop_4_error_tier_two;
-            STACK_SHRINK(4);
+            stack_pointer += -4;
             break;
         }
 
-        case BINARY_SUBSCR_LIST_INT: {
+        case _BINARY_SUBSCR_LIST_INT: {
             PyObject *sub;
             PyObject *list;
             PyObject *res;
             sub = stack_pointer[-1];
             list = stack_pointer[-2];
-            DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR);
-            DEOPT_IF(!PyList_CheckExact(list), BINARY_SUBSCR);
-
+            if (!PyLong_CheckExact(sub)) goto deoptimize;
+            if (!PyList_CheckExact(list)) goto deoptimize;
             // Deopt unless 0 <= sub < PyList_Size(list)
-            DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR);
+            if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) goto deoptimize;
             Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];
-            DEOPT_IF(index >= PyList_GET_SIZE(list), BINARY_SUBSCR);
+            if (index >= PyList_GET_SIZE(list)) goto deoptimize;
             STAT_INC(BINARY_SUBSCR, hit);
             res = PyList_GET_ITEM(list, index);
             assert(res != NULL);
             Py_INCREF(res);
             _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
             Py_DECREF(list);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             break;
         }
 
-        case BINARY_SUBSCR_STR_INT: {
+        case _BINARY_SUBSCR_STR_INT: {
             PyObject *sub;
             PyObject *str;
             PyObject *res;
             sub = stack_pointer[-1];
             str = stack_pointer[-2];
-            DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR);
-            DEOPT_IF(!PyUnicode_CheckExact(str), BINARY_SUBSCR);
-            DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR);
+            if (!PyLong_CheckExact(sub)) goto deoptimize;
+            if (!PyUnicode_CheckExact(str)) goto deoptimize;
+            if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) goto deoptimize;
             Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];
-            DEOPT_IF(PyUnicode_GET_LENGTH(str) <= index, BINARY_SUBSCR);
+            if (PyUnicode_GET_LENGTH(str) <= index) goto deoptimize;
             // Specialize for reading an ASCII character from any string:
             Py_UCS4 c = PyUnicode_READ_CHAR(str, index);
-            DEOPT_IF(Py_ARRAY_LENGTH(_Py_SINGLETON(strings).ascii) <= c, BINARY_SUBSCR);
+            if (Py_ARRAY_LENGTH(_Py_SINGLETON(strings).ascii) <= c) goto deoptimize;
             STAT_INC(BINARY_SUBSCR, hit);
             res = (PyObject*)&_Py_SINGLETON(strings).ascii[c];
             _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
             Py_DECREF(str);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             break;
         }
 
-        case BINARY_SUBSCR_TUPLE_INT: {
+        case _BINARY_SUBSCR_TUPLE_INT: {
             PyObject *sub;
             PyObject *tuple;
             PyObject *res;
             sub = stack_pointer[-1];
             tuple = stack_pointer[-2];
-            DEOPT_IF(!PyLong_CheckExact(sub), BINARY_SUBSCR);
-            DEOPT_IF(!PyTuple_CheckExact(tuple), BINARY_SUBSCR);
-
+            if (!PyLong_CheckExact(sub)) goto deoptimize;
+            if (!PyTuple_CheckExact(tuple)) goto deoptimize;
             // Deopt unless 0 <= sub < PyTuple_Size(list)
-            DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), BINARY_SUBSCR);
+            if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) goto deoptimize;
             Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];
-            DEOPT_IF(index >= PyTuple_GET_SIZE(tuple), BINARY_SUBSCR);
+            if (index >= PyTuple_GET_SIZE(tuple)) goto deoptimize;
             STAT_INC(BINARY_SUBSCR, hit);
             res = PyTuple_GET_ITEM(tuple, index);
             assert(res != NULL);
             Py_INCREF(res);
             _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
             Py_DECREF(tuple);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             break;
         }
 
-        case BINARY_SUBSCR_DICT: {
+        case _BINARY_SUBSCR_DICT: {
             PyObject *sub;
             PyObject *dict;
             PyObject *res;
             sub = stack_pointer[-1];
             dict = stack_pointer[-2];
-            DEOPT_IF(!PyDict_CheckExact(dict), BINARY_SUBSCR);
+            if (!PyDict_CheckExact(dict)) goto deoptimize;
             STAT_INC(BINARY_SUBSCR, hit);
             int rc = PyDict_GetItemRef(dict, sub, &res);
             if (rc == 0) {
             Py_DECREF(dict);
             Py_DECREF(sub);
             if (rc <= 0) goto pop_2_error_tier_two;
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            // not found or error
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             break;
         }
 
-        case LIST_APPEND: {
-            oparg = CURRENT_OPARG();
+        /* _BINARY_SUBSCR_GETITEM is not a viable micro-op for tier 2 */
+
+        case _LIST_APPEND: {
             PyObject *v;
             PyObject *list;
+            oparg = CURRENT_OPARG();
             v = stack_pointer[-1];
             list = stack_pointer[-2 - (oparg-1)];
             if (_PyList_AppendTakeRef((PyListObject *)list, v) < 0) goto pop_1_error_tier_two;
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             break;
         }
 
-        case SET_ADD: {
-            oparg = CURRENT_OPARG();
+        case _SET_ADD: {
             PyObject *v;
             PyObject *set;
+            oparg = CURRENT_OPARG();
             v = stack_pointer[-1];
             set = stack_pointer[-2 - (oparg-1)];
             int err = PySet_Add(set, v);
             Py_DECREF(v);
             if (err) goto pop_1_error_tier_two;
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             break;
         }
 
             Py_DECREF(container);
             Py_DECREF(sub);
             if (err) goto pop_3_error_tier_two;
-            STACK_SHRINK(3);
+            stack_pointer += -3;
             break;
         }
 
-        case STORE_SUBSCR_LIST_INT: {
+        case _STORE_SUBSCR_LIST_INT: {
             PyObject *sub;
             PyObject *list;
             PyObject *value;
             sub = stack_pointer[-1];
             list = stack_pointer[-2];
             value = stack_pointer[-3];
-            DEOPT_IF(!PyLong_CheckExact(sub), STORE_SUBSCR);
-            DEOPT_IF(!PyList_CheckExact(list), STORE_SUBSCR);
-
+            if (!PyLong_CheckExact(sub)) goto deoptimize;
+            if (!PyList_CheckExact(list)) goto deoptimize;
             // Ensure nonnegative, zero-or-one-digit ints.
-            DEOPT_IF(!_PyLong_IsNonNegativeCompact((PyLongObject *)sub), STORE_SUBSCR);
+            if (!_PyLong_IsNonNegativeCompact((PyLongObject *)sub)) goto deoptimize;
             Py_ssize_t index = ((PyLongObject*)sub)->long_value.ob_digit[0];
             // Ensure index < len(list)
-            DEOPT_IF(index >= PyList_GET_SIZE(list), STORE_SUBSCR);
+            if (index >= PyList_GET_SIZE(list)) goto deoptimize;
             STAT_INC(STORE_SUBSCR, hit);
-
             PyObject *old_value = PyList_GET_ITEM(list, index);
             PyList_SET_ITEM(list, index, value);
             assert(old_value != NULL);
             Py_DECREF(old_value);
             _Py_DECREF_SPECIALIZED(sub, (destructor)PyObject_Free);
             Py_DECREF(list);
-            STACK_SHRINK(3);
+            stack_pointer += -3;
             break;
         }
 
-        case STORE_SUBSCR_DICT: {
+        case _STORE_SUBSCR_DICT: {
             PyObject *sub;
             PyObject *dict;
             PyObject *value;
             sub = stack_pointer[-1];
             dict = stack_pointer[-2];
             value = stack_pointer[-3];
-            DEOPT_IF(!PyDict_CheckExact(dict), STORE_SUBSCR);
+            if (!PyDict_CheckExact(dict)) goto deoptimize;
             STAT_INC(STORE_SUBSCR, hit);
             int err = _PyDict_SetItem_Take2((PyDictObject *)dict, sub, value);
             Py_DECREF(dict);
             if (err) goto pop_3_error_tier_two;
-            STACK_SHRINK(3);
+            stack_pointer += -3;
             break;
         }
 
-        case DELETE_SUBSCR: {
+        case _DELETE_SUBSCR: {
             PyObject *sub;
             PyObject *container;
             sub = stack_pointer[-1];
             Py_DECREF(container);
             Py_DECREF(sub);
             if (err) goto pop_2_error_tier_two;
-            STACK_SHRINK(2);
+            stack_pointer += -2;
             break;
         }
 
-        case CALL_INTRINSIC_1: {
-            oparg = CURRENT_OPARG();
+        case _CALL_INTRINSIC_1: {
             PyObject *value;
             PyObject *res;
+            oparg = CURRENT_OPARG();
             value = stack_pointer[-1];
             assert(oparg <= MAX_INTRINSIC_1);
             res = _PyIntrinsics_UnaryFunctions[oparg].func(tstate, value);
             break;
         }
 
-        case CALL_INTRINSIC_2: {
-            oparg = CURRENT_OPARG();
+        case _CALL_INTRINSIC_2: {
             PyObject *value1;
             PyObject *value2;
             PyObject *res;
+            oparg = CURRENT_OPARG();
             value1 = stack_pointer[-1];
             value2 = stack_pointer[-2];
             assert(oparg <= MAX_INTRINSIC_2);
             Py_DECREF(value2);
             Py_DECREF(value1);
             if (res == NULL) goto pop_2_error_tier_two;
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             break;
         }
 
+        case _INTERPRETER_EXIT: {
+            PyObject *retval;
+            retval = stack_pointer[-1];
+            assert(frame == &entry_frame);
+            assert(_PyFrame_IsIncomplete(frame));
+            /* Restore previous frame and return. */
+            tstate->current_frame = frame->previous;
+            assert(!_PyErr_Occurred(tstate));
+            tstate->c_recursion_remaining += PY_EVAL_C_STACK_UNITS;
+            return retval;
+        }
+
         case _POP_FRAME: {
             PyObject *retval;
             retval = stack_pointer[-1];
-            STACK_SHRINK(1);
             #if TIER_ONE
             assert(frame != &entry_frame);
             #endif
-            STORE_SP();
+            stack_pointer += -1;
+            _PyFrame_SetStackPointer(frame, stack_pointer);
             assert(EMPTY());
             _Py_LeaveRecursiveCallPy(tstate);
             // GH-99729: We need to unlink the frame *before* clearing it:
             _PyFrame_StackPush(frame, retval);
             LOAD_SP();
             LOAD_IP(frame->return_offset);
-#if LLTRACE && TIER_ONE
+            #if LLTRACE && TIER_ONE
             lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS());
             if (lltrace < 0) {
                 goto exit_unwind;
             }
-#endif
+            #endif
             break;
         }
 
-        case GET_AITER: {
+        /* _INSTRUMENTED_RETURN_VALUE is not a viable micro-op for tier 2 */
+
+        /* _INSTRUMENTED_RETURN_CONST is not a viable micro-op for tier 2 */
+
+        case _GET_AITER: {
             PyObject *obj;
             PyObject *iter;
             obj = stack_pointer[-1];
             unaryfunc getter = NULL;
             PyTypeObject *type = Py_TYPE(obj);
-
             if (type->tp_as_async != NULL) {
                 getter = type->tp_as_async->am_aiter;
             }
-
             if (getter == NULL) {
                 _PyErr_Format(tstate, PyExc_TypeError,
                               "'async for' requires an object with "
                 Py_DECREF(obj);
                 if (true) goto pop_1_error_tier_two;
             }
-
             iter = (*getter)(obj);
             Py_DECREF(obj);
             if (iter == NULL) goto pop_1_error_tier_two;
-
             if (Py_TYPE(iter)->tp_as_async == NULL ||
-                    Py_TYPE(iter)->tp_as_async->am_anext == NULL) {
-
+                Py_TYPE(iter)->tp_as_async->am_anext == NULL) {
                 _PyErr_Format(tstate, PyExc_TypeError,
                               "'async for' received an object from __aiter__ "
                               "that does not implement __anext__: %.100s",
             break;
         }
 
-        case GET_ANEXT: {
+        case _GET_ANEXT: {
             PyObject *aiter;
             PyObject *awaitable;
             aiter = stack_pointer[-1];
             unaryfunc getter = NULL;
             PyObject *next_iter = NULL;
             PyTypeObject *type = Py_TYPE(aiter);
-
             if (PyAsyncGen_CheckExact(aiter)) {
                 awaitable = type->tp_as_async->am_anext(aiter);
                 if (awaitable == NULL) {
                 if (type->tp_as_async != NULL){
                     getter = type->tp_as_async->am_anext;
                 }
-
                 if (getter != NULL) {
                     next_iter = (*getter)(aiter);
                     if (next_iter == NULL) {
                                   type->tp_name);
                     GOTO_ERROR(error);
                 }
-
                 awaitable = _PyCoro_GetAwaitableIter(next_iter);
                 if (awaitable == NULL) {
                     _PyErr_FormatFromCause(
                         "'async for' received an invalid object "
                         "from __anext__: %.100s",
                         Py_TYPE(next_iter)->tp_name);
-
                     Py_DECREF(next_iter);
                     GOTO_ERROR(error);
                 } else {
                     Py_DECREF(next_iter);
                 }
             }
-            STACK_GROW(1);
-            stack_pointer[-1] = awaitable;
+            stack_pointer[0] = awaitable;
+            stack_pointer += 1;
             break;
         }
 
-        case GET_AWAITABLE: {
-            oparg = CURRENT_OPARG();
+        case _GET_AWAITABLE: {
             PyObject *iterable;
             PyObject *iter;
+            oparg = CURRENT_OPARG();
             iterable = stack_pointer[-1];
             iter = _PyCoro_GetAwaitableIter(iterable);
-
             if (iter == NULL) {
                 _PyEval_FormatAwaitableError(tstate, Py_TYPE(iterable), oparg);
             }
-
             Py_DECREF(iterable);
-
             if (iter != NULL && PyCoro_CheckExact(iter)) {
                 PyObject *yf = _PyGen_yf((PyGenObject*)iter);
                 if (yf != NULL) {
                     /* The code below jumps to `error` if `iter` is NULL. */
                 }
             }
-
             if (iter == NULL) goto pop_1_error_tier_two;
             stack_pointer[-1] = iter;
             break;
         }
 
-        case POP_EXCEPT: {
+        /* _SEND is not a viable micro-op for tier 2 */
+
+        /* _SEND_GEN is not a viable micro-op for tier 2 */
+
+        /* _INSTRUMENTED_YIELD_VALUE is not a viable micro-op for tier 2 */
+
+        case _YIELD_VALUE: {
+            PyObject *retval;
+            oparg = CURRENT_OPARG();
+            retval = stack_pointer[-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(frame != &entry_frame);
+            frame->instr_ptr = next_instr;
+            PyGenObject *gen = _PyFrame_GetGenerator(frame);
+            assert(FRAME_SUSPENDED_YIELD_FROM == FRAME_SUSPENDED + 1);
+            assert(oparg == 0 || oparg == 1);
+            gen->gi_frame_state = FRAME_SUSPENDED + oparg;
+            _PyFrame_SetStackPointer(frame, stack_pointer - 1);
+            tstate->exc_info = gen->gi_exc_state.previous_item;
+            gen->gi_exc_state.previous_item = NULL;
+            _Py_LeaveRecursiveCallPy(tstate);
+            _PyInterpreterFrame *gen_frame = frame;
+            frame = tstate->current_frame = frame->previous;
+            gen_frame->previous = NULL;
+            _PyFrame_StackPush(frame, retval);
+            /* We don't know which of these is relevant here, so keep them equal */
+            assert(INLINE_CACHE_ENTRIES_SEND == INLINE_CACHE_ENTRIES_FOR_ITER);
+            LOAD_IP(1 + INLINE_CACHE_ENTRIES_SEND);
+            goto resume_frame;
+        }
+
+        case _POP_EXCEPT: {
             PyObject *exc_value;
             exc_value = stack_pointer[-1];
             _PyErr_StackItem *exc_info = tstate->exc_info;
             Py_XSETREF(exc_info->exc_value, exc_value);
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             break;
         }
 
-        case LOAD_ASSERTION_ERROR: {
+        case _LOAD_ASSERTION_ERROR: {
             PyObject *value;
             value = Py_NewRef(PyExc_AssertionError);
-            STACK_GROW(1);
-            stack_pointer[-1] = value;
+            stack_pointer[0] = value;
+            stack_pointer += 1;
             break;
         }
 
-        case LOAD_BUILD_CLASS: {
+        case _LOAD_BUILD_CLASS: {
             PyObject *bc;
             if (PyMapping_GetOptionalItem(BUILTINS(), &_Py_ID(__build_class__), &bc) < 0) goto error_tier_two;
             if (bc == NULL) {
                                  "__build_class__ not found");
                 if (true) goto error_tier_two;
             }
-            STACK_GROW(1);
-            stack_pointer[-1] = bc;
+            stack_pointer[0] = bc;
+            stack_pointer += 1;
             break;
         }
 
-        case STORE_NAME: {
-            oparg = CURRENT_OPARG();
+        case _STORE_NAME: {
             PyObject *v;
+            oparg = CURRENT_OPARG();
             v = stack_pointer[-1];
             PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
             PyObject *ns = LOCALS();
                 if (true) goto pop_1_error_tier_two;
             }
             if (PyDict_CheckExact(ns))
-                err = PyDict_SetItem(ns, name, v);
+            err = PyDict_SetItem(ns, name, v);
             else
-                err = PyObject_SetItem(ns, name, v);
+            err = PyObject_SetItem(ns, name, v);
             Py_DECREF(v);
             if (err) goto pop_1_error_tier_two;
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             break;
         }
 
-        case DELETE_NAME: {
+        case _DELETE_NAME: {
             oparg = CURRENT_OPARG();
             PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
             PyObject *ns = LOCALS();
             // Can't use ERROR_IF here.
             if (err != 0) {
                 _PyEval_FormatExcCheckArg(tstate, PyExc_NameError,
-                                          NAME_ERROR_MSG,
-                                          name);
+                    NAME_ERROR_MSG,
+                    name);
                 GOTO_ERROR(error);
             }
             break;
         }
 
         case _UNPACK_SEQUENCE: {
-            oparg = CURRENT_OPARG();
             PyObject *seq;
+            oparg = CURRENT_OPARG();
             seq = stack_pointer[-1];
             PyObject **top = stack_pointer + oparg - 1;
             int res = _PyEval_UnpackIterable(tstate, seq, oparg, -1, top);
             Py_DECREF(seq);
             if (res == 0) goto pop_1_error_tier_two;
-            STACK_SHRINK(1);
-            STACK_GROW(oparg);
+            stack_pointer += -1 + oparg;
             break;
         }
 
-        case UNPACK_SEQUENCE_TWO_TUPLE: {
-            oparg = CURRENT_OPARG();
+        case _UNPACK_SEQUENCE_TWO_TUPLE: {
             PyObject *seq;
             PyObject **values;
+            oparg = CURRENT_OPARG();
             seq = stack_pointer[-1];
-            values = stack_pointer - 1;
-            DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE);
-            DEOPT_IF(PyTuple_GET_SIZE(seq) != 2, UNPACK_SEQUENCE);
+            values = &stack_pointer[-1];
+            if (!PyTuple_CheckExact(seq)) goto deoptimize;
+            if (PyTuple_GET_SIZE(seq) != 2) goto deoptimize;
             assert(oparg == 2);
             STAT_INC(UNPACK_SEQUENCE, hit);
             values[0] = Py_NewRef(PyTuple_GET_ITEM(seq, 1));
             values[1] = Py_NewRef(PyTuple_GET_ITEM(seq, 0));
             Py_DECREF(seq);
-            STACK_SHRINK(1);
-            STACK_GROW(oparg);
+            stack_pointer += -1 + oparg;
             break;
         }
 
-        case UNPACK_SEQUENCE_TUPLE: {
-            oparg = CURRENT_OPARG();
+        case _UNPACK_SEQUENCE_TUPLE: {
             PyObject *seq;
             PyObject **values;
+            oparg = CURRENT_OPARG();
             seq = stack_pointer[-1];
-            values = stack_pointer - 1;
-            DEOPT_IF(!PyTuple_CheckExact(seq), UNPACK_SEQUENCE);
-            DEOPT_IF(PyTuple_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE);
+            values = &stack_pointer[-1];
+            if (!PyTuple_CheckExact(seq)) goto deoptimize;
+            if (PyTuple_GET_SIZE(seq) != oparg) goto deoptimize;
             STAT_INC(UNPACK_SEQUENCE, hit);
             PyObject **items = _PyTuple_ITEMS(seq);
             for (int i = oparg; --i >= 0; ) {
                 *values++ = Py_NewRef(items[i]);
             }
             Py_DECREF(seq);
-            STACK_SHRINK(1);
-            STACK_GROW(oparg);
+            stack_pointer += -1 + oparg;
             break;
         }
 
-        case UNPACK_SEQUENCE_LIST: {
-            oparg = CURRENT_OPARG();
+        case _UNPACK_SEQUENCE_LIST: {
             PyObject *seq;
             PyObject **values;
+            oparg = CURRENT_OPARG();
             seq = stack_pointer[-1];
-            values = stack_pointer - 1;
-            DEOPT_IF(!PyList_CheckExact(seq), UNPACK_SEQUENCE);
-            DEOPT_IF(PyList_GET_SIZE(seq) != oparg, UNPACK_SEQUENCE);
+            values = &stack_pointer[-1];
+            if (!PyList_CheckExact(seq)) goto deoptimize;
+            if (PyList_GET_SIZE(seq) != oparg) goto deoptimize;
             STAT_INC(UNPACK_SEQUENCE, hit);
             PyObject **items = _PyList_ITEMS(seq);
             for (int i = oparg; --i >= 0; ) {
                 *values++ = Py_NewRef(items[i]);
             }
             Py_DECREF(seq);
-            STACK_SHRINK(1);
-            STACK_GROW(oparg);
+            stack_pointer += -1 + oparg;
             break;
         }
 
-        case UNPACK_EX: {
-            oparg = CURRENT_OPARG();
+        case _UNPACK_EX: {
             PyObject *seq;
+            oparg = CURRENT_OPARG();
             seq = stack_pointer[-1];
             int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8);
             PyObject **top = stack_pointer + totalargs - 1;
             int res = _PyEval_UnpackIterable(tstate, seq, oparg & 0xFF, oparg >> 8, top);
             Py_DECREF(seq);
             if (res == 0) goto pop_1_error_tier_two;
-            STACK_GROW((oparg & 0xFF) + (oparg >> 8));
+            stack_pointer += (oparg >> 8) + (oparg & 0xFF);
             break;
         }
 
         case _STORE_ATTR: {
-            oparg = CURRENT_OPARG();
             PyObject *owner;
             PyObject *v;
+            oparg = CURRENT_OPARG();
             owner = stack_pointer[-1];
             v = stack_pointer[-2];
             PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
             Py_DECREF(v);
             Py_DECREF(owner);
             if (err) goto pop_2_error_tier_two;
-            STACK_SHRINK(2);
+            stack_pointer += -2;
             break;
         }
 
-        case DELETE_ATTR: {
-            oparg = CURRENT_OPARG();
+        case _DELETE_ATTR: {
             PyObject *owner;
+            oparg = CURRENT_OPARG();
             owner = stack_pointer[-1];
             PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
             int err = PyObject_DelAttr(owner, name);
             Py_DECREF(owner);
             if (err) goto pop_1_error_tier_two;
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             break;
         }
 
-        case STORE_GLOBAL: {
-            oparg = CURRENT_OPARG();
+        case _STORE_GLOBAL: {
             PyObject *v;
+            oparg = CURRENT_OPARG();
             v = stack_pointer[-1];
             PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
             int err = PyDict_SetItem(GLOBALS(), name, v);
             Py_DECREF(v);
             if (err) goto pop_1_error_tier_two;
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             break;
         }
 
-        case DELETE_GLOBAL: {
+        case _DELETE_GLOBAL: {
             oparg = CURRENT_OPARG();
             PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
             int err;
             if (err != 0) {
                 if (_PyErr_ExceptionMatches(tstate, PyExc_KeyError)) {
                     _PyEval_FormatExcCheckArg(tstate, PyExc_NameError,
-                                              NAME_ERROR_MSG, name);
+                        NAME_ERROR_MSG, name);
                 }
                 GOTO_ERROR(error);
             }
             break;
         }
 
-        case LOAD_LOCALS: {
+        case _LOAD_LOCALS: {
             PyObject *locals;
             locals = LOCALS();
             if (locals == NULL) {
                 if (true) goto error_tier_two;
             }
             Py_INCREF(locals);
-            STACK_GROW(1);
-            stack_pointer[-1] = locals;
+            stack_pointer[0] = locals;
+            stack_pointer += 1;
             break;
         }
 
-        case LOAD_FROM_DICT_OR_GLOBALS: {
-            oparg = CURRENT_OPARG();
+        case _LOAD_FROM_DICT_OR_GLOBALS: {
             PyObject *mod_or_class_dict;
             PyObject *v;
+            oparg = CURRENT_OPARG();
             mod_or_class_dict = stack_pointer[-1];
             PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
             if (PyMapping_GetOptionalItem(mod_or_class_dict, name, &v) < 0) {
                     }
                     if (v == NULL) {
                         _PyEval_FormatExcCheckArg(
-                                    tstate, PyExc_NameError,
-                                    NAME_ERROR_MSG, name);
+                            tstate, PyExc_NameError,
+                            NAME_ERROR_MSG, name);
                         GOTO_ERROR(error);
                     }
                 }
             break;
         }
 
-        case LOAD_NAME: {
-            oparg = CURRENT_OPARG();
+        case _LOAD_NAME: {
             PyObject *v;
+            oparg = CURRENT_OPARG();
             PyObject *mod_or_class_dict = LOCALS();
             if (mod_or_class_dict == NULL) {
                 _PyErr_SetString(tstate, PyExc_SystemError,
                     }
                     if (v == NULL) {
                         _PyEval_FormatExcCheckArg(
-                                    tstate, PyExc_NameError,
-                                    NAME_ERROR_MSG, name);
+                            tstate, PyExc_NameError,
+                            NAME_ERROR_MSG, name);
                         GOTO_ERROR(error);
                     }
                 }
             }
-            STACK_GROW(1);
-            stack_pointer[-1] = v;
+            stack_pointer[0] = v;
+            stack_pointer += 1;
             break;
         }
 
         case _LOAD_GLOBAL: {
-            oparg = CURRENT_OPARG();
             PyObject *res;
             PyObject *null = NULL;
+            oparg = CURRENT_OPARG();
             PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
             if (PyDict_CheckExact(GLOBALS())
                 && PyDict_CheckExact(BUILTINS()))
             {
                 res = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(),
-                                         (PyDictObject *)BUILTINS(),
-                                         name);
+                    (PyDictObject *)BUILTINS(),
+                    name);
                 if (res == NULL) {
                     if (!_PyErr_Occurred(tstate)) {
                         /* _PyDict_LoadGlobal() returns NULL without raising
                          * an exception if the key doesn't exist */
                         _PyEval_FormatExcCheckArg(tstate, PyExc_NameError,
-                                                  NAME_ERROR_MSG, name);
+                            NAME_ERROR_MSG, name);
                     }
                     if (true) goto error_tier_two;
                 }
                     if (PyMapping_GetOptionalItem(BUILTINS(), name, &res) < 0) goto error_tier_two;
                     if (res == NULL) {
                         _PyEval_FormatExcCheckArg(
-                                    tstate, PyExc_NameError,
-                                    NAME_ERROR_MSG, name);
+                            tstate, PyExc_NameError,
+                            NAME_ERROR_MSG, name);
                         if (true) goto error_tier_two;
                     }
                 }
             }
             null = NULL;
-            STACK_GROW(1);
-            STACK_GROW(((oparg & 1) ? 1 : 0));
-            stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = res;
-            if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
+            stack_pointer[0] = res;
+             if (oparg & 1) stack_pointer[1] = null;
+            stack_pointer += 1 + ((oparg & 1));
             break;
         }
 
         case _GUARD_GLOBALS_VERSION: {
             uint16_t version = (uint16_t)CURRENT_OPERAND();
             PyDictObject *dict = (PyDictObject *)GLOBALS();
-            DEOPT_IF(!PyDict_CheckExact(dict), _GUARD_GLOBALS_VERSION);
-            DEOPT_IF(dict->ma_keys->dk_version != version, _GUARD_GLOBALS_VERSION);
+            if (!PyDict_CheckExact(dict)) goto deoptimize;
+            if (dict->ma_keys->dk_version != version) goto deoptimize;
             assert(DK_IS_UNICODE(dict->ma_keys));
             break;
         }
         case _GUARD_BUILTINS_VERSION: {
             uint16_t version = (uint16_t)CURRENT_OPERAND();
             PyDictObject *dict = (PyDictObject *)BUILTINS();
-            DEOPT_IF(!PyDict_CheckExact(dict), _GUARD_BUILTINS_VERSION);
-            DEOPT_IF(dict->ma_keys->dk_version != version, _GUARD_BUILTINS_VERSION);
+            if (!PyDict_CheckExact(dict)) goto deoptimize;
+            if (dict->ma_keys->dk_version != version) goto deoptimize;
             assert(DK_IS_UNICODE(dict->ma_keys));
             break;
         }
 
         case _LOAD_GLOBAL_MODULE: {
-            oparg = CURRENT_OPARG();
             PyObject *res;
             PyObject *null = NULL;
+            oparg = CURRENT_OPARG();
             uint16_t index = (uint16_t)CURRENT_OPERAND();
             PyDictObject *dict = (PyDictObject *)GLOBALS();
             PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(dict->ma_keys);
             res = entries[index].me_value;
-            DEOPT_IF(res == NULL, _LOAD_GLOBAL_MODULE);
+            if (res == NULL) goto deoptimize;
             Py_INCREF(res);
             STAT_INC(LOAD_GLOBAL, hit);
             null = NULL;
-            STACK_GROW(1);
-            STACK_GROW(((oparg & 1) ? 1 : 0));
-            stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = res;
-            if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
+            stack_pointer[0] = res;
+             if (oparg & 1) stack_pointer[1] = null;
+            stack_pointer += 1 + ((oparg & 1));
             break;
         }
 
         case _LOAD_GLOBAL_BUILTINS: {
-            oparg = CURRENT_OPARG();
             PyObject *res;
             PyObject *null = NULL;
+            oparg = CURRENT_OPARG();
             uint16_t index = (uint16_t)CURRENT_OPERAND();
             PyDictObject *bdict = (PyDictObject *)BUILTINS();
             PyDictUnicodeEntry *entries = DK_UNICODE_ENTRIES(bdict->ma_keys);
             res = entries[index].me_value;
-            DEOPT_IF(res == NULL, _LOAD_GLOBAL_BUILTINS);
+            if (res == NULL) goto deoptimize;
             Py_INCREF(res);
             STAT_INC(LOAD_GLOBAL, hit);
             null = NULL;
-            STACK_GROW(1);
-            STACK_GROW(((oparg & 1) ? 1 : 0));
-            stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = res;
-            if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
+            stack_pointer[0] = res;
+             if (oparg & 1) stack_pointer[1] = null;
+            stack_pointer += 1 + ((oparg & 1));
             break;
         }
 
-        case DELETE_FAST: {
+        case _DELETE_FAST: {
             oparg = CURRENT_OPARG();
             PyObject *v = GETLOCAL(oparg);
             if (v == NULL) goto unbound_local_error_tier_two;
             break;
         }
 
-        case MAKE_CELL: {
+        case _MAKE_CELL: {
             oparg = CURRENT_OPARG();
             // "initial" is probably NULL but not if it's an arg (or set
             // via PyFrame_LocalsToFast() before MAKE_CELL has run).
             break;
         }
 
-        case DELETE_DEREF: {
+        case _DELETE_DEREF: {
             oparg = CURRENT_OPARG();
             PyObject *cell = GETLOCAL(oparg);
             PyObject *oldobj = PyCell_GET(cell);
             break;
         }
 
-        case LOAD_FROM_DICT_OR_DEREF: {
-            oparg = CURRENT_OPARG();
+        case _LOAD_FROM_DICT_OR_DEREF: {
             PyObject *class_dict;
             PyObject *value;
+            oparg = CURRENT_OPARG();
             class_dict = stack_pointer[-1];
             PyObject *name;
             assert(class_dict);
             break;
         }
 
-        case LOAD_DEREF: {
-            oparg = CURRENT_OPARG();
+        case _LOAD_DEREF: {
             PyObject *value;
+            oparg = CURRENT_OPARG();
             PyObject *cell = GETLOCAL(oparg);
             value = PyCell_GET(cell);
             if (value == NULL) {
                 if (true) goto error_tier_two;
             }
             Py_INCREF(value);
-            STACK_GROW(1);
-            stack_pointer[-1] = value;
+            stack_pointer[0] = value;
+            stack_pointer += 1;
             break;
         }
 
-        case STORE_DEREF: {
-            oparg = CURRENT_OPARG();
+        case _STORE_DEREF: {
             PyObject *v;
+            oparg = CURRENT_OPARG();
             v = stack_pointer[-1];
             PyObject *cell = GETLOCAL(oparg);
             PyObject *oldobj = PyCell_GET(cell);
             PyCell_SET(cell, v);
             Py_XDECREF(oldobj);
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             break;
         }
 
-        case COPY_FREE_VARS: {
+        case _COPY_FREE_VARS: {
             oparg = CURRENT_OPARG();
             /* Copy closure variables to free variables */
             PyCodeObject *co = _PyFrame_GetCode(frame);
             break;
         }
 
-        case BUILD_STRING: {
-            oparg = CURRENT_OPARG();
+        case _BUILD_STRING: {
             PyObject **pieces;
             PyObject *str;
-            pieces = stack_pointer - oparg;
+            oparg = CURRENT_OPARG();
+            pieces = &stack_pointer[-oparg];
             str = _PyUnicode_JoinArray(&_Py_STR(empty), pieces, oparg);
             for (int _i = oparg; --_i >= 0;) {
                 Py_DECREF(pieces[_i]);
             }
-            if (str == NULL) { STACK_SHRINK(oparg); goto error_tier_two; }
-            STACK_SHRINK(oparg);
-            STACK_GROW(1);
-            stack_pointer[-1] = str;
+            if (str == NULL) { stack_pointer += -oparg; goto error_tier_two; }
+            stack_pointer[-oparg] = str;
+            stack_pointer += 1 - oparg;
             break;
         }
 
-        case BUILD_TUPLE: {
-            oparg = CURRENT_OPARG();
+        case _BUILD_TUPLE: {
             PyObject **values;
             PyObject *tup;
-            values = stack_pointer - oparg;
+            oparg = CURRENT_OPARG();
+            values = &stack_pointer[-oparg];
             tup = _PyTuple_FromArraySteal(values, oparg);
-            if (tup == NULL) { STACK_SHRINK(oparg); goto error_tier_two; }
-            STACK_SHRINK(oparg);
-            STACK_GROW(1);
-            stack_pointer[-1] = tup;
+            if (tup == NULL) { stack_pointer += -oparg; goto error_tier_two; }
+            stack_pointer[-oparg] = tup;
+            stack_pointer += 1 - oparg;
             break;
         }
 
-        case BUILD_LIST: {
-            oparg = CURRENT_OPARG();
+        case _BUILD_LIST: {
             PyObject **values;
             PyObject *list;
-            values = stack_pointer - oparg;
+            oparg = CURRENT_OPARG();
+            values = &stack_pointer[-oparg];
             list = _PyList_FromArraySteal(values, oparg);
-            if (list == NULL) { STACK_SHRINK(oparg); goto error_tier_two; }
-            STACK_SHRINK(oparg);
-            STACK_GROW(1);
-            stack_pointer[-1] = list;
+            if (list == NULL) { stack_pointer += -oparg; goto error_tier_two; }
+            stack_pointer[-oparg] = list;
+            stack_pointer += 1 - oparg;
             break;
         }
 
-        case LIST_EXTEND: {
-            oparg = CURRENT_OPARG();
+        case _LIST_EXTEND: {
             PyObject *iterable;
             PyObject *list;
+            oparg = CURRENT_OPARG();
             iterable = stack_pointer[-1];
             list = stack_pointer[-2 - (oparg-1)];
             PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable);
             if (none_val == NULL) {
                 if (_PyErr_ExceptionMatches(tstate, PyExc_TypeError) &&
-                   (Py_TYPE(iterable)->tp_iter == NULL && !PySequence_Check(iterable)))
+                    (Py_TYPE(iterable)->tp_iter == NULL && !PySequence_Check(iterable)))
                 {
                     _PyErr_Clear(tstate);
                     _PyErr_Format(tstate, PyExc_TypeError,
-                          "Value after * must be an iterable, not %.200s",
-                          Py_TYPE(iterable)->tp_name);
+                                  "Value after * must be an iterable, not %.200s",
+                                  Py_TYPE(iterable)->tp_name);
                 }
                 Py_DECREF(iterable);
                 if (true) goto pop_1_error_tier_two;
             }
             assert(Py_IsNone(none_val));
             Py_DECREF(iterable);
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             break;
         }
 
-        case SET_UPDATE: {
-            oparg = CURRENT_OPARG();
+        case _SET_UPDATE: {
             PyObject *iterable;
             PyObject *set;
+            oparg = CURRENT_OPARG();
             iterable = stack_pointer[-1];
             set = stack_pointer[-2 - (oparg-1)];
             int err = _PySet_Update(set, iterable);
             Py_DECREF(iterable);
             if (err < 0) goto pop_1_error_tier_two;
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             break;
         }
 
-        case BUILD_SET: {
-            oparg = CURRENT_OPARG();
+        case _BUILD_SET: {
             PyObject **values;
             PyObject *set;
-            values = stack_pointer - oparg;
+            oparg = CURRENT_OPARG();
+            values = &stack_pointer[-oparg];
             set = PySet_New(NULL);
             if (set == NULL)
-                GOTO_ERROR(error);
+            GOTO_ERROR(error);
             int err = 0;
             for (int i = 0; i < oparg; i++) {
                 PyObject *item = values[i];
                 if (err == 0)
-                    err = PySet_Add(set, item);
+                err = PySet_Add(set, item);
                 Py_DECREF(item);
             }
             if (err != 0) {
                 Py_DECREF(set);
-                if (true) { STACK_SHRINK(oparg); goto error_tier_two; }
+                if (true) { stack_pointer += -oparg; goto error_tier_two; }
             }
-            STACK_SHRINK(oparg);
-            STACK_GROW(1);
-            stack_pointer[-1] = set;
+            stack_pointer[-oparg] = set;
+            stack_pointer += 1 - oparg;
             break;
         }
 
-        case BUILD_MAP: {
-            oparg = CURRENT_OPARG();
+        case _BUILD_MAP: {
             PyObject **values;
             PyObject *map;
-            values = stack_pointer - oparg*2;
+            oparg = CURRENT_OPARG();
+            values = &stack_pointer[-oparg*2];
             map = _PyDict_FromItems(
-                    values, 2,
-                    values+1, 2,
-                    oparg);
+                                    values, 2,
+                                    values+1, 2,
+                                    oparg);
             for (int _i = oparg*2; --_i >= 0;) {
                 Py_DECREF(values[_i]);
             }
-            if (map == NULL) { STACK_SHRINK(oparg*2); goto error_tier_two; }
-            STACK_SHRINK(oparg*2);
-            STACK_GROW(1);
-            stack_pointer[-1] = map;
+            if (map == NULL) { stack_pointer += -oparg*2; goto error_tier_two; }
+            stack_pointer[-oparg*2] = map;
+            stack_pointer += 1 - oparg*2;
             break;
         }
 
-        case SETUP_ANNOTATIONS: {
+        case _SETUP_ANNOTATIONS: {
             int err;
             PyObject *ann_dict;
             if (LOCALS() == NULL) {
             break;
         }
 
-        case BUILD_CONST_KEY_MAP: {
-            oparg = CURRENT_OPARG();
+        case _BUILD_CONST_KEY_MAP: {
             PyObject *keys;
             PyObject **values;
             PyObject *map;
+            oparg = CURRENT_OPARG();
             keys = stack_pointer[-1];
-            values = stack_pointer - 1 - oparg;
+            values = &stack_pointer[-1 - oparg];
             if (!PyTuple_CheckExact(keys) ||
                 PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) {
                 _PyErr_SetString(tstate, PyExc_SystemError,
                 GOTO_ERROR(error);  // Pop the keys and values.
             }
             map = _PyDict_FromItems(
-                    &PyTuple_GET_ITEM(keys, 0), 1,
-                    values, 1, oparg);
+                                    &PyTuple_GET_ITEM(keys, 0), 1,
+                                    values, 1, oparg);
             for (int _i = oparg; --_i >= 0;) {
                 Py_DECREF(values[_i]);
             }
             Py_DECREF(keys);
-            if (map == NULL) { STACK_SHRINK(oparg); goto pop_1_error_tier_two; }
-            STACK_SHRINK(oparg);
-            stack_pointer[-1] = map;
+            if (map == NULL) { stack_pointer += -1 - oparg; goto error_tier_two; }
+            stack_pointer[-1 - oparg] = map;
+            stack_pointer += -oparg;
             break;
         }
 
-        case DICT_UPDATE: {
-            oparg = CURRENT_OPARG();
+        case _DICT_UPDATE: {
             PyObject *update;
             PyObject *dict;
+            oparg = CURRENT_OPARG();
             update = stack_pointer[-1];
             dict = stack_pointer[-2 - (oparg - 1)];
             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);
+                                  "'%.200s' object is not a mapping",
+                                  Py_TYPE(update)->tp_name);
                 }
                 Py_DECREF(update);
                 if (true) goto pop_1_error_tier_two;
             }
             Py_DECREF(update);
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             break;
         }
 
-        case DICT_MERGE: {
-            oparg = CURRENT_OPARG();
+        case _DICT_MERGE: {
             PyObject *update;
             PyObject *dict;
             PyObject *callable;
+            oparg = CURRENT_OPARG();
             update = stack_pointer[-1];
             dict = stack_pointer[-2 - (oparg - 1)];
             callable = stack_pointer[-5 - (oparg - 1)];
                 if (true) goto pop_1_error_tier_two;
             }
             Py_DECREF(update);
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             break;
         }
 
-        case MAP_ADD: {
-            oparg = CURRENT_OPARG();
+        case _MAP_ADD: {
             PyObject *value;
             PyObject *key;
             PyObject *dict;
+            oparg = CURRENT_OPARG();
             value = stack_pointer[-1];
             key = stack_pointer[-2];
             dict = stack_pointer[-3 - (oparg - 1)];
             /* 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_tier_two;
-            STACK_SHRINK(2);
+            stack_pointer += -2;
             break;
         }
 
-        case LOAD_SUPER_ATTR_ATTR: {
-            oparg = CURRENT_OPARG();
+        /* _INSTRUMENTED_LOAD_SUPER_ATTR is not a viable micro-op for tier 2 */
+
+        case _LOAD_SUPER_ATTR_ATTR: {
             PyObject *self;
             PyObject *class;
             PyObject *global_super;
             PyObject *attr;
+            oparg = CURRENT_OPARG();
             self = stack_pointer[-1];
             class = stack_pointer[-2];
             global_super = stack_pointer[-3];
             assert(!(oparg & 1));
-            DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);
-            DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR);
+            if (global_super != (PyObject *)&PySuper_Type) goto deoptimize;
+            if (!PyType_Check(class)) goto deoptimize;
             STAT_INC(LOAD_SUPER_ATTR, hit);
             PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
             attr = _PySuper_Lookup((PyTypeObject *)class, self, name, NULL);
             Py_DECREF(class);
             Py_DECREF(self);
             if (attr == NULL) goto pop_3_error_tier_two;
-            STACK_SHRINK(2);
-            stack_pointer[-1] = attr;
+            stack_pointer[-3] = attr;
+            stack_pointer += -2 + (((0) ? 1 : 0));
             break;
         }
 
-        case LOAD_SUPER_ATTR_METHOD: {
-            oparg = CURRENT_OPARG();
+        case _LOAD_SUPER_ATTR_METHOD: {
             PyObject *self;
             PyObject *class;
             PyObject *global_super;
             PyObject *attr;
             PyObject *self_or_null;
+            oparg = CURRENT_OPARG();
             self = stack_pointer[-1];
             class = stack_pointer[-2];
             global_super = stack_pointer[-3];
             assert(oparg & 1);
-            DEOPT_IF(global_super != (PyObject *)&PySuper_Type, LOAD_SUPER_ATTR);
-            DEOPT_IF(!PyType_Check(class), LOAD_SUPER_ATTR);
+            if (global_super != (PyObject *)&PySuper_Type) goto deoptimize;
+            if (!PyType_Check(class)) goto deoptimize;
             STAT_INC(LOAD_SUPER_ATTR, hit);
             PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 2);
             PyTypeObject *cls = (PyTypeObject *)class;
                 Py_DECREF(self);
                 self_or_null = NULL;
             }
-            STACK_SHRINK(1);
-            stack_pointer[-2] = attr;
-            stack_pointer[-1] = self_or_null;
+            stack_pointer[-3] = attr;
+            stack_pointer[-2] = self_or_null;
+            stack_pointer += -1;
             break;
         }
 
         case _LOAD_ATTR: {
-            oparg = CURRENT_OPARG();
             PyObject *owner;
             PyObject *attr;
             PyObject *self_or_null = NULL;
+            oparg = CURRENT_OPARG();
             owner = stack_pointer[-1];
             PyObject *name = GETITEM(FRAME_CO_NAMES, oparg >> 1);
             if (oparg & 1) {
                        the second element of the stack to NULL, to signal
                        CALL that it's not a method call.
                        NULL | meth | arg1 | ... | argN
-                    */
+                     */
                     Py_DECREF(owner);
                     if (attr == NULL) goto pop_1_error_tier_two;
                     self_or_null = NULL;
                 Py_DECREF(owner);
                 if (attr == NULL) goto pop_1_error_tier_two;
             }
-            STACK_GROW(((oparg & 1) ? 1 : 0));
-            stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
-            if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = self_or_null; }
+            stack_pointer[-1] = attr;
+             if (oparg & 1) stack_pointer[0] = self_or_null;
+            stack_pointer += ((oparg & 1));
             break;
         }
 
             uint32_t type_version = (uint32_t)CURRENT_OPERAND();
             PyTypeObject *tp = Py_TYPE(owner);
             assert(type_version != 0);
-            DEOPT_IF(tp->tp_version_tag != type_version, _GUARD_TYPE_VERSION);
+            if (tp->tp_version_tag != type_version) goto deoptimize;
             break;
         }
 
             assert(Py_TYPE(owner)->tp_dictoffset < 0);
             assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
             PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
-            DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv), _CHECK_MANAGED_OBJECT_HAS_VALUES);
+            if (!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv)) goto deoptimize;
             break;
         }
 
         case _LOAD_ATTR_INSTANCE_VALUE: {
-            oparg = CURRENT_OPARG();
             PyObject *owner;
             PyObject *attr;
             PyObject *null = NULL;
+            oparg = CURRENT_OPARG();
             owner = stack_pointer[-1];
             uint16_t index = (uint16_t)CURRENT_OPERAND();
             PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
             attr = _PyDictOrValues_GetValues(dorv)->values[index];
-            DEOPT_IF(attr == NULL, _LOAD_ATTR_INSTANCE_VALUE);
+            if (attr == NULL) goto deoptimize;
             STAT_INC(LOAD_ATTR, hit);
             Py_INCREF(attr);
             null = NULL;
             Py_DECREF(owner);
-            STACK_GROW(((oparg & 1) ? 1 : 0));
-            stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
-            if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
+            stack_pointer[-1] = attr;
+             if (oparg & 1) stack_pointer[0] = null;
+            stack_pointer += ((oparg & 1));
             break;
         }
 
             PyObject *owner;
             owner = stack_pointer[-1];
             uint32_t type_version = (uint32_t)CURRENT_OPERAND();
-            DEOPT_IF(!PyModule_CheckExact(owner), _CHECK_ATTR_MODULE);
+            if (!PyModule_CheckExact(owner)) goto deoptimize;
             PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
             assert(dict != NULL);
-            DEOPT_IF(dict->ma_keys->dk_version != type_version, _CHECK_ATTR_MODULE);
+            if (dict->ma_keys->dk_version != type_version) goto deoptimize;
             break;
         }
 
         case _LOAD_ATTR_MODULE: {
-            oparg = CURRENT_OPARG();
             PyObject *owner;
             PyObject *attr;
             PyObject *null = NULL;
+            oparg = CURRENT_OPARG();
             owner = stack_pointer[-1];
             uint16_t index = (uint16_t)CURRENT_OPERAND();
             PyDictObject *dict = (PyDictObject *)((PyModuleObject *)owner)->md_dict;
             assert(index < dict->ma_keys->dk_nentries);
             PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + index;
             attr = ep->me_value;
-            DEOPT_IF(attr == NULL, _LOAD_ATTR_MODULE);
+            if (attr == NULL) goto deoptimize;
             STAT_INC(LOAD_ATTR, hit);
             Py_INCREF(attr);
             null = NULL;
             Py_DECREF(owner);
-            STACK_GROW(((oparg & 1) ? 1 : 0));
-            stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
-            if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
+            stack_pointer[-1] = attr;
+             if (oparg & 1) stack_pointer[0] = null;
+            stack_pointer += ((oparg & 1));
             break;
         }
 
             owner = stack_pointer[-1];
             assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
             PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
-            DEOPT_IF(_PyDictOrValues_IsValues(dorv), _CHECK_ATTR_WITH_HINT);
+            if (_PyDictOrValues_IsValues(dorv)) goto deoptimize;
             PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
-            DEOPT_IF(dict == NULL, _CHECK_ATTR_WITH_HINT);
+            if (dict == NULL) goto deoptimize;
             assert(PyDict_CheckExact((PyObject *)dict));
             break;
         }
 
         case _LOAD_ATTR_WITH_HINT: {
-            oparg = CURRENT_OPARG();
             PyObject *owner;
             PyObject *attr;
             PyObject *null = NULL;
+            oparg = CURRENT_OPARG();
             owner = stack_pointer[-1];
             uint16_t hint = (uint16_t)CURRENT_OPERAND();
             PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
             PyDictObject *dict = (PyDictObject *)_PyDictOrValues_GetDict(dorv);
-            DEOPT_IF(hint >= (size_t)dict->ma_keys->dk_nentries, _LOAD_ATTR_WITH_HINT);
+            if (hint >= (size_t)dict->ma_keys->dk_nentries) goto deoptimize;
             PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
             if (DK_IS_UNICODE(dict->ma_keys)) {
                 PyDictUnicodeEntry *ep = DK_UNICODE_ENTRIES(dict->ma_keys) + hint;
-                DEOPT_IF(ep->me_key != name, _LOAD_ATTR_WITH_HINT);
+                if (ep->me_key != name) goto deoptimize;
                 attr = ep->me_value;
             }
             else {
                 PyDictKeyEntry *ep = DK_ENTRIES(dict->ma_keys) + hint;
-                DEOPT_IF(ep->me_key != name, _LOAD_ATTR_WITH_HINT);
+                if (ep->me_key != name) goto deoptimize;
                 attr = ep->me_value;
             }
-            DEOPT_IF(attr == NULL, _LOAD_ATTR_WITH_HINT);
+            if (attr == NULL) goto deoptimize;
             STAT_INC(LOAD_ATTR, hit);
             Py_INCREF(attr);
             null = NULL;
             Py_DECREF(owner);
-            STACK_GROW(((oparg & 1) ? 1 : 0));
-            stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
-            if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
+            stack_pointer[-1] = attr;
+             if (oparg & 1) stack_pointer[0] = null;
+            stack_pointer += ((oparg & 1));
             break;
         }
 
         case _LOAD_ATTR_SLOT: {
-            oparg = CURRENT_OPARG();
             PyObject *owner;
             PyObject *attr;
             PyObject *null = NULL;
+            oparg = CURRENT_OPARG();
             owner = stack_pointer[-1];
             uint16_t index = (uint16_t)CURRENT_OPERAND();
             char *addr = (char *)owner + index;
             attr = *(PyObject **)addr;
-            DEOPT_IF(attr == NULL, _LOAD_ATTR_SLOT);
+            if (attr == NULL) goto deoptimize;
             STAT_INC(LOAD_ATTR, hit);
             Py_INCREF(attr);
             null = NULL;
             Py_DECREF(owner);
-            STACK_GROW(((oparg & 1) ? 1 : 0));
-            stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
-            if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
+            stack_pointer[-1] = attr;
+             if (oparg & 1) stack_pointer[0] = null;
+            stack_pointer += ((oparg & 1));
             break;
         }
 
             PyObject *owner;
             owner = stack_pointer[-1];
             uint32_t type_version = (uint32_t)CURRENT_OPERAND();
-            DEOPT_IF(!PyType_Check(owner), _CHECK_ATTR_CLASS);
+            if (!PyType_Check(owner)) goto deoptimize;
             assert(type_version != 0);
-            DEOPT_IF(((PyTypeObject *)owner)->tp_version_tag != type_version, _CHECK_ATTR_CLASS);
+            if (((PyTypeObject *)owner)->tp_version_tag != type_version) goto deoptimize;
             break;
         }
 
         case _LOAD_ATTR_CLASS: {
-            oparg = CURRENT_OPARG();
             PyObject *owner;
             PyObject *attr;
             PyObject *null = NULL;
+            oparg = CURRENT_OPARG();
             owner = stack_pointer[-1];
-            PyObject *descr = (PyObject *)CURRENT_OPERAND();
+            PyObject * descr = (PyObject *)CURRENT_OPERAND();
             STAT_INC(LOAD_ATTR, hit);
             assert(descr != NULL);
             attr = Py_NewRef(descr);
             null = NULL;
             Py_DECREF(owner);
-            STACK_GROW(((oparg & 1) ? 1 : 0));
-            stack_pointer[-1 - (oparg & 1 ? 1 : 0)] = attr;
-            if (oparg & 1) { stack_pointer[-(oparg & 1 ? 1 : 0)] = null; }
+            stack_pointer[-1] = attr;
+             if (oparg & 1) stack_pointer[0] = null;
+            stack_pointer += ((oparg & 1));
             break;
         }
 
+        /* _LOAD_ATTR_PROPERTY is not a viable micro-op for tier 2 */
+
+        /* _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN is not a viable micro-op for tier 2 */
+
         case _GUARD_DORV_VALUES: {
             PyObject *owner;
             owner = stack_pointer[-1];
             assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
             PyDictOrValues dorv = *_PyObject_DictOrValuesPointer(owner);
-            DEOPT_IF(!_PyDictOrValues_IsValues(dorv), _GUARD_DORV_VALUES);
+            if (!_PyDictOrValues_IsValues(dorv)) goto deoptimize;
             break;
         }
 
                 Py_DECREF(old_value);
             }
             Py_DECREF(owner);
-            STACK_SHRINK(2);
+            stack_pointer += -2;
             break;
         }
 
+        /* _STORE_ATTR_WITH_HINT is not a viable micro-op for tier 2 */
+
         case _STORE_ATTR_SLOT: {
             PyObject *owner;
             PyObject *value;
             *(PyObject **)addr = value;
             Py_XDECREF(old_value);
             Py_DECREF(owner);
-            STACK_SHRINK(2);
+            stack_pointer += -2;
             break;
         }
 
         case _COMPARE_OP: {
-            oparg = CURRENT_OPARG();
             PyObject *right;
             PyObject *left;
             PyObject *res;
+            oparg = CURRENT_OPARG();
             right = stack_pointer[-1];
             left = stack_pointer[-2];
             assert((oparg >> 5) <= Py_GE);
                 if (res_bool < 0) goto pop_2_error_tier_two;
                 res = res_bool ? Py_True : Py_False;
             }
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             break;
         }
 
-        case COMPARE_OP_FLOAT: {
-            oparg = CURRENT_OPARG();
+        case _COMPARE_OP_FLOAT: {
             PyObject *right;
             PyObject *left;
             PyObject *res;
+            oparg = CURRENT_OPARG();
             right = stack_pointer[-1];
             left = stack_pointer[-2];
-            DEOPT_IF(!PyFloat_CheckExact(left), COMPARE_OP);
-            DEOPT_IF(!PyFloat_CheckExact(right), COMPARE_OP);
+            if (!PyFloat_CheckExact(left)) goto deoptimize;
+            if (!PyFloat_CheckExact(right)) goto deoptimize;
             STAT_INC(COMPARE_OP, hit);
             double dleft = PyFloat_AS_DOUBLE(left);
             double dright = PyFloat_AS_DOUBLE(right);
             _Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
             res = (sign_ish & oparg) ? Py_True : Py_False;
             // It's always a bool, so we don't care about oparg & 16.
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             break;
         }
 
-        case COMPARE_OP_INT: {
-            oparg = CURRENT_OPARG();
+        case _COMPARE_OP_INT: {
             PyObject *right;
             PyObject *left;
             PyObject *res;
+            oparg = CURRENT_OPARG();
             right = stack_pointer[-1];
             left = stack_pointer[-2];
-            DEOPT_IF(!PyLong_CheckExact(left), COMPARE_OP);
-            DEOPT_IF(!PyLong_CheckExact(right), COMPARE_OP);
-            DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)left), COMPARE_OP);
-            DEOPT_IF(!_PyLong_IsCompact((PyLongObject *)right), COMPARE_OP);
+            if (!PyLong_CheckExact(left)) goto deoptimize;
+            if (!PyLong_CheckExact(right)) goto deoptimize;
+            if (!_PyLong_IsCompact((PyLongObject *)left)) goto deoptimize;
+            if (!_PyLong_IsCompact((PyLongObject *)right)) goto deoptimize;
             STAT_INC(COMPARE_OP, hit);
             assert(_PyLong_DigitCount((PyLongObject *)left) <= 1 &&
                    _PyLong_DigitCount((PyLongObject *)right) <= 1);
             _Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
             res = (sign_ish & oparg) ? Py_True : Py_False;
             // It's always a bool, so we don't care about oparg & 16.
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             break;
         }
 
-        case COMPARE_OP_STR: {
-            oparg = CURRENT_OPARG();
+        case _COMPARE_OP_STR: {
             PyObject *right;
             PyObject *left;
             PyObject *res;
+            oparg = CURRENT_OPARG();
             right = stack_pointer[-1];
             left = stack_pointer[-2];
-            DEOPT_IF(!PyUnicode_CheckExact(left), COMPARE_OP);
-            DEOPT_IF(!PyUnicode_CheckExact(right), COMPARE_OP);
+            if (!PyUnicode_CheckExact(left)) goto deoptimize;
+            if (!PyUnicode_CheckExact(right)) goto deoptimize;
             STAT_INC(COMPARE_OP, hit);
             int eq = _PyUnicode_Equal(left, right);
             assert((oparg >> 5) == Py_EQ || (oparg >> 5) == Py_NE);
             assert(COMPARISON_NOT_EQUALS + 1 == COMPARISON_EQUALS);
             res = ((COMPARISON_NOT_EQUALS + eq) & oparg) ? Py_True : Py_False;
             // It's always a bool, so we don't care about oparg & 16.
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             break;
         }
 
-        case IS_OP: {
-            oparg = CURRENT_OPARG();
+        case _IS_OP: {
             PyObject *right;
             PyObject *left;
             PyObject *b;
+            oparg = CURRENT_OPARG();
             right = stack_pointer[-1];
             left = stack_pointer[-2];
             int res = Py_Is(left, right) ^ oparg;
             Py_DECREF(left);
             Py_DECREF(right);
             b = res ? Py_True : Py_False;
-            STACK_SHRINK(1);
-            stack_pointer[-1] = b;
+            stack_pointer[-2] = b;
+            stack_pointer += -1;
             break;
         }
 
-        case CONTAINS_OP: {
-            oparg = CURRENT_OPARG();
+        case _CONTAINS_OP: {
             PyObject *right;
             PyObject *left;
             PyObject *b;
+            oparg = CURRENT_OPARG();
             right = stack_pointer[-1];
             left = stack_pointer[-2];
             int res = PySequence_Contains(right, left);
             Py_DECREF(right);
             if (res < 0) goto pop_2_error_tier_two;
             b = (res ^ oparg) ? Py_True : Py_False;
-            STACK_SHRINK(1);
-            stack_pointer[-1] = b;
+            stack_pointer[-2] = b;
+            stack_pointer += -1;
             break;
         }
 
-        case CHECK_EG_MATCH: {
+        case _CHECK_EG_MATCH: {
             PyObject *match_type;
             PyObject *exc_value;
             PyObject *rest;
                 Py_DECREF(match_type);
                 if (true) goto pop_2_error_tier_two;
             }
-
             match = NULL;
             rest = NULL;
             int res = _PyEval_ExceptionGroupMatch(exc_value, match_type,
-                                                  &match, &rest);
+                &match, &rest);
             Py_DECREF(exc_value);
             Py_DECREF(match_type);
             if (res < 0) goto pop_2_error_tier_two;
-
             assert((match == NULL) == (rest == NULL));
             if (match == NULL) goto pop_2_error_tier_two;
-
             if (!Py_IsNone(match)) {
                 PyErr_SetHandledException(match);
             }
             break;
         }
 
-        case CHECK_EXC_MATCH: {
+        case _CHECK_EXC_MATCH: {
             PyObject *right;
             PyObject *left;
             PyObject *b;
             left = stack_pointer[-2];
             assert(PyExceptionInstance_Check(left));
             if (_PyEval_CheckExceptTypeValid(tstate, right) < 0) {
-                 Py_DECREF(right);
-                 if (true) goto pop_1_error_tier_two;
+                Py_DECREF(right);
+                if (true) goto pop_1_error_tier_two;
             }
-
             int res = PyErr_GivenExceptionMatches(left, right);
             Py_DECREF(right);
             b = res ? Py_True : Py_False;
             break;
         }
 
+        case _JUMP_FORWARD: {
+            oparg = CURRENT_OPARG();
+            JUMPBY(oparg);
+            break;
+        }
+
+        /* _JUMP_BACKWARD is not a viable micro-op for tier 2 */
+
+        /* _POP_JUMP_IF_FALSE is not a viable micro-op for tier 2 */
+
+        /* _POP_JUMP_IF_TRUE is not a viable micro-op for tier 2 */
+
         case _IS_NONE: {
             PyObject *value;
             PyObject *b;
             break;
         }
 
-        case GET_LEN: {
+        case _JUMP_BACKWARD_NO_INTERRUPT: {
+            oparg = CURRENT_OPARG();
+            /* This bytecode is used in the `yield from` or `await` loop.
+             * If there is an interrupt, we want it handled in the innermost
+             * generator or coroutine, so we deliberately do not check it here.
+             * (see bpo-30039).
+             */
+            JUMPBY(-oparg);
+            break;
+        }
+
+        case _GET_LEN: {
             PyObject *obj;
             PyObject *len_o;
             obj = stack_pointer[-1];
             if (len_i < 0) goto error_tier_two;
             len_o = PyLong_FromSsize_t(len_i);
             if (len_o == NULL) goto error_tier_two;
-            STACK_GROW(1);
-            stack_pointer[-1] = len_o;
+            stack_pointer[0] = len_o;
+            stack_pointer += 1;
             break;
         }
 
-        case MATCH_CLASS: {
-            oparg = CURRENT_OPARG();
+        case _MATCH_CLASS: {
             PyObject *names;
             PyObject *type;
             PyObject *subject;
             PyObject *attrs;
+            oparg = CURRENT_OPARG();
             names = stack_pointer[-1];
             type = stack_pointer[-2];
             subject = stack_pointer[-3];
             }
             else {
                 if (_PyErr_Occurred(tstate)) goto pop_3_error_tier_two;
+                // Error!
                 attrs = Py_None;  // Failure!
             }
-            STACK_SHRINK(2);
-            stack_pointer[-1] = attrs;
+            stack_pointer[-3] = attrs;
+            stack_pointer += -2;
             break;
         }
 
-        case MATCH_MAPPING: {
+        case _MATCH_MAPPING: {
             PyObject *subject;
             PyObject *res;
             subject = stack_pointer[-1];
             int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING;
             res = match ? Py_True : Py_False;
-            STACK_GROW(1);
-            stack_pointer[-1] = res;
+            stack_pointer[0] = res;
+            stack_pointer += 1;
             break;
         }
 
-        case MATCH_SEQUENCE: {
+        case _MATCH_SEQUENCE: {
             PyObject *subject;
             PyObject *res;
             subject = stack_pointer[-1];
             int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_SEQUENCE;
             res = match ? Py_True : Py_False;
-            STACK_GROW(1);
-            stack_pointer[-1] = res;
+            stack_pointer[0] = res;
+            stack_pointer += 1;
             break;
         }
 
-        case MATCH_KEYS: {
+        case _MATCH_KEYS: {
             PyObject *keys;
             PyObject *subject;
             PyObject *values_or_none;
             // On successful match, PUSH(values). Otherwise, PUSH(None).
             values_or_none = _PyEval_MatchKeys(tstate, subject, keys);
             if (values_or_none == NULL) goto error_tier_two;
-            STACK_GROW(1);
-            stack_pointer[-1] = values_or_none;
+            stack_pointer[0] = values_or_none;
+            stack_pointer += 1;
             break;
         }
 
-        case GET_ITER: {
+        case _GET_ITER: {
             PyObject *iterable;
             PyObject *iter;
             iterable = stack_pointer[-1];
             break;
         }
 
-        case GET_YIELD_FROM_ITER: {
+        case _GET_YIELD_FROM_ITER: {
             PyObject *iterable;
             PyObject *iter;
             iterable = stack_pointer[-1];
             break;
         }
 
+        /* _FOR_ITER is not a viable micro-op for tier 2 */
+
         case _FOR_ITER_TIER_TWO: {
             PyObject *iter;
             PyObject *next;
                 Py_DECREF(iter);
                 STACK_SHRINK(1);
                 /* The translator sets the deopt target just past END_FOR */
-                DEOPT_IF(true, _FOR_ITER_TIER_TWO);
+                if (true) goto deoptimize;
             }
             // Common case: no jump, leave it to the code generator
-            STACK_GROW(1);
-            stack_pointer[-1] = next;
+            stack_pointer[0] = next;
+            stack_pointer += 1;
             break;
         }
 
+        /* _INSTRUMENTED_FOR_ITER is not a viable micro-op for tier 2 */
+
         case _ITER_CHECK_LIST: {
             PyObject *iter;
             iter = stack_pointer[-1];
-            DEOPT_IF(Py_TYPE(iter) != &PyListIter_Type, _ITER_CHECK_LIST);
+            if (Py_TYPE(iter) != &PyListIter_Type) goto deoptimize;
             break;
         }
 
+        /* _ITER_JUMP_LIST is not a viable micro-op for tier 2 */
+
         case _GUARD_NOT_EXHAUSTED_LIST: {
             PyObject *iter;
             iter = stack_pointer[-1];
             _PyListIterObject *it = (_PyListIterObject *)iter;
             assert(Py_TYPE(iter) == &PyListIter_Type);
             PyListObject *seq = it->it_seq;
-            DEOPT_IF(seq == NULL, _GUARD_NOT_EXHAUSTED_LIST);
-            DEOPT_IF(it->it_index >= PyList_GET_SIZE(seq), _GUARD_NOT_EXHAUSTED_LIST);
+            if (seq == NULL) goto deoptimize;
+            if (it->it_index >= PyList_GET_SIZE(seq)) goto deoptimize;
             break;
         }
 
             assert(seq);
             assert(it->it_index < PyList_GET_SIZE(seq));
             next = Py_NewRef(PyList_GET_ITEM(seq, it->it_index++));
-            STACK_GROW(1);
-            stack_pointer[-1] = next;
+            stack_pointer[0] = next;
+            stack_pointer += 1;
             break;
         }
 
         case _ITER_CHECK_TUPLE: {
             PyObject *iter;
             iter = stack_pointer[-1];
-            DEOPT_IF(Py_TYPE(iter) != &PyTupleIter_Type, _ITER_CHECK_TUPLE);
+            if (Py_TYPE(iter) != &PyTupleIter_Type) goto deoptimize;
             break;
         }
 
+        /* _ITER_JUMP_TUPLE is not a viable micro-op for tier 2 */
+
         case _GUARD_NOT_EXHAUSTED_TUPLE: {
             PyObject *iter;
             iter = stack_pointer[-1];
             _PyTupleIterObject *it = (_PyTupleIterObject *)iter;
             assert(Py_TYPE(iter) == &PyTupleIter_Type);
             PyTupleObject *seq = it->it_seq;
-            DEOPT_IF(seq == NULL, _GUARD_NOT_EXHAUSTED_TUPLE);
-            DEOPT_IF(it->it_index >= PyTuple_GET_SIZE(seq), _GUARD_NOT_EXHAUSTED_TUPLE);
+            if (seq == NULL) goto deoptimize;
+            if (it->it_index >= PyTuple_GET_SIZE(seq)) goto deoptimize;
             break;
         }
 
             assert(seq);
             assert(it->it_index < PyTuple_GET_SIZE(seq));
             next = Py_NewRef(PyTuple_GET_ITEM(seq, it->it_index++));
-            STACK_GROW(1);
-            stack_pointer[-1] = next;
+            stack_pointer[0] = next;
+            stack_pointer += 1;
             break;
         }
 
             PyObject *iter;
             iter = stack_pointer[-1];
             _PyRangeIterObject *r = (_PyRangeIterObject *)iter;
-            DEOPT_IF(Py_TYPE(r) != &PyRangeIter_Type, _ITER_CHECK_RANGE);
+            if (Py_TYPE(r) != &PyRangeIter_Type) goto deoptimize;
             break;
         }
 
+        /* _ITER_JUMP_RANGE is not a viable micro-op for tier 2 */
+
         case _GUARD_NOT_EXHAUSTED_RANGE: {
             PyObject *iter;
             iter = stack_pointer[-1];
             _PyRangeIterObject *r = (_PyRangeIterObject *)iter;
             assert(Py_TYPE(r) == &PyRangeIter_Type);
-            DEOPT_IF(r->len <= 0, _GUARD_NOT_EXHAUSTED_RANGE);
+            if (r->len <= 0) goto deoptimize;
             break;
         }
 
             r->len--;
             next = PyLong_FromLong(value);
             if (next == NULL) goto error_tier_two;
-            STACK_GROW(1);
-            stack_pointer[-1] = next;
+            stack_pointer[0] = next;
+            stack_pointer += 1;
             break;
         }
 
-        case BEFORE_ASYNC_WITH: {
+        /* _FOR_ITER_GEN is not a viable micro-op for tier 2 */
+
+        case _BEFORE_ASYNC_WITH: {
             PyObject *mgr;
             PyObject *exit;
             PyObject *res;
                 Py_DECREF(exit);
                 if (true) goto pop_1_error_tier_two;
             }
-            STACK_GROW(1);
-            stack_pointer[-2] = exit;
-            stack_pointer[-1] = res;
+            stack_pointer[-1] = exit;
+            stack_pointer[0] = res;
+            stack_pointer += 1;
             break;
         }
 
-        case BEFORE_WITH: {
+        case _BEFORE_WITH: {
             PyObject *mgr;
             PyObject *exit;
             PyObject *res;
                 Py_DECREF(exit);
                 if (true) goto pop_1_error_tier_two;
             }
-            STACK_GROW(1);
-            stack_pointer[-2] = exit;
-            stack_pointer[-1] = res;
+            stack_pointer[-1] = exit;
+            stack_pointer[0] = res;
+            stack_pointer += 1;
             break;
         }
 
-        case WITH_EXCEPT_START: {
+        case _WITH_EXCEPT_START: {
             PyObject *val;
             PyObject *lasti;
             PyObject *exit_func;
                - exit_func: FOURTH = the context.__exit__ bound method
                We call FOURTH(type(TOP), TOP, GetTraceback(TOP)).
                Then we push the __exit__ return value.
-            */
+             */
             PyObject *exc, *tb;
-
             assert(val && PyExceptionInstance_Check(val));
             exc = PyExceptionInstance_Class(val);
             tb = PyException_GetTraceback(val);
             (void)lasti; // Shut up compiler warning if asserts are off
             PyObject *stack[4] = {NULL, exc, val, tb};
             res = PyObject_Vectorcall(exit_func, stack + 1,
-                    3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
+                                      3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
             if (res == NULL) goto error_tier_two;
-            STACK_GROW(1);
-            stack_pointer[-1] = res;
+            stack_pointer[0] = res;
+            stack_pointer += 1;
             break;
         }
 
-        case PUSH_EXC_INFO: {
+        case _PUSH_EXC_INFO: {
             PyObject *new_exc;
             PyObject *prev_exc;
             new_exc = stack_pointer[-1];
             }
             assert(PyExceptionInstance_Check(new_exc));
             exc_info->exc_value = Py_NewRef(new_exc);
-            STACK_GROW(1);
-            stack_pointer[-2] = prev_exc;
-            stack_pointer[-1] = new_exc;
+            stack_pointer[-1] = prev_exc;
+            stack_pointer[0] = new_exc;
+            stack_pointer += 1;
             break;
         }
 
             owner = stack_pointer[-1];
             assert(Py_TYPE(owner)->tp_flags & Py_TPFLAGS_MANAGED_DICT);
             PyDictOrValues *dorv = _PyObject_DictOrValuesPointer(owner);
-            DEOPT_IF(!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv), _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT);
+            if (!_PyDictOrValues_IsValues(*dorv) && !_PyObject_MakeInstanceAttributesFromDict(owner, dorv)) goto deoptimize;
             break;
         }
 
             uint32_t keys_version = (uint32_t)CURRENT_OPERAND();
             PyTypeObject *owner_cls = Py_TYPE(owner);
             PyHeapTypeObject *owner_heap_type = (PyHeapTypeObject *)owner_cls;
-            DEOPT_IF(owner_heap_type->ht_cached_keys->dk_version != keys_version, _GUARD_KEYS_VERSION);
+            if (owner_heap_type->ht_cached_keys->dk_version != keys_version) goto deoptimize;
             break;
         }
 
         case _LOAD_ATTR_METHOD_WITH_VALUES: {
-            oparg = CURRENT_OPARG();
             PyObject *owner;
             PyObject *attr;
-            PyObject *self;
+            PyObject *self = NULL;
+            oparg = CURRENT_OPARG();
             owner = stack_pointer[-1];
-            PyObject *descr = (PyObject *)CURRENT_OPERAND();
+            PyObject * descr = (PyObject *)CURRENT_OPERAND();
             assert(oparg & 1);
             /* Cached method object */
             STAT_INC(LOAD_ATTR, hit);
             attr = Py_NewRef(descr);
             assert(_PyType_HasFeature(Py_TYPE(attr), Py_TPFLAGS_METHOD_DESCRIPTOR));
             self = owner;
-            STACK_GROW(1);
-            stack_pointer[-2] = attr;
-            stack_pointer[-1] = self;
+            stack_pointer[-1] = attr;
+             if (1) stack_pointer[0] = self;
+            stack_pointer += (((1) ? 1 : 0));
             break;
         }
 
         case _LOAD_ATTR_METHOD_NO_DICT: {
-            oparg = CURRENT_OPARG();
             PyObject *owner;
             PyObject *attr;
-            PyObject *self;
+            PyObject *self = NULL;
+            oparg = CURRENT_OPARG();
             owner = stack_pointer[-1];
-            PyObject *descr = (PyObject *)CURRENT_OPERAND();
+            PyObject * descr = (PyObject *)CURRENT_OPERAND();
             assert(oparg & 1);
             assert(Py_TYPE(owner)->tp_dictoffset == 0);
             STAT_INC(LOAD_ATTR, hit);
             assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
             attr = Py_NewRef(descr);
             self = owner;
-            STACK_GROW(1);
-            stack_pointer[-2] = attr;
-            stack_pointer[-1] = self;
+            stack_pointer[-1] = attr;
+             if (1) stack_pointer[0] = self;
+            stack_pointer += (((1) ? 1 : 0));
             break;
         }
 
         case _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES: {
-            oparg = CURRENT_OPARG();
             PyObject *owner;
             PyObject *attr;
+            oparg = CURRENT_OPARG();
             owner = stack_pointer[-1];
-            PyObject *descr = (PyObject *)CURRENT_OPERAND();
+            PyObject * descr = (PyObject *)CURRENT_OPERAND();
             assert((oparg & 1) == 0);
             STAT_INC(LOAD_ATTR, hit);
             assert(descr != NULL);
             Py_DECREF(owner);
             attr = Py_NewRef(descr);
             stack_pointer[-1] = attr;
+            stack_pointer += (((0) ? 1 : 0));
             break;
         }
 
         case _LOAD_ATTR_NONDESCRIPTOR_NO_DICT: {
-            oparg = CURRENT_OPARG();
             PyObject *owner;
             PyObject *attr;
+            oparg = CURRENT_OPARG();
             owner = stack_pointer[-1];
-            PyObject *descr = (PyObject *)CURRENT_OPERAND();
+            PyObject * descr = (PyObject *)CURRENT_OPERAND();
             assert((oparg & 1) == 0);
             assert(Py_TYPE(owner)->tp_dictoffset == 0);
             STAT_INC(LOAD_ATTR, hit);
             Py_DECREF(owner);
             attr = Py_NewRef(descr);
             stack_pointer[-1] = attr;
+            stack_pointer += (((0) ? 1 : 0));
             break;
         }
 
             assert(dictoffset > 0);
             PyObject *dict = *(PyObject **)((char *)owner + dictoffset);
             /* This object has a __dict__, just not yet created */
-            DEOPT_IF(dict != NULL, _CHECK_ATTR_METHOD_LAZY_DICT);
+            if (dict != NULL) goto deoptimize;
             break;
         }
 
         case _LOAD_ATTR_METHOD_LAZY_DICT: {
-            oparg = CURRENT_OPARG();
             PyObject *owner;
             PyObject *attr;
-            PyObject *self;
+            PyObject *self = NULL;
+            oparg = CURRENT_OPARG();
             owner = stack_pointer[-1];
-            PyObject *descr = (PyObject *)CURRENT_OPERAND();
+            PyObject * descr = (PyObject *)CURRENT_OPERAND();
             assert(oparg & 1);
             STAT_INC(LOAD_ATTR, hit);
             assert(descr != NULL);
             assert(_PyType_HasFeature(Py_TYPE(descr), Py_TPFLAGS_METHOD_DESCRIPTOR));
             attr = Py_NewRef(descr);
             self = owner;
-            STACK_GROW(1);
-            stack_pointer[-2] = attr;
-            stack_pointer[-1] = self;
+            stack_pointer[-1] = attr;
+             if (1) stack_pointer[0] = self;
+            stack_pointer += (((1) ? 1 : 0));
             break;
         }
 
+        /* _INSTRUMENTED_CALL is not a viable micro-op for tier 2 */
+
+        /* _CALL is not a viable micro-op for tier 2 */
+
         case _CHECK_CALL_BOUND_METHOD_EXACT_ARGS: {
-            oparg = CURRENT_OPARG();
             PyObject *null;
             PyObject *callable;
+            oparg = CURRENT_OPARG();
             null = stack_pointer[-1 - oparg];
             callable = stack_pointer[-2 - oparg];
-            DEOPT_IF(null != NULL, _CHECK_CALL_BOUND_METHOD_EXACT_ARGS);
-            DEOPT_IF(Py_TYPE(callable) != &PyMethod_Type, _CHECK_CALL_BOUND_METHOD_EXACT_ARGS);
+            if (null != NULL) goto deoptimize;
+            if (Py_TYPE(callable) != &PyMethod_Type) goto deoptimize;
             break;
         }
 
         case _INIT_CALL_BOUND_METHOD_EXACT_ARGS: {
-            oparg = CURRENT_OPARG();
             PyObject *callable;
             PyObject *func;
             PyObject *self;
+            oparg = CURRENT_OPARG();
             callable = stack_pointer[-2 - oparg];
             STAT_INC(CALL, hit);
             self = Py_NewRef(((PyMethodObject *)callable)->im_self);
         }
 
         case _CHECK_PEP_523: {
-            DEOPT_IF(tstate->interp->eval_frame, _CHECK_PEP_523);
+            if (tstate->interp->eval_frame) goto deoptimize;
             break;
         }
 
         case _CHECK_FUNCTION_EXACT_ARGS: {
-            oparg = CURRENT_OPARG();
             PyObject *self_or_null;
             PyObject *callable;
+            oparg = CURRENT_OPARG();
             self_or_null = stack_pointer[-1 - oparg];
             callable = stack_pointer[-2 - oparg];
             uint32_t func_version = (uint32_t)CURRENT_OPERAND();
-            DEOPT_IF(!PyFunction_Check(callable), _CHECK_FUNCTION_EXACT_ARGS);
+            if (!PyFunction_Check(callable)) goto deoptimize;
             PyFunctionObject *func = (PyFunctionObject *)callable;
-            DEOPT_IF(func->func_version != func_version, _CHECK_FUNCTION_EXACT_ARGS);
+            if (func->func_version != func_version) goto deoptimize;
             PyCodeObject *code = (PyCodeObject *)func->func_code;
-            DEOPT_IF(code->co_argcount != oparg + (self_or_null != NULL), _CHECK_FUNCTION_EXACT_ARGS);
+            if (code->co_argcount != oparg + (self_or_null != NULL)) goto deoptimize;
             break;
         }
 
         case _CHECK_STACK_SPACE: {
-            oparg = CURRENT_OPARG();
             PyObject *callable;
+            oparg = CURRENT_OPARG();
             callable = stack_pointer[-2 - oparg];
             PyFunctionObject *func = (PyFunctionObject *)callable;
             PyCodeObject *code = (PyCodeObject *)func->func_code;
-            DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), _CHECK_STACK_SPACE);
-            DEOPT_IF(tstate->py_recursion_remaining <= 1, _CHECK_STACK_SPACE);
+            if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) goto deoptimize;
+            if (tstate->py_recursion_remaining <= 1) goto deoptimize;
             break;
         }
 
         case _INIT_CALL_PY_EXACT_ARGS: {
-            oparg = CURRENT_OPARG();
             PyObject **args;
             PyObject *self_or_null;
             PyObject *callable;
             _PyInterpreterFrame *new_frame;
-            args = stack_pointer - oparg;
+            oparg = CURRENT_OPARG();
+            args = &stack_pointer[-oparg];
             self_or_null = stack_pointer[-1 - oparg];
             callable = stack_pointer[-2 - oparg];
             int argcount = oparg;
             for (int i = 0; i < argcount; i++) {
                 new_frame->localsplus[i] = args[i];
             }
-            STACK_SHRINK(oparg);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = (PyObject *)new_frame;
+            stack_pointer[-2 - oparg] = (PyObject *)new_frame;
+            stack_pointer += -1 - oparg;
             break;
         }
 
         case _PUSH_FRAME: {
             _PyInterpreterFrame *new_frame;
             new_frame = (_PyInterpreterFrame *)stack_pointer[-1];
-            STACK_SHRINK(1);
             // Write it out explicitly because it's subtly different.
             // Eventually this should be the only occurrence of this code.
             assert(tstate->interp->eval_frame == NULL);
-            STORE_SP();
+            stack_pointer += -1;
+            _PyFrame_SetStackPointer(frame, stack_pointer);
             new_frame->previous = frame;
             CALL_STAT_INC(inlined_py_calls);
             frame = tstate->current_frame = new_frame;
             tstate->py_recursion_remaining--;
             LOAD_SP();
             LOAD_IP(0);
-#if LLTRACE && TIER_ONE
+            #if LLTRACE && TIER_ONE
             lltrace = maybe_lltrace_resume_frame(frame, &entry_frame, GLOBALS());
             if (lltrace < 0) {
                 goto exit_unwind;
             }
-#endif
+            #endif
+            stack_pointer += (((0) ? 1 : 0));
             break;
         }
 
-        case CALL_TYPE_1: {
-            oparg = CURRENT_OPARG();
+        /* _CALL_PY_WITH_DEFAULTS is not a viable micro-op for tier 2 */
+
+        case _CALL_TYPE_1: {
             PyObject **args;
             PyObject *null;
             PyObject *callable;
             PyObject *res;
-            args = stack_pointer - oparg;
+            oparg = CURRENT_OPARG();
+            args = &stack_pointer[-oparg];
             null = stack_pointer[-1 - oparg];
             callable = stack_pointer[-2 - oparg];
             assert(oparg == 1);
-            DEOPT_IF(null != NULL, CALL);
+            if (null != NULL) goto deoptimize;
             PyObject *obj = args[0];
-            DEOPT_IF(callable != (PyObject *)&PyType_Type, CALL);
+            if (callable != (PyObject *)&PyType_Type) goto deoptimize;
             STAT_INC(CALL, hit);
             res = Py_NewRef(Py_TYPE(obj));
             Py_DECREF(obj);
             Py_DECREF(&PyType_Type);  // I.e., callable
-            STACK_SHRINK(oparg);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2 - oparg] = res;
+            stack_pointer += -1 - oparg;
             break;
         }
 
-        case CALL_STR_1: {
-            oparg = CURRENT_OPARG();
+        case _CALL_STR_1: {
             PyObject **args;
             PyObject *null;
             PyObject *callable;
             PyObject *res;
-            args = stack_pointer - oparg;
+            oparg = CURRENT_OPARG();
+            args = &stack_pointer[-oparg];
             null = stack_pointer[-1 - oparg];
             callable = stack_pointer[-2 - oparg];
             assert(oparg == 1);
-            DEOPT_IF(null != NULL, CALL);
-            DEOPT_IF(callable != (PyObject *)&PyUnicode_Type, CALL);
+            if (null != NULL) goto deoptimize;
+            if (callable != (PyObject *)&PyUnicode_Type) goto deoptimize;
             STAT_INC(CALL, hit);
             PyObject *arg = args[0];
             res = PyObject_Str(arg);
             Py_DECREF(arg);
             Py_DECREF(&PyUnicode_Type);  // I.e., callable
-            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error_tier_two; }
-            STACK_SHRINK(oparg);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; }
+            stack_pointer[-2 - oparg] = res;
+            stack_pointer += -1 - oparg;
             CHECK_EVAL_BREAKER();
             break;
         }
 
-        case CALL_TUPLE_1: {
-            oparg = CURRENT_OPARG();
+        case _CALL_TUPLE_1: {
             PyObject **args;
             PyObject *null;
             PyObject *callable;
             PyObject *res;
-            args = stack_pointer - oparg;
+            oparg = CURRENT_OPARG();
+            args = &stack_pointer[-oparg];
             null = stack_pointer[-1 - oparg];
             callable = stack_pointer[-2 - oparg];
             assert(oparg == 1);
-            DEOPT_IF(null != NULL, CALL);
-            DEOPT_IF(callable != (PyObject *)&PyTuple_Type, CALL);
+            if (null != NULL) goto deoptimize;
+            if (callable != (PyObject *)&PyTuple_Type) goto deoptimize;
             STAT_INC(CALL, hit);
             PyObject *arg = args[0];
             res = PySequence_Tuple(arg);
             Py_DECREF(arg);
             Py_DECREF(&PyTuple_Type);  // I.e., tuple
-            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error_tier_two; }
-            STACK_SHRINK(oparg);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; }
+            stack_pointer[-2 - oparg] = res;
+            stack_pointer += -1 - oparg;
             CHECK_EVAL_BREAKER();
             break;
         }
 
-        case EXIT_INIT_CHECK: {
+        /* _CALL_ALLOC_AND_ENTER_INIT is not a viable micro-op for tier 2 */
+
+        case _EXIT_INIT_CHECK: {
             PyObject *should_be_none;
             should_be_none = stack_pointer[-1];
             assert(STACK_LEVEL() == 2);
             if (should_be_none != Py_None) {
                 PyErr_Format(PyExc_TypeError,
-                    "__init__() should return None, not '%.200s'",
-                    Py_TYPE(should_be_none)->tp_name);
+                             "__init__() should return None, not '%.200s'",
+                             Py_TYPE(should_be_none)->tp_name);
                 GOTO_ERROR(error);
             }
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             break;
         }
 
-        case CALL_BUILTIN_CLASS: {
-            oparg = CURRENT_OPARG();
+        case _CALL_BUILTIN_CLASS: {
             PyObject **args;
             PyObject *self_or_null;
             PyObject *callable;
             PyObject *res;
-            args = stack_pointer - oparg;
+            oparg = CURRENT_OPARG();
+            args = &stack_pointer[-oparg];
             self_or_null = stack_pointer[-1 - oparg];
             callable = stack_pointer[-2 - oparg];
             int total_args = oparg;
                 args--;
                 total_args++;
             }
-            DEOPT_IF(!PyType_Check(callable), CALL);
+            if (!PyType_Check(callable)) goto deoptimize;
             PyTypeObject *tp = (PyTypeObject *)callable;
-            DEOPT_IF(tp->tp_vectorcall == NULL, CALL);
+            if (tp->tp_vectorcall == NULL) goto deoptimize;
             STAT_INC(CALL, hit);
             res = tp->tp_vectorcall((PyObject *)tp, args, total_args, NULL);
             /* Free the arguments. */
                 Py_DECREF(args[i]);
             }
             Py_DECREF(tp);
-            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error_tier_two; }
-            STACK_SHRINK(oparg);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; }
+            stack_pointer[-2 - oparg] = res;
+            stack_pointer += -1 - oparg;
             CHECK_EVAL_BREAKER();
             break;
         }
 
-        case CALL_BUILTIN_O: {
-            oparg = CURRENT_OPARG();
+        case _CALL_BUILTIN_O: {
             PyObject **args;
             PyObject *self_or_null;
             PyObject *callable;
             PyObject *res;
-            args = stack_pointer - oparg;
+            oparg = CURRENT_OPARG();
+            args = &stack_pointer[-oparg];
             self_or_null = stack_pointer[-1 - oparg];
             callable = stack_pointer[-2 - oparg];
             /* Builtin METH_O functions */
                 args--;
                 total_args++;
             }
-            DEOPT_IF(total_args != 1, CALL);
-            DEOPT_IF(!PyCFunction_CheckExact(callable), CALL);
-            DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_O, CALL);
+            if (total_args != 1) goto deoptimize;
+            if (!PyCFunction_CheckExact(callable)) goto deoptimize;
+            if (PyCFunction_GET_FLAGS(callable) != METH_O) goto deoptimize;
             STAT_INC(CALL, hit);
             PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable);
             // This is slower but CPython promises to check all non-vectorcall
             res = _PyCFunction_TrampolineCall(cfunc, PyCFunction_GET_SELF(callable), arg);
             _Py_LeaveRecursiveCallTstate(tstate);
             assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
-
             Py_DECREF(arg);
             Py_DECREF(callable);
-            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error_tier_two; }
-            STACK_SHRINK(oparg);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; }
+            stack_pointer[-2 - oparg] = res;
+            stack_pointer += -1 - oparg;
             CHECK_EVAL_BREAKER();
             break;
         }
 
-        case CALL_BUILTIN_FAST: {
-            oparg = CURRENT_OPARG();
+        case _CALL_BUILTIN_FAST: {
             PyObject **args;
             PyObject *self_or_null;
             PyObject *callable;
             PyObject *res;
-            args = stack_pointer - oparg;
+            oparg = CURRENT_OPARG();
+            args = &stack_pointer[-oparg];
             self_or_null = stack_pointer[-1 - oparg];
             callable = stack_pointer[-2 - oparg];
             /* Builtin METH_FASTCALL functions, without keywords */
                 args--;
                 total_args++;
             }
-            DEOPT_IF(!PyCFunction_CheckExact(callable), CALL);
-            DEOPT_IF(PyCFunction_GET_FLAGS(callable) != METH_FASTCALL, CALL);
+            if (!PyCFunction_CheckExact(callable)) goto deoptimize;
+            if (PyCFunction_GET_FLAGS(callable) != METH_FASTCALL) goto deoptimize;
             STAT_INC(CALL, hit);
             PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable);
             /* res = func(self, args, nargs) */
                 args,
                 total_args);
             assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
-
             /* Free the arguments. */
             for (int i = 0; i < total_args; i++) {
                 Py_DECREF(args[i]);
             }
             Py_DECREF(callable);
-            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error_tier_two; }
-                /* Not deopting because this doesn't mean our optimization was
-                   wrong. `res` can be NULL for valid reasons. Eg. getattr(x,
-                   'invalid'). In those cases an exception is set, so we must
-                   handle it.
-                */
-            STACK_SHRINK(oparg);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; }
+            /* Not deopting because this doesn't mean our optimization was
+               wrong. `res` can be NULL for valid reasons. Eg. getattr(x,
+               'invalid'). In those cases an exception is set, so we must
+               handle it.
+             */
+            stack_pointer[-2 - oparg] = res;
+            stack_pointer += -1 - oparg;
             CHECK_EVAL_BREAKER();
             break;
         }
 
-        case CALL_BUILTIN_FAST_WITH_KEYWORDS: {
-            oparg = CURRENT_OPARG();
+        case _CALL_BUILTIN_FAST_WITH_KEYWORDS: {
             PyObject **args;
             PyObject *self_or_null;
             PyObject *callable;
             PyObject *res;
-            args = stack_pointer - oparg;
+            oparg = CURRENT_OPARG();
+            args = &stack_pointer[-oparg];
             self_or_null = stack_pointer[-1 - oparg];
             callable = stack_pointer[-2 - oparg];
             /* Builtin METH_FASTCALL | METH_KEYWORDS functions */
                 args--;
                 total_args++;
             }
-            DEOPT_IF(!PyCFunction_CheckExact(callable), CALL);
-            DEOPT_IF(PyCFunction_GET_FLAGS(callable) != (METH_FASTCALL | METH_KEYWORDS), CALL);
+            if (!PyCFunction_CheckExact(callable)) goto deoptimize;
+            if (PyCFunction_GET_FLAGS(callable) != (METH_FASTCALL | METH_KEYWORDS)) goto deoptimize;
             STAT_INC(CALL, hit);
             /* res = func(self, args, nargs, kwnames) */
             _PyCFunctionFastWithKeywords cfunc =
-                (_PyCFunctionFastWithKeywords)(void(*)(void))
-                PyCFunction_GET_FUNCTION(callable);
+            (_PyCFunctionFastWithKeywords)(void(*)(void))
+            PyCFunction_GET_FUNCTION(callable);
             res = cfunc(PyCFunction_GET_SELF(callable), args, total_args, NULL);
             assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
-
             /* Free the arguments. */
             for (int i = 0; i < total_args; i++) {
                 Py_DECREF(args[i]);
             }
             Py_DECREF(callable);
-            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error_tier_two; }
-            STACK_SHRINK(oparg);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; }
+            stack_pointer[-2 - oparg] = res;
+            stack_pointer += -1 - oparg;
             CHECK_EVAL_BREAKER();
             break;
         }
 
-        case CALL_LEN: {
-            oparg = CURRENT_OPARG();
+        case _CALL_LEN: {
             PyObject **args;
             PyObject *self_or_null;
             PyObject *callable;
             PyObject *res;
-            args = stack_pointer - oparg;
+            oparg = CURRENT_OPARG();
+            args = &stack_pointer[-oparg];
             self_or_null = stack_pointer[-1 - oparg];
             callable = stack_pointer[-2 - oparg];
             /* len(o) */
                 args--;
                 total_args++;
             }
-            DEOPT_IF(total_args != 1, CALL);
+            if (total_args != 1) goto deoptimize;
             PyInterpreterState *interp = tstate->interp;
-            DEOPT_IF(callable != interp->callable_cache.len, CALL);
+            if (callable != interp->callable_cache.len) goto deoptimize;
             STAT_INC(CALL, hit);
             PyObject *arg = args[0];
             Py_ssize_t len_i = PyObject_Length(arg);
             }
             res = PyLong_FromSsize_t(len_i);
             assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
-
             Py_DECREF(callable);
             Py_DECREF(arg);
-            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error_tier_two; }
-            STACK_SHRINK(oparg);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; }
+            stack_pointer[-2 - oparg] = res;
+            stack_pointer += -1 - oparg;
             break;
         }
 
-        case CALL_ISINSTANCE: {
-            oparg = CURRENT_OPARG();
+        case _CALL_ISINSTANCE: {
             PyObject **args;
             PyObject *self_or_null;
             PyObject *callable;
             PyObject *res;
-            args = stack_pointer - oparg;
+            oparg = CURRENT_OPARG();
+            args = &stack_pointer[-oparg];
             self_or_null = stack_pointer[-1 - oparg];
             callable = stack_pointer[-2 - oparg];
             /* isinstance(o, o2) */
                 args--;
                 total_args++;
             }
-            DEOPT_IF(total_args != 2, CALL);
+            if (total_args != 2) goto deoptimize;
             PyInterpreterState *interp = tstate->interp;
-            DEOPT_IF(callable != interp->callable_cache.isinstance, CALL);
+            if (callable != interp->callable_cache.isinstance) goto deoptimize;
             STAT_INC(CALL, hit);
             PyObject *cls = args[1];
             PyObject *inst = args[0];
             }
             res = PyBool_FromLong(retval);
             assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
-
             Py_DECREF(inst);
             Py_DECREF(cls);
             Py_DECREF(callable);
-            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error_tier_two; }
-            STACK_SHRINK(oparg);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; }
+            stack_pointer[-2 - oparg] = res;
+            stack_pointer += -1 - oparg;
             break;
         }
 
-        case CALL_METHOD_DESCRIPTOR_O: {
+        case _CALL_LIST_APPEND: {
+            PyObject **args;
+            PyObject *self;
+            PyObject *callable;
             oparg = CURRENT_OPARG();
+            args = &stack_pointer[-oparg];
+            self = stack_pointer[-1 - oparg];
+            callable = stack_pointer[-2 - oparg];
+            assert(oparg == 1);
+            PyInterpreterState *interp = tstate->interp;
+            if (callable != interp->callable_cache.list_append) goto deoptimize;
+            assert(self != NULL);
+            if (!PyList_Check(self)) goto deoptimize;
+            STAT_INC(CALL, hit);
+            if (_PyList_AppendTakeRef((PyListObject *)self, args[0]) < 0) {
+                goto pop_1_error;  // Since arg is DECREF'ed already
+            }
+            Py_DECREF(self);
+            Py_DECREF(callable);
+            STACK_SHRINK(3);
+            // Skip POP_TOP
+            assert(next_instr->op.code == POP_TOP);
+            SKIP_OVER(1);
+            DISPATCH();
+        }
+
+        case _CALL_METHOD_DESCRIPTOR_O: {
             PyObject **args;
             PyObject *self_or_null;
             PyObject *callable;
             PyObject *res;
-            args = stack_pointer - oparg;
+            oparg = CURRENT_OPARG();
+            args = &stack_pointer[-oparg];
             self_or_null = stack_pointer[-1 - oparg];
             callable = stack_pointer[-2 - oparg];
             int total_args = oparg;
                 total_args++;
             }
             PyMethodDescrObject *method = (PyMethodDescrObject *)callable;
-            DEOPT_IF(total_args != 2, CALL);
-            DEOPT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type), CALL);
+            if (total_args != 2) goto deoptimize;
+            if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) goto deoptimize;
             PyMethodDef *meth = method->d_method;
-            DEOPT_IF(meth->ml_flags != METH_O, CALL);
+            if (meth->ml_flags != METH_O) goto deoptimize;
             PyObject *arg = args[1];
             PyObject *self = args[0];
-            DEOPT_IF(!Py_IS_TYPE(self, method->d_common.d_type), CALL);
+            if (!Py_IS_TYPE(self, method->d_common.d_type)) goto deoptimize;
             STAT_INC(CALL, hit);
             PyCFunction cfunc = meth->ml_meth;
             // This is slower but CPython promises to check all non-vectorcall
             Py_DECREF(self);
             Py_DECREF(arg);
             Py_DECREF(callable);
-            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error_tier_two; }
-            STACK_SHRINK(oparg);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; }
+            stack_pointer[-2 - oparg] = res;
+            stack_pointer += -1 - oparg;
             CHECK_EVAL_BREAKER();
             break;
         }
 
-        case CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: {
-            oparg = CURRENT_OPARG();
+        case _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS: {
             PyObject **args;
             PyObject *self_or_null;
             PyObject *callable;
             PyObject *res;
-            args = stack_pointer - oparg;
+            oparg = CURRENT_OPARG();
+            args = &stack_pointer[-oparg];
             self_or_null = stack_pointer[-1 - oparg];
             callable = stack_pointer[-2 - oparg];
             int total_args = oparg;
                 total_args++;
             }
             PyMethodDescrObject *method = (PyMethodDescrObject *)callable;
-            DEOPT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type), CALL);
+            if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) goto deoptimize;
             PyMethodDef *meth = method->d_method;
-            DEOPT_IF(meth->ml_flags != (METH_FASTCALL|METH_KEYWORDS), CALL);
+            if (meth->ml_flags != (METH_FASTCALL|METH_KEYWORDS)) goto deoptimize;
             PyTypeObject *d_type = method->d_common.d_type;
             PyObject *self = args[0];
-            DEOPT_IF(!Py_IS_TYPE(self, d_type), CALL);
+            if (!Py_IS_TYPE(self, d_type)) goto deoptimize;
             STAT_INC(CALL, hit);
             int nargs = total_args - 1;
             _PyCFunctionFastWithKeywords cfunc =
-                (_PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;
+            (_PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;
             res = cfunc(self, args + 1, nargs, NULL);
             assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
-
             /* Free the arguments. */
             for (int i = 0; i < total_args; i++) {
                 Py_DECREF(args[i]);
             }
             Py_DECREF(callable);
-            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error_tier_two; }
-            STACK_SHRINK(oparg);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; }
+            stack_pointer[-2 - oparg] = res;
+            stack_pointer += -1 - oparg;
             CHECK_EVAL_BREAKER();
             break;
         }
 
-        case CALL_METHOD_DESCRIPTOR_NOARGS: {
-            oparg = CURRENT_OPARG();
+        case _CALL_METHOD_DESCRIPTOR_NOARGS: {
             PyObject **args;
             PyObject *self_or_null;
             PyObject *callable;
             PyObject *res;
-            args = stack_pointer - oparg;
+            oparg = CURRENT_OPARG();
+            args = &stack_pointer[-oparg];
             self_or_null = stack_pointer[-1 - oparg];
             callable = stack_pointer[-2 - oparg];
             assert(oparg == 0 || oparg == 1);
                 args--;
                 total_args++;
             }
-            DEOPT_IF(total_args != 1, CALL);
+            if (total_args != 1) goto deoptimize;
             PyMethodDescrObject *method = (PyMethodDescrObject *)callable;
-            DEOPT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type), CALL);
+            if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) goto deoptimize;
             PyMethodDef *meth = method->d_method;
             PyObject *self = args[0];
-            DEOPT_IF(!Py_IS_TYPE(self, method->d_common.d_type), CALL);
-            DEOPT_IF(meth->ml_flags != METH_NOARGS, CALL);
+            if (!Py_IS_TYPE(self, method->d_common.d_type)) goto deoptimize;
+            if (meth->ml_flags != METH_NOARGS) goto deoptimize;
             STAT_INC(CALL, hit);
             PyCFunction cfunc = meth->ml_meth;
             // This is slower but CPython promises to check all non-vectorcall
             assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
             Py_DECREF(self);
             Py_DECREF(callable);
-            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error_tier_two; }
-            STACK_SHRINK(oparg);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; }
+            stack_pointer[-2 - oparg] = res;
+            stack_pointer += -1 - oparg;
             CHECK_EVAL_BREAKER();
             break;
         }
 
-        case CALL_METHOD_DESCRIPTOR_FAST: {
-            oparg = CURRENT_OPARG();
+        case _CALL_METHOD_DESCRIPTOR_FAST: {
             PyObject **args;
             PyObject *self_or_null;
             PyObject *callable;
             PyObject *res;
-            args = stack_pointer - oparg;
+            oparg = CURRENT_OPARG();
+            args = &stack_pointer[-oparg];
             self_or_null = stack_pointer[-1 - oparg];
             callable = stack_pointer[-2 - oparg];
             int total_args = oparg;
             }
             PyMethodDescrObject *method = (PyMethodDescrObject *)callable;
             /* Builtin METH_FASTCALL methods, without keywords */
-            DEOPT_IF(!Py_IS_TYPE(method, &PyMethodDescr_Type), CALL);
+            if (!Py_IS_TYPE(method, &PyMethodDescr_Type)) goto deoptimize;
             PyMethodDef *meth = method->d_method;
-            DEOPT_IF(meth->ml_flags != METH_FASTCALL, CALL);
+            if (meth->ml_flags != METH_FASTCALL) goto deoptimize;
             PyObject *self = args[0];
-            DEOPT_IF(!Py_IS_TYPE(self, method->d_common.d_type), CALL);
+            if (!Py_IS_TYPE(self, method->d_common.d_type)) goto deoptimize;
             STAT_INC(CALL, hit);
             _PyCFunctionFast cfunc =
-                (_PyCFunctionFast)(void(*)(void))meth->ml_meth;
+            (_PyCFunctionFast)(void(*)(void))meth->ml_meth;
             int nargs = total_args - 1;
             res = cfunc(self, args + 1, nargs);
             assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
                 Py_DECREF(args[i]);
             }
             Py_DECREF(callable);
-            if (res == NULL) { STACK_SHRINK(oparg); goto pop_2_error_tier_two; }
-            STACK_SHRINK(oparg);
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            if (res == NULL) { stack_pointer += -2 - oparg; goto error_tier_two; }
+            stack_pointer[-2 - oparg] = res;
+            stack_pointer += -1 - oparg;
             CHECK_EVAL_BREAKER();
             break;
         }
 
-        case MAKE_FUNCTION: {
+        /* _INSTRUMENTED_CALL_KW is not a viable micro-op for tier 2 */
+
+        /* _CALL_KW is not a viable micro-op for tier 2 */
+
+        /* _INSTRUMENTED_CALL_FUNCTION_EX is not a viable micro-op for tier 2 */
+
+        /* _CALL_FUNCTION_EX is not a viable micro-op for tier 2 */
+
+        case _MAKE_FUNCTION: {
             PyObject *codeobj;
             PyObject *func;
             codeobj = stack_pointer[-1];
-
             PyFunctionObject *func_obj = (PyFunctionObject *)
-                PyFunction_New(codeobj, GLOBALS());
-
+            PyFunction_New(codeobj, GLOBALS());
             Py_DECREF(codeobj);
             if (func_obj == NULL) {
                 GOTO_ERROR(error);
             }
-
             _PyFunction_SetVersion(
-                func_obj, ((PyCodeObject *)codeobj)->co_version);
+                                   func_obj, ((PyCodeObject *)codeobj)->co_version);
             func = (PyObject *)func_obj;
             stack_pointer[-1] = func;
             break;
         }
 
-        case SET_FUNCTION_ATTRIBUTE: {
-            oparg = CURRENT_OPARG();
+        case _SET_FUNCTION_ATTRIBUTE: {
             PyObject *func;
             PyObject *attr;
+            oparg = CURRENT_OPARG();
             func = stack_pointer[-1];
             attr = stack_pointer[-2];
             assert(PyFunction_Check(func));
             PyFunctionObject *func_obj = (PyFunctionObject *)func;
             switch(oparg) {
                 case MAKE_FUNCTION_CLOSURE:
-                    assert(func_obj->func_closure == NULL);
-                    func_obj->func_closure = attr;
-                    break;
+                assert(func_obj->func_closure == NULL);
+                func_obj->func_closure = attr;
+                break;
                 case MAKE_FUNCTION_ANNOTATIONS:
-                    assert(func_obj->func_annotations == NULL);
-                    func_obj->func_annotations = attr;
-                    break;
+                assert(func_obj->func_annotations == NULL);
+                func_obj->func_annotations = attr;
+                break;
                 case MAKE_FUNCTION_KWDEFAULTS:
-                    assert(PyDict_CheckExact(attr));
-                    assert(func_obj->func_kwdefaults == NULL);
-                    func_obj->func_kwdefaults = attr;
-                    break;
+                assert(PyDict_CheckExact(attr));
+                assert(func_obj->func_kwdefaults == NULL);
+                func_obj->func_kwdefaults = attr;
+                break;
                 case MAKE_FUNCTION_DEFAULTS:
-                    assert(PyTuple_CheckExact(attr));
-                    assert(func_obj->func_defaults == NULL);
-                    func_obj->func_defaults = attr;
-                    break;
+                assert(PyTuple_CheckExact(attr));
+                assert(func_obj->func_defaults == NULL);
+                func_obj->func_defaults = attr;
+                break;
                 default:
-                    Py_UNREACHABLE();
+                Py_UNREACHABLE();
             }
-            STACK_SHRINK(1);
-            stack_pointer[-1] = func;
+            stack_pointer[-2] = func;
+            stack_pointer += -1;
             break;
         }
 
-        case BUILD_SLICE: {
-            oparg = CURRENT_OPARG();
+        case _RETURN_GENERATOR: {
+            assert(PyFunction_Check(frame->f_funcobj));
+            PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj;
+            PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func);
+            if (gen == NULL) {
+                GOTO_ERROR(error);
+            }
+            assert(EMPTY());
+            _PyFrame_SetStackPointer(frame, stack_pointer);
+            _PyInterpreterFrame *gen_frame = (_PyInterpreterFrame *)gen->gi_iframe;
+            frame->instr_ptr = next_instr;
+            _PyFrame_Copy(frame, gen_frame);
+            assert(frame->frame_obj == NULL);
+            gen->gi_frame_state = FRAME_CREATED;
+            gen_frame->owner = FRAME_OWNED_BY_GENERATOR;
+            _Py_LeaveRecursiveCallPy(tstate);
+            assert(frame != &entry_frame);
+            _PyInterpreterFrame *prev = frame->previous;
+            _PyThreadState_PopFrame(tstate, frame);
+            frame = tstate->current_frame = prev;
+            _PyFrame_StackPush(frame, (PyObject *)gen);
+            LOAD_IP(frame->return_offset);
+            goto resume_frame;
+        }
+
+        case _BUILD_SLICE: {
             PyObject *step = NULL;
             PyObject *stop;
             PyObject *start;
             PyObject *slice;
-            if (oparg == 3) { step = stack_pointer[-(oparg == 3 ? 1 : 0)]; }
-            stop = stack_pointer[-1 - (oparg == 3 ? 1 : 0)];
-            start = stack_pointer[-2 - (oparg == 3 ? 1 : 0)];
+            oparg = CURRENT_OPARG();
+        if (oparg == 3) { step = stack_pointer[-(((oparg == 3) ? 1 : 0))]; }
+            stop = stack_pointer[-1 - (((oparg == 3) ? 1 : 0))];
+            start = stack_pointer[-2 - (((oparg == 3) ? 1 : 0))];
             slice = PySlice_New(start, stop, step);
             Py_DECREF(start);
             Py_DECREF(stop);
             Py_XDECREF(step);
-            if (slice == NULL) { STACK_SHRINK(((oparg == 3) ? 1 : 0)); goto pop_2_error_tier_two; }
-            STACK_SHRINK(((oparg == 3) ? 1 : 0));
-            STACK_SHRINK(1);
-            stack_pointer[-1] = slice;
+            if (slice == NULL) { stack_pointer += -2 - (((oparg == 3) ? 1 : 0)); goto error_tier_two; }
+            stack_pointer[-2 - (((oparg == 3) ? 1 : 0))] = slice;
+            stack_pointer += -1 - (((oparg == 3) ? 1 : 0));
             break;
         }
 
-        case CONVERT_VALUE: {
-            oparg = CURRENT_OPARG();
+        case _CONVERT_VALUE: {
             PyObject *value;
             PyObject *result;
+            oparg = CURRENT_OPARG();
             value = stack_pointer[-1];
             convertion_func_ptr  conv_fn;
             assert(oparg >= FVC_STR && oparg <= FVC_ASCII);
             break;
         }
 
-        case FORMAT_SIMPLE: {
+        case _FORMAT_SIMPLE: {
             PyObject *value;
             PyObject *res;
             value = stack_pointer[-1];
             break;
         }
 
-        case FORMAT_WITH_SPEC: {
+        case _FORMAT_WITH_SPEC: {
             PyObject *fmt_spec;
             PyObject *value;
             PyObject *res;
             Py_DECREF(value);
             Py_DECREF(fmt_spec);
             if (res == NULL) goto pop_2_error_tier_two;
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             break;
         }
 
-        case COPY: {
-            oparg = CURRENT_OPARG();
+        case _COPY: {
             PyObject *bottom;
             PyObject *top;
+            oparg = CURRENT_OPARG();
             bottom = stack_pointer[-1 - (oparg-1)];
             assert(oparg > 0);
             top = Py_NewRef(bottom);
-            STACK_GROW(1);
-            stack_pointer[-1] = top;
+            stack_pointer[0] = top;
+            stack_pointer += 1;
             break;
         }
 
         case _BINARY_OP: {
-            oparg = CURRENT_OPARG();
             PyObject *rhs;
             PyObject *lhs;
             PyObject *res;
+            oparg = CURRENT_OPARG();
             rhs = stack_pointer[-1];
             lhs = stack_pointer[-2];
             assert(_PyEval_BinaryOps[oparg]);
             Py_DECREF(lhs);
             Py_DECREF(rhs);
             if (res == NULL) goto pop_2_error_tier_two;
-            STACK_SHRINK(1);
-            stack_pointer[-1] = res;
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
             break;
         }
 
-        case SWAP: {
-            oparg = CURRENT_OPARG();
+        case _SWAP: {
             PyObject *top;
             PyObject *bottom;
+            oparg = CURRENT_OPARG();
             top = stack_pointer[-1];
             bottom = stack_pointer[-2 - (oparg-2)];
             assert(oparg >= 2);
             break;
         }
 
+        /* _INSTRUMENTED_INSTRUCTION is not a viable micro-op for tier 2 */
+
+        /* _INSTRUMENTED_JUMP_FORWARD is not a viable micro-op for tier 2 */
+
+        /* _INSTRUMENTED_JUMP_BACKWARD is not a viable micro-op for tier 2 */
+
+        /* _INSTRUMENTED_POP_JUMP_IF_TRUE is not a viable micro-op for tier 2 */
+
+        /* _INSTRUMENTED_POP_JUMP_IF_FALSE is not a viable micro-op for tier 2 */
+
+        /* _INSTRUMENTED_POP_JUMP_IF_NONE is not a viable micro-op for tier 2 */
+
+        /* _INSTRUMENTED_POP_JUMP_IF_NOT_NONE is not a viable micro-op for tier 2 */
+
         case _GUARD_IS_TRUE_POP: {
             PyObject *flag;
             flag = stack_pointer[-1];
-            DEOPT_IF(Py_IsFalse(flag), _GUARD_IS_TRUE_POP);
+            if (Py_IsFalse(flag)) goto deoptimize;
             assert(Py_IsTrue(flag));
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             break;
         }
 
         case _GUARD_IS_FALSE_POP: {
             PyObject *flag;
             flag = stack_pointer[-1];
-            DEOPT_IF(Py_IsTrue(flag), _GUARD_IS_FALSE_POP);
+            if (Py_IsTrue(flag)) goto deoptimize;
             assert(Py_IsFalse(flag));
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             break;
         }
 
         case _GUARD_IS_NONE_POP: {
             PyObject *val;
             val = stack_pointer[-1];
-            DEOPT_IF(!Py_IsNone(val), _GUARD_IS_NONE_POP);
-            STACK_SHRINK(1);
+            if (!Py_IsNone(val)) goto deoptimize;
+            stack_pointer += -1;
             break;
         }
 
         case _GUARD_IS_NOT_NONE_POP: {
             PyObject *val;
             val = stack_pointer[-1];
-            DEOPT_IF(Py_IsNone(val), _GUARD_IS_NOT_NONE_POP);
+            if (Py_IsNone(val)) goto deoptimize;
             Py_DECREF(val);
-            STACK_SHRINK(1);
+            stack_pointer += -1;
             break;
         }
 
         }
 
         case _INSERT: {
-            oparg = CURRENT_OPARG();
             PyObject *top;
+            oparg = CURRENT_OPARG();
             top = stack_pointer[-1];
             // Inserts TOS at position specified by oparg;
             memmove(&stack_pointer[-1 - oparg], &stack_pointer[-oparg], oparg * sizeof(stack_pointer[0]));
 
         case _CHECK_VALIDITY: {
             TIER_TWO_ONLY
-            DEOPT_IF(!current_executor->base.vm_data.valid, _CHECK_VALIDITY);
+            if (!current_executor->base.vm_data.valid) goto deoptimize;
             break;
         }
 
index 24243ecfb5b8dfb13a64b326b7a6390df4c5245e..8f68bc6cb5ab403631b3412bd20b3371eb7c2e1e 100644 (file)
@@ -1,6 +1,6 @@
 // This file is generated by Tools/cases_generator/tier1_generator.py
 // from:
-//   ['./Python/bytecodes.c']
+//   Python/bytecodes.c
 // Do not edit!
 
 #ifdef TIER_TWO
             frame->instr_ptr = next_instr;
             next_instr += 1;
             INSTRUCTION_STATS(CACHE);
+            TIER_ONE_ONLY
             assert(0 && "Executing a cache.");
             Py_UNREACHABLE();
         }
             frame->instr_ptr = next_instr;
             next_instr += 1;
             INSTRUCTION_STATS(EXTENDED_ARG);
+            TIER_ONE_ONLY
             assert(oparg);
             opcode = next_instr->op.code;
             oparg = oparg << 8 | next_instr->op.arg;
             frame->instr_ptr = next_instr;
             next_instr += 1;
             INSTRUCTION_STATS(RESERVED);
+            TIER_ONE_ONLY
             assert(0 && "Executing RESERVED instruction.");
             Py_UNREACHABLE();
         }
index 945de63d209935ce1896bd6d4f93c4069118d2e6..bcc13538e51d9be8ea8f37766c50a383eea79715 100644 (file)
@@ -15,6 +15,7 @@ class Properties:
     needs_this: bool
     always_exits: bool
     stores_sp: bool
+    tier_one_only: bool
 
     def dump(self, indent: str) -> None:
         print(indent, end="")
@@ -33,6 +34,7 @@ class Properties:
             needs_this=any(p.needs_this for p in properties),
             always_exits=any(p.always_exits for p in properties),
             stores_sp=any(p.stores_sp for p in properties),
+            tier_one_only=any(p.tier_one_only for p in properties),
         )
 
 
@@ -46,6 +48,7 @@ SKIP_PROPERTIES = Properties(
     needs_this=False,
     always_exits=False,
     stores_sp=False,
+    tier_one_only=False,
 )
 
 
@@ -124,6 +127,21 @@ class Uop:
             self._size = sum(c.size for c in self.caches)
         return self._size
 
+    def is_viable(self) -> bool:
+        if self.name == "_SAVE_RETURN_OFFSET":
+            return True  # Adjusts next_instr, but only in tier 1 code
+        if self.properties.needs_this:
+            return False
+        if "INSTRUMENTED" in self.name:
+            return False
+        if "replaced" in self.annotations:
+            return False
+        if self.name in ("INTERPRETER_EXIT", "JUMP_BACKWARD"):
+            return False
+        if len([c for c in self.caches if c.name != "unused"]) > 1:
+            return False
+        return True
+
 
 Part = Uop | Skip
 
@@ -292,6 +310,7 @@ def compute_properties(op: parser.InstDef) -> Properties:
         needs_this=variable_used(op, "this_instr"),
         always_exits=always_exits(op),
         stores_sp=variable_used(op, "STORE_SP"),
+        tier_one_only=variable_used(op, "TIER_ONE_ONLY"),
     )
 
 
index f7c362131a7a9f8a8ddd1c270c88e2336f65643e..c6ed5911b846bf4f0a680f06f776640bd7244a4b 100644 (file)
@@ -128,13 +128,6 @@ arg_parser.add_argument(
 arg_parser.add_argument(
     "input", nargs=argparse.REMAINDER, help="Instruction definition file(s)"
 )
-arg_parser.add_argument(
-    "-e",
-    "--executor-cases",
-    type=str,
-    help="Write executor cases to this file",
-    default=DEFAULT_EXECUTOR_OUTPUT,
-)
 arg_parser.add_argument(
     "-a",
     "--abstract-interpreter-cases",
@@ -846,7 +839,6 @@ def main() -> None:
     a.assign_opcode_ids()
     a.write_opcode_targets(args.opcode_targets_h)
     a.write_metadata(args.metadata, args.pymetadata)
-    a.write_executor_instructions(args.executor_cases, args.emit_line_directives)
     a.write_abstract_interpreter_instructions(
         args.abstract_interpreter_cases, args.emit_line_directives
     )
index 76900d1efffd5d3e480c54889672f405fe0e0bc7..e0674a7343498d5b0753994b62570e2cc6ca3351 100644 (file)
 from pathlib import Path
 from typing import TextIO
 
+from analyzer import (
+    Analysis,
+    Instruction,
+    Uop,
+    Part,
+    analyze_files,
+    Skip,
+    StackItem,
+    analysis_error,
+)
+from cwriter import CWriter
+from typing import Callable, Mapping, TextIO, Iterator
+from lexer import Token
+from stack import StackOffset, Stack
+
+
 ROOT = Path(__file__).parent.parent.parent
-DEFAULT_INPUT = (ROOT / "Python/bytecodes.c").absolute()
+DEFAULT_INPUT = (ROOT / "Python/bytecodes.c").absolute().as_posix()
 
 
 def root_relative_path(filename: str) -> str:
-    return Path(filename).relative_to(ROOT).as_posix()
+    return Path(filename).absolute().relative_to(ROOT).as_posix()
 
 
-def write_header(generator: str, source: str, outfile: TextIO) -> None:
+def write_header(generator: str, sources: list[str], outfile: TextIO) -> None:
     outfile.write(
         f"""// This file is generated by {root_relative_path(generator)}
 // from:
-//   {source}
+//   {", ".join(root_relative_path(src) for src in sources)}
 // Do not edit!
 """
     )
+
+
+def emit_to(out: CWriter, tkn_iter: Iterator[Token], end: str) -> None:
+    parens = 0
+    for tkn in tkn_iter:
+        if tkn.kind == end and parens == 0:
+            return
+        if tkn.kind == "LPAREN":
+            parens += 1
+        if tkn.kind == "RPAREN":
+            parens -= 1
+        out.emit(tkn)
+
+
+def replace_deopt(
+    out: CWriter,
+    tkn: Token,
+    tkn_iter: Iterator[Token],
+    uop: Uop,
+    unused: Stack,
+    inst: Instruction | None,
+) -> None:
+    out.emit_at("DEOPT_IF", tkn)
+    out.emit(next(tkn_iter))
+    emit_to(out, tkn_iter, "RPAREN")
+    next(tkn_iter)  # Semi colon
+    out.emit(", ")
+    assert inst is not None
+    assert inst.family is not None
+    out.emit(inst.family.name)
+    out.emit(");\n")
+
+
+def replace_error(
+    out: CWriter,
+    tkn: Token,
+    tkn_iter: Iterator[Token],
+    uop: Uop,
+    stack: Stack,
+    inst: Instruction | None,
+) -> None:
+    out.emit_at("if ", tkn)
+    out.emit(next(tkn_iter))
+    emit_to(out, tkn_iter, "COMMA")
+    label = next(tkn_iter).text
+    next(tkn_iter)  # RPAREN
+    next(tkn_iter)  # Semi colon
+    out.emit(") ")
+    c_offset = stack.peek_offset.to_c()
+    try:
+        offset = -int(c_offset)
+        close = ";\n"
+    except ValueError:
+        offset = None
+        out.emit(f"{{ stack_pointer += {c_offset}; ")
+        close = "; }\n"
+    out.emit("goto ")
+    if offset:
+        out.emit(f"pop_{offset}_")
+    out.emit(label)
+    out.emit(close)
+
+
+def replace_decrefs(
+    out: CWriter,
+    tkn: Token,
+    tkn_iter: Iterator[Token],
+    uop: Uop,
+    stack: Stack,
+    inst: Instruction | None,
+) -> None:
+    next(tkn_iter)
+    next(tkn_iter)
+    next(tkn_iter)
+    out.emit_at("", tkn)
+    for var in uop.stack.inputs:
+        if var.name == "unused" or var.name == "null" or var.peek:
+            continue
+        if var.size != "1":
+            out.emit(f"for (int _i = {var.size}; --_i >= 0;) {{\n")
+            out.emit(f"Py_DECREF({var.name}[_i]);\n")
+            out.emit("}\n")
+        elif var.condition:
+            out.emit(f"Py_XDECREF({var.name});\n")
+        else:
+            out.emit(f"Py_DECREF({var.name});\n")
+
+
+def replace_store_sp(
+    out: CWriter,
+    tkn: Token,
+    tkn_iter: Iterator[Token],
+    uop: Uop,
+    stack: Stack,
+    inst: Instruction | None,
+) -> None:
+    next(tkn_iter)
+    next(tkn_iter)
+    next(tkn_iter)
+    out.emit_at("", tkn)
+    stack.flush(out)
+    out.emit("_PyFrame_SetStackPointer(frame, stack_pointer);\n")
+
+
+def replace_check_eval_breaker(
+    out: CWriter,
+    tkn: Token,
+    tkn_iter: Iterator[Token],
+    uop: Uop,
+    stack: Stack,
+    inst: Instruction | None,
+) -> None:
+    next(tkn_iter)
+    next(tkn_iter)
+    next(tkn_iter)
+    if not uop.properties.ends_with_eval_breaker:
+        out.emit_at("CHECK_EVAL_BREAKER();", tkn)
+
+
+REPLACEMENT_FUNCTIONS = {
+    "DEOPT_IF": replace_deopt,
+    "ERROR_IF": replace_error,
+    "DECREF_INPUTS": replace_decrefs,
+    "CHECK_EVAL_BREAKER": replace_check_eval_breaker,
+    "STORE_SP": replace_store_sp,
+}
+
+ReplacementFunctionType = Callable[
+    [CWriter, Token, Iterator[Token], Uop, Stack, Instruction | None], None
+]
+
+
+def emit_tokens(
+    out: CWriter,
+    uop: Uop,
+    stack: Stack,
+    inst: Instruction | None,
+    replacement_functions: Mapping[
+        str, ReplacementFunctionType
+    ] = REPLACEMENT_FUNCTIONS,
+) -> None:
+    tkns = uop.body[1:-1]
+    if not tkns:
+        return
+    tkn_iter = iter(tkns)
+    out.start_line()
+    for tkn in tkn_iter:
+        if tkn.kind == "IDENTIFIER" and tkn.text in replacement_functions:
+            replacement_functions[tkn.text](out, tkn, tkn_iter, uop, stack, inst)
+        else:
+            out.emit(tkn)
index a1f6f62156ebd3fc39e862e782f80b744bc711ab..ddbb409bbced39cec1793497f1c32986d6d36a24 100644 (file)
@@ -24,7 +24,7 @@ from typing import TextIO
 DEFAULT_OUTPUT = ROOT / "Include/opcode_ids.h"
 
 
-def generate_opcode_header(filenames: str, analysis: Analysis, outfile: TextIO) -> None:
+def generate_opcode_header(filenames: list[str], analysis: Analysis, outfile: TextIO) -> None:
     write_header(__file__, filenames, outfile)
     out = CWriter(outfile, 0, False)
     out.emit("\n")
index 9cd8e1a3b2edf84fa4f84efde568cef672f8adf8..c36a56ebf2d38166256e2692eb99179827d8ba7a 100644 (file)
@@ -2,6 +2,7 @@ import sys
 from analyzer import StackItem
 from dataclasses import dataclass
 from formatting import maybe_parenthesize
+from cwriter import CWriter
 
 
 def var_size(var: StackItem) -> str:
@@ -79,3 +80,89 @@ class StackOffset:
     def clear(self) -> None:
         self.popped = []
         self.pushed = []
+
+
+class SizeMismatch(Exception):
+    pass
+
+
+class Stack:
+    def __init__(self) -> None:
+        self.top_offset = StackOffset()
+        self.base_offset = StackOffset()
+        self.peek_offset = StackOffset()
+        self.variables: list[StackItem] = []
+        self.defined: set[str] = set()
+
+    def pop(self, var: StackItem) -> str:
+        self.top_offset.pop(var)
+        if not var.peek:
+            self.peek_offset.pop(var)
+        indirect = "&" if var.is_array() else ""
+        if self.variables:
+            popped = self.variables.pop()
+            if popped.size != var.size:
+                raise SizeMismatch(
+                    f"Size mismatch when popping '{popped.name}' from stack to assign to {var.name}. "
+                    f"Expected {var.size} got {popped.size}"
+                )
+            if popped.name == var.name:
+                return ""
+            elif popped.name == "unused":
+                self.defined.add(var.name)
+                return (
+                    f"{var.name} = {indirect}stack_pointer[{self.top_offset.to_c()}];\n"
+                )
+            elif var.name == "unused":
+                return ""
+            else:
+                self.defined.add(var.name)
+                return f"{var.name} = {popped.name};\n"
+        self.base_offset.pop(var)
+        if var.name == "unused":
+            return ""
+        else:
+            self.defined.add(var.name)
+        cast = f"({var.type})" if (not indirect and var.type) else ""
+        assign = (
+            f"{var.name} = {cast}{indirect}stack_pointer[{self.base_offset.to_c()}];"
+        )
+        if var.condition:
+            return f"if ({var.condition}) {{ {assign} }}\n"
+        return f"{assign}\n"
+
+    def push(self, var: StackItem) -> str:
+        self.variables.append(var)
+        if var.is_array() and var.name not in self.defined and var.name != "unused":
+            c_offset = self.top_offset.to_c()
+            self.top_offset.push(var)
+            self.defined.add(var.name)
+            return f"{var.name} = &stack_pointer[{c_offset}];\n"
+        else:
+            self.top_offset.push(var)
+            return ""
+
+    def flush(self, out: CWriter) -> None:
+        for var in self.variables:
+            if not var.peek:
+                cast = "(PyObject *)" if var.type else ""
+                if var.name != "unused" and not var.is_array():
+                    if var.condition:
+                        out.emit(f" if ({var.condition}) ")
+                    out.emit(
+                        f"stack_pointer[{self.base_offset.to_c()}] = {cast}{var.name};\n"
+                    )
+            self.base_offset.push(var)
+        if self.base_offset.to_c() != self.top_offset.to_c():
+            print("base", self.base_offset.to_c(), "top", self.top_offset.to_c())
+            assert False
+        number = self.base_offset.to_c()
+        if number != "0":
+            out.emit(f"stack_pointer += {number};\n")
+        self.variables = []
+        self.base_offset.clear()
+        self.top_offset.clear()
+        self.peek_offset.clear()
+
+    def as_comment(self) -> str:
+        return f"/* Variables: {[v.name for v in self.variables]}. Base offset: {self.base_offset.to_c()}. Top offset: {self.top_offset.to_c()} */"
index 56ae660a6868225a0af6152ad84e6a9913eb89fe..11885dca6fe1a2286f60e9b586b73379b6c8fbbf 100644 (file)
@@ -21,11 +21,12 @@ from generators_common import (
     DEFAULT_INPUT,
     ROOT,
     write_header,
+    emit_tokens,
 )
 from cwriter import CWriter
 from typing import TextIO, Iterator
 from lexer import Token
-from stack import StackOffset
+from stack import StackOffset, Stack, SizeMismatch
 
 
 DEFAULT_OUTPUT = ROOT / "Python/generated_cases.c.h"
@@ -34,88 +35,6 @@ DEFAULT_OUTPUT = ROOT / "Python/generated_cases.c.h"
 FOOTER = "#undef TIER_ONE\n"
 
 
-class SizeMismatch(Exception):
-    pass
-
-
-class Stack:
-    def __init__(self) -> None:
-        self.top_offset = StackOffset()
-        self.base_offset = StackOffset()
-        self.peek_offset = StackOffset()
-        self.variables: list[StackItem] = []
-        self.defined: set[str] = set()
-
-    def pop(self, var: StackItem) -> str:
-        self.top_offset.pop(var)
-        if not var.peek:
-            self.peek_offset.pop(var)
-        indirect = "&" if var.is_array() else ""
-        if self.variables:
-            popped = self.variables.pop()
-            if popped.size != var.size:
-                raise SizeMismatch(
-                    f"Size mismatch when popping '{popped.name}' from stack to assign to {var.name}. "
-                    f"Expected {var.size} got {popped.size}"
-                )
-            if popped.name == var.name:
-                return ""
-            elif popped.name == "unused":
-                self.defined.add(var.name)
-                return (
-                    f"{var.name} = {indirect}stack_pointer[{self.top_offset.to_c()}];\n"
-                )
-            elif var.name == "unused":
-                return ""
-            else:
-                self.defined.add(var.name)
-                return f"{var.name} = {popped.name};\n"
-        self.base_offset.pop(var)
-        if var.name == "unused":
-            return ""
-        else:
-            self.defined.add(var.name)
-        assign = f"{var.name} = {indirect}stack_pointer[{self.base_offset.to_c()}];"
-        if var.condition:
-            return f"if ({var.condition}) {{ {assign} }}\n"
-        return f"{assign}\n"
-
-    def push(self, var: StackItem) -> str:
-        self.variables.append(var)
-        if var.is_array() and var.name not in self.defined and var.name != "unused":
-            c_offset = self.top_offset.to_c()
-            self.top_offset.push(var)
-            self.defined.add(var.name)
-            return f"{var.name} = &stack_pointer[{c_offset}];\n"
-        else:
-            self.top_offset.push(var)
-            return ""
-
-    def flush(self, out: CWriter) -> None:
-        for var in self.variables:
-            if not var.peek:
-                if var.name != "unused" and not var.is_array():
-                    if var.condition:
-                        out.emit(f" if ({var.condition}) ")
-                    out.emit(
-                        f"stack_pointer[{self.base_offset.to_c()}] = {var.name};\n"
-                    )
-            self.base_offset.push(var)
-        if self.base_offset.to_c() != self.top_offset.to_c():
-            print("base", self.base_offset.to_c(), "top", self.top_offset.to_c())
-            assert False
-        number = self.base_offset.to_c()
-        if number != "0":
-            out.emit(f"stack_pointer += {number};\n")
-        self.variables = []
-        self.base_offset.clear()
-        self.top_offset.clear()
-        self.peek_offset.clear()
-
-    def as_comment(self) -> str:
-        return f"/* Variables: {[v.name for v in self.variables]}. Base offset: {self.base_offset.to_c()}. Top offset: {self.top_offset.to_c()} */"
-
-
 def declare_variables(inst: Instruction, out: CWriter) -> None:
     variables = {"unused"}
     for uop in inst.parts:
@@ -138,145 +57,6 @@ def declare_variables(inst: Instruction, out: CWriter) -> None:
                         out.emit(f"{type}{var.name};\n")
 
 
-def emit_to(out: CWriter, tkn_iter: Iterator[Token], end: str) -> None:
-    parens = 0
-    for tkn in tkn_iter:
-        if tkn.kind == end and parens == 0:
-            return
-        if tkn.kind == "LPAREN":
-            parens += 1
-        if tkn.kind == "RPAREN":
-            parens -= 1
-        out.emit(tkn)
-
-
-def replace_deopt(
-    out: CWriter,
-    tkn: Token,
-    tkn_iter: Iterator[Token],
-    uop: Uop,
-    unused: Stack,
-    inst: Instruction,
-) -> None:
-    out.emit_at("DEOPT_IF", tkn)
-    out.emit(next(tkn_iter))
-    emit_to(out, tkn_iter, "RPAREN")
-    next(tkn_iter)  # Semi colon
-    out.emit(", ")
-    assert inst.family is not None
-    out.emit(inst.family.name)
-    out.emit(");\n")
-
-
-def replace_error(
-    out: CWriter,
-    tkn: Token,
-    tkn_iter: Iterator[Token],
-    uop: Uop,
-    stack: Stack,
-    inst: Instruction,
-) -> None:
-    out.emit_at("if ", tkn)
-    out.emit(next(tkn_iter))
-    emit_to(out, tkn_iter, "COMMA")
-    label = next(tkn_iter).text
-    next(tkn_iter)  # RPAREN
-    next(tkn_iter)  # Semi colon
-    out.emit(") ")
-    c_offset = stack.peek_offset.to_c()
-    try:
-        offset = -int(c_offset)
-        close = ";\n"
-    except ValueError:
-        offset = None
-        out.emit(f"{{ stack_pointer += {c_offset}; ")
-        close = "; }\n"
-    out.emit("goto ")
-    if offset:
-        out.emit(f"pop_{offset}_")
-    out.emit(label)
-    out.emit(close)
-
-
-def replace_decrefs(
-    out: CWriter,
-    tkn: Token,
-    tkn_iter: Iterator[Token],
-    uop: Uop,
-    stack: Stack,
-    inst: Instruction,
-) -> None:
-    next(tkn_iter)
-    next(tkn_iter)
-    next(tkn_iter)
-    out.emit_at("", tkn)
-    for var in uop.stack.inputs:
-        if var.name == "unused" or var.name == "null" or var.peek:
-            continue
-        if var.size != "1":
-            out.emit(f"for (int _i = {var.size}; --_i >= 0;) {{\n")
-            out.emit(f"Py_DECREF({var.name}[_i]);\n")
-            out.emit("}\n")
-        elif var.condition:
-            out.emit(f"Py_XDECREF({var.name});\n")
-        else:
-            out.emit(f"Py_DECREF({var.name});\n")
-
-
-def replace_store_sp(
-    out: CWriter,
-    tkn: Token,
-    tkn_iter: Iterator[Token],
-    uop: Uop,
-    stack: Stack,
-    inst: Instruction,
-) -> None:
-    next(tkn_iter)
-    next(tkn_iter)
-    next(tkn_iter)
-    out.emit_at("", tkn)
-    stack.flush(out)
-    out.emit("_PyFrame_SetStackPointer(frame, stack_pointer);\n")
-
-
-def replace_check_eval_breaker(
-    out: CWriter,
-    tkn: Token,
-    tkn_iter: Iterator[Token],
-    uop: Uop,
-    stack: Stack,
-    inst: Instruction,
-) -> None:
-    next(tkn_iter)
-    next(tkn_iter)
-    next(tkn_iter)
-    if not uop.properties.ends_with_eval_breaker:
-        out.emit_at("CHECK_EVAL_BREAKER();", tkn)
-
-
-REPLACEMENT_FUNCTIONS = {
-    "DEOPT_IF": replace_deopt,
-    "ERROR_IF": replace_error,
-    "DECREF_INPUTS": replace_decrefs,
-    "CHECK_EVAL_BREAKER": replace_check_eval_breaker,
-    "STORE_SP": replace_store_sp,
-}
-
-
-# Move this to formatter
-def emit_tokens(out: CWriter, uop: Uop, stack: Stack, inst: Instruction) -> None:
-    tkns = uop.body[1:-1]
-    if not tkns:
-        return
-    tkn_iter = iter(tkns)
-    out.start_line()
-    for tkn in tkn_iter:
-        if tkn.kind == "IDENTIFIER" and tkn.text in REPLACEMENT_FUNCTIONS:
-            REPLACEMENT_FUNCTIONS[tkn.text](out, tkn, tkn_iter, uop, stack, inst)
-        else:
-            out.emit(tkn)
-
-
 def write_uop(
     uop: Part, out: CWriter, offset: int, stack: Stack, inst: Instruction, braces: bool
 ) -> int:
@@ -334,7 +114,7 @@ def uses_this(inst: Instruction) -> bool:
 
 
 def generate_tier1(
-    filenames: str, analysis: Analysis, outfile: TextIO, lines: bool
+    filenames: list[str], analysis: Analysis, outfile: TextIO, lines: bool
 ) -> None:
     write_header(__file__, filenames, outfile)
     outfile.write(
@@ -404,7 +184,7 @@ arg_parser.add_argument(
 if __name__ == "__main__":
     args = arg_parser.parse_args()
     if len(args.input) == 0:
-        args.input.append(DEFAULT_INPUT.as_posix())
+        args.input.append(DEFAULT_INPUT)
     data = analyze_files(args.input)
     with open(args.output, "w") as outfile:
         generate_tier1(args.input, data, outfile, args.emit_line_directives)
diff --git a/Tools/cases_generator/tier2_generator.py b/Tools/cases_generator/tier2_generator.py
new file mode 100644 (file)
index 0000000..d2b5039
--- /dev/null
@@ -0,0 +1,202 @@
+"""Generate the cases for the tier 2 interpreter.
+Reads the instruction definitions from bytecodes.c.
+Writes the cases to executor_cases.c.h, which is #included in ceval.c.
+"""
+
+import argparse
+import os.path
+import sys
+
+from analyzer import (
+    Analysis,
+    Instruction,
+    Uop,
+    Part,
+    analyze_files,
+    Skip,
+    StackItem,
+    analysis_error,
+)
+from generators_common import (
+    DEFAULT_INPUT,
+    ROOT,
+    write_header,
+    emit_tokens,
+    emit_to,
+    REPLACEMENT_FUNCTIONS,
+)
+from cwriter import CWriter
+from typing import TextIO, Iterator
+from lexer import Token
+from stack import StackOffset, Stack, SizeMismatch
+
+DEFAULT_OUTPUT = ROOT / "Python/executor_cases.c.h"
+
+
+def declare_variables(uop: Uop, out: CWriter) -> None:
+    variables = {"unused"}
+    for var in reversed(uop.stack.inputs):
+        if var.name not in variables:
+            type = var.type if var.type else "PyObject *"
+            variables.add(var.name)
+            if var.condition:
+                out.emit(f"{type}{var.name} = NULL;\n")
+            else:
+                out.emit(f"{type}{var.name};\n")
+    for var in uop.stack.outputs:
+        if var.name not in variables:
+            variables.add(var.name)
+            type = var.type if var.type else "PyObject *"
+            if var.condition:
+                out.emit(f"{type}{var.name} = NULL;\n")
+            else:
+                out.emit(f"{type}{var.name};\n")
+
+
+def tier2_replace_error(
+    out: CWriter,
+    tkn: Token,
+    tkn_iter: Iterator[Token],
+    uop: Uop,
+    stack: Stack,
+    inst: Instruction | None,
+) -> None:
+    out.emit_at("if ", tkn)
+    out.emit(next(tkn_iter))
+    emit_to(out, tkn_iter, "COMMA")
+    label = next(tkn_iter).text
+    next(tkn_iter)  # RPAREN
+    next(tkn_iter)  # Semi colon
+    out.emit(") ")
+    c_offset = stack.peek_offset.to_c()
+    try:
+        offset = -int(c_offset)
+        close = ";\n"
+    except ValueError:
+        offset = None
+        out.emit(f"{{ stack_pointer += {c_offset}; ")
+        close = "; }\n"
+    out.emit("goto ")
+    if offset:
+        out.emit(f"pop_{offset}_")
+    out.emit(label + "_tier_two")
+    out.emit(close)
+
+
+def tier2_replace_deopt(
+    out: CWriter,
+    tkn: Token,
+    tkn_iter: Iterator[Token],
+    uop: Uop,
+    unused: Stack,
+    inst: Instruction | None,
+) -> None:
+    out.emit_at("if ", tkn)
+    out.emit(next(tkn_iter))
+    emit_to(out, tkn_iter, "RPAREN")
+    next(tkn_iter)  # Semi colon
+    out.emit(") goto deoptimize;\n")
+
+
+TIER2_REPLACEMENT_FUNCTIONS = REPLACEMENT_FUNCTIONS.copy()
+TIER2_REPLACEMENT_FUNCTIONS["ERROR_IF"] = tier2_replace_error
+TIER2_REPLACEMENT_FUNCTIONS["DEOPT_IF"] = tier2_replace_deopt
+
+
+def is_super(uop: Uop) -> bool:
+    for tkn in uop.body:
+        if tkn.kind == "IDENTIFIER" and tkn.text == "oparg1":
+            return True
+    return False
+
+
+def write_uop(uop: Uop, out: CWriter, stack: Stack) -> None:
+    try:
+        out.start_line()
+        if uop.properties.oparg:
+            out.emit("oparg = CURRENT_OPARG();\n")
+        for var in reversed(uop.stack.inputs):
+            out.emit(stack.pop(var))
+        if not uop.properties.stores_sp:
+            for i, var in enumerate(uop.stack.outputs):
+                out.emit(stack.push(var))
+        for cache in uop.caches:
+            if cache.name != "unused":
+                if cache.size == 4:
+                    type = "PyObject *"
+                else:
+                    type = f"uint{cache.size*16}_t"
+                out.emit(f"{type} {cache.name} = ({type})CURRENT_OPERAND();\n")
+        emit_tokens(out, uop, stack, None, TIER2_REPLACEMENT_FUNCTIONS)
+        if uop.properties.stores_sp:
+            for i, var in enumerate(uop.stack.outputs):
+                out.emit(stack.push(var))
+    except SizeMismatch as ex:
+        raise analysis_error(ex.args[0], uop.body[0])
+
+
+SKIPS = ("_EXTENDED_ARG",)
+
+
+def generate_tier2(
+    filenames: list[str], analysis: Analysis, outfile: TextIO, lines: bool
+) -> None:
+    write_header(__file__, filenames, outfile)
+    outfile.write(
+        """
+#ifdef TIER_ONE
+    #error "This file is for Tier 2 only"
+#endif
+#define TIER_TWO 2
+"""
+    )
+    out = CWriter(outfile, 2, lines)
+    out.emit("\n")
+    for name, uop in analysis.uops.items():
+        if uop.properties.tier_one_only:
+            continue
+        if is_super(uop):
+            continue
+        if not uop.is_viable():
+            out.emit(f"/* {uop.name} is not a viable micro-op for tier 2 */\n\n")
+            continue
+        out.emit(f"case {uop.name}: {{\n")
+        declare_variables(uop, out)
+        stack = Stack()
+        write_uop(uop, out, stack)
+        out.start_line()
+        if not uop.properties.always_exits:
+            stack.flush(out)
+            if uop.properties.ends_with_eval_breaker:
+                out.emit("CHECK_EVAL_BREAKER();\n")
+            out.emit("break;\n")
+        out.start_line()
+        out.emit("}")
+        out.emit("\n\n")
+    outfile.write("#undef TIER_TWO\n")
+
+
+arg_parser = argparse.ArgumentParser(
+    description="Generate the code for the tier 2 interpreter.",
+    formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+)
+
+arg_parser.add_argument(
+    "-o", "--output", type=str, help="Generated code", default=DEFAULT_OUTPUT
+)
+
+arg_parser.add_argument(
+    "-l", "--emit-line-directives", help="Emit #line directives", action="store_true"
+)
+
+arg_parser.add_argument(
+    "input", nargs=argparse.REMAINDER, help="Instruction definition file(s)"
+)
+
+if __name__ == "__main__":
+    args = arg_parser.parse_args()
+    if len(args.input) == 0:
+        args.input.append(DEFAULT_INPUT)
+    data = analyze_files(args.input)
+    with open(args.output, "w") as outfile:
+        generate_tier2(args.input, data, outfile, args.emit_line_directives)
index 4a96dbc171ee221f3043f8781cbc5cfcf7a8808c..277da25835f6fbb465fb8c2589993adfc75dd6e6 100644 (file)
@@ -24,8 +24,11 @@ from typing import TextIO
 DEFAULT_OUTPUT = ROOT / "Include/internal/pycore_uop_ids.h"
 
 
+OMIT = {"_CACHE", "_RESERVED", "_EXTENDED_ARG"}
+
+
 def generate_uop_ids(
-    filenames: str, analysis: Analysis, outfile: TextIO, distinct_namespace: bool
+    filenames: list[str], analysis: Analysis, outfile: TextIO, distinct_namespace: bool
 ) -> None:
     write_header(__file__, filenames, outfile)
     out = CWriter(outfile, 0, False)
@@ -45,11 +48,15 @@ extern "C" {
     next_id += 1
     out.emit(f"#define _SET_IP {next_id}\n")
     next_id += 1
-    PRE_DEFINED = {"_EXIT_TRACE", "_SET_IP", "_CACHE", "_RESERVED", "_EXTENDED_ARG"}
+    PRE_DEFINED = {"_EXIT_TRACE", "_SET_IP"}
 
     for uop in analysis.uops.values():
         if uop.name in PRE_DEFINED:
             continue
+        # TODO: We should omit all tier-1 only uops, but
+        # generate_cases.py still generates code for those.
+        if uop.name in OMIT:
+            continue
         if uop.implicitly_created and not distinct_namespace:
             out.emit(f"#define {uop.name} {uop.name[1:]}\n")
         else:
@@ -85,7 +92,7 @@ arg_parser.add_argument(
 if __name__ == "__main__":
     args = arg_parser.parse_args()
     if len(args.input) == 0:
-        args.input.append(DEFAULT_INPUT.as_posix())
+        args.input.append(DEFAULT_INPUT)
     data = analyze_files(args.input)
     with open(args.output, "w") as outfile:
         generate_uop_ids(args.input, data, outfile, args.namespace)