https://github.com/python/cpython/commit/667a86e076eeadc0d0e6e0f0da58882ed748865b
commit: 667a86e076eeadc0d0e6e0f0da58882ed748865b
branch: main
author: Nadeshiko Manju <m...@manjusaka.me>
committer: Fidget-Spinner <kenjin4...@gmail.com>
date: 2025-06-16T13:25:50+08:00
summary:

gh-131798: JIT: replace _CHECK_METHOD_VERSION with 
_CHECK_FUNCTION_VERSION_INLINE (GH-135022)

Signed-off-by: Manjusaka <m...@manjusaka.me>
Co-authored-by: Brandt Bucher <brandtbuc...@gmail.com>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-06-02-20-13-37.gh-issue-131798.JQRFvR.rst
M Lib/test/test_capi/test_opt.py
M Python/optimizer_bytecodes.c
M Python/optimizer_cases.c.h

diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py
index bf22ef2a5922e7..3fc2cb33795a5f 100644
--- a/Lib/test/test_capi/test_opt.py
+++ b/Lib/test/test_capi/test_opt.py
@@ -1381,6 +1381,21 @@ def testfunc(n):
         # Removed guard
         self.assertNotIn("_CHECK_FUNCTION_EXACT_ARGS", uops)
 
+    def test_method_guards_removed_or_reduced(self):
+        def testfunc(n):
+            result = 0
+            for i in range(n):
+                result += test_bound_method(i)
+            return result
+        res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
+        self.assertEqual(res, sum(range(TIER2_THRESHOLD)))
+        self.assertIsNotNone(ex)
+        uops = get_opnames(ex)
+        self.assertIn("_PUSH_FRAME", uops)
+        # Strength reduced version
+        self.assertIn("_CHECK_FUNCTION_VERSION_INLINE", uops)
+        self.assertNotIn("_CHECK_METHOD_VERSION", uops)
+
     def test_jit_error_pops(self):
         """
         Tests that the correct number of pops are inserted into the
@@ -2294,5 +2309,12 @@ def testfunc(n):
 def global_identity(x):
     return x
 
+class TestObject:
+    def test(self, *args, **kwargs):
+        return args[0]
+
+test_object = TestObject()
+test_bound_method = TestObject.test.__get__(test_object)
+
 if __name__ == "__main__":
     unittest.main()
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-06-02-20-13-37.gh-issue-131798.JQRFvR.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-06-02-20-13-37.gh-issue-131798.JQRFvR.rst
new file mode 100644
index 00000000000000..0e68c793e5e133
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-06-02-20-13-37.gh-issue-131798.JQRFvR.rst
@@ -0,0 +1 @@
+Optimize ``_CHECK_METHOD_VERSION`` into ``_CHECK_FUNCTION_VERSION_INLINE`` in 
JIT-compiled code.
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index c2469547d77943..5a9a3a943a7b02 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -672,6 +672,16 @@ dummy_func(void) {
         sym_set_type(callable, &PyFunction_Type);
     }
 
+    op(_CHECK_METHOD_VERSION, (func_version/2, callable, null, unused[oparg] 
-- callable, null, unused[oparg])) {
+        if (sym_is_const(ctx, callable) && sym_matches_type(callable, 
&PyMethod_Type)) {
+            PyMethodObject *method = (PyMethodObject *)sym_get_const(ctx, 
callable);
+            assert(PyMethod_Check(method));
+            REPLACE_OP(this_instr, _CHECK_FUNCTION_VERSION_INLINE, 0, 
func_version);
+            this_instr->operand1 = (uintptr_t)method->im_func;
+        }
+        sym_set_type(callable, &PyMethod_Type);
+    }
+
     op(_CHECK_FUNCTION_EXACT_ARGS, (callable, self_or_null, unused[oparg] -- 
callable, self_or_null, unused[oparg])) {
         assert(sym_matches_type(callable, &PyFunction_Type));
         if (sym_is_const(ctx, callable)) {
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index d9313be0bb0df6..8c4f0399c75a73 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -1833,6 +1833,16 @@
         }
 
         case _CHECK_METHOD_VERSION: {
+            JitOptSymbol *callable;
+            callable = stack_pointer[-2 - oparg];
+            uint32_t func_version = (uint32_t)this_instr->operand0;
+            if (sym_is_const(ctx, callable) && sym_matches_type(callable, 
&PyMethod_Type)) {
+                PyMethodObject *method = (PyMethodObject *)sym_get_const(ctx, 
callable);
+                assert(PyMethod_Check(method));
+                REPLACE_OP(this_instr, _CHECK_FUNCTION_VERSION_INLINE, 0, 
func_version);
+                this_instr->operand1 = (uintptr_t)method->im_func;
+            }
+            sym_set_type(callable, &PyMethod_Type);
             break;
         }
 

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: arch...@mail-archive.com

Reply via email to