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..03b875b625a031 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -2071,6 +2071,28 @@ 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); + } + else { + res = sym_new_type(ctx, &PyBool_Type); + } + } + + 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); + } + else { + res = sym_new_type(ctx, &PyBool_Type); + } + } + 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..e9ef7dce0a9147 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -3176,8 +3176,17 @@ } 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); + } + else { + res = sym_new_type(ctx, &PyBool_Type); + } CHECK_STACK_BOUNDS(1); stack_pointer[0] = res; stack_pointer += 1; @@ -3186,8 +3195,17 @@ } 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); + } + else { + res = sym_new_type(ctx, &PyBool_Type); + } CHECK_STACK_BOUNDS(1); stack_pointer[0] = res; stack_pointer += 1;