From 7f8b4b22c29b4307fd96fb523e59199dd3c6e39d Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Sat, 14 Feb 2026 16:05:32 +0100 Subject: [PATCH 1/3] gh-138912: Add fast path for match class patterns without sub-patterns --- Doc/library/dis.rst | 8 + Include/internal/pycore_magic_number.h | 3 +- Include/internal/pycore_opcode_metadata.h | 10 +- Include/internal/pycore_uop_ids.h | 430 +++++++++--------- Include/internal/pycore_uop_metadata.h | 15 + Include/opcode_ids.h | 197 ++++---- Lib/_opcode_metadata.py | 197 ++++---- Lib/test/test_dis.py | 3 +- ...-02-14-16-19-22.gh-issue-138912.TKMC9K.rst | 3 + Modules/_testinternalcapi/test_cases.c.h | 46 ++ Modules/_testinternalcapi/test_targets.h | 9 +- Programs/test_frozenmain.h | 26 +- Python/bytecodes.c | 16 + Python/codegen.c | 22 + Python/executor_cases.c.h | 57 +++ Python/generated_cases.c.h | 46 ++ Python/opcode_targets.h | 9 +- Python/optimizer_cases.c.h | 7 + 18 files changed, 669 insertions(+), 435 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-16-19-22.gh-issue-138912.TKMC9K.rst diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 1f7014e9cd426f0..f304a9644e25a22 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -1752,6 +1752,14 @@ iterations of the loop. .. versionadded:: 3.13 +.. opcode:: MATCH_CLASS_ISINSTANCE + + Read match subject ``Stack[-2]`` and the type object ``Stack[-1]`` from stack. + Pop ``Stack[-1]`` and push ``True`` or ``False`` for the result of :func:`isinstance`. + + .. versionadded:: 3.15 + + .. opcode:: MATCH_CLASS (count) ``STACK[-1]`` is a tuple of keyword attribute names, ``STACK[-2]`` is the class diff --git a/Include/internal/pycore_magic_number.h b/Include/internal/pycore_magic_number.h index 3fcf650426d36d0..95f97fb8430a747 100644 --- a/Include/internal/pycore_magic_number.h +++ b/Include/internal/pycore_magic_number.h @@ -292,6 +292,7 @@ Known values: Python 3.15a4 3659 (Add CALL_FUNCTION_EX specialization) Python 3.15a4 3660 (Change generator preamble code) Python 3.15a4 3661 (Lazy imports IMPORT_NAME opcode changes) + Python 3.15a7 3662 (Add MATCH_CLASS_ISINSTANCE opcode) Python 3.16 will start with 3700 @@ -305,7 +306,7 @@ PC/launcher.c must also be updated. */ -#define PYC_MAGIC_NUMBER 3661 +#define PYC_MAGIC_NUMBER 3662 /* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes (little-endian) and then appending b'\r\n'. */ #define PYC_MAGIC_NUMBER_TOKEN \ diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index 4c1e7aebd0d2914..baa2e47ec9c6875 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -386,6 +386,8 @@ int _PyOpcode_num_popped(int opcode, int oparg) { return 3 + (oparg - 1); case MATCH_CLASS: return 3; + case MATCH_CLASS_ISINSTANCE: + return 2; case MATCH_KEYS: return 2; case MATCH_MAPPING: @@ -877,6 +879,8 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { return 1 + (oparg - 1); case MATCH_CLASS: return 1; + case MATCH_CLASS_ISINSTANCE: + return 2; case MATCH_KEYS: return 3; case MATCH_MAPPING: @@ -1261,6 +1265,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [MAKE_FUNCTION] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [MAP_ADD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [MATCH_CLASS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, + [MATCH_CLASS_ISINSTANCE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [MATCH_KEYS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [MATCH_MAPPING] = { true, INSTR_FMT_IX, 0 }, [MATCH_SEQUENCE] = { true, INSTR_FMT_IX, 0 }, @@ -1479,6 +1484,7 @@ _PyOpcode_macro_expansion[256] = { [MAKE_FUNCTION] = { .nuops = 1, .uops = { { _MAKE_FUNCTION, OPARG_SIMPLE, 0 } } }, [MAP_ADD] = { .nuops = 1, .uops = { { _MAP_ADD, OPARG_SIMPLE, 0 } } }, [MATCH_CLASS] = { .nuops = 1, .uops = { { _MATCH_CLASS, OPARG_SIMPLE, 0 } } }, + [MATCH_CLASS_ISINSTANCE] = { .nuops = 1, .uops = { { _MATCH_CLASS_ISINSTANCE, OPARG_SIMPLE, 0 } } }, [MATCH_KEYS] = { .nuops = 1, .uops = { { _MATCH_KEYS, OPARG_SIMPLE, 0 } } }, [MATCH_MAPPING] = { .nuops = 1, .uops = { { _MATCH_MAPPING, OPARG_SIMPLE, 0 } } }, [MATCH_SEQUENCE] = { .nuops = 1, .uops = { { _MATCH_SEQUENCE, OPARG_SIMPLE, 0 } } }, @@ -1714,6 +1720,7 @@ const char *_PyOpcode_OpName[267] = { [MAKE_FUNCTION] = "MAKE_FUNCTION", [MAP_ADD] = "MAP_ADD", [MATCH_CLASS] = "MATCH_CLASS", + [MATCH_CLASS_ISINSTANCE] = "MATCH_CLASS_ISINSTANCE", [MATCH_KEYS] = "MATCH_KEYS", [MATCH_MAPPING] = "MATCH_MAPPING", [MATCH_SEQUENCE] = "MATCH_SEQUENCE", @@ -1811,7 +1818,6 @@ const uint8_t _PyOpcode_Caches[256] = { PyAPI_DATA(const uint8_t) _PyOpcode_Deopt[256]; #ifdef NEED_OPCODE_METADATA const uint8_t _PyOpcode_Deopt[256] = { - [121] = 121, [122] = 122, [123] = 123, [124] = 124, @@ -2007,6 +2013,7 @@ const uint8_t _PyOpcode_Deopt[256] = { [MAKE_FUNCTION] = MAKE_FUNCTION, [MAP_ADD] = MAP_ADD, [MATCH_CLASS] = MATCH_CLASS, + [MATCH_CLASS_ISINSTANCE] = MATCH_CLASS_ISINSTANCE, [MATCH_KEYS] = MATCH_KEYS, [MATCH_MAPPING] = MATCH_MAPPING, [MATCH_SEQUENCE] = MATCH_SEQUENCE, @@ -2072,7 +2079,6 @@ const uint8_t _PyOpcode_Deopt[256] = { #endif // NEED_OPCODE_METADATA #define EXTRA_CASES \ - case 121: \ case 122: \ case 123: \ case 124: \ diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index ebf21b12633c78e..65b7982acfba52a 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -287,6 +287,7 @@ extern "C" { #define _MAKE_WARM 513 #define _MAP_ADD MAP_ADD #define _MATCH_CLASS MATCH_CLASS +#define _MATCH_CLASS_ISINSTANCE MATCH_CLASS_ISINSTANCE #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE @@ -1038,220 +1039,221 @@ extern "C" { #define _MAKE_WARM_r33 1235 #define _MAP_ADD_r20 1236 #define _MATCH_CLASS_r31 1237 -#define _MATCH_KEYS_r23 1238 -#define _MATCH_MAPPING_r02 1239 -#define _MATCH_MAPPING_r12 1240 -#define _MATCH_MAPPING_r23 1241 -#define _MATCH_SEQUENCE_r02 1242 -#define _MATCH_SEQUENCE_r12 1243 -#define _MATCH_SEQUENCE_r23 1244 -#define _MAYBE_EXPAND_METHOD_r00 1245 -#define _MAYBE_EXPAND_METHOD_KW_r11 1246 -#define _MONITOR_CALL_r00 1247 -#define _MONITOR_CALL_KW_r11 1248 -#define _MONITOR_JUMP_BACKWARD_r00 1249 -#define _MONITOR_JUMP_BACKWARD_r11 1250 -#define _MONITOR_JUMP_BACKWARD_r22 1251 -#define _MONITOR_JUMP_BACKWARD_r33 1252 -#define _MONITOR_RESUME_r00 1253 -#define _NOP_r00 1254 -#define _NOP_r11 1255 -#define _NOP_r22 1256 -#define _NOP_r33 1257 -#define _POP_CALL_r20 1258 -#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1259 -#define _POP_CALL_ONE_r30 1260 -#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1261 -#define _POP_CALL_TWO_r30 1262 -#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1263 -#define _POP_EXCEPT_r10 1264 -#define _POP_ITER_r20 1265 -#define _POP_JUMP_IF_FALSE_r00 1266 -#define _POP_JUMP_IF_FALSE_r10 1267 -#define _POP_JUMP_IF_FALSE_r21 1268 -#define _POP_JUMP_IF_FALSE_r32 1269 -#define _POP_JUMP_IF_TRUE_r00 1270 -#define _POP_JUMP_IF_TRUE_r10 1271 -#define _POP_JUMP_IF_TRUE_r21 1272 -#define _POP_JUMP_IF_TRUE_r32 1273 -#define _POP_TOP_r10 1274 -#define _POP_TOP_FLOAT_r00 1275 -#define _POP_TOP_FLOAT_r10 1276 -#define _POP_TOP_FLOAT_r21 1277 -#define _POP_TOP_FLOAT_r32 1278 -#define _POP_TOP_INT_r00 1279 -#define _POP_TOP_INT_r10 1280 -#define _POP_TOP_INT_r21 1281 -#define _POP_TOP_INT_r32 1282 -#define _POP_TOP_LOAD_CONST_INLINE_r11 1283 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1284 -#define _POP_TOP_NOP_r00 1285 -#define _POP_TOP_NOP_r10 1286 -#define _POP_TOP_NOP_r21 1287 -#define _POP_TOP_NOP_r32 1288 -#define _POP_TOP_UNICODE_r00 1289 -#define _POP_TOP_UNICODE_r10 1290 -#define _POP_TOP_UNICODE_r21 1291 -#define _POP_TOP_UNICODE_r32 1292 -#define _POP_TWO_r20 1293 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1294 -#define _PUSH_EXC_INFO_r02 1295 -#define _PUSH_EXC_INFO_r12 1296 -#define _PUSH_EXC_INFO_r23 1297 -#define _PUSH_FRAME_r10 1298 -#define _PUSH_NULL_r01 1299 -#define _PUSH_NULL_r12 1300 -#define _PUSH_NULL_r23 1301 -#define _PUSH_NULL_CONDITIONAL_r00 1302 -#define _PY_FRAME_EX_r31 1303 -#define _PY_FRAME_GENERAL_r01 1304 -#define _PY_FRAME_KW_r11 1305 -#define _QUICKEN_RESUME_r00 1306 -#define _QUICKEN_RESUME_r11 1307 -#define _QUICKEN_RESUME_r22 1308 -#define _QUICKEN_RESUME_r33 1309 -#define _REPLACE_WITH_TRUE_r02 1310 -#define _REPLACE_WITH_TRUE_r12 1311 -#define _REPLACE_WITH_TRUE_r23 1312 -#define _RESUME_CHECK_r00 1313 -#define _RESUME_CHECK_r11 1314 -#define _RESUME_CHECK_r22 1315 -#define _RESUME_CHECK_r33 1316 -#define _RETURN_GENERATOR_r01 1317 -#define _RETURN_VALUE_r11 1318 -#define _SAVE_RETURN_OFFSET_r00 1319 -#define _SAVE_RETURN_OFFSET_r11 1320 -#define _SAVE_RETURN_OFFSET_r22 1321 -#define _SAVE_RETURN_OFFSET_r33 1322 -#define _SEND_r22 1323 -#define _SEND_GEN_FRAME_r22 1324 -#define _SETUP_ANNOTATIONS_r00 1325 -#define _SET_ADD_r10 1326 -#define _SET_FUNCTION_ATTRIBUTE_r01 1327 -#define _SET_FUNCTION_ATTRIBUTE_r11 1328 -#define _SET_FUNCTION_ATTRIBUTE_r21 1329 -#define _SET_FUNCTION_ATTRIBUTE_r32 1330 -#define _SET_IP_r00 1331 -#define _SET_IP_r11 1332 -#define _SET_IP_r22 1333 -#define _SET_IP_r33 1334 -#define _SET_UPDATE_r10 1335 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1336 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1337 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1338 -#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1339 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1340 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1341 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1342 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1343 -#define _SPILL_OR_RELOAD_r01 1344 -#define _SPILL_OR_RELOAD_r02 1345 -#define _SPILL_OR_RELOAD_r03 1346 -#define _SPILL_OR_RELOAD_r10 1347 -#define _SPILL_OR_RELOAD_r12 1348 -#define _SPILL_OR_RELOAD_r13 1349 -#define _SPILL_OR_RELOAD_r20 1350 -#define _SPILL_OR_RELOAD_r21 1351 -#define _SPILL_OR_RELOAD_r23 1352 -#define _SPILL_OR_RELOAD_r30 1353 -#define _SPILL_OR_RELOAD_r31 1354 -#define _SPILL_OR_RELOAD_r32 1355 -#define _START_EXECUTOR_r00 1356 -#define _STORE_ATTR_r20 1357 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1358 -#define _STORE_ATTR_SLOT_r21 1359 -#define _STORE_ATTR_WITH_HINT_r21 1360 -#define _STORE_DEREF_r10 1361 -#define _STORE_FAST_LOAD_FAST_r11 1362 -#define _STORE_FAST_STORE_FAST_r20 1363 -#define _STORE_GLOBAL_r10 1364 -#define _STORE_NAME_r10 1365 -#define _STORE_SLICE_r30 1366 -#define _STORE_SUBSCR_r30 1367 -#define _STORE_SUBSCR_DICT_r31 1368 -#define _STORE_SUBSCR_LIST_INT_r32 1369 -#define _SWAP_r11 1370 -#define _SWAP_2_r02 1371 -#define _SWAP_2_r12 1372 -#define _SWAP_2_r22 1373 -#define _SWAP_2_r33 1374 -#define _SWAP_3_r03 1375 -#define _SWAP_3_r13 1376 -#define _SWAP_3_r23 1377 -#define _SWAP_3_r33 1378 -#define _SWAP_FAST_r01 1379 -#define _SWAP_FAST_r11 1380 -#define _SWAP_FAST_r22 1381 -#define _SWAP_FAST_r33 1382 -#define _SWAP_FAST_0_r01 1383 -#define _SWAP_FAST_0_r11 1384 -#define _SWAP_FAST_0_r22 1385 -#define _SWAP_FAST_0_r33 1386 -#define _SWAP_FAST_1_r01 1387 -#define _SWAP_FAST_1_r11 1388 -#define _SWAP_FAST_1_r22 1389 -#define _SWAP_FAST_1_r33 1390 -#define _SWAP_FAST_2_r01 1391 -#define _SWAP_FAST_2_r11 1392 -#define _SWAP_FAST_2_r22 1393 -#define _SWAP_FAST_2_r33 1394 -#define _SWAP_FAST_3_r01 1395 -#define _SWAP_FAST_3_r11 1396 -#define _SWAP_FAST_3_r22 1397 -#define _SWAP_FAST_3_r33 1398 -#define _SWAP_FAST_4_r01 1399 -#define _SWAP_FAST_4_r11 1400 -#define _SWAP_FAST_4_r22 1401 -#define _SWAP_FAST_4_r33 1402 -#define _SWAP_FAST_5_r01 1403 -#define _SWAP_FAST_5_r11 1404 -#define _SWAP_FAST_5_r22 1405 -#define _SWAP_FAST_5_r33 1406 -#define _SWAP_FAST_6_r01 1407 -#define _SWAP_FAST_6_r11 1408 -#define _SWAP_FAST_6_r22 1409 -#define _SWAP_FAST_6_r33 1410 -#define _SWAP_FAST_7_r01 1411 -#define _SWAP_FAST_7_r11 1412 -#define _SWAP_FAST_7_r22 1413 -#define _SWAP_FAST_7_r33 1414 -#define _TIER2_RESUME_CHECK_r00 1415 -#define _TIER2_RESUME_CHECK_r11 1416 -#define _TIER2_RESUME_CHECK_r22 1417 -#define _TIER2_RESUME_CHECK_r33 1418 -#define _TO_BOOL_r11 1419 -#define _TO_BOOL_BOOL_r01 1420 -#define _TO_BOOL_BOOL_r11 1421 -#define _TO_BOOL_BOOL_r22 1422 -#define _TO_BOOL_BOOL_r33 1423 -#define _TO_BOOL_INT_r02 1424 -#define _TO_BOOL_INT_r12 1425 -#define _TO_BOOL_INT_r23 1426 -#define _TO_BOOL_LIST_r02 1427 -#define _TO_BOOL_LIST_r12 1428 -#define _TO_BOOL_LIST_r23 1429 -#define _TO_BOOL_NONE_r01 1430 -#define _TO_BOOL_NONE_r11 1431 -#define _TO_BOOL_NONE_r22 1432 -#define _TO_BOOL_NONE_r33 1433 -#define _TO_BOOL_STR_r02 1434 -#define _TO_BOOL_STR_r12 1435 -#define _TO_BOOL_STR_r23 1436 -#define _TRACE_RECORD_r00 1437 -#define _UNARY_INVERT_r12 1438 -#define _UNARY_NEGATIVE_r12 1439 -#define _UNARY_NOT_r01 1440 -#define _UNARY_NOT_r11 1441 -#define _UNARY_NOT_r22 1442 -#define _UNARY_NOT_r33 1443 -#define _UNPACK_EX_r10 1444 -#define _UNPACK_SEQUENCE_r10 1445 -#define _UNPACK_SEQUENCE_LIST_r10 1446 -#define _UNPACK_SEQUENCE_TUPLE_r10 1447 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1448 -#define _WITH_EXCEPT_START_r33 1449 -#define _YIELD_VALUE_r11 1450 -#define MAX_UOP_REGS_ID 1450 +#define _MATCH_CLASS_ISINSTANCE_r22 1238 +#define _MATCH_KEYS_r23 1239 +#define _MATCH_MAPPING_r02 1240 +#define _MATCH_MAPPING_r12 1241 +#define _MATCH_MAPPING_r23 1242 +#define _MATCH_SEQUENCE_r02 1243 +#define _MATCH_SEQUENCE_r12 1244 +#define _MATCH_SEQUENCE_r23 1245 +#define _MAYBE_EXPAND_METHOD_r00 1246 +#define _MAYBE_EXPAND_METHOD_KW_r11 1247 +#define _MONITOR_CALL_r00 1248 +#define _MONITOR_CALL_KW_r11 1249 +#define _MONITOR_JUMP_BACKWARD_r00 1250 +#define _MONITOR_JUMP_BACKWARD_r11 1251 +#define _MONITOR_JUMP_BACKWARD_r22 1252 +#define _MONITOR_JUMP_BACKWARD_r33 1253 +#define _MONITOR_RESUME_r00 1254 +#define _NOP_r00 1255 +#define _NOP_r11 1256 +#define _NOP_r22 1257 +#define _NOP_r33 1258 +#define _POP_CALL_r20 1259 +#define _POP_CALL_LOAD_CONST_INLINE_BORROW_r21 1260 +#define _POP_CALL_ONE_r30 1261 +#define _POP_CALL_ONE_LOAD_CONST_INLINE_BORROW_r31 1262 +#define _POP_CALL_TWO_r30 1263 +#define _POP_CALL_TWO_LOAD_CONST_INLINE_BORROW_r31 1264 +#define _POP_EXCEPT_r10 1265 +#define _POP_ITER_r20 1266 +#define _POP_JUMP_IF_FALSE_r00 1267 +#define _POP_JUMP_IF_FALSE_r10 1268 +#define _POP_JUMP_IF_FALSE_r21 1269 +#define _POP_JUMP_IF_FALSE_r32 1270 +#define _POP_JUMP_IF_TRUE_r00 1271 +#define _POP_JUMP_IF_TRUE_r10 1272 +#define _POP_JUMP_IF_TRUE_r21 1273 +#define _POP_JUMP_IF_TRUE_r32 1274 +#define _POP_TOP_r10 1275 +#define _POP_TOP_FLOAT_r00 1276 +#define _POP_TOP_FLOAT_r10 1277 +#define _POP_TOP_FLOAT_r21 1278 +#define _POP_TOP_FLOAT_r32 1279 +#define _POP_TOP_INT_r00 1280 +#define _POP_TOP_INT_r10 1281 +#define _POP_TOP_INT_r21 1282 +#define _POP_TOP_INT_r32 1283 +#define _POP_TOP_LOAD_CONST_INLINE_r11 1284 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW_r11 1285 +#define _POP_TOP_NOP_r00 1286 +#define _POP_TOP_NOP_r10 1287 +#define _POP_TOP_NOP_r21 1288 +#define _POP_TOP_NOP_r32 1289 +#define _POP_TOP_UNICODE_r00 1290 +#define _POP_TOP_UNICODE_r10 1291 +#define _POP_TOP_UNICODE_r21 1292 +#define _POP_TOP_UNICODE_r32 1293 +#define _POP_TWO_r20 1294 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW_r21 1295 +#define _PUSH_EXC_INFO_r02 1296 +#define _PUSH_EXC_INFO_r12 1297 +#define _PUSH_EXC_INFO_r23 1298 +#define _PUSH_FRAME_r10 1299 +#define _PUSH_NULL_r01 1300 +#define _PUSH_NULL_r12 1301 +#define _PUSH_NULL_r23 1302 +#define _PUSH_NULL_CONDITIONAL_r00 1303 +#define _PY_FRAME_EX_r31 1304 +#define _PY_FRAME_GENERAL_r01 1305 +#define _PY_FRAME_KW_r11 1306 +#define _QUICKEN_RESUME_r00 1307 +#define _QUICKEN_RESUME_r11 1308 +#define _QUICKEN_RESUME_r22 1309 +#define _QUICKEN_RESUME_r33 1310 +#define _REPLACE_WITH_TRUE_r02 1311 +#define _REPLACE_WITH_TRUE_r12 1312 +#define _REPLACE_WITH_TRUE_r23 1313 +#define _RESUME_CHECK_r00 1314 +#define _RESUME_CHECK_r11 1315 +#define _RESUME_CHECK_r22 1316 +#define _RESUME_CHECK_r33 1317 +#define _RETURN_GENERATOR_r01 1318 +#define _RETURN_VALUE_r11 1319 +#define _SAVE_RETURN_OFFSET_r00 1320 +#define _SAVE_RETURN_OFFSET_r11 1321 +#define _SAVE_RETURN_OFFSET_r22 1322 +#define _SAVE_RETURN_OFFSET_r33 1323 +#define _SEND_r22 1324 +#define _SEND_GEN_FRAME_r22 1325 +#define _SETUP_ANNOTATIONS_r00 1326 +#define _SET_ADD_r10 1327 +#define _SET_FUNCTION_ATTRIBUTE_r01 1328 +#define _SET_FUNCTION_ATTRIBUTE_r11 1329 +#define _SET_FUNCTION_ATTRIBUTE_r21 1330 +#define _SET_FUNCTION_ATTRIBUTE_r32 1331 +#define _SET_IP_r00 1332 +#define _SET_IP_r11 1333 +#define _SET_IP_r22 1334 +#define _SET_IP_r33 1335 +#define _SET_UPDATE_r10 1336 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r02 1337 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r12 1338 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r22 1339 +#define _SHUFFLE_2_LOAD_CONST_INLINE_BORROW_r32 1340 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1341 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1342 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1343 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1344 +#define _SPILL_OR_RELOAD_r01 1345 +#define _SPILL_OR_RELOAD_r02 1346 +#define _SPILL_OR_RELOAD_r03 1347 +#define _SPILL_OR_RELOAD_r10 1348 +#define _SPILL_OR_RELOAD_r12 1349 +#define _SPILL_OR_RELOAD_r13 1350 +#define _SPILL_OR_RELOAD_r20 1351 +#define _SPILL_OR_RELOAD_r21 1352 +#define _SPILL_OR_RELOAD_r23 1353 +#define _SPILL_OR_RELOAD_r30 1354 +#define _SPILL_OR_RELOAD_r31 1355 +#define _SPILL_OR_RELOAD_r32 1356 +#define _START_EXECUTOR_r00 1357 +#define _STORE_ATTR_r20 1358 +#define _STORE_ATTR_INSTANCE_VALUE_r21 1359 +#define _STORE_ATTR_SLOT_r21 1360 +#define _STORE_ATTR_WITH_HINT_r21 1361 +#define _STORE_DEREF_r10 1362 +#define _STORE_FAST_LOAD_FAST_r11 1363 +#define _STORE_FAST_STORE_FAST_r20 1364 +#define _STORE_GLOBAL_r10 1365 +#define _STORE_NAME_r10 1366 +#define _STORE_SLICE_r30 1367 +#define _STORE_SUBSCR_r30 1368 +#define _STORE_SUBSCR_DICT_r31 1369 +#define _STORE_SUBSCR_LIST_INT_r32 1370 +#define _SWAP_r11 1371 +#define _SWAP_2_r02 1372 +#define _SWAP_2_r12 1373 +#define _SWAP_2_r22 1374 +#define _SWAP_2_r33 1375 +#define _SWAP_3_r03 1376 +#define _SWAP_3_r13 1377 +#define _SWAP_3_r23 1378 +#define _SWAP_3_r33 1379 +#define _SWAP_FAST_r01 1380 +#define _SWAP_FAST_r11 1381 +#define _SWAP_FAST_r22 1382 +#define _SWAP_FAST_r33 1383 +#define _SWAP_FAST_0_r01 1384 +#define _SWAP_FAST_0_r11 1385 +#define _SWAP_FAST_0_r22 1386 +#define _SWAP_FAST_0_r33 1387 +#define _SWAP_FAST_1_r01 1388 +#define _SWAP_FAST_1_r11 1389 +#define _SWAP_FAST_1_r22 1390 +#define _SWAP_FAST_1_r33 1391 +#define _SWAP_FAST_2_r01 1392 +#define _SWAP_FAST_2_r11 1393 +#define _SWAP_FAST_2_r22 1394 +#define _SWAP_FAST_2_r33 1395 +#define _SWAP_FAST_3_r01 1396 +#define _SWAP_FAST_3_r11 1397 +#define _SWAP_FAST_3_r22 1398 +#define _SWAP_FAST_3_r33 1399 +#define _SWAP_FAST_4_r01 1400 +#define _SWAP_FAST_4_r11 1401 +#define _SWAP_FAST_4_r22 1402 +#define _SWAP_FAST_4_r33 1403 +#define _SWAP_FAST_5_r01 1404 +#define _SWAP_FAST_5_r11 1405 +#define _SWAP_FAST_5_r22 1406 +#define _SWAP_FAST_5_r33 1407 +#define _SWAP_FAST_6_r01 1408 +#define _SWAP_FAST_6_r11 1409 +#define _SWAP_FAST_6_r22 1410 +#define _SWAP_FAST_6_r33 1411 +#define _SWAP_FAST_7_r01 1412 +#define _SWAP_FAST_7_r11 1413 +#define _SWAP_FAST_7_r22 1414 +#define _SWAP_FAST_7_r33 1415 +#define _TIER2_RESUME_CHECK_r00 1416 +#define _TIER2_RESUME_CHECK_r11 1417 +#define _TIER2_RESUME_CHECK_r22 1418 +#define _TIER2_RESUME_CHECK_r33 1419 +#define _TO_BOOL_r11 1420 +#define _TO_BOOL_BOOL_r01 1421 +#define _TO_BOOL_BOOL_r11 1422 +#define _TO_BOOL_BOOL_r22 1423 +#define _TO_BOOL_BOOL_r33 1424 +#define _TO_BOOL_INT_r02 1425 +#define _TO_BOOL_INT_r12 1426 +#define _TO_BOOL_INT_r23 1427 +#define _TO_BOOL_LIST_r02 1428 +#define _TO_BOOL_LIST_r12 1429 +#define _TO_BOOL_LIST_r23 1430 +#define _TO_BOOL_NONE_r01 1431 +#define _TO_BOOL_NONE_r11 1432 +#define _TO_BOOL_NONE_r22 1433 +#define _TO_BOOL_NONE_r33 1434 +#define _TO_BOOL_STR_r02 1435 +#define _TO_BOOL_STR_r12 1436 +#define _TO_BOOL_STR_r23 1437 +#define _TRACE_RECORD_r00 1438 +#define _UNARY_INVERT_r12 1439 +#define _UNARY_NEGATIVE_r12 1440 +#define _UNARY_NOT_r01 1441 +#define _UNARY_NOT_r11 1442 +#define _UNARY_NOT_r22 1443 +#define _UNARY_NOT_r33 1444 +#define _UNPACK_EX_r10 1445 +#define _UNPACK_SEQUENCE_r10 1446 +#define _UNPACK_SEQUENCE_LIST_r10 1447 +#define _UNPACK_SEQUENCE_TUPLE_r10 1448 +#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1449 +#define _WITH_EXCEPT_START_r33 1450 +#define _YIELD_VALUE_r11 1451 +#define MAX_UOP_REGS_ID 1451 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 7921d229f11db3a..bd2c6c781f3c351 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -218,6 +218,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_IMPORT_FROM] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_IS_NONE] = HAS_ESCAPES_FLAG, [_GET_LEN] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, + [_MATCH_CLASS_ISINSTANCE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_MATCH_CLASS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_MATCH_MAPPING] = 0, [_MATCH_SEQUENCE] = 0, @@ -2045,6 +2046,15 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, + [_MATCH_CLASS_ISINSTANCE] = { + .best = { 2, 2, 2, 2 }, + .entries = { + { -1, -1, -1 }, + { -1, -1, -1 }, + { 2, 2, _MATCH_CLASS_ISINSTANCE_r22 }, + { -1, -1, -1 }, + }, + }, [_MATCH_CLASS] = { .best = { 3, 3, 3, 3 }, .entries = { @@ -3857,6 +3867,7 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_IMPORT_FROM_r12] = _IMPORT_FROM, [_IS_NONE_r11] = _IS_NONE, [_GET_LEN_r12] = _GET_LEN, + [_MATCH_CLASS_ISINSTANCE_r22] = _MATCH_CLASS_ISINSTANCE, [_MATCH_CLASS_r31] = _MATCH_CLASS, [_MATCH_MAPPING_r02] = _MATCH_MAPPING, [_MATCH_MAPPING_r12] = _MATCH_MAPPING, @@ -5113,6 +5124,8 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_MAP_ADD_r20] = "_MAP_ADD_r20", [_MATCH_CLASS] = "_MATCH_CLASS", [_MATCH_CLASS_r31] = "_MATCH_CLASS_r31", + [_MATCH_CLASS_ISINSTANCE] = "_MATCH_CLASS_ISINSTANCE", + [_MATCH_CLASS_ISINSTANCE_r22] = "_MATCH_CLASS_ISINSTANCE_r22", [_MATCH_KEYS] = "_MATCH_KEYS", [_MATCH_KEYS_r23] = "_MATCH_KEYS_r23", [_MATCH_MAPPING] = "_MATCH_MAPPING", @@ -5766,6 +5779,8 @@ int _PyUop_num_popped(int opcode, int oparg) return 1; case _GET_LEN: return 0; + case _MATCH_CLASS_ISINSTANCE: + return 1; case _MATCH_CLASS: return 3; case _MATCH_MAPPING: diff --git a/Include/opcode_ids.h b/Include/opcode_ids.h index c46368444f4c597..2deb73e16ed0d89 100644 --- a/Include/opcode_ids.h +++ b/Include/opcode_ids.h @@ -34,103 +34,104 @@ extern "C" { #define LOAD_BUILD_CLASS 21 #define LOAD_LOCALS 22 #define MAKE_FUNCTION 23 -#define MATCH_KEYS 24 -#define MATCH_MAPPING 25 -#define MATCH_SEQUENCE 26 -#define NOP 27 -#define NOT_TAKEN 28 -#define POP_EXCEPT 29 -#define POP_ITER 30 -#define POP_TOP 31 -#define PUSH_EXC_INFO 32 -#define PUSH_NULL 33 -#define RETURN_GENERATOR 34 -#define RETURN_VALUE 35 -#define SETUP_ANNOTATIONS 36 -#define STORE_SLICE 37 -#define STORE_SUBSCR 38 -#define TO_BOOL 39 -#define UNARY_INVERT 40 -#define UNARY_NEGATIVE 41 -#define UNARY_NOT 42 -#define WITH_EXCEPT_START 43 -#define BINARY_OP 44 -#define BUILD_INTERPOLATION 45 -#define BUILD_LIST 46 -#define BUILD_MAP 47 -#define BUILD_SET 48 -#define BUILD_SLICE 49 -#define BUILD_STRING 50 -#define BUILD_TUPLE 51 -#define CALL 52 -#define CALL_INTRINSIC_1 53 -#define CALL_INTRINSIC_2 54 -#define CALL_KW 55 -#define COMPARE_OP 56 -#define CONTAINS_OP 57 -#define CONVERT_VALUE 58 -#define COPY 59 -#define COPY_FREE_VARS 60 -#define DELETE_ATTR 61 -#define DELETE_DEREF 62 -#define DELETE_FAST 63 -#define DELETE_GLOBAL 64 -#define DELETE_NAME 65 -#define DICT_MERGE 66 -#define DICT_UPDATE 67 -#define END_ASYNC_FOR 68 -#define EXTENDED_ARG 69 -#define FOR_ITER 70 -#define GET_AWAITABLE 71 -#define IMPORT_FROM 72 -#define IMPORT_NAME 73 -#define IS_OP 74 -#define JUMP_BACKWARD 75 -#define JUMP_BACKWARD_NO_INTERRUPT 76 -#define JUMP_FORWARD 77 -#define LIST_APPEND 78 -#define LIST_EXTEND 79 -#define LOAD_ATTR 80 -#define LOAD_COMMON_CONSTANT 81 -#define LOAD_CONST 82 -#define LOAD_DEREF 83 -#define LOAD_FAST 84 -#define LOAD_FAST_AND_CLEAR 85 -#define LOAD_FAST_BORROW 86 -#define LOAD_FAST_BORROW_LOAD_FAST_BORROW 87 -#define LOAD_FAST_CHECK 88 -#define LOAD_FAST_LOAD_FAST 89 -#define LOAD_FROM_DICT_OR_DEREF 90 -#define LOAD_FROM_DICT_OR_GLOBALS 91 -#define LOAD_GLOBAL 92 -#define LOAD_NAME 93 -#define LOAD_SMALL_INT 94 -#define LOAD_SPECIAL 95 -#define LOAD_SUPER_ATTR 96 -#define MAKE_CELL 97 -#define MAP_ADD 98 -#define MATCH_CLASS 99 -#define POP_JUMP_IF_FALSE 100 -#define POP_JUMP_IF_NONE 101 -#define POP_JUMP_IF_NOT_NONE 102 -#define POP_JUMP_IF_TRUE 103 -#define RAISE_VARARGS 104 -#define RERAISE 105 -#define SEND 106 -#define SET_ADD 107 -#define SET_FUNCTION_ATTRIBUTE 108 -#define SET_UPDATE 109 -#define STORE_ATTR 110 -#define STORE_DEREF 111 -#define STORE_FAST 112 -#define STORE_FAST_LOAD_FAST 113 -#define STORE_FAST_STORE_FAST 114 -#define STORE_GLOBAL 115 -#define STORE_NAME 116 -#define SWAP 117 -#define UNPACK_EX 118 -#define UNPACK_SEQUENCE 119 -#define YIELD_VALUE 120 +#define MATCH_CLASS_ISINSTANCE 24 +#define MATCH_KEYS 25 +#define MATCH_MAPPING 26 +#define MATCH_SEQUENCE 27 +#define NOP 28 +#define NOT_TAKEN 29 +#define POP_EXCEPT 30 +#define POP_ITER 31 +#define POP_TOP 32 +#define PUSH_EXC_INFO 33 +#define PUSH_NULL 34 +#define RETURN_GENERATOR 35 +#define RETURN_VALUE 36 +#define SETUP_ANNOTATIONS 37 +#define STORE_SLICE 38 +#define STORE_SUBSCR 39 +#define TO_BOOL 40 +#define UNARY_INVERT 41 +#define UNARY_NEGATIVE 42 +#define UNARY_NOT 43 +#define WITH_EXCEPT_START 44 +#define BINARY_OP 45 +#define BUILD_INTERPOLATION 46 +#define BUILD_LIST 47 +#define BUILD_MAP 48 +#define BUILD_SET 49 +#define BUILD_SLICE 50 +#define BUILD_STRING 51 +#define BUILD_TUPLE 52 +#define CALL 53 +#define CALL_INTRINSIC_1 54 +#define CALL_INTRINSIC_2 55 +#define CALL_KW 56 +#define COMPARE_OP 57 +#define CONTAINS_OP 58 +#define CONVERT_VALUE 59 +#define COPY 60 +#define COPY_FREE_VARS 61 +#define DELETE_ATTR 62 +#define DELETE_DEREF 63 +#define DELETE_FAST 64 +#define DELETE_GLOBAL 65 +#define DELETE_NAME 66 +#define DICT_MERGE 67 +#define DICT_UPDATE 68 +#define END_ASYNC_FOR 69 +#define EXTENDED_ARG 70 +#define FOR_ITER 71 +#define GET_AWAITABLE 72 +#define IMPORT_FROM 73 +#define IMPORT_NAME 74 +#define IS_OP 75 +#define JUMP_BACKWARD 76 +#define JUMP_BACKWARD_NO_INTERRUPT 77 +#define JUMP_FORWARD 78 +#define LIST_APPEND 79 +#define LIST_EXTEND 80 +#define LOAD_ATTR 81 +#define LOAD_COMMON_CONSTANT 82 +#define LOAD_CONST 83 +#define LOAD_DEREF 84 +#define LOAD_FAST 85 +#define LOAD_FAST_AND_CLEAR 86 +#define LOAD_FAST_BORROW 87 +#define LOAD_FAST_BORROW_LOAD_FAST_BORROW 88 +#define LOAD_FAST_CHECK 89 +#define LOAD_FAST_LOAD_FAST 90 +#define LOAD_FROM_DICT_OR_DEREF 91 +#define LOAD_FROM_DICT_OR_GLOBALS 92 +#define LOAD_GLOBAL 93 +#define LOAD_NAME 94 +#define LOAD_SMALL_INT 95 +#define LOAD_SPECIAL 96 +#define LOAD_SUPER_ATTR 97 +#define MAKE_CELL 98 +#define MAP_ADD 99 +#define MATCH_CLASS 100 +#define POP_JUMP_IF_FALSE 101 +#define POP_JUMP_IF_NONE 102 +#define POP_JUMP_IF_NOT_NONE 103 +#define POP_JUMP_IF_TRUE 104 +#define RAISE_VARARGS 105 +#define RERAISE 106 +#define SEND 107 +#define SET_ADD 108 +#define SET_FUNCTION_ATTRIBUTE 109 +#define SET_UPDATE 110 +#define STORE_ATTR 111 +#define STORE_DEREF 112 +#define STORE_FAST 113 +#define STORE_FAST_LOAD_FAST 114 +#define STORE_FAST_STORE_FAST 115 +#define STORE_GLOBAL 116 +#define STORE_NAME 117 +#define SWAP 118 +#define UNPACK_EX 119 +#define UNPACK_SEQUENCE 120 +#define YIELD_VALUE 121 #define RESUME 128 #define BINARY_OP_ADD_FLOAT 129 #define BINARY_OP_ADD_INT 130 @@ -251,7 +252,7 @@ extern "C" { #define SETUP_WITH 265 #define STORE_FAST_MAYBE_NULL 266 -#define HAVE_ARGUMENT 43 +#define HAVE_ARGUMENT 44 #define MIN_SPECIALIZED_OPCODE 129 #define MIN_INSTRUMENTED_OPCODE 233 diff --git a/Lib/_opcode_metadata.py b/Lib/_opcode_metadata.py index 8f14d81a43ee752..85124e6f8f22d49 100644 --- a/Lib/_opcode_metadata.py +++ b/Lib/_opcode_metadata.py @@ -242,103 +242,104 @@ 'LOAD_BUILD_CLASS': 21, 'LOAD_LOCALS': 22, 'MAKE_FUNCTION': 23, - 'MATCH_KEYS': 24, - 'MATCH_MAPPING': 25, - 'MATCH_SEQUENCE': 26, - 'NOP': 27, - 'NOT_TAKEN': 28, - 'POP_EXCEPT': 29, - 'POP_ITER': 30, - 'POP_TOP': 31, - 'PUSH_EXC_INFO': 32, - 'PUSH_NULL': 33, - 'RETURN_GENERATOR': 34, - 'RETURN_VALUE': 35, - 'SETUP_ANNOTATIONS': 36, - 'STORE_SLICE': 37, - 'STORE_SUBSCR': 38, - 'TO_BOOL': 39, - 'UNARY_INVERT': 40, - 'UNARY_NEGATIVE': 41, - 'UNARY_NOT': 42, - 'WITH_EXCEPT_START': 43, - 'BINARY_OP': 44, - 'BUILD_INTERPOLATION': 45, - 'BUILD_LIST': 46, - 'BUILD_MAP': 47, - 'BUILD_SET': 48, - 'BUILD_SLICE': 49, - 'BUILD_STRING': 50, - 'BUILD_TUPLE': 51, - 'CALL': 52, - 'CALL_INTRINSIC_1': 53, - 'CALL_INTRINSIC_2': 54, - 'CALL_KW': 55, - 'COMPARE_OP': 56, - 'CONTAINS_OP': 57, - 'CONVERT_VALUE': 58, - 'COPY': 59, - 'COPY_FREE_VARS': 60, - 'DELETE_ATTR': 61, - 'DELETE_DEREF': 62, - 'DELETE_FAST': 63, - 'DELETE_GLOBAL': 64, - 'DELETE_NAME': 65, - 'DICT_MERGE': 66, - 'DICT_UPDATE': 67, - 'END_ASYNC_FOR': 68, - 'EXTENDED_ARG': 69, - 'FOR_ITER': 70, - 'GET_AWAITABLE': 71, - 'IMPORT_FROM': 72, - 'IMPORT_NAME': 73, - 'IS_OP': 74, - 'JUMP_BACKWARD': 75, - 'JUMP_BACKWARD_NO_INTERRUPT': 76, - 'JUMP_FORWARD': 77, - 'LIST_APPEND': 78, - 'LIST_EXTEND': 79, - 'LOAD_ATTR': 80, - 'LOAD_COMMON_CONSTANT': 81, - 'LOAD_CONST': 82, - 'LOAD_DEREF': 83, - 'LOAD_FAST': 84, - 'LOAD_FAST_AND_CLEAR': 85, - 'LOAD_FAST_BORROW': 86, - 'LOAD_FAST_BORROW_LOAD_FAST_BORROW': 87, - 'LOAD_FAST_CHECK': 88, - 'LOAD_FAST_LOAD_FAST': 89, - 'LOAD_FROM_DICT_OR_DEREF': 90, - 'LOAD_FROM_DICT_OR_GLOBALS': 91, - 'LOAD_GLOBAL': 92, - 'LOAD_NAME': 93, - 'LOAD_SMALL_INT': 94, - 'LOAD_SPECIAL': 95, - 'LOAD_SUPER_ATTR': 96, - 'MAKE_CELL': 97, - 'MAP_ADD': 98, - 'MATCH_CLASS': 99, - 'POP_JUMP_IF_FALSE': 100, - 'POP_JUMP_IF_NONE': 101, - 'POP_JUMP_IF_NOT_NONE': 102, - 'POP_JUMP_IF_TRUE': 103, - 'RAISE_VARARGS': 104, - 'RERAISE': 105, - 'SEND': 106, - 'SET_ADD': 107, - 'SET_FUNCTION_ATTRIBUTE': 108, - 'SET_UPDATE': 109, - 'STORE_ATTR': 110, - 'STORE_DEREF': 111, - 'STORE_FAST': 112, - 'STORE_FAST_LOAD_FAST': 113, - 'STORE_FAST_STORE_FAST': 114, - 'STORE_GLOBAL': 115, - 'STORE_NAME': 116, - 'SWAP': 117, - 'UNPACK_EX': 118, - 'UNPACK_SEQUENCE': 119, - 'YIELD_VALUE': 120, + 'MATCH_CLASS_ISINSTANCE': 24, + 'MATCH_KEYS': 25, + 'MATCH_MAPPING': 26, + 'MATCH_SEQUENCE': 27, + 'NOP': 28, + 'NOT_TAKEN': 29, + 'POP_EXCEPT': 30, + 'POP_ITER': 31, + 'POP_TOP': 32, + 'PUSH_EXC_INFO': 33, + 'PUSH_NULL': 34, + 'RETURN_GENERATOR': 35, + 'RETURN_VALUE': 36, + 'SETUP_ANNOTATIONS': 37, + 'STORE_SLICE': 38, + 'STORE_SUBSCR': 39, + 'TO_BOOL': 40, + 'UNARY_INVERT': 41, + 'UNARY_NEGATIVE': 42, + 'UNARY_NOT': 43, + 'WITH_EXCEPT_START': 44, + 'BINARY_OP': 45, + 'BUILD_INTERPOLATION': 46, + 'BUILD_LIST': 47, + 'BUILD_MAP': 48, + 'BUILD_SET': 49, + 'BUILD_SLICE': 50, + 'BUILD_STRING': 51, + 'BUILD_TUPLE': 52, + 'CALL': 53, + 'CALL_INTRINSIC_1': 54, + 'CALL_INTRINSIC_2': 55, + 'CALL_KW': 56, + 'COMPARE_OP': 57, + 'CONTAINS_OP': 58, + 'CONVERT_VALUE': 59, + 'COPY': 60, + 'COPY_FREE_VARS': 61, + 'DELETE_ATTR': 62, + 'DELETE_DEREF': 63, + 'DELETE_FAST': 64, + 'DELETE_GLOBAL': 65, + 'DELETE_NAME': 66, + 'DICT_MERGE': 67, + 'DICT_UPDATE': 68, + 'END_ASYNC_FOR': 69, + 'EXTENDED_ARG': 70, + 'FOR_ITER': 71, + 'GET_AWAITABLE': 72, + 'IMPORT_FROM': 73, + 'IMPORT_NAME': 74, + 'IS_OP': 75, + 'JUMP_BACKWARD': 76, + 'JUMP_BACKWARD_NO_INTERRUPT': 77, + 'JUMP_FORWARD': 78, + 'LIST_APPEND': 79, + 'LIST_EXTEND': 80, + 'LOAD_ATTR': 81, + 'LOAD_COMMON_CONSTANT': 82, + 'LOAD_CONST': 83, + 'LOAD_DEREF': 84, + 'LOAD_FAST': 85, + 'LOAD_FAST_AND_CLEAR': 86, + 'LOAD_FAST_BORROW': 87, + 'LOAD_FAST_BORROW_LOAD_FAST_BORROW': 88, + 'LOAD_FAST_CHECK': 89, + 'LOAD_FAST_LOAD_FAST': 90, + 'LOAD_FROM_DICT_OR_DEREF': 91, + 'LOAD_FROM_DICT_OR_GLOBALS': 92, + 'LOAD_GLOBAL': 93, + 'LOAD_NAME': 94, + 'LOAD_SMALL_INT': 95, + 'LOAD_SPECIAL': 96, + 'LOAD_SUPER_ATTR': 97, + 'MAKE_CELL': 98, + 'MAP_ADD': 99, + 'MATCH_CLASS': 100, + 'POP_JUMP_IF_FALSE': 101, + 'POP_JUMP_IF_NONE': 102, + 'POP_JUMP_IF_NOT_NONE': 103, + 'POP_JUMP_IF_TRUE': 104, + 'RAISE_VARARGS': 105, + 'RERAISE': 106, + 'SEND': 107, + 'SET_ADD': 108, + 'SET_FUNCTION_ATTRIBUTE': 109, + 'SET_UPDATE': 110, + 'STORE_ATTR': 111, + 'STORE_DEREF': 112, + 'STORE_FAST': 113, + 'STORE_FAST_LOAD_FAST': 114, + 'STORE_FAST_STORE_FAST': 115, + 'STORE_GLOBAL': 116, + 'STORE_NAME': 117, + 'SWAP': 118, + 'UNPACK_EX': 119, + 'UNPACK_SEQUENCE': 120, + 'YIELD_VALUE': 121, 'INSTRUMENTED_END_FOR': 233, 'INSTRUMENTED_POP_ITER': 234, 'INSTRUMENTED_END_SEND': 235, @@ -372,5 +373,5 @@ 'STORE_FAST_MAYBE_NULL': 266, } -HAVE_ARGUMENT = 43 +HAVE_ARGUMENT = 44 MIN_INSTRUMENTED_OPCODE = 233 diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index cefd64ddfe84173..41a8591223adb76 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -1035,7 +1035,8 @@ def test_widths(self): long_opcodes = set(['JUMP_BACKWARD_NO_INTERRUPT', 'LOAD_FAST_BORROW_LOAD_FAST_BORROW', 'INSTRUMENTED_CALL_FUNCTION_EX', - 'ANNOTATIONS_PLACEHOLDER']) + 'ANNOTATIONS_PLACEHOLDER', + 'MATCH_CLASS_ISINSTANCE']) for op, opname in enumerate(dis.opname): if opname in long_opcodes or opname.startswith("INSTRUMENTED"): continue diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-16-19-22.gh-issue-138912.TKMC9K.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-16-19-22.gh-issue-138912.TKMC9K.rst new file mode 100644 index 000000000000000..1e9d0067027631e --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-16-19-22.gh-issue-138912.TKMC9K.rst @@ -0,0 +1,3 @@ +Add :opcode:`MATCH_CLASS_ISINSTANCE` opcode to improve the performance of +:keyword:`match` class patterns without any sub-patterns by ~24%. +Patch by Marc Mueller. diff --git a/Modules/_testinternalcapi/test_cases.c.h b/Modules/_testinternalcapi/test_cases.c.h index fde6db4933f74ab..e1bf1aeb9589706 100644 --- a/Modules/_testinternalcapi/test_cases.c.h +++ b/Modules/_testinternalcapi/test_cases.c.h @@ -9992,6 +9992,52 @@ DISPATCH(); } + TARGET(MATCH_CLASS_ISINSTANCE) { + #if _Py_TAIL_CALL_INTERP + int opcode = MATCH_CLASS_ISINSTANCE; + (void)(opcode); + #endif + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(MATCH_CLASS_ISINSTANCE); + _PyStackRef subject; + _PyStackRef type; + _PyStackRef res; + type = stack_pointer[-1]; + subject = stack_pointer[-2]; + PyObject *subject_o = PyStackRef_AsPyObjectBorrow(subject); + PyObject *type_o = PyStackRef_AsPyObjectBorrow(type); + if (!PyType_Check(type_o)) { + const char *e = "called match pattern must be a class"; + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyErr_Format(tstate, PyExc_TypeError, e); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(type); + stack_pointer = _PyFrame_GetStackPointer(frame); + JUMP_TO_LABEL(error); + } + _PyFrame_SetStackPointer(frame, stack_pointer); + int retval = PyObject_IsInstance(subject_o, type_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(type); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (retval < 0) { + JUMP_TO_LABEL(error); + } + assert(!_PyErr_Occurred(tstate)); + res = retval ? PyStackRef_True : PyStackRef_False; + stack_pointer[0] = res; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + DISPATCH(); + } + TARGET(MATCH_KEYS) { #if _Py_TAIL_CALL_INTERP int opcode = MATCH_KEYS; diff --git a/Modules/_testinternalcapi/test_targets.h b/Modules/_testinternalcapi/test_targets.h index f57c33feec2ac29..0be9dbbf36e32eb 100644 --- a/Modules/_testinternalcapi/test_targets.h +++ b/Modules/_testinternalcapi/test_targets.h @@ -24,6 +24,7 @@ static void *opcode_targets_table[256] = { &&TARGET_LOAD_BUILD_CLASS, &&TARGET_LOAD_LOCALS, &&TARGET_MAKE_FUNCTION, + &&TARGET_MATCH_CLASS_ISINSTANCE, &&TARGET_MATCH_KEYS, &&TARGET_MATCH_MAPPING, &&TARGET_MATCH_SEQUENCE, @@ -127,7 +128,6 @@ static void *opcode_targets_table[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_RESUME, &&TARGET_BINARY_OP_ADD_FLOAT, &&TARGET_BINARY_OP_ADD_INT, @@ -380,7 +380,7 @@ static void *opcode_tracing_targets_table[256] = { &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, - &&_unknown_opcode, + &&TARGET_TRACE_RECORD, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -699,6 +699,7 @@ static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MAKE_CELL(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MAKE_FUNCTION(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MAP_ADD(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_CLASS(TAIL_CALL_PARAMS); +static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_CLASS_ISINSTANCE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_KEYS(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_MAPPING(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_SEQUENCE(TAIL_CALL_PARAMS); @@ -940,6 +941,7 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [MAKE_FUNCTION] = _TAIL_CALL_MAKE_FUNCTION, [MAP_ADD] = _TAIL_CALL_MAP_ADD, [MATCH_CLASS] = _TAIL_CALL_MATCH_CLASS, + [MATCH_CLASS_ISINSTANCE] = _TAIL_CALL_MATCH_CLASS_ISINSTANCE, [MATCH_KEYS] = _TAIL_CALL_MATCH_KEYS, [MATCH_MAPPING] = _TAIL_CALL_MATCH_MAPPING, [MATCH_SEQUENCE] = _TAIL_CALL_MATCH_SEQUENCE, @@ -1000,7 +1002,6 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_UNPACK_SEQUENCE_TWO_TUPLE, [WITH_EXCEPT_START] = _TAIL_CALL_WITH_EXCEPT_START, [YIELD_VALUE] = _TAIL_CALL_YIELD_VALUE, - [121] = _TAIL_CALL_UNKNOWN_OPCODE, [122] = _TAIL_CALL_UNKNOWN_OPCODE, [123] = _TAIL_CALL_UNKNOWN_OPCODE, [124] = _TAIL_CALL_UNKNOWN_OPCODE, @@ -1198,6 +1199,7 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [MAKE_FUNCTION] = _TAIL_CALL_TRACE_RECORD, [MAP_ADD] = _TAIL_CALL_TRACE_RECORD, [MATCH_CLASS] = _TAIL_CALL_TRACE_RECORD, + [MATCH_CLASS_ISINSTANCE] = _TAIL_CALL_TRACE_RECORD, [MATCH_KEYS] = _TAIL_CALL_TRACE_RECORD, [MATCH_MAPPING] = _TAIL_CALL_TRACE_RECORD, [MATCH_SEQUENCE] = _TAIL_CALL_TRACE_RECORD, @@ -1258,7 +1260,6 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_TRACE_RECORD, [WITH_EXCEPT_START] = _TAIL_CALL_TRACE_RECORD, [YIELD_VALUE] = _TAIL_CALL_TRACE_RECORD, - [121] = _TAIL_CALL_UNKNOWN_OPCODE, [122] = _TAIL_CALL_UNKNOWN_OPCODE, [123] = _TAIL_CALL_UNKNOWN_OPCODE, [124] = _TAIL_CALL_UNKNOWN_OPCODE, diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index f808544045e1539..f5f1f85045d1bd9 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -1,19 +1,19 @@ // Auto-generated by Programs/freeze_test_frozenmain.py unsigned char M_test_frozenmain[] = { 227,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0, - 0,0,0,0,0,243,184,0,0,0,128,0,94,0,82,1, - 73,0,116,0,94,0,82,1,73,4,116,1,93,2,33,0, - 82,2,52,1,0,0,0,0,0,0,31,0,93,2,33,0, - 82,3,93,0,80,6,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,52,2,0,0,0,0,0,0, - 31,0,93,1,80,8,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,33,0,52,0,0,0,0,0, - 0,0,82,4,44,26,0,0,0,0,0,0,0,0,0,0, - 116,5,82,7,16,0,70,24,0,0,116,6,93,2,33,0, - 82,5,93,6,12,0,82,6,93,5,93,6,44,26,0,0, - 0,0,0,0,0,0,0,0,12,0,50,4,52,1,0,0, - 0,0,0,0,31,0,75,26,0,0,9,0,30,0,82,1, - 35,0,41,8,233,0,0,0,0,78,122,18,70,114,111,122, + 0,0,0,0,0,243,184,0,0,0,128,0,95,0,83,1, + 74,0,117,0,95,0,83,1,74,4,117,1,94,2,34,0, + 83,2,53,1,0,0,0,0,0,0,32,0,94,2,34,0, + 83,3,94,0,81,6,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,53,2,0,0,0,0,0,0, + 32,0,94,1,81,8,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,34,0,53,0,0,0,0,0, + 0,0,83,4,45,26,0,0,0,0,0,0,0,0,0,0, + 117,5,83,7,16,0,71,24,0,0,117,6,94,2,34,0, + 83,5,94,6,12,0,83,6,94,5,94,6,45,26,0,0, + 0,0,0,0,0,0,0,0,12,0,51,4,53,1,0,0, + 0,0,0,0,32,0,76,26,0,0,9,0,31,0,83,1, + 36,0,41,8,233,0,0,0,0,78,122,18,70,114,111,122, 101,110,32,72,101,108,108,111,32,87,111,114,108,100,122,8, 115,121,115,46,97,114,103,118,218,6,99,111,110,102,105,103, 122,7,99,111,110,102,105,103,32,122,2,58,32,41,5,218, diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 01eaf4a59b645a5..bb80efd25d0fac1 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -3199,6 +3199,22 @@ dummy_func( len = PyStackRef_FromPyObjectSteal(len_o); } + inst(MATCH_CLASS_ISINSTANCE, (subject, type -- subject, res)) { + PyObject *subject_o = PyStackRef_AsPyObjectBorrow(subject); + PyObject *type_o = PyStackRef_AsPyObjectBorrow(type); + if (!PyType_Check(type_o)) { + const char *e = "called match pattern must be a class"; + _PyErr_Format(tstate, PyExc_TypeError, e); + PyStackRef_CLOSE(type); + ERROR_IF(true); + } + int retval = PyObject_IsInstance(subject_o, type_o); + PyStackRef_CLOSE(type); + ERROR_IF(retval < 0); + assert(!_PyErr_Occurred(tstate)); + res = retval ? PyStackRef_True : PyStackRef_False; + } + inst(MATCH_CLASS, (subject, type, names -- attrs)) { // Pop TOS and TOS1. Set TOS to a tuple of attributes on success, or // None on failure. diff --git a/Python/codegen.c b/Python/codegen.c index 42fccb07d31dbae..e2f100a87e4f4fc 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -6068,6 +6068,24 @@ validate_kwd_attrs(compiler *c, asdl_identifier_seq *attrs, asdl_pattern_seq* pa return SUCCESS; } +static int +codegen_pattern_class_fast(compiler *c, pattern_ty p, pattern_context *pc) +{ + NEW_JUMP_TARGET_LABEL(c, end); + assert(p->kind == MatchClass_kind); + assert(!asdl_seq_LEN(p->v.MatchClass.patterns)); + assert(!asdl_seq_LEN(p->v.MatchClass.kwd_attrs)); + VISIT(c, expr, p->v.MatchClass.cls); + ADDOP(c, LOC(p), MATCH_CLASS_ISINSTANCE); + // TOS is now subject: + pc->on_top++; + RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE)); + pc->on_top--; + // Success! POP subject: + ADDOP(c, LOC(p), POP_TOP); + return SUCCESS; +} + static int codegen_pattern_class(compiler *c, pattern_ty p, pattern_context *pc) { @@ -6091,6 +6109,10 @@ codegen_pattern_class(compiler *c, pattern_ty p, pattern_context *pc) if (nattrs) { RETURN_IF_ERROR(validate_kwd_attrs(c, kwd_attrs, kwd_patterns)); } + if (!nargs && !nattrs) { + // Fast path if there are no sub-patterns + return codegen_pattern_class_fast(c, p, pc); + } VISIT(c, expr, p->v.MatchClass.cls); PyObject *attr_names = PyTuple_New(nattrs); if (attr_names == NULL) { diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 8b36d1abf2e9166..c953e1d21569d83 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -10715,6 +10715,63 @@ break; } + case _MATCH_CLASS_ISINSTANCE_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef type; + _PyStackRef subject; + _PyStackRef res; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + type = _stack_item_1; + subject = _stack_item_0; + PyObject *subject_o = PyStackRef_AsPyObjectBorrow(subject); + PyObject *type_o = PyStackRef_AsPyObjectBorrow(type); + if (!PyType_Check(type_o)) { + const char *e = "called match pattern must be a class"; + stack_pointer[0] = subject; + stack_pointer[1] = type; + stack_pointer += 2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyErr_Format(tstate, PyExc_TypeError, e); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(type); + stack_pointer = _PyFrame_GetStackPointer(frame); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + stack_pointer[0] = subject; + stack_pointer[1] = type; + stack_pointer += 2; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + int retval = PyObject_IsInstance(subject_o, type_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(type); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (retval < 0) { + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_ERROR(); + } + assert(!_PyErr_Occurred(tstate)); + res = retval ? PyStackRef_True : PyStackRef_False; + _tos_cache1 = res; + _tos_cache0 = subject; + _tos_cache2 = PyStackRef_ZERO_BITS; + SET_CURRENT_CACHED_VALUES(2); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _MATCH_CLASS_r31: { CHECK_CURRENT_CACHED_VALUES(3); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index bc9ae7e0ab3be37..b19ef8580d29b92 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -9990,6 +9990,52 @@ DISPATCH(); } + TARGET(MATCH_CLASS_ISINSTANCE) { + #if _Py_TAIL_CALL_INTERP + int opcode = MATCH_CLASS_ISINSTANCE; + (void)(opcode); + #endif + frame->instr_ptr = next_instr; + next_instr += 1; + INSTRUCTION_STATS(MATCH_CLASS_ISINSTANCE); + _PyStackRef subject; + _PyStackRef type; + _PyStackRef res; + type = stack_pointer[-1]; + subject = stack_pointer[-2]; + PyObject *subject_o = PyStackRef_AsPyObjectBorrow(subject); + PyObject *type_o = PyStackRef_AsPyObjectBorrow(type); + if (!PyType_Check(type_o)) { + const char *e = "called match pattern must be a class"; + _PyFrame_SetStackPointer(frame, stack_pointer); + _PyErr_Format(tstate, PyExc_TypeError, e); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(type); + stack_pointer = _PyFrame_GetStackPointer(frame); + JUMP_TO_LABEL(error); + } + _PyFrame_SetStackPointer(frame, stack_pointer); + int retval = PyObject_IsInstance(subject_o, type_o); + stack_pointer = _PyFrame_GetStackPointer(frame); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + _PyFrame_SetStackPointer(frame, stack_pointer); + PyStackRef_CLOSE(type); + stack_pointer = _PyFrame_GetStackPointer(frame); + if (retval < 0) { + JUMP_TO_LABEL(error); + } + assert(!_PyErr_Occurred(tstate)); + res = retval ? PyStackRef_True : PyStackRef_False; + stack_pointer[0] = res; + stack_pointer += 1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + DISPATCH(); + } + TARGET(MATCH_KEYS) { #if _Py_TAIL_CALL_INTERP int opcode = MATCH_KEYS; diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index f57c33feec2ac29..0be9dbbf36e32eb 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -24,6 +24,7 @@ static void *opcode_targets_table[256] = { &&TARGET_LOAD_BUILD_CLASS, &&TARGET_LOAD_LOCALS, &&TARGET_MAKE_FUNCTION, + &&TARGET_MATCH_CLASS_ISINSTANCE, &&TARGET_MATCH_KEYS, &&TARGET_MATCH_MAPPING, &&TARGET_MATCH_SEQUENCE, @@ -127,7 +128,6 @@ static void *opcode_targets_table[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, - &&_unknown_opcode, &&TARGET_RESUME, &&TARGET_BINARY_OP_ADD_FLOAT, &&TARGET_BINARY_OP_ADD_INT, @@ -380,7 +380,7 @@ static void *opcode_tracing_targets_table[256] = { &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, - &&_unknown_opcode, + &&TARGET_TRACE_RECORD, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -699,6 +699,7 @@ static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MAKE_CELL(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MAKE_FUNCTION(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MAP_ADD(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_CLASS(TAIL_CALL_PARAMS); +static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_CLASS_ISINSTANCE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_KEYS(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_MAPPING(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_SEQUENCE(TAIL_CALL_PARAMS); @@ -940,6 +941,7 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [MAKE_FUNCTION] = _TAIL_CALL_MAKE_FUNCTION, [MAP_ADD] = _TAIL_CALL_MAP_ADD, [MATCH_CLASS] = _TAIL_CALL_MATCH_CLASS, + [MATCH_CLASS_ISINSTANCE] = _TAIL_CALL_MATCH_CLASS_ISINSTANCE, [MATCH_KEYS] = _TAIL_CALL_MATCH_KEYS, [MATCH_MAPPING] = _TAIL_CALL_MATCH_MAPPING, [MATCH_SEQUENCE] = _TAIL_CALL_MATCH_SEQUENCE, @@ -1000,7 +1002,6 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_UNPACK_SEQUENCE_TWO_TUPLE, [WITH_EXCEPT_START] = _TAIL_CALL_WITH_EXCEPT_START, [YIELD_VALUE] = _TAIL_CALL_YIELD_VALUE, - [121] = _TAIL_CALL_UNKNOWN_OPCODE, [122] = _TAIL_CALL_UNKNOWN_OPCODE, [123] = _TAIL_CALL_UNKNOWN_OPCODE, [124] = _TAIL_CALL_UNKNOWN_OPCODE, @@ -1198,6 +1199,7 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [MAKE_FUNCTION] = _TAIL_CALL_TRACE_RECORD, [MAP_ADD] = _TAIL_CALL_TRACE_RECORD, [MATCH_CLASS] = _TAIL_CALL_TRACE_RECORD, + [MATCH_CLASS_ISINSTANCE] = _TAIL_CALL_TRACE_RECORD, [MATCH_KEYS] = _TAIL_CALL_TRACE_RECORD, [MATCH_MAPPING] = _TAIL_CALL_TRACE_RECORD, [MATCH_SEQUENCE] = _TAIL_CALL_TRACE_RECORD, @@ -1258,7 +1260,6 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_TRACE_RECORD, [WITH_EXCEPT_START] = _TAIL_CALL_TRACE_RECORD, [YIELD_VALUE] = _TAIL_CALL_TRACE_RECORD, - [121] = _TAIL_CALL_UNKNOWN_OPCODE, [122] = _TAIL_CALL_UNKNOWN_OPCODE, [123] = _TAIL_CALL_UNKNOWN_OPCODE, [124] = _TAIL_CALL_UNKNOWN_OPCODE, diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index a93e85329297cd4..2fe6b36c2c8e32b 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -2548,6 +2548,13 @@ break; } + case _MATCH_CLASS_ISINSTANCE: { + JitOptRef res; + res = sym_new_not_null(ctx); + stack_pointer[-1] = res; + break; + } + case _MATCH_CLASS: { JitOptRef attrs; attrs = sym_new_not_null(ctx); From 1ed79b78a9b939e7d00e4395c3b31f63f5c0931d Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Sat, 14 Mar 2026 17:47:49 +0100 Subject: [PATCH 2/3] Fix test case --- Lib/test/test_capi/test_opt.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index e5fada1f40ce431..0737ed066ca5e4a 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -3953,12 +3953,13 @@ def testfunc(n): def test_match_class(self): def testfunc(n): class A: + __match_args__ = ("val",) val = 1 x = A() ret = 0 for _ in range(n): match x: - case A(): + case A(1): ret += x.val return ret @@ -3967,7 +3968,7 @@ class A: uops = get_opnames(ex) self.assertIn("_MATCH_CLASS", uops) - self.assertEqual(count_ops(ex, "_POP_TOP_NOP"), 4) + self.assertEqual(count_ops(ex, "_POP_TOP_NOP"), 5) def test_143026(self): # https://github.com/python/cpython/issues/143026 From 53fd8f49f2e9ba86fd55a361a8d1c4756d3d36db Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Tue, 30 Jun 2026 12:37:45 +0200 Subject: [PATCH 3/3] Replace MATCH_CLASS_ISINSTANCE with CALL_INTRINSIC_2 Co-Authored-By: Pieter Eendebak --- Doc/library/dis.rst | 52 +-- Include/internal/pycore_intrinsics.h | 3 +- Include/internal/pycore_magic_number.h | 3 +- Include/internal/pycore_opcode_metadata.h | 10 +- Include/internal/pycore_uop_ids.h | 434 +++++++++--------- Include/internal/pycore_uop_metadata.h | 15 - Include/opcode_ids.h | 193 ++++---- Lib/_opcode_metadata.py | 193 ++++---- Lib/test/test_dis.py | 3 +- ...-02-14-16-19-22.gh-issue-138912.TKMC9K.rst | 5 +- Modules/_testinternalcapi/test_cases.c.h | 50 -- Modules/_testinternalcapi/test_targets.h | 9 +- Programs/test_frozenmain.h | 26 +- Python/bytecodes.c | 16 - Python/codegen.c | 25 +- Python/executor_cases.c.h | 61 --- Python/generated_cases.c.h | 50 -- Python/intrinsics.c | 20 + Python/opcode_targets.h | 9 +- Python/optimizer_cases.c.h | 7 - 20 files changed, 487 insertions(+), 697 deletions(-) diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index eb24d0b7c97f6de..188c382e87baccd 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -1755,14 +1755,6 @@ iterations of the loop. .. versionadded:: 3.13 -.. opcode:: MATCH_CLASS_ISINSTANCE - - Read match subject ``Stack[-2]`` and the type object ``Stack[-1]`` from stack. - Pop ``Stack[-1]`` and push ``True`` or ``False`` for the result of :func:`isinstance`. - - .. versionadded:: 3.15 - - .. opcode:: MATCH_CLASS (count) ``STACK[-1]`` is a tuple of keyword attribute names, ``STACK[-2]`` is the class @@ -1907,28 +1899,34 @@ iterations of the loop. The operand determines which intrinsic function is called: - +----------------------------------------+-----------------------------------+ - | Operand | Description | - +========================================+===================================+ - | ``INTRINSIC_2_INVALID`` | Not valid | - +----------------------------------------+-----------------------------------+ - | ``INTRINSIC_PREP_RERAISE_STAR`` | Calculates the | - | | :exc:`ExceptionGroup` to raise | - | | from a ``try-except*``. | - +----------------------------------------+-----------------------------------+ - | ``INTRINSIC_TYPEVAR_WITH_BOUND`` | Creates a :class:`typing.TypeVar` | - | | with a bound. | - +----------------------------------------+-----------------------------------+ - | ``INTRINSIC_TYPEVAR_WITH_CONSTRAINTS`` | Creates a | - | | :class:`typing.TypeVar` with | - | | constraints. | - +----------------------------------------+-----------------------------------+ - | ``INTRINSIC_SET_FUNCTION_TYPE_PARAMS`` | Sets the ``__type_params__`` | - | | attribute of a function. | - +----------------------------------------+-----------------------------------+ + +----------------------------------------+-----------------------------------------+ + | Operand | Description | + +========================================+=========================================+ + | ``INTRINSIC_2_INVALID`` | Not valid | + +----------------------------------------+-----------------------------------------+ + | ``INTRINSIC_PREP_RERAISE_STAR`` | Calculates the | + | | :exc:`ExceptionGroup` to raise | + | | from a ``try-except*``. | + +----------------------------------------+-----------------------------------------+ + | ``INTRINSIC_TYPEVAR_WITH_BOUND`` | Creates a :class:`typing.TypeVar` | + | | with a bound. | + +----------------------------------------+-----------------------------------------+ + | ``INTRINSIC_TYPEVAR_WITH_CONSTRAINTS`` | Creates a | + | | :class:`typing.TypeVar` with | + | | constraints. | + +----------------------------------------+-----------------------------------------+ + | ``INTRINSIC_SET_FUNCTION_TYPE_PARAMS`` | Sets the ``__type_params__`` | + | | attribute of a function. | + +----------------------------------------+-----------------------------------------+ + | ``INTRINSIC_MATCH_CLASS_ISINSTANCE`` | Do :func:`isinstance` checks for | + | | :ref:`Class patterns `. | + +----------------------------------------+-----------------------------------------+ .. versionadded:: 3.12 + .. versionchanged:: 3.16 + Added ``INTRINSIC_MATCH_CLASS_ISINSTANCE``. + .. opcode:: LOAD_SPECIAL diff --git a/Include/internal/pycore_intrinsics.h b/Include/internal/pycore_intrinsics.h index 59a7b16073f886c..cea7f3c6363cae5 100644 --- a/Include/internal/pycore_intrinsics.h +++ b/Include/internal/pycore_intrinsics.h @@ -30,8 +30,9 @@ #define INTRINSIC_TYPEVAR_WITH_CONSTRAINTS 3 #define INTRINSIC_SET_FUNCTION_TYPE_PARAMS 4 #define INTRINSIC_SET_TYPEPARAM_DEFAULT 5 +#define INTRINSIC_MATCH_CLASS_ISINSTANCE 6 -#define MAX_INTRINSIC_2 5 +#define MAX_INTRINSIC_2 6 typedef PyObject *(*intrinsic_func1)(PyThreadState* tstate, PyObject *value); typedef PyObject *(*intrinsic_func2)(PyThreadState* tstate, PyObject *value1, PyObject *value2); diff --git a/Include/internal/pycore_magic_number.h b/Include/internal/pycore_magic_number.h index ffd4b1e238e894b..53ed570f99f118a 100644 --- a/Include/internal/pycore_magic_number.h +++ b/Include/internal/pycore_magic_number.h @@ -302,7 +302,6 @@ Known values: Python 3.16a1 3702 (Replace DELETE_NAME with PUSH_NULL; STORE_NAME) Python 3.16a1 3703 (Replace DELETE_GLOBAL with PUSH_NULL; STORE_GLOBAL) Python 3.16a1 3704 (Replace DELETE_ATTR with PUSH_NULL; STORE_ATTR) - Python 3.16a1 3705 (Add MATCH_CLASS_ISINSTANCE opcode) Python 3.17 will start with 3750 @@ -316,7 +315,7 @@ PC/launcher.c must also be updated. */ -#define PYC_MAGIC_NUMBER 3705 +#define PYC_MAGIC_NUMBER 3704 /* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes (little-endian) and then appending b'\r\n'. */ #define PYC_MAGIC_NUMBER_TOKEN \ diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index 49e1277bba98d20..647f6b6cbb989ad 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -384,8 +384,6 @@ int _PyOpcode_num_popped(int opcode, int oparg) { return 3 + (oparg - 1); case MATCH_CLASS: return 3; - case MATCH_CLASS_ISINSTANCE: - return 2; case MATCH_KEYS: return 2; case MATCH_MAPPING: @@ -881,8 +879,6 @@ int _PyOpcode_num_pushed(int opcode, int oparg) { return 1 + (oparg - 1); case MATCH_CLASS: return 1; - case MATCH_CLASS_ISINSTANCE: - return 2; case MATCH_KEYS: return 3; case MATCH_MAPPING: @@ -1272,7 +1268,6 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [MAKE_FUNCTION] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, [MAP_ADD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [MATCH_CLASS] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG }, - [MATCH_CLASS_ISINSTANCE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [MATCH_KEYS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [MATCH_MAPPING] = { true, INSTR_FMT_IX, 0 }, [MATCH_SEQUENCE] = { true, INSTR_FMT_IX, 0 }, @@ -1494,7 +1489,6 @@ _PyOpcode_macro_expansion[256] = { [MAKE_FUNCTION] = { .nuops = 2, .uops = { { _MAKE_FUNCTION, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, [MAP_ADD] = { .nuops = 1, .uops = { { _MAP_ADD, OPARG_SIMPLE, 0 } } }, [MATCH_CLASS] = { .nuops = 4, .uops = { { _MATCH_CLASS, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 }, { _POP_TOP, OPARG_SIMPLE, 0 } } }, - [MATCH_CLASS_ISINSTANCE] = { .nuops = 1, .uops = { { _MATCH_CLASS_ISINSTANCE, OPARG_SIMPLE, 0 } } }, [MATCH_KEYS] = { .nuops = 1, .uops = { { _MATCH_KEYS, OPARG_SIMPLE, 0 } } }, [MATCH_MAPPING] = { .nuops = 1, .uops = { { _MATCH_MAPPING, OPARG_SIMPLE, 0 } } }, [MATCH_SEQUENCE] = { .nuops = 1, .uops = { { _MATCH_SEQUENCE, OPARG_SIMPLE, 0 } } }, @@ -1731,7 +1725,6 @@ const char *_PyOpcode_OpName[267] = { [MAKE_FUNCTION] = "MAKE_FUNCTION", [MAP_ADD] = "MAP_ADD", [MATCH_CLASS] = "MATCH_CLASS", - [MATCH_CLASS_ISINSTANCE] = "MATCH_CLASS_ISINSTANCE", [MATCH_KEYS] = "MATCH_KEYS", [MATCH_MAPPING] = "MATCH_MAPPING", [MATCH_SEQUENCE] = "MATCH_SEQUENCE", @@ -1834,6 +1827,7 @@ const uint8_t _PyOpcode_Caches[256] = { PyAPI_DATA(const uint8_t) _PyOpcode_Deopt[256]; #ifdef NEED_OPCODE_METADATA const uint8_t _PyOpcode_Deopt[256] = { + [117] = 117, [118] = 118, [119] = 119, [120] = 120, @@ -2026,7 +2020,6 @@ const uint8_t _PyOpcode_Deopt[256] = { [MAKE_FUNCTION] = MAKE_FUNCTION, [MAP_ADD] = MAP_ADD, [MATCH_CLASS] = MATCH_CLASS, - [MATCH_CLASS_ISINSTANCE] = MATCH_CLASS_ISINSTANCE, [MATCH_KEYS] = MATCH_KEYS, [MATCH_MAPPING] = MATCH_MAPPING, [MATCH_SEQUENCE] = MATCH_SEQUENCE, @@ -2095,6 +2088,7 @@ const uint8_t _PyOpcode_Deopt[256] = { #endif // NEED_OPCODE_METADATA #define EXTRA_CASES \ + case 117: \ case 118: \ case 119: \ case 120: \ diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 566ea1a6b0f96aa..cd34aaa9d34afde 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -333,7 +333,6 @@ extern "C" { #define _MAKE_WARM 572 #define _MAP_ADD MAP_ADD #define _MATCH_CLASS 573 -#define _MATCH_CLASS_ISINSTANCE MATCH_CLASS_ISINSTANCE #define _MATCH_KEYS MATCH_KEYS #define _MATCH_MAPPING MATCH_MAPPING #define _MATCH_SEQUENCE MATCH_SEQUENCE @@ -1219,223 +1218,222 @@ extern "C" { #define _MAKE_WARM_r33 1433 #define _MAP_ADD_r20 1434 #define _MATCH_CLASS_r33 1435 -#define _MATCH_CLASS_ISINSTANCE_r22 1436 -#define _MATCH_KEYS_r23 1437 -#define _MATCH_MAPPING_r02 1438 -#define _MATCH_MAPPING_r12 1439 -#define _MATCH_MAPPING_r23 1440 -#define _MATCH_SEQUENCE_r02 1441 -#define _MATCH_SEQUENCE_r12 1442 -#define _MATCH_SEQUENCE_r23 1443 -#define _MAYBE_EXPAND_METHOD_r00 1444 -#define _MAYBE_EXPAND_METHOD_KW_r11 1445 -#define _MONITOR_CALL_r00 1446 -#define _MONITOR_CALL_KW_r11 1447 -#define _MONITOR_JUMP_BACKWARD_r00 1448 -#define _MONITOR_JUMP_BACKWARD_r11 1449 -#define _MONITOR_JUMP_BACKWARD_r22 1450 -#define _MONITOR_JUMP_BACKWARD_r33 1451 -#define _MONITOR_RESUME_r00 1452 -#define _NOP_r00 1453 -#define _NOP_r11 1454 -#define _NOP_r22 1455 -#define _NOP_r33 1456 -#define _POP_EXCEPT_r10 1457 -#define _POP_ITER_r20 1458 -#define _POP_JUMP_IF_FALSE_r00 1459 -#define _POP_JUMP_IF_FALSE_r10 1460 -#define _POP_JUMP_IF_FALSE_r21 1461 -#define _POP_JUMP_IF_FALSE_r32 1462 -#define _POP_JUMP_IF_TRUE_r00 1463 -#define _POP_JUMP_IF_TRUE_r10 1464 -#define _POP_JUMP_IF_TRUE_r21 1465 -#define _POP_JUMP_IF_TRUE_r32 1466 -#define _POP_TOP_r10 1467 -#define _POP_TOP_FLOAT_r00 1468 -#define _POP_TOP_FLOAT_r10 1469 -#define _POP_TOP_FLOAT_r21 1470 -#define _POP_TOP_FLOAT_r32 1471 -#define _POP_TOP_INT_r00 1472 -#define _POP_TOP_INT_r10 1473 -#define _POP_TOP_INT_r21 1474 -#define _POP_TOP_INT_r32 1475 -#define _POP_TOP_NOP_r00 1476 -#define _POP_TOP_NOP_r10 1477 -#define _POP_TOP_NOP_r21 1478 -#define _POP_TOP_NOP_r32 1479 -#define _POP_TOP_OPARG_r00 1480 -#define _POP_TOP_UNICODE_r00 1481 -#define _POP_TOP_UNICODE_r10 1482 -#define _POP_TOP_UNICODE_r21 1483 -#define _POP_TOP_UNICODE_r32 1484 -#define _PUSH_EXC_INFO_r02 1485 -#define _PUSH_EXC_INFO_r12 1486 -#define _PUSH_EXC_INFO_r23 1487 -#define _PUSH_FRAME_r10 1488 -#define _PUSH_NULL_r01 1489 -#define _PUSH_NULL_r12 1490 -#define _PUSH_NULL_r23 1491 -#define _PUSH_NULL_CONDITIONAL_r00 1492 -#define _PUSH_TAGGED_ZERO_r01 1493 -#define _PUSH_TAGGED_ZERO_r12 1494 -#define _PUSH_TAGGED_ZERO_r23 1495 -#define _PY_FRAME_EX_r31 1496 -#define _PY_FRAME_GENERAL_r01 1497 -#define _PY_FRAME_KW_r11 1498 -#define _REPLACE_WITH_TRUE_r02 1499 -#define _REPLACE_WITH_TRUE_r12 1500 -#define _REPLACE_WITH_TRUE_r23 1501 -#define _RESUME_CHECK_r00 1502 -#define _RESUME_CHECK_r11 1503 -#define _RESUME_CHECK_r22 1504 -#define _RESUME_CHECK_r33 1505 -#define _RETURN_GENERATOR_r01 1506 -#define _RETURN_VALUE_r11 1507 -#define _RROT_3_r03 1508 -#define _RROT_3_r13 1509 -#define _RROT_3_r23 1510 -#define _RROT_3_r33 1511 -#define _SAVE_RETURN_OFFSET_r00 1512 -#define _SAVE_RETURN_OFFSET_r11 1513 -#define _SAVE_RETURN_OFFSET_r22 1514 -#define _SAVE_RETURN_OFFSET_r33 1515 -#define _SEND_ASYNC_GEN_r33 1516 -#define _SEND_ASYNC_GEN_TIER_TWO_r33 1517 -#define _SEND_GEN_FRAME_r33 1518 -#define _SEND_VIRTUAL_r33 1519 -#define _SEND_VIRTUAL_TIER_TWO_r03 1520 -#define _SEND_VIRTUAL_TIER_TWO_r13 1521 -#define _SEND_VIRTUAL_TIER_TWO_r23 1522 -#define _SEND_VIRTUAL_TIER_TWO_r33 1523 -#define _SETUP_ANNOTATIONS_r00 1524 -#define _SET_ADD_r10 1525 -#define _SET_FUNCTION_ATTRIBUTE_r01 1526 -#define _SET_FUNCTION_ATTRIBUTE_r11 1527 -#define _SET_FUNCTION_ATTRIBUTE_r21 1528 -#define _SET_FUNCTION_ATTRIBUTE_r32 1529 -#define _SET_IP_r00 1530 -#define _SET_IP_r11 1531 -#define _SET_IP_r22 1532 -#define _SET_IP_r33 1533 -#define _SET_UPDATE_r11 1534 -#define _SPILL_OR_RELOAD_r01 1535 -#define _SPILL_OR_RELOAD_r02 1536 -#define _SPILL_OR_RELOAD_r03 1537 -#define _SPILL_OR_RELOAD_r10 1538 -#define _SPILL_OR_RELOAD_r12 1539 -#define _SPILL_OR_RELOAD_r13 1540 -#define _SPILL_OR_RELOAD_r20 1541 -#define _SPILL_OR_RELOAD_r21 1542 -#define _SPILL_OR_RELOAD_r23 1543 -#define _SPILL_OR_RELOAD_r30 1544 -#define _SPILL_OR_RELOAD_r31 1545 -#define _SPILL_OR_RELOAD_r32 1546 -#define _START_EXECUTOR_r00 1547 -#define _STORE_ATTR_r20 1548 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1549 -#define _STORE_ATTR_SLOT_r21 1550 -#define _STORE_ATTR_WITH_HINT_r21 1551 -#define _STORE_DEREF_r10 1552 -#define _STORE_FAST_LOAD_FAST_r11 1553 -#define _STORE_FAST_STORE_FAST_r20 1554 -#define _STORE_GLOBAL_r10 1555 -#define _STORE_NAME_r10 1556 -#define _STORE_SLICE_r30 1557 -#define _STORE_SUBSCR_r30 1558 -#define _STORE_SUBSCR_DICT_r31 1559 -#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1560 -#define _STORE_SUBSCR_LIST_INT_r32 1561 -#define _SWAP_r11 1562 -#define _SWAP_2_r02 1563 -#define _SWAP_2_r12 1564 -#define _SWAP_2_r22 1565 -#define _SWAP_2_r33 1566 -#define _SWAP_3_r03 1567 -#define _SWAP_3_r13 1568 -#define _SWAP_3_r23 1569 -#define _SWAP_3_r33 1570 -#define _SWAP_FAST_r01 1571 -#define _SWAP_FAST_r11 1572 -#define _SWAP_FAST_r22 1573 -#define _SWAP_FAST_r33 1574 -#define _SWAP_FAST_0_r01 1575 -#define _SWAP_FAST_0_r11 1576 -#define _SWAP_FAST_0_r22 1577 -#define _SWAP_FAST_0_r33 1578 -#define _SWAP_FAST_1_r01 1579 -#define _SWAP_FAST_1_r11 1580 -#define _SWAP_FAST_1_r22 1581 -#define _SWAP_FAST_1_r33 1582 -#define _SWAP_FAST_2_r01 1583 -#define _SWAP_FAST_2_r11 1584 -#define _SWAP_FAST_2_r22 1585 -#define _SWAP_FAST_2_r33 1586 -#define _SWAP_FAST_3_r01 1587 -#define _SWAP_FAST_3_r11 1588 -#define _SWAP_FAST_3_r22 1589 -#define _SWAP_FAST_3_r33 1590 -#define _SWAP_FAST_4_r01 1591 -#define _SWAP_FAST_4_r11 1592 -#define _SWAP_FAST_4_r22 1593 -#define _SWAP_FAST_4_r33 1594 -#define _SWAP_FAST_5_r01 1595 -#define _SWAP_FAST_5_r11 1596 -#define _SWAP_FAST_5_r22 1597 -#define _SWAP_FAST_5_r33 1598 -#define _SWAP_FAST_6_r01 1599 -#define _SWAP_FAST_6_r11 1600 -#define _SWAP_FAST_6_r22 1601 -#define _SWAP_FAST_6_r33 1602 -#define _SWAP_FAST_7_r01 1603 -#define _SWAP_FAST_7_r11 1604 -#define _SWAP_FAST_7_r22 1605 -#define _SWAP_FAST_7_r33 1606 -#define _TIER2_RESUME_CHECK_r00 1607 -#define _TIER2_RESUME_CHECK_r11 1608 -#define _TIER2_RESUME_CHECK_r22 1609 -#define _TIER2_RESUME_CHECK_r33 1610 -#define _TO_BOOL_r11 1611 -#define _TO_BOOL_BOOL_r01 1612 -#define _TO_BOOL_BOOL_r11 1613 -#define _TO_BOOL_BOOL_r22 1614 -#define _TO_BOOL_BOOL_r33 1615 -#define _TO_BOOL_INT_r02 1616 -#define _TO_BOOL_INT_r12 1617 -#define _TO_BOOL_INT_r23 1618 -#define _TO_BOOL_LIST_r02 1619 -#define _TO_BOOL_LIST_r12 1620 -#define _TO_BOOL_LIST_r23 1621 -#define _TO_BOOL_NONE_r01 1622 -#define _TO_BOOL_NONE_r11 1623 -#define _TO_BOOL_NONE_r22 1624 -#define _TO_BOOL_NONE_r33 1625 -#define _TO_BOOL_STR_r02 1626 -#define _TO_BOOL_STR_r12 1627 -#define _TO_BOOL_STR_r23 1628 -#define _TRACE_RECORD_r00 1629 -#define _UNARY_INVERT_r12 1630 -#define _UNARY_NEGATIVE_r12 1631 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1632 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1633 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1634 -#define _UNARY_NOT_r01 1635 -#define _UNARY_NOT_r11 1636 -#define _UNARY_NOT_r22 1637 -#define _UNARY_NOT_r33 1638 -#define _UNPACK_EX_r10 1639 -#define _UNPACK_SEQUENCE_r10 1640 -#define _UNPACK_SEQUENCE_LIST_r10 1641 -#define _UNPACK_SEQUENCE_TUPLE_r10 1642 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1643 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1644 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1645 -#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1646 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1647 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1648 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1649 -#define _WITH_EXCEPT_START_r33 1650 -#define _YIELD_VALUE_r11 1651 -#define MAX_UOP_REGS_ID 1651 +#define _MATCH_KEYS_r23 1436 +#define _MATCH_MAPPING_r02 1437 +#define _MATCH_MAPPING_r12 1438 +#define _MATCH_MAPPING_r23 1439 +#define _MATCH_SEQUENCE_r02 1440 +#define _MATCH_SEQUENCE_r12 1441 +#define _MATCH_SEQUENCE_r23 1442 +#define _MAYBE_EXPAND_METHOD_r00 1443 +#define _MAYBE_EXPAND_METHOD_KW_r11 1444 +#define _MONITOR_CALL_r00 1445 +#define _MONITOR_CALL_KW_r11 1446 +#define _MONITOR_JUMP_BACKWARD_r00 1447 +#define _MONITOR_JUMP_BACKWARD_r11 1448 +#define _MONITOR_JUMP_BACKWARD_r22 1449 +#define _MONITOR_JUMP_BACKWARD_r33 1450 +#define _MONITOR_RESUME_r00 1451 +#define _NOP_r00 1452 +#define _NOP_r11 1453 +#define _NOP_r22 1454 +#define _NOP_r33 1455 +#define _POP_EXCEPT_r10 1456 +#define _POP_ITER_r20 1457 +#define _POP_JUMP_IF_FALSE_r00 1458 +#define _POP_JUMP_IF_FALSE_r10 1459 +#define _POP_JUMP_IF_FALSE_r21 1460 +#define _POP_JUMP_IF_FALSE_r32 1461 +#define _POP_JUMP_IF_TRUE_r00 1462 +#define _POP_JUMP_IF_TRUE_r10 1463 +#define _POP_JUMP_IF_TRUE_r21 1464 +#define _POP_JUMP_IF_TRUE_r32 1465 +#define _POP_TOP_r10 1466 +#define _POP_TOP_FLOAT_r00 1467 +#define _POP_TOP_FLOAT_r10 1468 +#define _POP_TOP_FLOAT_r21 1469 +#define _POP_TOP_FLOAT_r32 1470 +#define _POP_TOP_INT_r00 1471 +#define _POP_TOP_INT_r10 1472 +#define _POP_TOP_INT_r21 1473 +#define _POP_TOP_INT_r32 1474 +#define _POP_TOP_NOP_r00 1475 +#define _POP_TOP_NOP_r10 1476 +#define _POP_TOP_NOP_r21 1477 +#define _POP_TOP_NOP_r32 1478 +#define _POP_TOP_OPARG_r00 1479 +#define _POP_TOP_UNICODE_r00 1480 +#define _POP_TOP_UNICODE_r10 1481 +#define _POP_TOP_UNICODE_r21 1482 +#define _POP_TOP_UNICODE_r32 1483 +#define _PUSH_EXC_INFO_r02 1484 +#define _PUSH_EXC_INFO_r12 1485 +#define _PUSH_EXC_INFO_r23 1486 +#define _PUSH_FRAME_r10 1487 +#define _PUSH_NULL_r01 1488 +#define _PUSH_NULL_r12 1489 +#define _PUSH_NULL_r23 1490 +#define _PUSH_NULL_CONDITIONAL_r00 1491 +#define _PUSH_TAGGED_ZERO_r01 1492 +#define _PUSH_TAGGED_ZERO_r12 1493 +#define _PUSH_TAGGED_ZERO_r23 1494 +#define _PY_FRAME_EX_r31 1495 +#define _PY_FRAME_GENERAL_r01 1496 +#define _PY_FRAME_KW_r11 1497 +#define _REPLACE_WITH_TRUE_r02 1498 +#define _REPLACE_WITH_TRUE_r12 1499 +#define _REPLACE_WITH_TRUE_r23 1500 +#define _RESUME_CHECK_r00 1501 +#define _RESUME_CHECK_r11 1502 +#define _RESUME_CHECK_r22 1503 +#define _RESUME_CHECK_r33 1504 +#define _RETURN_GENERATOR_r01 1505 +#define _RETURN_VALUE_r11 1506 +#define _RROT_3_r03 1507 +#define _RROT_3_r13 1508 +#define _RROT_3_r23 1509 +#define _RROT_3_r33 1510 +#define _SAVE_RETURN_OFFSET_r00 1511 +#define _SAVE_RETURN_OFFSET_r11 1512 +#define _SAVE_RETURN_OFFSET_r22 1513 +#define _SAVE_RETURN_OFFSET_r33 1514 +#define _SEND_ASYNC_GEN_r33 1515 +#define _SEND_ASYNC_GEN_TIER_TWO_r33 1516 +#define _SEND_GEN_FRAME_r33 1517 +#define _SEND_VIRTUAL_r33 1518 +#define _SEND_VIRTUAL_TIER_TWO_r03 1519 +#define _SEND_VIRTUAL_TIER_TWO_r13 1520 +#define _SEND_VIRTUAL_TIER_TWO_r23 1521 +#define _SEND_VIRTUAL_TIER_TWO_r33 1522 +#define _SETUP_ANNOTATIONS_r00 1523 +#define _SET_ADD_r10 1524 +#define _SET_FUNCTION_ATTRIBUTE_r01 1525 +#define _SET_FUNCTION_ATTRIBUTE_r11 1526 +#define _SET_FUNCTION_ATTRIBUTE_r21 1527 +#define _SET_FUNCTION_ATTRIBUTE_r32 1528 +#define _SET_IP_r00 1529 +#define _SET_IP_r11 1530 +#define _SET_IP_r22 1531 +#define _SET_IP_r33 1532 +#define _SET_UPDATE_r11 1533 +#define _SPILL_OR_RELOAD_r01 1534 +#define _SPILL_OR_RELOAD_r02 1535 +#define _SPILL_OR_RELOAD_r03 1536 +#define _SPILL_OR_RELOAD_r10 1537 +#define _SPILL_OR_RELOAD_r12 1538 +#define _SPILL_OR_RELOAD_r13 1539 +#define _SPILL_OR_RELOAD_r20 1540 +#define _SPILL_OR_RELOAD_r21 1541 +#define _SPILL_OR_RELOAD_r23 1542 +#define _SPILL_OR_RELOAD_r30 1543 +#define _SPILL_OR_RELOAD_r31 1544 +#define _SPILL_OR_RELOAD_r32 1545 +#define _START_EXECUTOR_r00 1546 +#define _STORE_ATTR_r20 1547 +#define _STORE_ATTR_INSTANCE_VALUE_r21 1548 +#define _STORE_ATTR_SLOT_r21 1549 +#define _STORE_ATTR_WITH_HINT_r21 1550 +#define _STORE_DEREF_r10 1551 +#define _STORE_FAST_LOAD_FAST_r11 1552 +#define _STORE_FAST_STORE_FAST_r20 1553 +#define _STORE_GLOBAL_r10 1554 +#define _STORE_NAME_r10 1555 +#define _STORE_SLICE_r30 1556 +#define _STORE_SUBSCR_r30 1557 +#define _STORE_SUBSCR_DICT_r31 1558 +#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1559 +#define _STORE_SUBSCR_LIST_INT_r32 1560 +#define _SWAP_r11 1561 +#define _SWAP_2_r02 1562 +#define _SWAP_2_r12 1563 +#define _SWAP_2_r22 1564 +#define _SWAP_2_r33 1565 +#define _SWAP_3_r03 1566 +#define _SWAP_3_r13 1567 +#define _SWAP_3_r23 1568 +#define _SWAP_3_r33 1569 +#define _SWAP_FAST_r01 1570 +#define _SWAP_FAST_r11 1571 +#define _SWAP_FAST_r22 1572 +#define _SWAP_FAST_r33 1573 +#define _SWAP_FAST_0_r01 1574 +#define _SWAP_FAST_0_r11 1575 +#define _SWAP_FAST_0_r22 1576 +#define _SWAP_FAST_0_r33 1577 +#define _SWAP_FAST_1_r01 1578 +#define _SWAP_FAST_1_r11 1579 +#define _SWAP_FAST_1_r22 1580 +#define _SWAP_FAST_1_r33 1581 +#define _SWAP_FAST_2_r01 1582 +#define _SWAP_FAST_2_r11 1583 +#define _SWAP_FAST_2_r22 1584 +#define _SWAP_FAST_2_r33 1585 +#define _SWAP_FAST_3_r01 1586 +#define _SWAP_FAST_3_r11 1587 +#define _SWAP_FAST_3_r22 1588 +#define _SWAP_FAST_3_r33 1589 +#define _SWAP_FAST_4_r01 1590 +#define _SWAP_FAST_4_r11 1591 +#define _SWAP_FAST_4_r22 1592 +#define _SWAP_FAST_4_r33 1593 +#define _SWAP_FAST_5_r01 1594 +#define _SWAP_FAST_5_r11 1595 +#define _SWAP_FAST_5_r22 1596 +#define _SWAP_FAST_5_r33 1597 +#define _SWAP_FAST_6_r01 1598 +#define _SWAP_FAST_6_r11 1599 +#define _SWAP_FAST_6_r22 1600 +#define _SWAP_FAST_6_r33 1601 +#define _SWAP_FAST_7_r01 1602 +#define _SWAP_FAST_7_r11 1603 +#define _SWAP_FAST_7_r22 1604 +#define _SWAP_FAST_7_r33 1605 +#define _TIER2_RESUME_CHECK_r00 1606 +#define _TIER2_RESUME_CHECK_r11 1607 +#define _TIER2_RESUME_CHECK_r22 1608 +#define _TIER2_RESUME_CHECK_r33 1609 +#define _TO_BOOL_r11 1610 +#define _TO_BOOL_BOOL_r01 1611 +#define _TO_BOOL_BOOL_r11 1612 +#define _TO_BOOL_BOOL_r22 1613 +#define _TO_BOOL_BOOL_r33 1614 +#define _TO_BOOL_INT_r02 1615 +#define _TO_BOOL_INT_r12 1616 +#define _TO_BOOL_INT_r23 1617 +#define _TO_BOOL_LIST_r02 1618 +#define _TO_BOOL_LIST_r12 1619 +#define _TO_BOOL_LIST_r23 1620 +#define _TO_BOOL_NONE_r01 1621 +#define _TO_BOOL_NONE_r11 1622 +#define _TO_BOOL_NONE_r22 1623 +#define _TO_BOOL_NONE_r33 1624 +#define _TO_BOOL_STR_r02 1625 +#define _TO_BOOL_STR_r12 1626 +#define _TO_BOOL_STR_r23 1627 +#define _TRACE_RECORD_r00 1628 +#define _UNARY_INVERT_r12 1629 +#define _UNARY_NEGATIVE_r12 1630 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1631 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1632 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1633 +#define _UNARY_NOT_r01 1634 +#define _UNARY_NOT_r11 1635 +#define _UNARY_NOT_r22 1636 +#define _UNARY_NOT_r33 1637 +#define _UNPACK_EX_r10 1638 +#define _UNPACK_SEQUENCE_r10 1639 +#define _UNPACK_SEQUENCE_LIST_r10 1640 +#define _UNPACK_SEQUENCE_TUPLE_r10 1641 +#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1642 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1643 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1644 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1645 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1646 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1647 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1648 +#define _WITH_EXCEPT_START_r33 1649 +#define _YIELD_VALUE_r11 1650 +#define MAX_UOP_REGS_ID 1650 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 1507cc96b296164..d4cceb5a500cab5 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -254,7 +254,6 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_IMPORT_FROM] = HAS_ARG_FLAG | HAS_NAME_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_IS_NONE] = HAS_ESCAPES_FLAG, [_GET_LEN] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, - [_MATCH_CLASS_ISINSTANCE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_MATCH_CLASS] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_MATCH_MAPPING] = 0, [_MATCH_SEQUENCE] = 0, @@ -2417,15 +2416,6 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { { -1, -1, -1 }, }, }, - [_MATCH_CLASS_ISINSTANCE] = { - .best = { 2, 2, 2, 2 }, - .entries = { - { -1, -1, -1 }, - { -1, -1, -1 }, - { 2, 2, _MATCH_CLASS_ISINSTANCE_r22 }, - { -1, -1, -1 }, - }, - }, [_MATCH_CLASS] = { .best = { 3, 3, 3, 3 }, .entries = { @@ -4430,7 +4420,6 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_IMPORT_FROM_r12] = _IMPORT_FROM, [_IS_NONE_r11] = _IS_NONE, [_GET_LEN_r12] = _GET_LEN, - [_MATCH_CLASS_ISINSTANCE_r22] = _MATCH_CLASS_ISINSTANCE, [_MATCH_CLASS_r33] = _MATCH_CLASS, [_MATCH_MAPPING_r02] = _MATCH_MAPPING, [_MATCH_MAPPING_r12] = _MATCH_MAPPING, @@ -5884,8 +5873,6 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_MAP_ADD_r20] = "_MAP_ADD_r20", [_MATCH_CLASS] = "_MATCH_CLASS", [_MATCH_CLASS_r33] = "_MATCH_CLASS_r33", - [_MATCH_CLASS_ISINSTANCE] = "_MATCH_CLASS_ISINSTANCE", - [_MATCH_CLASS_ISINSTANCE_r22] = "_MATCH_CLASS_ISINSTANCE_r22", [_MATCH_KEYS] = "_MATCH_KEYS", [_MATCH_KEYS_r23] = "_MATCH_KEYS_r23", [_MATCH_MAPPING] = "_MATCH_MAPPING", @@ -6617,8 +6604,6 @@ int _PyUop_num_popped(int opcode, int oparg) return 1; case _GET_LEN: return 0; - case _MATCH_CLASS_ISINSTANCE: - return 1; case _MATCH_CLASS: return 3; case _MATCH_MAPPING: diff --git a/Include/opcode_ids.h b/Include/opcode_ids.h index 85fc31de9fe54fa..11342ae451b9f6c 100644 --- a/Include/opcode_ids.h +++ b/Include/opcode_ids.h @@ -32,102 +32,101 @@ extern "C" { #define LOAD_BUILD_CLASS 19 #define LOAD_LOCALS 20 #define MAKE_FUNCTION 21 -#define MATCH_CLASS_ISINSTANCE 22 -#define MATCH_KEYS 23 -#define MATCH_MAPPING 24 -#define MATCH_SEQUENCE 25 -#define NOP 26 -#define NOT_TAKEN 27 -#define POP_EXCEPT 28 -#define POP_ITER 29 -#define POP_TOP 30 -#define PUSH_EXC_INFO 31 -#define PUSH_NULL 32 -#define RETURN_GENERATOR 33 -#define RETURN_VALUE 34 -#define SETUP_ANNOTATIONS 35 -#define STORE_SLICE 36 -#define STORE_SUBSCR 37 -#define TO_BOOL 38 -#define UNARY_INVERT 39 -#define UNARY_NEGATIVE 40 -#define UNARY_NOT 41 -#define WITH_EXCEPT_START 42 -#define BINARY_OP 43 -#define BUILD_INTERPOLATION 44 -#define BUILD_LIST 45 -#define BUILD_MAP 46 -#define BUILD_SET 47 -#define BUILD_SLICE 48 -#define BUILD_STRING 49 -#define BUILD_TUPLE 50 -#define CALL 51 -#define CALL_INTRINSIC_1 52 -#define CALL_INTRINSIC_2 53 -#define CALL_KW 54 -#define COMPARE_OP 55 -#define CONTAINS_OP 56 -#define CONVERT_VALUE 57 -#define COPY 58 -#define COPY_FREE_VARS 59 -#define DELETE_DEREF 60 -#define DELETE_FAST 61 -#define DICT_MERGE 62 -#define DICT_UPDATE 63 -#define END_ASYNC_FOR 64 -#define EXTENDED_ARG 65 -#define FOR_ITER 66 -#define GET_AWAITABLE 67 -#define GET_ITER 68 -#define IMPORT_FROM 69 -#define IMPORT_NAME 70 -#define IS_OP 71 -#define JUMP_BACKWARD 72 -#define JUMP_BACKWARD_NO_INTERRUPT 73 -#define JUMP_FORWARD 74 -#define LIST_APPEND 75 -#define LIST_EXTEND 76 -#define LOAD_ATTR 77 -#define LOAD_COMMON_CONSTANT 78 -#define LOAD_CONST 79 -#define LOAD_DEREF 80 -#define LOAD_FAST 81 -#define LOAD_FAST_AND_CLEAR 82 -#define LOAD_FAST_BORROW 83 -#define LOAD_FAST_BORROW_LOAD_FAST_BORROW 84 -#define LOAD_FAST_CHECK 85 -#define LOAD_FAST_LOAD_FAST 86 -#define LOAD_FROM_DICT_OR_DEREF 87 -#define LOAD_FROM_DICT_OR_GLOBALS 88 -#define LOAD_GLOBAL 89 -#define LOAD_NAME 90 -#define LOAD_SMALL_INT 91 -#define LOAD_SPECIAL 92 -#define LOAD_SUPER_ATTR 93 -#define MAKE_CELL 94 -#define MAP_ADD 95 -#define MATCH_CLASS 96 -#define POP_JUMP_IF_FALSE 97 -#define POP_JUMP_IF_NONE 98 -#define POP_JUMP_IF_NOT_NONE 99 -#define POP_JUMP_IF_TRUE 100 -#define RAISE_VARARGS 101 -#define RERAISE 102 -#define SEND 103 -#define SET_ADD 104 -#define SET_FUNCTION_ATTRIBUTE 105 -#define SET_UPDATE 106 -#define STORE_ATTR 107 -#define STORE_DEREF 108 -#define STORE_FAST 109 -#define STORE_FAST_LOAD_FAST 110 -#define STORE_FAST_STORE_FAST 111 -#define STORE_GLOBAL 112 -#define STORE_NAME 113 -#define SWAP 114 -#define UNPACK_EX 115 -#define UNPACK_SEQUENCE 116 -#define YIELD_VALUE 117 +#define MATCH_KEYS 22 +#define MATCH_MAPPING 23 +#define MATCH_SEQUENCE 24 +#define NOP 25 +#define NOT_TAKEN 26 +#define POP_EXCEPT 27 +#define POP_ITER 28 +#define POP_TOP 29 +#define PUSH_EXC_INFO 30 +#define PUSH_NULL 31 +#define RETURN_GENERATOR 32 +#define RETURN_VALUE 33 +#define SETUP_ANNOTATIONS 34 +#define STORE_SLICE 35 +#define STORE_SUBSCR 36 +#define TO_BOOL 37 +#define UNARY_INVERT 38 +#define UNARY_NEGATIVE 39 +#define UNARY_NOT 40 +#define WITH_EXCEPT_START 41 +#define BINARY_OP 42 +#define BUILD_INTERPOLATION 43 +#define BUILD_LIST 44 +#define BUILD_MAP 45 +#define BUILD_SET 46 +#define BUILD_SLICE 47 +#define BUILD_STRING 48 +#define BUILD_TUPLE 49 +#define CALL 50 +#define CALL_INTRINSIC_1 51 +#define CALL_INTRINSIC_2 52 +#define CALL_KW 53 +#define COMPARE_OP 54 +#define CONTAINS_OP 55 +#define CONVERT_VALUE 56 +#define COPY 57 +#define COPY_FREE_VARS 58 +#define DELETE_DEREF 59 +#define DELETE_FAST 60 +#define DICT_MERGE 61 +#define DICT_UPDATE 62 +#define END_ASYNC_FOR 63 +#define EXTENDED_ARG 64 +#define FOR_ITER 65 +#define GET_AWAITABLE 66 +#define GET_ITER 67 +#define IMPORT_FROM 68 +#define IMPORT_NAME 69 +#define IS_OP 70 +#define JUMP_BACKWARD 71 +#define JUMP_BACKWARD_NO_INTERRUPT 72 +#define JUMP_FORWARD 73 +#define LIST_APPEND 74 +#define LIST_EXTEND 75 +#define LOAD_ATTR 76 +#define LOAD_COMMON_CONSTANT 77 +#define LOAD_CONST 78 +#define LOAD_DEREF 79 +#define LOAD_FAST 80 +#define LOAD_FAST_AND_CLEAR 81 +#define LOAD_FAST_BORROW 82 +#define LOAD_FAST_BORROW_LOAD_FAST_BORROW 83 +#define LOAD_FAST_CHECK 84 +#define LOAD_FAST_LOAD_FAST 85 +#define LOAD_FROM_DICT_OR_DEREF 86 +#define LOAD_FROM_DICT_OR_GLOBALS 87 +#define LOAD_GLOBAL 88 +#define LOAD_NAME 89 +#define LOAD_SMALL_INT 90 +#define LOAD_SPECIAL 91 +#define LOAD_SUPER_ATTR 92 +#define MAKE_CELL 93 +#define MAP_ADD 94 +#define MATCH_CLASS 95 +#define POP_JUMP_IF_FALSE 96 +#define POP_JUMP_IF_NONE 97 +#define POP_JUMP_IF_NOT_NONE 98 +#define POP_JUMP_IF_TRUE 99 +#define RAISE_VARARGS 100 +#define RERAISE 101 +#define SEND 102 +#define SET_ADD 103 +#define SET_FUNCTION_ATTRIBUTE 104 +#define SET_UPDATE 105 +#define STORE_ATTR 106 +#define STORE_DEREF 107 +#define STORE_FAST 108 +#define STORE_FAST_LOAD_FAST 109 +#define STORE_FAST_STORE_FAST 110 +#define STORE_GLOBAL 111 +#define STORE_NAME 112 +#define SWAP 113 +#define UNPACK_EX 114 +#define UNPACK_SEQUENCE 115 +#define YIELD_VALUE 116 #define RESUME 128 #define BINARY_OP_ADD_FLOAT 129 #define BINARY_OP_ADD_INT 130 @@ -254,7 +253,7 @@ extern "C" { #define SETUP_WITH 265 #define STORE_FAST_MAYBE_NULL 266 -#define HAVE_ARGUMENT 42 +#define HAVE_ARGUMENT 41 #define MIN_SPECIALIZED_OPCODE 129 #define MIN_INSTRUMENTED_OPCODE 233 diff --git a/Lib/_opcode_metadata.py b/Lib/_opcode_metadata.py index 7fa55e27d60189d..df92eae151d2488 100644 --- a/Lib/_opcode_metadata.py +++ b/Lib/_opcode_metadata.py @@ -252,102 +252,101 @@ LOAD_BUILD_CLASS=19, LOAD_LOCALS=20, MAKE_FUNCTION=21, - MATCH_CLASS_ISINSTANCE=22, - MATCH_KEYS=23, - MATCH_MAPPING=24, - MATCH_SEQUENCE=25, - NOP=26, - NOT_TAKEN=27, - POP_EXCEPT=28, - POP_ITER=29, - POP_TOP=30, - PUSH_EXC_INFO=31, - PUSH_NULL=32, - RETURN_GENERATOR=33, - RETURN_VALUE=34, - SETUP_ANNOTATIONS=35, - STORE_SLICE=36, - STORE_SUBSCR=37, - TO_BOOL=38, - UNARY_INVERT=39, - UNARY_NEGATIVE=40, - UNARY_NOT=41, - WITH_EXCEPT_START=42, - BINARY_OP=43, - BUILD_INTERPOLATION=44, - BUILD_LIST=45, - BUILD_MAP=46, - BUILD_SET=47, - BUILD_SLICE=48, - BUILD_STRING=49, - BUILD_TUPLE=50, - CALL=51, - CALL_INTRINSIC_1=52, - CALL_INTRINSIC_2=53, - CALL_KW=54, - COMPARE_OP=55, - CONTAINS_OP=56, - CONVERT_VALUE=57, - COPY=58, - COPY_FREE_VARS=59, - DELETE_DEREF=60, - DELETE_FAST=61, - DICT_MERGE=62, - DICT_UPDATE=63, - END_ASYNC_FOR=64, - EXTENDED_ARG=65, - FOR_ITER=66, - GET_AWAITABLE=67, - GET_ITER=68, - IMPORT_FROM=69, - IMPORT_NAME=70, - IS_OP=71, - JUMP_BACKWARD=72, - JUMP_BACKWARD_NO_INTERRUPT=73, - JUMP_FORWARD=74, - LIST_APPEND=75, - LIST_EXTEND=76, - LOAD_ATTR=77, - LOAD_COMMON_CONSTANT=78, - LOAD_CONST=79, - LOAD_DEREF=80, - LOAD_FAST=81, - LOAD_FAST_AND_CLEAR=82, - LOAD_FAST_BORROW=83, - LOAD_FAST_BORROW_LOAD_FAST_BORROW=84, - LOAD_FAST_CHECK=85, - LOAD_FAST_LOAD_FAST=86, - LOAD_FROM_DICT_OR_DEREF=87, - LOAD_FROM_DICT_OR_GLOBALS=88, - LOAD_GLOBAL=89, - LOAD_NAME=90, - LOAD_SMALL_INT=91, - LOAD_SPECIAL=92, - LOAD_SUPER_ATTR=93, - MAKE_CELL=94, - MAP_ADD=95, - MATCH_CLASS=96, - POP_JUMP_IF_FALSE=97, - POP_JUMP_IF_NONE=98, - POP_JUMP_IF_NOT_NONE=99, - POP_JUMP_IF_TRUE=100, - RAISE_VARARGS=101, - RERAISE=102, - SEND=103, - SET_ADD=104, - SET_FUNCTION_ATTRIBUTE=105, - SET_UPDATE=106, - STORE_ATTR=107, - STORE_DEREF=108, - STORE_FAST=109, - STORE_FAST_LOAD_FAST=110, - STORE_FAST_STORE_FAST=111, - STORE_GLOBAL=112, - STORE_NAME=113, - SWAP=114, - UNPACK_EX=115, - UNPACK_SEQUENCE=116, - YIELD_VALUE=117, + MATCH_KEYS=22, + MATCH_MAPPING=23, + MATCH_SEQUENCE=24, + NOP=25, + NOT_TAKEN=26, + POP_EXCEPT=27, + POP_ITER=28, + POP_TOP=29, + PUSH_EXC_INFO=30, + PUSH_NULL=31, + RETURN_GENERATOR=32, + RETURN_VALUE=33, + SETUP_ANNOTATIONS=34, + STORE_SLICE=35, + STORE_SUBSCR=36, + TO_BOOL=37, + UNARY_INVERT=38, + UNARY_NEGATIVE=39, + UNARY_NOT=40, + WITH_EXCEPT_START=41, + BINARY_OP=42, + BUILD_INTERPOLATION=43, + BUILD_LIST=44, + BUILD_MAP=45, + BUILD_SET=46, + BUILD_SLICE=47, + BUILD_STRING=48, + BUILD_TUPLE=49, + CALL=50, + CALL_INTRINSIC_1=51, + CALL_INTRINSIC_2=52, + CALL_KW=53, + COMPARE_OP=54, + CONTAINS_OP=55, + CONVERT_VALUE=56, + COPY=57, + COPY_FREE_VARS=58, + DELETE_DEREF=59, + DELETE_FAST=60, + DICT_MERGE=61, + DICT_UPDATE=62, + END_ASYNC_FOR=63, + EXTENDED_ARG=64, + FOR_ITER=65, + GET_AWAITABLE=66, + GET_ITER=67, + IMPORT_FROM=68, + IMPORT_NAME=69, + IS_OP=70, + JUMP_BACKWARD=71, + JUMP_BACKWARD_NO_INTERRUPT=72, + JUMP_FORWARD=73, + LIST_APPEND=74, + LIST_EXTEND=75, + LOAD_ATTR=76, + LOAD_COMMON_CONSTANT=77, + LOAD_CONST=78, + LOAD_DEREF=79, + LOAD_FAST=80, + LOAD_FAST_AND_CLEAR=81, + LOAD_FAST_BORROW=82, + LOAD_FAST_BORROW_LOAD_FAST_BORROW=83, + LOAD_FAST_CHECK=84, + LOAD_FAST_LOAD_FAST=85, + LOAD_FROM_DICT_OR_DEREF=86, + LOAD_FROM_DICT_OR_GLOBALS=87, + LOAD_GLOBAL=88, + LOAD_NAME=89, + LOAD_SMALL_INT=90, + LOAD_SPECIAL=91, + LOAD_SUPER_ATTR=92, + MAKE_CELL=93, + MAP_ADD=94, + MATCH_CLASS=95, + POP_JUMP_IF_FALSE=96, + POP_JUMP_IF_NONE=97, + POP_JUMP_IF_NOT_NONE=98, + POP_JUMP_IF_TRUE=99, + RAISE_VARARGS=100, + RERAISE=101, + SEND=102, + SET_ADD=103, + SET_FUNCTION_ATTRIBUTE=104, + SET_UPDATE=105, + STORE_ATTR=106, + STORE_DEREF=107, + STORE_FAST=108, + STORE_FAST_LOAD_FAST=109, + STORE_FAST_STORE_FAST=110, + STORE_GLOBAL=111, + STORE_NAME=112, + SWAP=113, + UNPACK_EX=114, + UNPACK_SEQUENCE=115, + YIELD_VALUE=116, INSTRUMENTED_END_FOR=233, INSTRUMENTED_POP_ITER=234, INSTRUMENTED_END_SEND=235, @@ -381,5 +380,5 @@ STORE_FAST_MAYBE_NULL=266, ) -HAVE_ARGUMENT = 42 +HAVE_ARGUMENT = 41 MIN_INSTRUMENTED_OPCODE = 233 diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 8185e2f0ca14e2c..c75992761d1334f 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -1041,8 +1041,7 @@ def test_widths(self): 'LOAD_FAST_BORROW_LOAD_FAST_BORROW', 'INSTRUMENTED_CALL_FUNCTION_EX', 'YIELD_FROM_CORO_CHECK', - 'ANNOTATIONS_PLACEHOLDER', - 'MATCH_CLASS_ISINSTANCE']) + 'ANNOTATIONS_PLACEHOLDER']) for op, opname in enumerate(dis.opname): if opname in long_opcodes or opname.startswith("INSTRUMENTED"): continue diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-16-19-22.gh-issue-138912.TKMC9K.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-16-19-22.gh-issue-138912.TKMC9K.rst index 1e9d0067027631e..6236c6335ceca3c 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-16-19-22.gh-issue-138912.TKMC9K.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-14-16-19-22.gh-issue-138912.TKMC9K.rst @@ -1,3 +1,2 @@ -Add :opcode:`MATCH_CLASS_ISINSTANCE` opcode to improve the performance of -:keyword:`match` class patterns without any sub-patterns by ~24%. -Patch by Marc Mueller. +Add fast path for :keyword:`match` class patterns without any sub-patterns +to improve performance by ~15%. diff --git a/Modules/_testinternalcapi/test_cases.c.h b/Modules/_testinternalcapi/test_cases.c.h index 78a66da8814b12f..ab80c422687bf2a 100644 --- a/Modules/_testinternalcapi/test_cases.c.h +++ b/Modules/_testinternalcapi/test_cases.c.h @@ -10906,56 +10906,6 @@ DISPATCH(); } - TARGET(MATCH_CLASS_ISINSTANCE) { - #if _Py_TAIL_CALL_INTERP - int opcode = MATCH_CLASS_ISINSTANCE; - (void)(opcode); - #endif - frame->instr_ptr = next_instr; - next_instr += 1; - INSTRUCTION_STATS(MATCH_CLASS_ISINSTANCE); - _PyStackRef subject; - _PyStackRef type; - _PyStackRef res; - type = stack_pointer[-1]; - subject = stack_pointer[-2]; - PyObject *subject_o = PyStackRef_AsPyObjectBorrow(subject); - PyObject *type_o = PyStackRef_AsPyObjectBorrow(type); - if (!PyType_Check(type_o)) { - const char *e = "called match pattern must be a class"; - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyFrame_StackPointerValidate(frame); - _PyErr_Format(tstate, PyExc_TypeError, e); - _PyFrame_StackPointerInvalidate(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyFrame_StackPointerValidate(frame); - PyStackRef_CLOSE(type); - _PyFrame_StackPointerInvalidate(frame); - JUMP_TO_LABEL(error); - } - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyFrame_StackPointerValidate(frame); - int retval = PyObject_IsInstance(subject_o, type_o); - _PyFrame_StackPointerInvalidate(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyFrame_StackPointerValidate(frame); - PyStackRef_CLOSE(type); - _PyFrame_StackPointerInvalidate(frame); - if (retval < 0) { - JUMP_TO_LABEL(error); - } - assert(!_PyErr_Occurred(tstate)); - res = retval ? PyStackRef_True : PyStackRef_False; - stack_pointer[0] = res; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - DISPATCH(); - } - TARGET(MATCH_KEYS) { #if _Py_TAIL_CALL_INTERP int opcode = MATCH_KEYS; diff --git a/Modules/_testinternalcapi/test_targets.h b/Modules/_testinternalcapi/test_targets.h index d8540d435e7b1ab..91b424773224e4b 100644 --- a/Modules/_testinternalcapi/test_targets.h +++ b/Modules/_testinternalcapi/test_targets.h @@ -22,7 +22,6 @@ static void *opcode_targets_table[256] = { &&TARGET_LOAD_BUILD_CLASS, &&TARGET_LOAD_LOCALS, &&TARGET_MAKE_FUNCTION, - &&TARGET_MATCH_CLASS_ISINSTANCE, &&TARGET_MATCH_KEYS, &&TARGET_MATCH_MAPPING, &&TARGET_MATCH_SEQUENCE, @@ -128,6 +127,7 @@ static void *opcode_targets_table[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_RESUME, &&TARGET_BINARY_OP_ADD_FLOAT, &&TARGET_BINARY_OP_ADD_INT, @@ -376,7 +376,7 @@ static void *opcode_tracing_targets_table[256] = { &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, - &&TARGET_TRACE_RECORD, + &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -699,7 +699,6 @@ static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MAKE_CELL(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MAKE_FUNCTION(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MAP_ADD(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_CLASS(TAIL_CALL_PARAMS); -static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_CLASS_ISINSTANCE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_KEYS(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_MAPPING(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_SEQUENCE(TAIL_CALL_PARAMS); @@ -943,7 +942,6 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [MAKE_FUNCTION] = _TAIL_CALL_MAKE_FUNCTION, [MAP_ADD] = _TAIL_CALL_MAP_ADD, [MATCH_CLASS] = _TAIL_CALL_MATCH_CLASS, - [MATCH_CLASS_ISINSTANCE] = _TAIL_CALL_MATCH_CLASS_ISINSTANCE, [MATCH_KEYS] = _TAIL_CALL_MATCH_KEYS, [MATCH_MAPPING] = _TAIL_CALL_MATCH_MAPPING, [MATCH_SEQUENCE] = _TAIL_CALL_MATCH_SEQUENCE, @@ -1007,6 +1005,7 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_UNPACK_SEQUENCE_TWO_TUPLE, [WITH_EXCEPT_START] = _TAIL_CALL_WITH_EXCEPT_START, [YIELD_VALUE] = _TAIL_CALL_YIELD_VALUE, + [117] = _TAIL_CALL_UNKNOWN_OPCODE, [118] = _TAIL_CALL_UNKNOWN_OPCODE, [119] = _TAIL_CALL_UNKNOWN_OPCODE, [120] = _TAIL_CALL_UNKNOWN_OPCODE, @@ -1201,7 +1200,6 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [MAKE_FUNCTION] = _TAIL_CALL_TRACE_RECORD, [MAP_ADD] = _TAIL_CALL_TRACE_RECORD, [MATCH_CLASS] = _TAIL_CALL_TRACE_RECORD, - [MATCH_CLASS_ISINSTANCE] = _TAIL_CALL_TRACE_RECORD, [MATCH_KEYS] = _TAIL_CALL_TRACE_RECORD, [MATCH_MAPPING] = _TAIL_CALL_TRACE_RECORD, [MATCH_SEQUENCE] = _TAIL_CALL_TRACE_RECORD, @@ -1265,6 +1263,7 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_TRACE_RECORD, [WITH_EXCEPT_START] = _TAIL_CALL_TRACE_RECORD, [YIELD_VALUE] = _TAIL_CALL_TRACE_RECORD, + [117] = _TAIL_CALL_UNKNOWN_OPCODE, [118] = _TAIL_CALL_UNKNOWN_OPCODE, [119] = _TAIL_CALL_UNKNOWN_OPCODE, [120] = _TAIL_CALL_UNKNOWN_OPCODE, diff --git a/Programs/test_frozenmain.h b/Programs/test_frozenmain.h index ffa81f2d1ce6870..c82b791439a3fa1 100644 --- a/Programs/test_frozenmain.h +++ b/Programs/test_frozenmain.h @@ -1,19 +1,19 @@ // Auto-generated by Programs/freeze_test_frozenmain.py unsigned char M_test_frozenmain[] = { 227,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0, - 0,0,0,0,0,243,188,0,0,0,128,0,0,0,91,0, - 78,7,70,0,113,0,91,0,78,7,70,4,113,1,90,2, - 32,0,79,1,51,1,0,0,0,0,0,0,30,0,90,2, - 32,0,79,2,90,0,77,6,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,51,2,0,0,0,0, - 0,0,30,0,90,1,77,8,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,32,0,51,0,0,0, - 0,0,0,0,79,3,43,26,0,0,0,0,0,0,0,0, - 0,0,113,5,79,6,68,0,0,0,66,24,0,0,113,6, - 90,2,32,0,79,4,90,6,12,0,79,5,90,5,90,6, - 43,26,0,0,0,0,0,0,0,0,0,0,12,0,49,4, - 51,1,0,0,0,0,0,0,30,0,72,26,0,0,9,0, - 29,0,78,7,34,0,41,7,233,0,0,0,0,122,18,70, + 0,0,0,0,0,243,188,0,0,0,128,0,0,0,90,0, + 77,7,69,0,112,0,90,0,77,7,69,4,112,1,89,2, + 31,0,78,1,50,1,0,0,0,0,0,0,29,0,89,2, + 31,0,78,2,89,0,76,6,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,50,2,0,0,0,0, + 0,0,29,0,89,1,76,8,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,31,0,50,0,0,0, + 0,0,0,0,78,3,42,26,0,0,0,0,0,0,0,0, + 0,0,112,5,78,6,67,0,0,0,65,24,0,0,112,6, + 89,2,31,0,78,4,89,6,12,0,78,5,89,5,89,6, + 42,26,0,0,0,0,0,0,0,0,0,0,12,0,48,4, + 50,1,0,0,0,0,0,0,29,0,71,26,0,0,9,0, + 28,0,77,7,33,0,41,7,233,0,0,0,0,122,18,70, 114,111,122,101,110,32,72,101,108,108,111,32,87,111,114,108, 100,122,8,115,121,115,46,97,114,103,118,218,6,99,111,110, 102,105,103,122,7,99,111,110,102,105,103,32,122,2,58,32, diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 55fd67df1e14f14..689feeb0a1e0700 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -3678,22 +3678,6 @@ dummy_func( len = PyStackRef_FromPyObjectSteal(len_o); } - inst(MATCH_CLASS_ISINSTANCE, (subject, type -- subject, res)) { - PyObject *subject_o = PyStackRef_AsPyObjectBorrow(subject); - PyObject *type_o = PyStackRef_AsPyObjectBorrow(type); - if (!PyType_Check(type_o)) { - const char *e = "called match pattern must be a class"; - _PyErr_Format(tstate, PyExc_TypeError, e); - PyStackRef_CLOSE(type); - ERROR_IF(true); - } - int retval = PyObject_IsInstance(subject_o, type_o); - PyStackRef_CLOSE(type); - ERROR_IF(retval < 0); - assert(!_PyErr_Occurred(tstate)); - res = retval ? PyStackRef_True : PyStackRef_False; - } - op(_MATCH_CLASS, (subject, type, names -- attrs, s, tp, n)) { // Pop TOS and TOS1. Set TOS to a tuple of attributes on success, or // None on failure. diff --git a/Python/codegen.c b/Python/codegen.c index 97085b90b29fb0a..79dac1046eb1d44 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -6156,24 +6156,6 @@ validate_kwd_attrs(compiler *c, asdl_identifier_seq *attrs, asdl_pattern_seq* pa return SUCCESS; } -static int -codegen_pattern_class_fast(compiler *c, pattern_ty p, pattern_context *pc) -{ - NEW_JUMP_TARGET_LABEL(c, end); - assert(p->kind == MatchClass_kind); - assert(!asdl_seq_LEN(p->v.MatchClass.patterns)); - assert(!asdl_seq_LEN(p->v.MatchClass.kwd_attrs)); - VISIT(c, expr, p->v.MatchClass.cls); - ADDOP(c, LOC(p), MATCH_CLASS_ISINSTANCE); - // TOS is now subject: - pc->on_top++; - RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE)); - pc->on_top--; - // Success! POP subject: - ADDOP(c, LOC(p), POP_TOP); - return SUCCESS; -} - static int codegen_pattern_class(compiler *c, pattern_ty p, pattern_context *pc) { @@ -6197,9 +6179,12 @@ codegen_pattern_class(compiler *c, pattern_ty p, pattern_context *pc) if (nattrs) { RETURN_IF_ERROR(validate_kwd_attrs(c, kwd_attrs, kwd_patterns)); } - if (!nargs && !nattrs) { + if (nargs + nattrs == 0) { // Fast path if there are no sub-patterns - return codegen_pattern_class_fast(c, p, pc); + VISIT(c, expr, p->v.MatchClass.cls); + ADDOP_I(c, LOC(p), CALL_INTRINSIC_2, INTRINSIC_MATCH_CLASS_ISINSTANCE); + RETURN_IF_ERROR(jump_to_fail_pop(c, LOC(p), pc, POP_JUMP_IF_FALSE)); + return SUCCESS; } VISIT(c, expr, p->v.MatchClass.cls); PyObject *attr_names = PyTuple_New(nattrs); diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 24931a744445b1a..a012f14f7fbebe2 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -14208,67 +14208,6 @@ break; } - case _MATCH_CLASS_ISINSTANCE_r22: { - CHECK_CURRENT_CACHED_VALUES(2); - ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__); - _PyStackRef type; - _PyStackRef subject; - _PyStackRef res; - _PyStackRef _stack_item_0 = _tos_cache0; - _PyStackRef _stack_item_1 = _tos_cache1; - type = _stack_item_1; - subject = _stack_item_0; - PyObject *subject_o = PyStackRef_AsPyObjectBorrow(subject); - PyObject *type_o = PyStackRef_AsPyObjectBorrow(type); - if (!PyType_Check(type_o)) { - const char *e = "called match pattern must be a class"; - stack_pointer[0] = subject; - stack_pointer[1] = type; - stack_pointer += 2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyFrame_StackPointerValidate(frame); - _PyErr_Format(tstate, PyExc_TypeError, e); - _PyFrame_StackPointerInvalidate(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyFrame_StackPointerValidate(frame); - PyStackRef_CLOSE(type); - _PyFrame_StackPointerInvalidate(frame); - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_ERROR(); - } - stack_pointer[0] = subject; - stack_pointer[1] = type; - stack_pointer += 2; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyFrame_StackPointerValidate(frame); - int retval = PyObject_IsInstance(subject_o, type_o); - _PyFrame_StackPointerInvalidate(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyFrame_StackPointerValidate(frame); - PyStackRef_CLOSE(type); - _PyFrame_StackPointerInvalidate(frame); - if (retval < 0) { - SET_CURRENT_CACHED_VALUES(0); - JUMP_TO_ERROR(); - } - assert(!_PyErr_Occurred(tstate)); - res = retval ? PyStackRef_True : PyStackRef_False; - _tos_cache1 = res; - _tos_cache0 = subject; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(2); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__); - break; - } - case _MATCH_CLASS_r33: { CHECK_CURRENT_CACHED_VALUES(3); ASSERT_WITHIN_STACK_BOUNDS_IGNORING_CACHE(__FILE__, __LINE__); diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index d0d7e3e6621d603..b72116d367634d8 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -10904,56 +10904,6 @@ DISPATCH(); } - TARGET(MATCH_CLASS_ISINSTANCE) { - #if _Py_TAIL_CALL_INTERP - int opcode = MATCH_CLASS_ISINSTANCE; - (void)(opcode); - #endif - frame->instr_ptr = next_instr; - next_instr += 1; - INSTRUCTION_STATS(MATCH_CLASS_ISINSTANCE); - _PyStackRef subject; - _PyStackRef type; - _PyStackRef res; - type = stack_pointer[-1]; - subject = stack_pointer[-2]; - PyObject *subject_o = PyStackRef_AsPyObjectBorrow(subject); - PyObject *type_o = PyStackRef_AsPyObjectBorrow(type); - if (!PyType_Check(type_o)) { - const char *e = "called match pattern must be a class"; - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyFrame_StackPointerValidate(frame); - _PyErr_Format(tstate, PyExc_TypeError, e); - _PyFrame_StackPointerInvalidate(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyFrame_StackPointerValidate(frame); - PyStackRef_CLOSE(type); - _PyFrame_StackPointerInvalidate(frame); - JUMP_TO_LABEL(error); - } - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyFrame_StackPointerValidate(frame); - int retval = PyObject_IsInstance(subject_o, type_o); - _PyFrame_StackPointerInvalidate(frame); - stack_pointer += -1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - _PyFrame_SetStackPointer(frame, stack_pointer); - _PyFrame_StackPointerValidate(frame); - PyStackRef_CLOSE(type); - _PyFrame_StackPointerInvalidate(frame); - if (retval < 0) { - JUMP_TO_LABEL(error); - } - assert(!_PyErr_Occurred(tstate)); - res = retval ? PyStackRef_True : PyStackRef_False; - stack_pointer[0] = res; - stack_pointer += 1; - ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); - DISPATCH(); - } - TARGET(MATCH_KEYS) { #if _Py_TAIL_CALL_INTERP int opcode = MATCH_KEYS; diff --git a/Python/intrinsics.c b/Python/intrinsics.c index f081f33cc83b88c..63410d8dbe584ad 100644 --- a/Python/intrinsics.c +++ b/Python/intrinsics.c @@ -270,6 +270,25 @@ make_typevar_with_constraints(PyThreadState* Py_UNUSED(ignored), PyObject *name, return _Py_make_typevar(name, NULL, evaluate_constraints); } +static PyObject * +match_class_isinstance(PyThreadState* tstate, PyObject *subject, PyObject *type) +{ + /* Fast path for class patterns with no sub-patterns, e.g. `case C():` + Equivalent to the isinstance check performed by _PyEval_MatchClass, + including the same TypeError when the pattern does not refer to a + class. */ + if (!PyType_Check(type)) { + _PyErr_SetString(tstate, PyExc_TypeError, + "class pattern must refer to a class"); + return NULL; + } + int res = PyObject_IsInstance(subject, type); + if (res < 0) { + return NULL; + } + return res ? Py_True : Py_False; +} + const intrinsic_func2_info _PyIntrinsics_BinaryFunctions[] = { INTRINSIC_FUNC_ENTRY(INTRINSIC_2_INVALID, no_intrinsic2) @@ -278,6 +297,7 @@ _PyIntrinsics_BinaryFunctions[] = { INTRINSIC_FUNC_ENTRY(INTRINSIC_TYPEVAR_WITH_CONSTRAINTS, make_typevar_with_constraints) INTRINSIC_FUNC_ENTRY(INTRINSIC_SET_FUNCTION_TYPE_PARAMS, _Py_set_function_type_params) INTRINSIC_FUNC_ENTRY(INTRINSIC_SET_TYPEPARAM_DEFAULT, _Py_set_typeparam_default) + INTRINSIC_FUNC_ENTRY(INTRINSIC_MATCH_CLASS_ISINSTANCE, match_class_isinstance) }; #undef INTRINSIC_FUNC_ENTRY diff --git a/Python/opcode_targets.h b/Python/opcode_targets.h index d8540d435e7b1ab..91b424773224e4b 100644 --- a/Python/opcode_targets.h +++ b/Python/opcode_targets.h @@ -22,7 +22,6 @@ static void *opcode_targets_table[256] = { &&TARGET_LOAD_BUILD_CLASS, &&TARGET_LOAD_LOCALS, &&TARGET_MAKE_FUNCTION, - &&TARGET_MATCH_CLASS_ISINSTANCE, &&TARGET_MATCH_KEYS, &&TARGET_MATCH_MAPPING, &&TARGET_MATCH_SEQUENCE, @@ -128,6 +127,7 @@ static void *opcode_targets_table[256] = { &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, + &&_unknown_opcode, &&TARGET_RESUME, &&TARGET_BINARY_OP_ADD_FLOAT, &&TARGET_BINARY_OP_ADD_INT, @@ -376,7 +376,7 @@ static void *opcode_tracing_targets_table[256] = { &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, &&TARGET_TRACE_RECORD, - &&TARGET_TRACE_RECORD, + &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, &&_unknown_opcode, @@ -699,7 +699,6 @@ static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MAKE_CELL(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MAKE_FUNCTION(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MAP_ADD(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_CLASS(TAIL_CALL_PARAMS); -static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_CLASS_ISINSTANCE(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_KEYS(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_MAPPING(TAIL_CALL_PARAMS); static PyObject *Py_PRESERVE_NONE_CC _TAIL_CALL_MATCH_SEQUENCE(TAIL_CALL_PARAMS); @@ -943,7 +942,6 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [MAKE_FUNCTION] = _TAIL_CALL_MAKE_FUNCTION, [MAP_ADD] = _TAIL_CALL_MAP_ADD, [MATCH_CLASS] = _TAIL_CALL_MATCH_CLASS, - [MATCH_CLASS_ISINSTANCE] = _TAIL_CALL_MATCH_CLASS_ISINSTANCE, [MATCH_KEYS] = _TAIL_CALL_MATCH_KEYS, [MATCH_MAPPING] = _TAIL_CALL_MATCH_MAPPING, [MATCH_SEQUENCE] = _TAIL_CALL_MATCH_SEQUENCE, @@ -1007,6 +1005,7 @@ static py_tail_call_funcptr instruction_funcptr_handler_table[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_UNPACK_SEQUENCE_TWO_TUPLE, [WITH_EXCEPT_START] = _TAIL_CALL_WITH_EXCEPT_START, [YIELD_VALUE] = _TAIL_CALL_YIELD_VALUE, + [117] = _TAIL_CALL_UNKNOWN_OPCODE, [118] = _TAIL_CALL_UNKNOWN_OPCODE, [119] = _TAIL_CALL_UNKNOWN_OPCODE, [120] = _TAIL_CALL_UNKNOWN_OPCODE, @@ -1201,7 +1200,6 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [MAKE_FUNCTION] = _TAIL_CALL_TRACE_RECORD, [MAP_ADD] = _TAIL_CALL_TRACE_RECORD, [MATCH_CLASS] = _TAIL_CALL_TRACE_RECORD, - [MATCH_CLASS_ISINSTANCE] = _TAIL_CALL_TRACE_RECORD, [MATCH_KEYS] = _TAIL_CALL_TRACE_RECORD, [MATCH_MAPPING] = _TAIL_CALL_TRACE_RECORD, [MATCH_SEQUENCE] = _TAIL_CALL_TRACE_RECORD, @@ -1265,6 +1263,7 @@ static py_tail_call_funcptr instruction_funcptr_tracing_table[256] = { [UNPACK_SEQUENCE_TWO_TUPLE] = _TAIL_CALL_TRACE_RECORD, [WITH_EXCEPT_START] = _TAIL_CALL_TRACE_RECORD, [YIELD_VALUE] = _TAIL_CALL_TRACE_RECORD, + [117] = _TAIL_CALL_UNKNOWN_OPCODE, [118] = _TAIL_CALL_UNKNOWN_OPCODE, [119] = _TAIL_CALL_UNKNOWN_OPCODE, [120] = _TAIL_CALL_UNKNOWN_OPCODE, diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index d24c03c499cb834..3ad23c3a74f7087 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -3497,13 +3497,6 @@ break; } - case _MATCH_CLASS_ISINSTANCE: { - JitOptRef res; - res = sym_new_not_null(ctx); - stack_pointer[-1] = res; - break; - } - case _MATCH_CLASS: { JitOptRef names; JitOptRef type;