]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-143092: Make CALL_LIST_APPEND and BINARY_OP_INPLACE_ADD_UNICODE normal instruction...
authorKen Jin <kenjin@python.org>
Wed, 24 Dec 2025 22:03:00 +0000 (06:03 +0800)
committerGitHub <noreply@github.com>
Wed, 24 Dec 2025 22:03:00 +0000 (22:03 +0000)
These super instructions need many special cases in the interpreter, specializer, and JIT. It's best we convert them to normal instructions.

14 files changed:
Include/internal/pycore_opcode_metadata.h
Include/internal/pycore_tstate.h
Include/internal/pycore_uop_ids.h
Include/internal/pycore_uop_metadata.h
Lib/_opcode_metadata.py
Lib/test/test_capi/test_opt.py
Misc/NEWS.d/next/Core_and_Builtins/2025-12-23-23-06-11.gh-issue-143092.6MISbb.rst [new file with mode: 0644]
Python/bytecodes.c
Python/executor_cases.c.h
Python/generated_cases.c.h
Python/optimizer.c
Python/optimizer_bytecodes.c
Python/optimizer_cases.c.h
Python/specialize.c

index 08bddfbfbe661919ecb53f5fc6fce2ca249825b9..8920dd42d7384ae51ee45e7e6b614d79bd9dd1c2 100644 (file)
@@ -534,7 +534,7 @@ int _PyOpcode_num_pushed(int opcode, int oparg)  {
         case BINARY_OP_EXTEND:
             return 1;
         case BINARY_OP_INPLACE_ADD_UNICODE:
-            return 0;
+            return 1;
         case BINARY_OP_MULTIPLY_FLOAT:
             return 1;
         case BINARY_OP_MULTIPLY_INT:
@@ -610,7 +610,7 @@ int _PyOpcode_num_pushed(int opcode, int oparg)  {
         case CALL_LEN:
             return 1;
         case CALL_LIST_APPEND:
-            return 0;
+            return 1;
         case CALL_METHOD_DESCRIPTOR_FAST:
             return 1;
         case CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS:
index a57f1f45c135a60f574fb1b1d72c0e70c1606ff2..1a7ebb01403208e38c11f586ff704284e99a0c67 100644 (file)
@@ -37,7 +37,6 @@ typedef struct _PyJitTracerInitialState {
 
 typedef struct _PyJitTracerPreviousState {
     bool dependencies_still_valid;
-    bool instr_is_super;
     int code_max_size;
     int code_curr_size;
     int instr_oparg;
index 69f1c3829cd239b9c668108f59f37d8e3507b413..42fb9464b6a13de0968766f6cc5a1c9b2989f649 100644 (file)
@@ -371,7 +371,7 @@ extern "C" {
 #define _BINARY_OP_ADD_UNICODE_r13 564
 #define _BINARY_OP_ADD_UNICODE_r23 565
 #define _BINARY_OP_EXTEND_r21 566
-#define _BINARY_OP_INPLACE_ADD_UNICODE_r20 567
+#define _BINARY_OP_INPLACE_ADD_UNICODE_r21 567
 #define _BINARY_OP_MULTIPLY_FLOAT_r03 568
 #define _BINARY_OP_MULTIPLY_FLOAT_r13 569
 #define _BINARY_OP_MULTIPLY_FLOAT_r23 570
@@ -412,10 +412,10 @@ extern "C" {
 #define _CALL_ISINSTANCE_r31 605
 #define _CALL_KW_NON_PY_r11 606
 #define _CALL_LEN_r33 607
-#define _CALL_LIST_APPEND_r02 608
-#define _CALL_LIST_APPEND_r12 609
-#define _CALL_LIST_APPEND_r22 610
-#define _CALL_LIST_APPEND_r32 611
+#define _CALL_LIST_APPEND_r03 608
+#define _CALL_LIST_APPEND_r13 609
+#define _CALL_LIST_APPEND_r23 610
+#define _CALL_LIST_APPEND_r33 611
 #define _CALL_METHOD_DESCRIPTOR_FAST_r01 612
 #define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01 613
 #define _CALL_METHOD_DESCRIPTOR_NOARGS_r01 614
index 0a49231e53f44aad38534fede70148543d740ab8..8b14ca794ce8d5fba8d8c5246296f7a751b5b8dd 100644 (file)
@@ -1065,7 +1065,7 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = {
         .entries = {
             { -1, -1, -1 },
             { -1, -1, -1 },
-            { 0, 2, _BINARY_OP_INPLACE_ADD_UNICODE_r20 },
+            { 1, 2, _BINARY_OP_INPLACE_ADD_UNICODE_r21 },
             { -1, -1, -1 },
         },
     },
@@ -2629,10 +2629,10 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = {
     [_CALL_LIST_APPEND] = {
         .best = { 0, 1, 2, 3 },
         .entries = {
-            { 2, 0, _CALL_LIST_APPEND_r02 },
-            { 2, 1, _CALL_LIST_APPEND_r12 },
-            { 2, 2, _CALL_LIST_APPEND_r22 },
-            { 2, 3, _CALL_LIST_APPEND_r32 },
+            { 3, 0, _CALL_LIST_APPEND_r03 },
+            { 3, 1, _CALL_LIST_APPEND_r13 },
+            { 3, 2, _CALL_LIST_APPEND_r23 },
+            { 3, 3, _CALL_LIST_APPEND_r33 },
         },
     },
     [_CALL_METHOD_DESCRIPTOR_O] = {
@@ -3437,7 +3437,7 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = {
     [_BINARY_OP_ADD_UNICODE_r03] = _BINARY_OP_ADD_UNICODE,
     [_BINARY_OP_ADD_UNICODE_r13] = _BINARY_OP_ADD_UNICODE,
     [_BINARY_OP_ADD_UNICODE_r23] = _BINARY_OP_ADD_UNICODE,
-    [_BINARY_OP_INPLACE_ADD_UNICODE_r20] = _BINARY_OP_INPLACE_ADD_UNICODE,
+    [_BINARY_OP_INPLACE_ADD_UNICODE_r21] = _BINARY_OP_INPLACE_ADD_UNICODE,
     [_GUARD_BINARY_OP_EXTEND_r22] = _GUARD_BINARY_OP_EXTEND,
     [_BINARY_OP_EXTEND_r21] = _BINARY_OP_EXTEND,
     [_BINARY_SLICE_r31] = _BINARY_SLICE,
@@ -3743,10 +3743,10 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = {
     [_GUARD_CALLABLE_LIST_APPEND_r13] = _GUARD_CALLABLE_LIST_APPEND,
     [_GUARD_CALLABLE_LIST_APPEND_r23] = _GUARD_CALLABLE_LIST_APPEND,
     [_GUARD_CALLABLE_LIST_APPEND_r33] = _GUARD_CALLABLE_LIST_APPEND,
-    [_CALL_LIST_APPEND_r02] = _CALL_LIST_APPEND,
-    [_CALL_LIST_APPEND_r12] = _CALL_LIST_APPEND,
-    [_CALL_LIST_APPEND_r22] = _CALL_LIST_APPEND,
-    [_CALL_LIST_APPEND_r32] = _CALL_LIST_APPEND,
+    [_CALL_LIST_APPEND_r03] = _CALL_LIST_APPEND,
+    [_CALL_LIST_APPEND_r13] = _CALL_LIST_APPEND,
+    [_CALL_LIST_APPEND_r23] = _CALL_LIST_APPEND,
+    [_CALL_LIST_APPEND_r33] = _CALL_LIST_APPEND,
     [_CALL_METHOD_DESCRIPTOR_O_r01] = _CALL_METHOD_DESCRIPTOR_O,
     [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS_r01] = _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS,
     [_CALL_METHOD_DESCRIPTOR_NOARGS_r01] = _CALL_METHOD_DESCRIPTOR_NOARGS,
@@ -3944,7 +3944,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = {
     [_BINARY_OP_EXTEND] = "_BINARY_OP_EXTEND",
     [_BINARY_OP_EXTEND_r21] = "_BINARY_OP_EXTEND_r21",
     [_BINARY_OP_INPLACE_ADD_UNICODE] = "_BINARY_OP_INPLACE_ADD_UNICODE",
-    [_BINARY_OP_INPLACE_ADD_UNICODE_r20] = "_BINARY_OP_INPLACE_ADD_UNICODE_r20",
+    [_BINARY_OP_INPLACE_ADD_UNICODE_r21] = "_BINARY_OP_INPLACE_ADD_UNICODE_r21",
     [_BINARY_OP_MULTIPLY_FLOAT] = "_BINARY_OP_MULTIPLY_FLOAT",
     [_BINARY_OP_MULTIPLY_FLOAT_r03] = "_BINARY_OP_MULTIPLY_FLOAT_r03",
     [_BINARY_OP_MULTIPLY_FLOAT_r13] = "_BINARY_OP_MULTIPLY_FLOAT_r13",
@@ -4015,10 +4015,10 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = {
     [_CALL_LEN] = "_CALL_LEN",
     [_CALL_LEN_r33] = "_CALL_LEN_r33",
     [_CALL_LIST_APPEND] = "_CALL_LIST_APPEND",
-    [_CALL_LIST_APPEND_r02] = "_CALL_LIST_APPEND_r02",
-    [_CALL_LIST_APPEND_r12] = "_CALL_LIST_APPEND_r12",
-    [_CALL_LIST_APPEND_r22] = "_CALL_LIST_APPEND_r22",
-    [_CALL_LIST_APPEND_r32] = "_CALL_LIST_APPEND_r32",
+    [_CALL_LIST_APPEND_r03] = "_CALL_LIST_APPEND_r03",
+    [_CALL_LIST_APPEND_r13] = "_CALL_LIST_APPEND_r13",
+    [_CALL_LIST_APPEND_r23] = "_CALL_LIST_APPEND_r23",
+    [_CALL_LIST_APPEND_r33] = "_CALL_LIST_APPEND_r33",
     [_CALL_METHOD_DESCRIPTOR_FAST] = "_CALL_METHOD_DESCRIPTOR_FAST",
     [_CALL_METHOD_DESCRIPTOR_FAST_r01] = "_CALL_METHOD_DESCRIPTOR_FAST_r01",
     [_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS] = "_CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS",
index e681cb17e43e047f647c0f013cfba799fbf8fe47..b3dce93710a23f4ad51ac45f2f39a8d3ef5e5115 100644 (file)
@@ -28,6 +28,7 @@ _specializations = {
         "BINARY_OP_SUBSCR_STR_INT",
         "BINARY_OP_SUBSCR_DICT",
         "BINARY_OP_SUBSCR_GETITEM",
+        "BINARY_OP_INPLACE_ADD_UNICODE",
         "BINARY_OP_EXTEND",
         "BINARY_OP_INPLACE_ADD_UNICODE",
     ],
@@ -125,6 +126,7 @@ _specialized_opmap = {
     'BINARY_OP_ADD_UNICODE': 131,
     'BINARY_OP_EXTEND': 132,
     'BINARY_OP_INPLACE_ADD_UNICODE': 3,
+    'BINARY_OP_INPLACE_ADD_UNICODE': 3,
     'BINARY_OP_MULTIPLY_FLOAT': 133,
     'BINARY_OP_MULTIPLY_INT': 134,
     'BINARY_OP_SUBSCR_DICT': 135,
index 8f7314d579df6ff75211a18cafc16872f990adb9..9c9135411f90789044ce1e833737bb9d739bdaa4 100644 (file)
@@ -3152,6 +3152,47 @@ class TestUopsOptimization(unittest.TestCase):
         """), PYTHON_JIT="1")
         self.assertEqual(result[0].rc, 0, result)
 
+    def test_143092(self):
+        def f1():
+            a = "a"
+            for i in range(50):
+                x = a[i % len(a)]
+
+            s = ""
+            for _ in range(10):
+                s += ""
+
+            class A: ...
+            class B: ...
+
+            match s:
+                case int(): ...
+                case str(): ...
+                case dict(): ...
+
+            (
+                u0,
+                *u1,
+                u2,
+                u4,
+                u5,
+                u6,
+                u7,
+                u8,
+                u9, u10, u11,
+                u12, u13, u14, u15, u16, u17, u18, u19, u20, u21, u22, u23, u24, u25, u26, u27, u28, u29,
+            ) = [None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
+                 None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
+                 None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
+                 None, None, None, None, None, None, None, None,]
+
+            s = ""
+            for _ in range(10):
+                s += ""
+                s += ""
+
+        for i in range(TIER2_THRESHOLD * 10):
+            f1()
 
 def global_identity(x):
     return x
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-23-23-06-11.gh-issue-143092.6MISbb.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-23-23-06-11.gh-issue-143092.6MISbb.rst
new file mode 100644 (file)
index 0000000..dddfc56
--- /dev/null
@@ -0,0 +1 @@
+Fix a crash in the JIT when dealing with ``list.append(x)`` style code.
index 9232a16551d8a25329488e0462f3ebbcc98b64a4..b909ee187950ec3bcb138a455e71f6b4e4e8022f 100644 (file)
@@ -588,7 +588,7 @@ dummy_func(
             BINARY_OP_SUBSCR_STR_INT,
             BINARY_OP_SUBSCR_DICT,
             BINARY_OP_SUBSCR_GETITEM,
-            // BINARY_OP_INPLACE_ADD_UNICODE,  // See comments at that opcode.
+            BINARY_OP_INPLACE_ADD_UNICODE,
             BINARY_OP_EXTEND,
         };
 
@@ -762,13 +762,10 @@ dummy_func(
         macro(BINARY_OP_ADD_UNICODE) =
             _GUARD_TOS_UNICODE + _GUARD_NOS_UNICODE + unused/5 + _BINARY_OP_ADD_UNICODE + _POP_TOP_UNICODE + _POP_TOP_UNICODE;
 
-        // This is a subtle one. It's a super-instruction for
-        // BINARY_OP_ADD_UNICODE followed by STORE_FAST
-        // where the store goes into the left argument.
-        // So the inputs are the same as for all BINARY_OP
-        // specializations, but there is no output.
-        // At the end we just skip over the STORE_FAST.
-        op(_BINARY_OP_INPLACE_ADD_UNICODE, (left, right --)) {
+        // This is a subtle one. We write NULL to the local
+        // of the following STORE_FAST and leave the result for STORE_FAST
+        // later to store.
+        op(_BINARY_OP_INPLACE_ADD_UNICODE, (left, right -- res)) {
             PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
             assert(PyUnicode_CheckExact(left_o));
             assert(PyUnicode_CheckExact(PyStackRef_AsPyObjectBorrow(right)));
@@ -796,20 +793,16 @@ dummy_func(
              * that the string is safe to mutate.
              */
             assert(Py_REFCNT(left_o) >= 2 || !PyStackRef_IsHeapSafe(left));
-            PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc);
-            DEAD(left);
             PyObject *temp = PyStackRef_AsPyObjectSteal(*target_local);
-            PyObject *right_o = PyStackRef_AsPyObjectSteal(right);
+            PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
             PyUnicode_Append(&temp, right_o);
-            *target_local = PyStackRef_FromPyObjectSteal(temp);
-            Py_DECREF(right_o);
-            ERROR_IF(PyStackRef_IsNull(*target_local));
-        #if TIER_ONE
-            // The STORE_FAST is already done. This is done here in tier one,
-            // and during trace projection in tier two:
-            assert(next_instr->op.code == STORE_FAST);
-            SKIP_OVER(1);
-        #endif
+            PyStackRef_CLOSE_SPECIALIZED(right, _PyUnicode_ExactDealloc);
+            DEAD(right);
+            PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc);
+            DEAD(left);
+            ERROR_IF(temp == NULL);
+            res = PyStackRef_FromPyObjectSteal(temp);
+            *target_local = PyStackRef_NULL;
         }
 
        op(_GUARD_BINARY_OP_EXTEND, (descr/4, left, right -- left, right)) {
@@ -4330,8 +4323,7 @@ dummy_func(
             DEOPT_IF(callable_o != interp->callable_cache.list_append);
         }
 
-        // This is secretly a super-instruction
-        op(_CALL_LIST_APPEND, (callable, self, arg -- c, s)) {
+        op(_CALL_LIST_APPEND, (callable, self, arg -- none, c, s)) {
             assert(oparg == 1);
             PyObject *self_o = PyStackRef_AsPyObjectBorrow(self);
 
@@ -4344,13 +4336,9 @@ dummy_func(
             }
             c = callable;
             s = self;
-            INPUTS_DEAD();
-        #if TIER_ONE
-            // Skip the following POP_TOP. This is done here in tier one, and
-            // during trace projection in tier two:
-            assert(next_instr->op.code == POP_TOP);
-            SKIP_OVER(1);
-        #endif
+            DEAD(callable);
+            DEAD(self);
+            none = PyStackRef_None;
         }
 
          op(_CALL_METHOD_DESCRIPTOR_O, (callable, self_or_null, args[oparg] -- res)) {
@@ -5598,15 +5586,9 @@ dummy_func(
             // Super instructions. Instruction deopted. There's a mismatch in what the stack expects
             // in the optimizer. So we have to reflect in the trace correctly.
             _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
-            if ((_tstate->jit_tracer_state.prev_state.instr->op.code == CALL_LIST_APPEND &&
-                opcode == POP_TOP) ||
-                (_tstate->jit_tracer_state.prev_state.instr->op.code == BINARY_OP_INPLACE_ADD_UNICODE &&
-                opcode == STORE_FAST)) {
-                _tstate->jit_tracer_state.prev_state.instr_is_super = true;
-            }
-            else {
-                _tstate->jit_tracer_state.prev_state.instr = next_instr;
-            }
+            // JIT should have disabled super instructions, as we can
+            // do these optimizations ourselves in the JIT.
+            _tstate->jit_tracer_state.prev_state.instr = next_instr;
             PyObject *prev_code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
             if (_tstate->jit_tracer_state.prev_state.instr_code != (PyCodeObject *)prev_code) {
                 Py_SETREF(_tstate->jit_tracer_state.prev_state.instr_code, (PyCodeObject*)Py_NewRef((prev_code)));
index aa98d4019dbdffac96fe86a904de5a793efa5b87..b50347615c02f831883836d7470963fce31d0c82 100644 (file)
             break;
         }
 
-        case _BINARY_OP_INPLACE_ADD_UNICODE_r20: {
+        case _BINARY_OP_INPLACE_ADD_UNICODE_r21: {
             CHECK_CURRENT_CACHED_VALUES(2);
             assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
             _PyStackRef right;
             _PyStackRef left;
+            _PyStackRef res;
             _PyStackRef _stack_item_0 = _tos_cache0;
             _PyStackRef _stack_item_1 = _tos_cache1;
             right = _stack_item_1;
             }
             STAT_INC(BINARY_OP, hit);
             assert(Py_REFCNT(left_o) >= 2 || !PyStackRef_IsHeapSafe(left));
-            PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc);
             PyObject *temp = PyStackRef_AsPyObjectSteal(*target_local);
-            PyObject *right_o = PyStackRef_AsPyObjectSteal(right);
+            PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
+            stack_pointer[0] = left;
+            stack_pointer[1] = right;
+            stack_pointer += 2;
+            ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
             _PyFrame_SetStackPointer(frame, stack_pointer);
             PyUnicode_Append(&temp, right_o);
             stack_pointer = _PyFrame_GetStackPointer(frame);
-            *target_local = PyStackRef_FromPyObjectSteal(temp);
-            _PyFrame_SetStackPointer(frame, stack_pointer);
-            Py_DECREF(right_o);
-            stack_pointer = _PyFrame_GetStackPointer(frame);
-            if (PyStackRef_IsNull(*target_local)) {
+            PyStackRef_CLOSE_SPECIALIZED(right, _PyUnicode_ExactDealloc);
+            PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc);
+            if (temp == NULL) {
+                stack_pointer += -2;
+                ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
                 SET_CURRENT_CACHED_VALUES(0);
                 JUMP_TO_ERROR();
             }
-            #if TIER_ONE
-
-            assert(next_instr->op.code == STORE_FAST);
-            SKIP_OVER(1);
-            #endif
-            _tos_cache0 = PyStackRef_ZERO_BITS;
+            res = PyStackRef_FromPyObjectSteal(temp);
+            *target_local = PyStackRef_NULL;
+            _tos_cache0 = res;
             _tos_cache1 = PyStackRef_ZERO_BITS;
             _tos_cache2 = PyStackRef_ZERO_BITS;
-            SET_CURRENT_CACHED_VALUES(0);
+            SET_CURRENT_CACHED_VALUES(1);
+            stack_pointer += -2;
+            ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
             assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
             break;
         }
             break;
         }
 
-        case _CALL_LIST_APPEND_r02: {
+        case _CALL_LIST_APPEND_r03: {
             CHECK_CURRENT_CACHED_VALUES(0);
             assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
             _PyStackRef arg;
             _PyStackRef self;
             _PyStackRef callable;
+            _PyStackRef none;
             _PyStackRef c;
             _PyStackRef s;
             oparg = CURRENT_OPARG();
             }
             c = callable;
             s = self;
-            #if TIER_ONE
-
-            assert(next_instr->op.code == POP_TOP);
-            SKIP_OVER(1);
-            #endif
-            _tos_cache1 = s;
-            _tos_cache0 = c;
-            SET_CURRENT_CACHED_VALUES(2);
+            none = PyStackRef_None;
+            _tos_cache2 = s;
+            _tos_cache1 = c;
+            _tos_cache0 = none;
+            SET_CURRENT_CACHED_VALUES(3);
             stack_pointer += -3;
             ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
             assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
             break;
         }
 
-        case _CALL_LIST_APPEND_r12: {
+        case _CALL_LIST_APPEND_r13: {
             CHECK_CURRENT_CACHED_VALUES(1);
             assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
             _PyStackRef arg;
             _PyStackRef self;
             _PyStackRef callable;
+            _PyStackRef none;
             _PyStackRef c;
             _PyStackRef s;
             _PyStackRef _stack_item_0 = _tos_cache0;
             }
             c = callable;
             s = self;
-            #if TIER_ONE
-
-            assert(next_instr->op.code == POP_TOP);
-            SKIP_OVER(1);
-            #endif
-            _tos_cache1 = s;
-            _tos_cache0 = c;
-            SET_CURRENT_CACHED_VALUES(2);
+            none = PyStackRef_None;
+            _tos_cache2 = s;
+            _tos_cache1 = c;
+            _tos_cache0 = none;
+            SET_CURRENT_CACHED_VALUES(3);
             stack_pointer += -2;
             ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
             assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
             break;
         }
 
-        case _CALL_LIST_APPEND_r22: {
+        case _CALL_LIST_APPEND_r23: {
             CHECK_CURRENT_CACHED_VALUES(2);
             assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
             _PyStackRef arg;
             _PyStackRef self;
             _PyStackRef callable;
+            _PyStackRef none;
             _PyStackRef c;
             _PyStackRef s;
             _PyStackRef _stack_item_0 = _tos_cache0;
             }
             c = callable;
             s = self;
-            #if TIER_ONE
-
-            assert(next_instr->op.code == POP_TOP);
-            SKIP_OVER(1);
-            #endif
-            _tos_cache1 = s;
-            _tos_cache0 = c;
-            SET_CURRENT_CACHED_VALUES(2);
+            none = PyStackRef_None;
+            _tos_cache2 = s;
+            _tos_cache1 = c;
+            _tos_cache0 = none;
+            SET_CURRENT_CACHED_VALUES(3);
             stack_pointer += -1;
             ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
             assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
             break;
         }
 
-        case _CALL_LIST_APPEND_r32: {
+        case _CALL_LIST_APPEND_r33: {
             CHECK_CURRENT_CACHED_VALUES(3);
             assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
             _PyStackRef arg;
             _PyStackRef self;
             _PyStackRef callable;
+            _PyStackRef none;
             _PyStackRef c;
             _PyStackRef s;
             _PyStackRef _stack_item_0 = _tos_cache0;
             }
             c = callable;
             s = self;
-            #if TIER_ONE
-
-            assert(next_instr->op.code == POP_TOP);
-            SKIP_OVER(1);
-            #endif
-            _tos_cache1 = s;
-            _tos_cache0 = c;
-            SET_CURRENT_CACHED_VALUES(2);
+            none = PyStackRef_None;
+            _tos_cache2 = s;
+            _tos_cache1 = c;
+            _tos_cache0 = none;
+            SET_CURRENT_CACHED_VALUES(3);
             assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
             break;
         }
index 5f326d5c3caffc24759e7f58b91c3c03e8e80c5d..50759933814c4fb4482a31bc093bafeddd03906f 100644 (file)
             _PyStackRef nos;
             _PyStackRef left;
             _PyStackRef right;
+            _PyStackRef res;
             // _GUARD_TOS_UNICODE
             {
                 value = stack_pointer[-1];
                 }
                 STAT_INC(BINARY_OP, hit);
                 assert(Py_REFCNT(left_o) >= 2 || !PyStackRef_IsHeapSafe(left));
-                PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc);
                 PyObject *temp = PyStackRef_AsPyObjectSteal(*target_local);
-                PyObject *right_o = PyStackRef_AsPyObjectSteal(right);
-                stack_pointer += -2;
-                ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
+                PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
                 _PyFrame_SetStackPointer(frame, stack_pointer);
                 PyUnicode_Append(&temp, right_o);
                 stack_pointer = _PyFrame_GetStackPointer(frame);
-                *target_local = PyStackRef_FromPyObjectSteal(temp);
-                _PyFrame_SetStackPointer(frame, stack_pointer);
-                Py_DECREF(right_o);
-                stack_pointer = _PyFrame_GetStackPointer(frame);
-                if (PyStackRef_IsNull(*target_local)) {
-                    JUMP_TO_LABEL(error);
+                PyStackRef_CLOSE_SPECIALIZED(right, _PyUnicode_ExactDealloc);
+                PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc);
+                if (temp == NULL) {
+                    JUMP_TO_LABEL(pop_2_error);
                 }
-                #if TIER_ONE
-
-                assert(next_instr->op.code == STORE_FAST);
-                SKIP_OVER(1);
-                #endif
+                res = PyStackRef_FromPyObjectSteal(temp);
+                *target_local = PyStackRef_NULL;
             }
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
+            ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
             DISPATCH();
         }
 
             _PyStackRef nos;
             _PyStackRef self;
             _PyStackRef arg;
+            _PyStackRef none;
             _PyStackRef c;
             _PyStackRef s;
             _PyStackRef value;
                 }
                 c = callable;
                 s = self;
-                #if TIER_ONE
-
-                assert(next_instr->op.code == POP_TOP);
-                SKIP_OVER(1);
-                #endif
+                none = PyStackRef_None;
             }
             // _POP_TOP
             {
                 value = s;
-                stack_pointer[-3] = c;
-                stack_pointer += -2;
+                stack_pointer[-3] = none;
+                stack_pointer[-2] = c;
+                stack_pointer += -1;
                 ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
                 _PyFrame_SetStackPointer(frame, stack_pointer);
                 PyStackRef_XCLOSE(value);
                 DISPATCH();
             }
             _PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
-            if ((_tstate->jit_tracer_state.prev_state.instr->op.code == CALL_LIST_APPEND &&
-                 opcode == POP_TOP) ||
-                (_tstate->jit_tracer_state.prev_state.instr->op.code == BINARY_OP_INPLACE_ADD_UNICODE &&
-                 opcode == STORE_FAST)) {
-                _tstate->jit_tracer_state.prev_state.instr_is_super = true;
-            }
-            else {
-                _tstate->jit_tracer_state.prev_state.instr = next_instr;
-            }
+            _tstate->jit_tracer_state.prev_state.instr = next_instr;
             PyObject *prev_code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
             if (_tstate->jit_tracer_state.prev_state.instr_code != (PyCodeObject *)prev_code) {
                 _PyFrame_SetStackPointer(frame, stack_pointer);
index 0f8ddb4ba558d345c6ba7685d2b4896cdb26c6fe..5e97f20f869efd6304fa5bc0fa0a2843b359d65a 100644 (file)
@@ -703,12 +703,6 @@ _PyJit_translate_single_bytecode_to_trace(
     }
 #endif
 
-    // Skip over super instructions.
-    if (_tstate->jit_tracer_state.prev_state.instr_is_super) {
-        _tstate->jit_tracer_state.prev_state.instr_is_super = false;
-        return 1;
-    }
-
     if (opcode == ENTER_EXECUTOR) {
         goto full;
     }
@@ -1077,7 +1071,6 @@ _PyJit_TryInitializeTracing(
     _tstate->jit_tracer_state.prev_state.instr_frame = frame;
     _tstate->jit_tracer_state.prev_state.instr_oparg = oparg;
     _tstate->jit_tracer_state.prev_state.instr_stacklevel = curr_stackdepth;
-    _tstate->jit_tracer_state.prev_state.instr_is_super = false;
     assert(curr_instr->op.code == JUMP_BACKWARD_JIT || (exit != NULL));
     _tstate->jit_tracer_state.initial_state.jump_backward_instr = curr_instr;
 
index c53a2fb7570c0dc25c0d272d4d46ccfec7343580..1575b9e38424c5bde7a02ebb11f844bf1a57c71c 100644 (file)
@@ -299,14 +299,12 @@ dummy_func(void) {
     }
 
     op(_BINARY_OP_ADD_UNICODE, (left, right -- res, l, r)) {
-        REPLACE_OPCODE_IF_EVALUATES_PURE(left, right);
         res = sym_new_type(ctx, &PyUnicode_Type);
         l = left;
         r = right;
     }
 
-    op(_BINARY_OP_INPLACE_ADD_UNICODE, (left, right --)) {
-        JitOptRef res;
+    op(_BINARY_OP_INPLACE_ADD_UNICODE, (left, right -- res)) {
         if (sym_is_const(ctx, left) && sym_is_const(ctx, right)) {
             assert(PyUnicode_CheckExact(sym_get_const(ctx, left)));
             assert(PyUnicode_CheckExact(sym_get_const(ctx, right)));
@@ -320,8 +318,7 @@ dummy_func(void) {
         else {
             res = sym_new_type(ctx, &PyUnicode_Type);
         }
-        // _STORE_FAST:
-        GETLOCAL(this_instr->operand0) = res;
+        GETLOCAL(this_instr->operand0) = sym_new_null(ctx);
     }
 
     op(_BINARY_OP_SUBSCR_INIT_CALL, (container, sub, getitem  -- new_frame)) {
@@ -1043,10 +1040,11 @@ dummy_func(void) {
         sym_set_const(flag, Py_True);
     }
 
-    op(_CALL_LIST_APPEND, (callable, self, arg -- c, s)) {
+    op(_CALL_LIST_APPEND, (callable, self, arg -- none, c, s)) {
         (void)(arg);
         c = callable;
         s = self;
+        none = sym_new_const(ctx, Py_None);
     }
 
     op(_GUARD_IS_FALSE_POP, (flag -- )) {
index 9f1337e7ef3b92ebe215baa25accdd931fcff00a..a8b043fbc875d29b91bf9a8449fa595c13f1bfb3 100644 (file)
             JitOptRef r;
             right = stack_pointer[-1];
             left = stack_pointer[-2];
-            if (
-                sym_is_safe_const(ctx, left) &&
-                sym_is_safe_const(ctx, right)
-            ) {
-                JitOptRef left_sym = left;
-                JitOptRef right_sym = right;
-                _PyStackRef left = sym_get_const_as_stackref(ctx, left_sym);
-                _PyStackRef right = sym_get_const_as_stackref(ctx, right_sym);
-                _PyStackRef res_stackref;
-                _PyStackRef l_stackref;
-                _PyStackRef r_stackref;
-                /* Start of uop copied from bytecodes for constant evaluation */
-                PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
-                PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
-                assert(PyUnicode_CheckExact(left_o));
-                assert(PyUnicode_CheckExact(right_o));
-                STAT_INC(BINARY_OP, hit);
-                PyObject *res_o = PyUnicode_Concat(left_o, right_o);
-                res_stackref = PyStackRef_FromPyObjectSteal(res_o);
-                if (PyStackRef_IsNull(res)) {
-                    JUMP_TO_LABEL(error);
-                }
-                l_stackref = left;
-                r_stackref = right;
-                /* End of uop copied from bytecodes for constant evaluation */
-                res = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(res_stackref));
-                l = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(l_stackref));
-                r = sym_new_const_steal(ctx, PyStackRef_AsPyObjectSteal(r_stackref));
-                CHECK_STACK_BOUNDS(1);
-                stack_pointer[-2] = res;
-                stack_pointer[-1] = l;
-                stack_pointer[0] = r;
-                stack_pointer += 1;
-                ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
-                break;
-            }
             res = sym_new_type(ctx, &PyUnicode_Type);
             l = left;
             r = right;
         case _BINARY_OP_INPLACE_ADD_UNICODE: {
             JitOptRef right;
             JitOptRef left;
+            JitOptRef res;
             right = stack_pointer[-1];
             left = stack_pointer[-2];
-            JitOptRef res;
             if (sym_is_const(ctx, left) && sym_is_const(ctx, right)) {
                 assert(PyUnicode_CheckExact(sym_get_const(ctx, left)));
                 assert(PyUnicode_CheckExact(sym_get_const(ctx, right)));
                     goto error;
                 }
                 res = sym_new_const(ctx, temp);
+                CHECK_STACK_BOUNDS(-1);
+                stack_pointer[-2] = res;
+                stack_pointer += -1;
+                ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
                 Py_DECREF(temp);
             }
             else {
                 res = sym_new_type(ctx, &PyUnicode_Type);
+                stack_pointer += -1;
             }
-            GETLOCAL(this_instr->operand0) = res;
-            CHECK_STACK_BOUNDS(-2);
-            stack_pointer += -2;
-            ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
+            GETLOCAL(this_instr->operand0) = sym_new_null(ctx);
+            stack_pointer[-1] = res;
             break;
         }
 
             JitOptRef arg;
             JitOptRef self;
             JitOptRef callable;
+            JitOptRef none;
             JitOptRef c;
             JitOptRef s;
             arg = stack_pointer[-1];
             (void)(arg);
             c = callable;
             s = self;
-            CHECK_STACK_BOUNDS(-1);
-            stack_pointer[-3] = c;
-            stack_pointer[-2] = s;
-            stack_pointer += -1;
-            ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
+            none = sym_new_const(ctx, Py_None);
+            stack_pointer[-3] = none;
+            stack_pointer[-2] = c;
+            stack_pointer[-1] = s;
             break;
         }
 
index 19433bc7a74319aa27af7bb46e66619d736c628f..e67078afdd9df34213553ec6650669f97aa376f3 100644 (file)
@@ -1623,10 +1623,8 @@ specialize_method_descriptor(PyMethodDescrObject *descr, PyObject *self_or_null,
             }
             PyInterpreterState *interp = _PyInterpreterState_GET();
             PyObject *list_append = interp->callable_cache.list_append;
-            _Py_CODEUNIT next = instr[INLINE_CACHE_ENTRIES_CALL + 1];
-            bool pop = (next.op.code == POP_TOP);
             int oparg = instr->op.arg;
-            if ((PyObject *)descr == list_append && oparg == 1 && pop) {
+            if ((PyObject *)descr == list_append && oparg == 1) {
                 assert(self_or_null != NULL);
                 if (PyList_CheckExact(self_or_null)) {
                     specialize(instr, CALL_LIST_APPEND);