]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-131798: JIT: Optimize `_CHECK_IS_NOT_PY_CALLABLE_EX` and `_CHECK_IS_NOT_PY_CALLABL...
authorWulian233 <1055917385@qq.com>
Mon, 13 Apr 2026 14:41:06 +0000 (22:41 +0800)
committerGitHub <noreply@github.com>
Mon, 13 Apr 2026 14:41:06 +0000 (22:41 +0800)
Lib/test/test_capi/test_opt.py
Python/optimizer_bytecodes.c
Python/optimizer_cases.c.h

index 663783f435fe2a7159e2f8d499bca42dba6761e3..0b112afb8181b129cb6023dd97b878cec0f88f73 100644 (file)
@@ -2845,6 +2845,35 @@ class TestUopsOptimization(unittest.TestCase):
         uops = get_opnames(ex)
         self.assertNotIn("_CHECK_IS_NOT_PY_CALLABLE", uops)
 
+    def test_check_is_not_py_callable_ex(self):
+        def testfunc(n):
+            total = 0
+            xs = (1, 2, 3)
+            args = (xs,)
+            for _ in range(n):
+                total += len(*args)
+            return total
+
+        res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
+        self.assertEqual(res, 3 * TIER2_THRESHOLD)
+        self.assertIsNotNone(ex)
+        uops = get_opnames(ex)
+        self.assertNotIn("_CHECK_IS_NOT_PY_CALLABLE_EX", uops)
+
+    def test_check_is_not_py_callable_kw(self):
+        def testfunc(n):
+            total = 0
+            xs = (3, 1, 2)
+            for _ in range(n):
+                total += sorted(xs, reverse=False)[0]
+            return total
+
+        res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD)
+        self.assertEqual(res, TIER2_THRESHOLD)
+        self.assertIsNotNone(ex)
+        uops = get_opnames(ex)
+        self.assertNotIn("_CHECK_IS_NOT_PY_CALLABLE_KW", uops)
+
     def test_call_len_string(self):
         def testfunc(n):
             for _ in range(n):
index 18cb2e24690e04f17474d494dc74619512d22174..3332a9627c1523c3b48fbb9c738d1138c6ca4192 100644 (file)
@@ -1320,6 +1320,20 @@ dummy_func(void) {
         }
     }
 
+    op(_CHECK_IS_NOT_PY_CALLABLE_EX, (func_st, unused, unused, unused -- func_st, unused, unused, unused)) {
+        PyTypeObject *type = sym_get_type(func_st);
+        if (type && type != &PyFunction_Type) {
+            ADD_OP(_NOP, 0, 0);
+        }
+    }
+
+    op(_CHECK_IS_NOT_PY_CALLABLE_KW, (callable, unused, unused[oparg], unused -- callable, unused, unused[oparg], unused)) {
+        PyTypeObject *type = sym_get_type(callable);
+        if (type && type != &PyFunction_Type && type != &PyMethod_Type) {
+            ADD_OP(_NOP, 0, 0);
+        }
+    }
+
     op(_PUSH_FRAME, (new_frame -- )) {
         SYNC_SP();
         if (!CURRENT_FRAME_IS_INIT_SHIM()) {
index 9ef7eafc2a3481016955446ab9eee827605ada2f..deb92f5d9ab0f1604ff3f971de76c61163369161 100644 (file)
         }
 
         case _CHECK_IS_NOT_PY_CALLABLE_KW: {
+            JitOptRef callable;
+            callable = stack_pointer[-3 - oparg];
+            PyTypeObject *type = sym_get_type(callable);
+            if (type && type != &PyFunction_Type && type != &PyMethod_Type) {
+                ADD_OP(_NOP, 0, 0);
+            }
             break;
         }
 
         }
 
         case _CHECK_IS_NOT_PY_CALLABLE_EX: {
+            JitOptRef func_st;
+            func_st = stack_pointer[-4];
+            PyTypeObject *type = sym_get_type(func_st);
+            if (type && type != &PyFunction_Type) {
+                ADD_OP(_NOP, 0, 0);
+            }
             break;
         }