From: Wulian233 <1055917385@qq.com> Date: Mon, 13 Apr 2026 14:41:06 +0000 (+0800) Subject: gh-131798: JIT: Optimize `_CHECK_IS_NOT_PY_CALLABLE_EX` and `_CHECK_IS_NOT_PY_CALLABL... X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=afaf58b5739dabf50a5db69c301d547eb421b3bf;p=thirdparty%2FPython%2Fcpython.git gh-131798: JIT: Optimize `_CHECK_IS_NOT_PY_CALLABLE_EX` and `_CHECK_IS_NOT_PY_CALLABLE_KW` (GH-148494) --- diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 663783f435fe..0b112afb8181 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -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): diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 18cb2e24690e..3332a9627c15 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -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()) { diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 9ef7eafc2a34..deb92f5d9ab0 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -4672,6 +4672,12 @@ } 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; } @@ -4708,6 +4714,12 @@ } 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; }