diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 2248920c266aef5..2f42c8240ee7da3 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -5710,10 +5710,42 @@ class A: res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) self.assertEqual(res, TIER2_THRESHOLD) uops = get_opnames(ex) - 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.assertNotIn("_MATCH_MAPPING", uops) + self.assertIn("_LOAD_COMMON_CONSTANT", 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.assertNotIn("_MATCH_SEQUENCE", uops) + self.assertIn("_LOAD_COMMON_CONSTANT", 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 c968185d77c3317..ed76eed97dbcd32 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -2595,6 +2595,28 @@ dummy_func(void) { n = names; } + op(_MATCH_MAPPING, (subject -- subject, res)) { + PyTypeObject *type = sym_get_type(subject); + if (type != NULL) { + int match = type->tp_flags & Py_TPFLAGS_MAPPING; + REPLACE_OP(this_instr, _LOAD_COMMON_CONSTANT, match? CONSTANT_TRUE : CONSTANT_FALSE, 0); + } + else { + res = sym_new_type(ctx, &PyBool_Type); + } + } + + op(_MATCH_SEQUENCE, (subject -- subject, res)) { + PyTypeObject *type = sym_get_type(subject); + if (type != NULL) { + int match = type->tp_flags & Py_TPFLAGS_SEQUENCE; + REPLACE_OP(this_instr, _LOAD_COMMON_CONSTANT, match? CONSTANT_TRUE : CONSTANT_FALSE, 0); + } + 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 d52ebb9804197da..e4407bfdf30486c 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -3542,8 +3542,17 @@ } case _MATCH_MAPPING: { + JitOptRef subject; JitOptRef res; - res = sym_new_not_null(ctx); + subject = stack_pointer[-1]; + PyTypeObject *type = sym_get_type(subject); + if (type != NULL) { + int match = type->tp_flags & Py_TPFLAGS_MAPPING; + REPLACE_OP(this_instr, _LOAD_COMMON_CONSTANT, match? CONSTANT_TRUE : CONSTANT_FALSE, 0); + } + else { + res = sym_new_type(ctx, &PyBool_Type); + } CHECK_STACK_BOUNDS(1); stack_pointer[0] = res; stack_pointer += 1; @@ -3552,8 +3561,17 @@ } case _MATCH_SEQUENCE: { + JitOptRef subject; JitOptRef res; - res = sym_new_not_null(ctx); + subject = stack_pointer[-1]; + PyTypeObject *type = sym_get_type(subject); + if (type != NULL) { + int match = type->tp_flags & Py_TPFLAGS_SEQUENCE; + REPLACE_OP(this_instr, _LOAD_COMMON_CONSTANT, match? CONSTANT_TRUE : CONSTANT_FALSE, 0); + } + else { + res = sym_new_type(ctx, &PyBool_Type); + } CHECK_STACK_BOUNDS(1); stack_pointer[0] = res; stack_pointer += 1;