From afaf58b5739dabf50a5db69c301d547eb421b3bf Mon Sep 17 00:00:00 2001 From: Wulian233 <1055917385@qq.com> Date: Mon, 13 Apr 2026 22:41:06 +0800 Subject: [PATCH] gh-131798: JIT: Optimize `_CHECK_IS_NOT_PY_CALLABLE_EX` and `_CHECK_IS_NOT_PY_CALLABLE_KW` (GH-148494) --- Lib/test/test_capi/test_opt.py | 29 +++++++++++++++++++++++++++++ Python/optimizer_bytecodes.c | 14 ++++++++++++++ Python/optimizer_cases.c.h | 12 ++++++++++++ 3 files changed, 55 insertions(+) diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 663783f435f..0b112afb818 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -2845,6 +2845,35 @@ def testfunc(n): 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 18cb2e24690..3332a9627c1 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 9ef7eafc2a3..deb92f5d9ab 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; }