From 16f6ab06e531354ada9907277bde44bc98ca3538 Mon Sep 17 00:00:00 2001 From: Sacul0457Deve <183588943+Sacul0457@users.noreply.github.com.> Date: Sun, 5 Apr 2026 22:07:05 +0800 Subject: [PATCH 1/2] optimize MATCH_SEQUENCE/MAPPING --- Lib/test/test_capi/test_opt.py | 35 ++++++++++++++++++++++++++++++++++ Python/optimizer_bytecodes.c | 16 ++++++++++++++++ Python/optimizer_cases.c.h | 16 ++++++++++++++-- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 56f90194b480a1..941140bf21fe4b 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -4684,6 +4684,41 @@ class A: self.assertIn("_MATCH_CLASS", uops) self.assertEqual(count_ops(ex, "_POP_TOP_NOP"), 4) + def test_match_mapping(self): + def testfunc(n): + x = {} + ret = 0 + for _ in range(n): + x["a"] = 1 + match x: + case {}: + ret += 1 + return ret + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + uops = get_opnames(ex) + + self.assertIn("_MATCH_MAPPING", uops) + self.assertNotIn("_GUARD_BIT_IS_SET_POP", uops) + + def test_match_sequence(self): + def testfunc(n): + ret = 0 + for _ in range(n): + x = 1, 2 + match x: + case a, b: + ret += 1 + return ret + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + uops = get_opnames(ex) + + self.assertIn("_MATCH_SEQUENCE", uops) + self.assertNotIn("_GUARD_BIT_IS_SET_POP", uops) + def test_dict_update(self): def testfunc(n): d = {1: 2, 3: 4} diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index f2645553513f3d..5500cccdcb1ec7 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -2071,6 +2071,22 @@ dummy_func(void) { n = names; } + op(_MATCH_MAPPING, (subject -- subject, res)) { + if (sym_has_type(subject)) { + PyTypeObject *type = sym_get_type(subject); + int match = type->tp_flags & Py_TPFLAGS_MAPPING; + res = match ? sym_new_const(ctx, Py_True) : sym_new_const(ctx, Py_False); + } + } + + op(_MATCH_SEQUENCE, (subject -- subject, res)) { + if (sym_has_type(subject)) { + PyTypeObject *type = sym_get_type(subject); + int match = type->tp_flags & Py_TPFLAGS_SEQUENCE; + res = match ? sym_new_const(ctx, Py_True) : sym_new_const(ctx, Py_False); + } + } + op(_DICT_UPDATE, (dict, unused[oparg - 1], update -- dict, unused[oparg - 1], upd)) { (void)dict; upd = update; diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index fb3ec39a42eabc..86d582b7cb5b44 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -3176,8 +3176,14 @@ } case _MATCH_MAPPING: { + JitOptRef subject; JitOptRef res; - res = sym_new_not_null(ctx); + subject = stack_pointer[-1]; + if (sym_has_type(subject)) { + PyTypeObject *type = sym_get_type(subject); + int match = type->tp_flags & Py_TPFLAGS_MAPPING; + res = match ? sym_new_const(ctx, Py_True) : sym_new_const(ctx, Py_False); + } CHECK_STACK_BOUNDS(1); stack_pointer[0] = res; stack_pointer += 1; @@ -3186,8 +3192,14 @@ } case _MATCH_SEQUENCE: { + JitOptRef subject; JitOptRef res; - res = sym_new_not_null(ctx); + subject = stack_pointer[-1]; + if (sym_has_type(subject)) { + PyTypeObject *type = sym_get_type(subject); + int match = type->tp_flags & Py_TPFLAGS_SEQUENCE; + res = match ? sym_new_const(ctx, Py_True) : sym_new_const(ctx, Py_False); + } CHECK_STACK_BOUNDS(1); stack_pointer[0] = res; stack_pointer += 1; From c366767d70dfddf0d2f3f892152f9fb1c92e0b5e Mon Sep 17 00:00:00 2001 From: Sacul0457Deve <183588943+Sacul0457@users.noreply.github.com.> Date: Sun, 5 Apr 2026 22:19:23 +0800 Subject: [PATCH 2/2] add else case to set the type to PyBool_Type --- Python/optimizer_bytecodes.c | 6 ++++++ Python/optimizer_cases.c.h | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 5500cccdcb1ec7..03b875b625a031 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -2077,6 +2077,9 @@ dummy_func(void) { int match = type->tp_flags & Py_TPFLAGS_MAPPING; res = match ? sym_new_const(ctx, Py_True) : sym_new_const(ctx, Py_False); } + else { + res = sym_new_type(ctx, &PyBool_Type); + } } op(_MATCH_SEQUENCE, (subject -- subject, res)) { @@ -2085,6 +2088,9 @@ dummy_func(void) { int match = type->tp_flags & Py_TPFLAGS_SEQUENCE; res = match ? sym_new_const(ctx, Py_True) : sym_new_const(ctx, Py_False); } + else { + res = sym_new_type(ctx, &PyBool_Type); + } } op(_DICT_UPDATE, (dict, unused[oparg - 1], update -- dict, unused[oparg - 1], upd)) { diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 86d582b7cb5b44..e9ef7dce0a9147 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -3184,6 +3184,9 @@ int match = type->tp_flags & Py_TPFLAGS_MAPPING; res = match ? sym_new_const(ctx, Py_True) : sym_new_const(ctx, Py_False); } + else { + res = sym_new_type(ctx, &PyBool_Type); + } CHECK_STACK_BOUNDS(1); stack_pointer[0] = res; stack_pointer += 1; @@ -3200,6 +3203,9 @@ int match = type->tp_flags & Py_TPFLAGS_SEQUENCE; res = match ? sym_new_const(ctx, Py_True) : sym_new_const(ctx, Py_False); } + else { + res = sym_new_type(ctx, &PyBool_Type); + } CHECK_STACK_BOUNDS(1); stack_pointer[0] = res; stack_pointer += 1;