]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-148210: fix incorrect `_BINARY_OP_SUBSCR_DICT` JIT optimization (GH-148213)
authorKumar Aditya <kumaraditya@python.org>
Wed, 8 Apr 2026 15:23:20 +0000 (20:53 +0530)
committerGitHub <noreply@github.com>
Wed, 8 Apr 2026 15:23:20 +0000 (23:23 +0800)
Lib/test/test_capi/test_opt.py
Python/optimizer_bytecodes.c
Python/optimizer_cases.c.h

index b25c3c4c4e70a62bc9364216d298945f1c86407b..f89f0d8bc4ee2a1f39d7f1dcc0161de859aa345c 100644 (file)
@@ -2340,6 +2340,21 @@ class TestUopsOptimization(unittest.TestCase):
         self.assertIn("_BINARY_OP_SUBSCR_DICT_KNOWN_HASH", uops)
         self.assertNotIn("_BINARY_OP_SUBSCR_DICT", uops)
 
+
+    def test_binary_op_subscr_constant_frozendict_known_hash(self):
+        def testfunc(n):
+            x = 0
+            for _ in range(n):
+                x += FROZEN_DICT_CONST['x']
+            return x
+
+        res, ex = self._run_with_optimizer(testfunc, 2 * TIER2_THRESHOLD)
+        self.assertEqual(res, 2 * TIER2_THRESHOLD)
+        self.assertIsNotNone(ex)
+        uops = get_opnames(ex)
+        self.assertNotIn("_BINARY_OP_SUBSCR_DICT_KNOWN_HASH", uops)
+        self.assertNotIn("_BINARY_OP_SUBSCR_DICT", uops)
+
     def test_store_subscr_dict_known_hash(self):
         # str, int, bytes, float, complex, tuple and any python object which has generic hash
         def testfunc(n):
index f0abdc098dd8f1bf4476b37b86e48f62e793d17a..3ba404b81ea043aafb06a8c1ddbb265edcf75bbc 100644 (file)
@@ -515,18 +515,18 @@ dummy_func(void) {
     }
 
     op(_BINARY_OP_SUBSCR_DICT, (dict_st, sub_st -- res, ds, ss)) {
-        PyObject *sub = sym_get_const(ctx, sub_st);
-        if (sub != NULL) {
-            optimize_dict_known_hash(ctx, dependencies, this_instr,
-                                     sub, _BINARY_OP_SUBSCR_DICT_KNOWN_HASH);
-        }
         res = sym_new_not_null(ctx);
         ds = dict_st;
         ss = sub_st;
+        PyObject *sub = sym_get_const(ctx, sub_st);
         if (sym_is_not_container(sub_st) &&
             sym_matches_type(dict_st, &PyFrozenDict_Type)) {
             REPLACE_OPCODE_IF_EVALUATES_PURE(dict_st, sub_st, res);
         }
+        else if (sub != NULL) {
+            optimize_dict_known_hash(ctx, dependencies, this_instr,
+                                     sub, _BINARY_OP_SUBSCR_DICT_KNOWN_HASH);
+        }
     }
 
     op(_BINARY_OP_SUBSCR_LIST_SLICE, (list_st, sub_st -- res, ls, ss)) {
index 6f9b0e6a4d0373366aa4aba5d41aedce27e2ab59..2c8a0bff13ce3520f947d9ed305f25c9be218c31 100644 (file)
             JitOptRef ss;
             sub_st = stack_pointer[-1];
             dict_st = stack_pointer[-2];
-            PyObject *sub = sym_get_const(ctx, sub_st);
-            if (sub != NULL) {
-                optimize_dict_known_hash(ctx, dependencies, this_instr,
-                                     sub, _BINARY_OP_SUBSCR_DICT_KNOWN_HASH);
-            }
             res = sym_new_not_null(ctx);
             ds = dict_st;
             ss = sub_st;
+            PyObject *sub = sym_get_const(ctx, sub_st);
             if (sym_is_not_container(sub_st) &&
                 sym_matches_type(dict_st, &PyFrozenDict_Type)) {
                 if (
                     break;
                 }
             }
+            else if (sub != NULL) {
+                optimize_dict_known_hash(ctx, dependencies, this_instr,
+                                     sub, _BINARY_OP_SUBSCR_DICT_KNOWN_HASH);
+            }
             CHECK_STACK_BOUNDS(1);
             stack_pointer[-2] = res;
             stack_pointer[-1] = ds;