]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-134584: JIT: Borrow references for immortal promoted globals (GH-142921)
authorKen Jin <kenjin@python.org>
Fri, 19 Dec 2025 19:06:34 +0000 (03:06 +0800)
committerGitHub <noreply@github.com>
Fri, 19 Dec 2025 19:06:34 +0000 (19:06 +0000)
JIT: Borrow references for immortal promoted globals

Lib/test/test_capi/test_opt.py
Python/optimizer_bytecodes.c
Python/optimizer_cases.c.h

index 9a822834c14f3664a88969c3b84814c948341411..3ea93277dab295c76ea39393b4ba5dd2c12186b6 100644 (file)
@@ -3008,6 +3008,44 @@ class TestUopsOptimization(unittest.TestCase):
         for _ in range(TIER2_THRESHOLD+1):
             obj.attr = EvilAttr(obj.__dict__)
 
+    def test_promoted_global_refcount_eliminated(self):
+        result = script_helper.run_python_until_end('-c', textwrap.dedent("""
+        import _testinternalcapi
+        import opcode
+        import _opcode
+
+        def get_first_executor(func):
+            code = func.__code__
+            co_code = code.co_code
+            for i in range(0, len(co_code), 2):
+                try:
+                    return _opcode.get_executor(code, i)
+                except ValueError:
+                    pass
+            return None
+
+        def get_opnames(ex):
+            return {item[0] for item in ex}
+
+
+        def testfunc(n):
+            y = []
+            for i in range(n):
+                x = tuple(y)
+            return x
+
+        testfunc(_testinternalcapi.TIER2_THRESHOLD)
+
+        ex = get_first_executor(testfunc)
+        assert ex is not None
+        uops = get_opnames(ex)
+        assert "_LOAD_GLOBAL_BUILTIN" not in uops
+        assert "_LOAD_CONST_INLINE_BORROW" in uops
+        assert "_POP_TOP_NOP" in uops
+        assert "_POP_TOP" not in uops
+        """), PYTHON_JIT="1")
+        self.assertEqual(result[0].rc, 0, result)
+
     def test_constant_fold_tuple(self):
         def testfunc(n):
             for _ in range(n):
index d2527fd85e3f12ddd165a636cf3849d5bc1baf18..cd789db1fe89d2c7c66be675013413f4629b53e1 100644 (file)
@@ -1376,7 +1376,12 @@ dummy_func(void) {
             res = sym_new_not_null(ctx);
         }
         else {
-            res = sym_new_const(ctx, cnst);
+            if (_Py_IsImmortal(cnst)) {
+                res = PyJitRef_Borrow(sym_new_const(ctx, cnst));
+            }
+            else {
+                res = sym_new_const(ctx, cnst);
+            }
         }
     }
 
@@ -1411,7 +1416,12 @@ dummy_func(void) {
             res = sym_new_not_null(ctx);
         }
         else {
-            res = sym_new_const(ctx, cnst);
+            if (_Py_IsImmortal(cnst)) {
+                res = PyJitRef_Borrow(sym_new_const(ctx, cnst));
+            }
+            else {
+                res = sym_new_const(ctx, cnst);
+            }
         }
     }
 
index 0389c6192e1cac2f4f6ff65babab572a848dc4bd..85d3d0412151038f7a8036918c926c7e09b3c430 100644 (file)
                 res = sym_new_not_null(ctx);
             }
             else {
-                res = sym_new_const(ctx, cnst);
+                if (_Py_IsImmortal(cnst)) {
+                    res = PyJitRef_Borrow(sym_new_const(ctx, cnst));
+                }
+                else {
+                    res = sym_new_const(ctx, cnst);
+                }
             }
             CHECK_STACK_BOUNDS(1);
             stack_pointer[0] = res;
                 res = sym_new_not_null(ctx);
             }
             else {
-                res = sym_new_const(ctx, cnst);
+                if (_Py_IsImmortal(cnst)) {
+                    res = PyJitRef_Borrow(sym_new_const(ctx, cnst));
+                }
+                else {
+                    res = sym_new_const(ctx, cnst);
+                }
             }
             CHECK_STACK_BOUNDS(1);
             stack_pointer[0] = res;