From 03d2f035d6dcfeee0c39b4b8a3ddb4dda01cddb6 Mon Sep 17 00:00:00 2001 From: Wulian233 <1055917385@qq.com> Date: Sun, 12 Apr 2026 21:07:19 +0800 Subject: [PATCH] gh-131798: Add `_CHECK_IS_NOT_PY_CALLABLE` to the JIT optimizer (GH-148434) --- Lib/test/test_capi/test_opt.py | 15 +++++++++++++++ Python/optimizer_bytecodes.c | 7 +++++++ Python/optimizer_cases.c.h | 6 ++++++ 3 files changed, 28 insertions(+) diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index f11413cc6254..2678a620763b 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -2755,6 +2755,21 @@ class TestUopsOptimization(unittest.TestCase): self.assertNotIn("_GUARD_TOS_INT", uops) self.assertIn("_POP_TOP_NOP", uops) + def test_check_is_not_py_callable(self): + def testfunc(n): + total = 0 + f = len + xs = (1, 2, 3) + for _ in range(n): + total += f(xs) + 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", 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 39dc4877af88..6e5af4793419 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -1217,6 +1217,13 @@ dummy_func(void) { (void)framesize; } + op(_CHECK_IS_NOT_PY_CALLABLE, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) { + 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 746653906874..d90ad285a11f 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -3651,6 +3651,12 @@ } case _CHECK_IS_NOT_PY_CALLABLE: { + JitOptRef callable; + callable = stack_pointer[-2 - oparg]; + PyTypeObject *type = sym_get_type(callable); + if (type && type != &PyFunction_Type && type != &PyMethod_Type) { + ADD_OP(_NOP, 0, 0); + } break; } -- 2.47.3