From: Neko Asakura Date: Tue, 14 Apr 2026 14:44:39 +0000 (-0400) Subject: gh-148510: restore `func_version` check in `_LOAD_ATTR_PROPERTY_FRAME` (GH-148528) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=52a7f1b7f88d7f25e4cf02b6bc5e7521848d99f0;p=thirdparty%2FPython%2Fcpython.git gh-148510: restore `func_version` check in `_LOAD_ATTR_PROPERTY_FRAME` (GH-148528) --- diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index aa7b44d9e7f1..ce07b71192bf 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -1451,7 +1451,7 @@ _PyOpcode_macro_expansion[256] = { [LOAD_ATTR_MODULE] = { .nuops = 4, .uops = { { _LOAD_ATTR_MODULE, 2, 1 }, { _LOAD_ATTR_MODULE, OPERAND1_1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_NONDESCRIPTOR_NO_DICT] = { .nuops = 3, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_NONDESCRIPTOR_NO_DICT, 4, 5 } } }, [LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = { .nuops = 5, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT, OPARG_SIMPLE, 3 }, { _GUARD_KEYS_VERSION, 2, 3 }, { _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES, 4, 5 } } }, - [LOAD_ATTR_PROPERTY] = { .nuops = 6, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_PEP_523, OPARG_SIMPLE, 3 }, { _LOAD_ATTR_PROPERTY_FRAME, 4, 5 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 9 }, { _PUSH_FRAME, OPARG_SIMPLE, 9 } } }, + [LOAD_ATTR_PROPERTY] = { .nuops = 7, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _CHECK_PEP_523, OPARG_SIMPLE, 3 }, { _LOAD_ATTR_PROPERTY_FRAME, 2, 3 }, { _LOAD_ATTR_PROPERTY_FRAME, OPERAND1_4, 5 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 9 }, { _PUSH_FRAME, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_SLOT] = { .nuops = 5, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_SLOT, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, [LOAD_ATTR_WITH_HINT] = { .nuops = 5, .uops = { { _RECORD_TOS_TYPE, OPARG_SIMPLE, 1 }, { _GUARD_TYPE_VERSION, 2, 1 }, { _LOAD_ATTR_WITH_HINT, 1, 3 }, { _POP_TOP, OPARG_SIMPLE, 4 }, { _PUSH_NULL_CONDITIONAL, OPARG_SIMPLE, 9 } } }, [LOAD_BUILD_CLASS] = { .nuops = 1, .uops = { { _LOAD_BUILD_CLASS, OPARG_SIMPLE, 0 } } }, diff --git a/Include/internal/pycore_optimizer.h b/Include/internal/pycore_optimizer.h index 78bbdc2026e9..a809a7e25526 100644 --- a/Include/internal/pycore_optimizer.h +++ b/Include/internal/pycore_optimizer.h @@ -402,6 +402,7 @@ extern JitOptRef _Py_uop_sym_new_null(JitOptContext *ctx); extern bool _Py_uop_sym_has_type(JitOptRef sym); extern bool _Py_uop_sym_matches_type(JitOptRef sym, PyTypeObject *typ); extern bool _Py_uop_sym_matches_type_version(JitOptRef sym, unsigned int version); +extern unsigned int _Py_uop_sym_get_type_version(JitOptRef sym); extern void _Py_uop_sym_set_null(JitOptContext *ctx, JitOptRef sym); extern void _Py_uop_sym_set_non_null(JitOptContext *ctx, JitOptRef sym); extern void _Py_uop_sym_set_type(JitOptContext *ctx, JitOptRef sym, PyTypeObject *typ); diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 390bfa27c100..105878aef3ae 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -1025,341 +1025,344 @@ extern "C" { #define _LOAD_ATTR_MODULE_r12 1235 #define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT_r11 1236 #define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11 1237 -#define _LOAD_ATTR_PROPERTY_FRAME_r11 1238 -#define _LOAD_ATTR_SLOT_r02 1239 -#define _LOAD_ATTR_SLOT_r12 1240 -#define _LOAD_ATTR_SLOT_r23 1241 -#define _LOAD_ATTR_WITH_HINT_r12 1242 -#define _LOAD_BUILD_CLASS_r01 1243 -#define _LOAD_BYTECODE_r00 1244 -#define _LOAD_COMMON_CONSTANT_r01 1245 -#define _LOAD_COMMON_CONSTANT_r12 1246 -#define _LOAD_COMMON_CONSTANT_r23 1247 -#define _LOAD_CONST_r01 1248 -#define _LOAD_CONST_r12 1249 -#define _LOAD_CONST_r23 1250 -#define _LOAD_CONST_INLINE_r01 1251 -#define _LOAD_CONST_INLINE_r12 1252 -#define _LOAD_CONST_INLINE_r23 1253 -#define _LOAD_CONST_INLINE_BORROW_r01 1254 -#define _LOAD_CONST_INLINE_BORROW_r12 1255 -#define _LOAD_CONST_INLINE_BORROW_r23 1256 -#define _LOAD_DEREF_r01 1257 -#define _LOAD_FAST_r01 1258 -#define _LOAD_FAST_r12 1259 -#define _LOAD_FAST_r23 1260 -#define _LOAD_FAST_0_r01 1261 -#define _LOAD_FAST_0_r12 1262 -#define _LOAD_FAST_0_r23 1263 -#define _LOAD_FAST_1_r01 1264 -#define _LOAD_FAST_1_r12 1265 -#define _LOAD_FAST_1_r23 1266 -#define _LOAD_FAST_2_r01 1267 -#define _LOAD_FAST_2_r12 1268 -#define _LOAD_FAST_2_r23 1269 -#define _LOAD_FAST_3_r01 1270 -#define _LOAD_FAST_3_r12 1271 -#define _LOAD_FAST_3_r23 1272 -#define _LOAD_FAST_4_r01 1273 -#define _LOAD_FAST_4_r12 1274 -#define _LOAD_FAST_4_r23 1275 -#define _LOAD_FAST_5_r01 1276 -#define _LOAD_FAST_5_r12 1277 -#define _LOAD_FAST_5_r23 1278 -#define _LOAD_FAST_6_r01 1279 -#define _LOAD_FAST_6_r12 1280 -#define _LOAD_FAST_6_r23 1281 -#define _LOAD_FAST_7_r01 1282 -#define _LOAD_FAST_7_r12 1283 -#define _LOAD_FAST_7_r23 1284 -#define _LOAD_FAST_AND_CLEAR_r01 1285 -#define _LOAD_FAST_AND_CLEAR_r12 1286 -#define _LOAD_FAST_AND_CLEAR_r23 1287 -#define _LOAD_FAST_BORROW_r01 1288 -#define _LOAD_FAST_BORROW_r12 1289 -#define _LOAD_FAST_BORROW_r23 1290 -#define _LOAD_FAST_BORROW_0_r01 1291 -#define _LOAD_FAST_BORROW_0_r12 1292 -#define _LOAD_FAST_BORROW_0_r23 1293 -#define _LOAD_FAST_BORROW_1_r01 1294 -#define _LOAD_FAST_BORROW_1_r12 1295 -#define _LOAD_FAST_BORROW_1_r23 1296 -#define _LOAD_FAST_BORROW_2_r01 1297 -#define _LOAD_FAST_BORROW_2_r12 1298 -#define _LOAD_FAST_BORROW_2_r23 1299 -#define _LOAD_FAST_BORROW_3_r01 1300 -#define _LOAD_FAST_BORROW_3_r12 1301 -#define _LOAD_FAST_BORROW_3_r23 1302 -#define _LOAD_FAST_BORROW_4_r01 1303 -#define _LOAD_FAST_BORROW_4_r12 1304 -#define _LOAD_FAST_BORROW_4_r23 1305 -#define _LOAD_FAST_BORROW_5_r01 1306 -#define _LOAD_FAST_BORROW_5_r12 1307 -#define _LOAD_FAST_BORROW_5_r23 1308 -#define _LOAD_FAST_BORROW_6_r01 1309 -#define _LOAD_FAST_BORROW_6_r12 1310 -#define _LOAD_FAST_BORROW_6_r23 1311 -#define _LOAD_FAST_BORROW_7_r01 1312 -#define _LOAD_FAST_BORROW_7_r12 1313 -#define _LOAD_FAST_BORROW_7_r23 1314 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1315 -#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1316 -#define _LOAD_FAST_CHECK_r01 1317 -#define _LOAD_FAST_CHECK_r12 1318 -#define _LOAD_FAST_CHECK_r23 1319 -#define _LOAD_FAST_LOAD_FAST_r02 1320 -#define _LOAD_FAST_LOAD_FAST_r13 1321 -#define _LOAD_FROM_DICT_OR_DEREF_r11 1322 -#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1323 -#define _LOAD_GLOBAL_r00 1324 -#define _LOAD_GLOBAL_BUILTINS_r01 1325 -#define _LOAD_GLOBAL_MODULE_r01 1326 -#define _LOAD_LOCALS_r01 1327 -#define _LOAD_LOCALS_r12 1328 -#define _LOAD_LOCALS_r23 1329 -#define _LOAD_NAME_r01 1330 -#define _LOAD_SMALL_INT_r01 1331 -#define _LOAD_SMALL_INT_r12 1332 -#define _LOAD_SMALL_INT_r23 1333 -#define _LOAD_SMALL_INT_0_r01 1334 -#define _LOAD_SMALL_INT_0_r12 1335 -#define _LOAD_SMALL_INT_0_r23 1336 -#define _LOAD_SMALL_INT_1_r01 1337 -#define _LOAD_SMALL_INT_1_r12 1338 -#define _LOAD_SMALL_INT_1_r23 1339 -#define _LOAD_SMALL_INT_2_r01 1340 -#define _LOAD_SMALL_INT_2_r12 1341 -#define _LOAD_SMALL_INT_2_r23 1342 -#define _LOAD_SMALL_INT_3_r01 1343 -#define _LOAD_SMALL_INT_3_r12 1344 -#define _LOAD_SMALL_INT_3_r23 1345 -#define _LOAD_SPECIAL_r00 1346 -#define _LOAD_SUPER_ATTR_ATTR_r31 1347 -#define _LOAD_SUPER_ATTR_METHOD_r32 1348 -#define _LOCK_OBJECT_r01 1349 -#define _LOCK_OBJECT_r11 1350 -#define _LOCK_OBJECT_r22 1351 -#define _LOCK_OBJECT_r33 1352 -#define _MAKE_CALLARGS_A_TUPLE_r33 1353 -#define _MAKE_CELL_r00 1354 -#define _MAKE_FUNCTION_r12 1355 -#define _MAKE_HEAP_SAFE_r01 1356 -#define _MAKE_HEAP_SAFE_r11 1357 -#define _MAKE_HEAP_SAFE_r22 1358 -#define _MAKE_HEAP_SAFE_r33 1359 -#define _MAKE_WARM_r00 1360 -#define _MAKE_WARM_r11 1361 -#define _MAKE_WARM_r22 1362 -#define _MAKE_WARM_r33 1363 -#define _MAP_ADD_r20 1364 -#define _MATCH_CLASS_r33 1365 -#define _MATCH_KEYS_r23 1366 -#define _MATCH_MAPPING_r02 1367 -#define _MATCH_MAPPING_r12 1368 -#define _MATCH_MAPPING_r23 1369 -#define _MATCH_SEQUENCE_r02 1370 -#define _MATCH_SEQUENCE_r12 1371 -#define _MATCH_SEQUENCE_r23 1372 -#define _MAYBE_EXPAND_METHOD_r00 1373 -#define _MAYBE_EXPAND_METHOD_KW_r11 1374 -#define _MONITOR_CALL_r00 1375 -#define _MONITOR_CALL_KW_r11 1376 -#define _MONITOR_JUMP_BACKWARD_r00 1377 -#define _MONITOR_JUMP_BACKWARD_r11 1378 -#define _MONITOR_JUMP_BACKWARD_r22 1379 -#define _MONITOR_JUMP_BACKWARD_r33 1380 -#define _MONITOR_RESUME_r00 1381 -#define _NOP_r00 1382 -#define _NOP_r11 1383 -#define _NOP_r22 1384 -#define _NOP_r33 1385 -#define _POP_EXCEPT_r10 1386 -#define _POP_ITER_r20 1387 -#define _POP_JUMP_IF_FALSE_r00 1388 -#define _POP_JUMP_IF_FALSE_r10 1389 -#define _POP_JUMP_IF_FALSE_r21 1390 -#define _POP_JUMP_IF_FALSE_r32 1391 -#define _POP_JUMP_IF_TRUE_r00 1392 -#define _POP_JUMP_IF_TRUE_r10 1393 -#define _POP_JUMP_IF_TRUE_r21 1394 -#define _POP_JUMP_IF_TRUE_r32 1395 -#define _POP_TOP_r10 1396 -#define _POP_TOP_FLOAT_r00 1397 -#define _POP_TOP_FLOAT_r10 1398 -#define _POP_TOP_FLOAT_r21 1399 -#define _POP_TOP_FLOAT_r32 1400 -#define _POP_TOP_INT_r00 1401 -#define _POP_TOP_INT_r10 1402 -#define _POP_TOP_INT_r21 1403 -#define _POP_TOP_INT_r32 1404 -#define _POP_TOP_NOP_r00 1405 -#define _POP_TOP_NOP_r10 1406 -#define _POP_TOP_NOP_r21 1407 -#define _POP_TOP_NOP_r32 1408 -#define _POP_TOP_OPARG_r00 1409 -#define _POP_TOP_UNICODE_r00 1410 -#define _POP_TOP_UNICODE_r10 1411 -#define _POP_TOP_UNICODE_r21 1412 -#define _POP_TOP_UNICODE_r32 1413 -#define _PUSH_EXC_INFO_r02 1414 -#define _PUSH_EXC_INFO_r12 1415 -#define _PUSH_EXC_INFO_r23 1416 -#define _PUSH_FRAME_r10 1417 -#define _PUSH_NULL_r01 1418 -#define _PUSH_NULL_r12 1419 -#define _PUSH_NULL_r23 1420 -#define _PUSH_NULL_CONDITIONAL_r00 1421 -#define _PY_FRAME_EX_r31 1422 -#define _PY_FRAME_GENERAL_r01 1423 -#define _PY_FRAME_KW_r11 1424 -#define _REPLACE_WITH_TRUE_r02 1425 -#define _REPLACE_WITH_TRUE_r12 1426 -#define _REPLACE_WITH_TRUE_r23 1427 -#define _RESUME_CHECK_r00 1428 -#define _RESUME_CHECK_r11 1429 -#define _RESUME_CHECK_r22 1430 -#define _RESUME_CHECK_r33 1431 -#define _RETURN_GENERATOR_r01 1432 -#define _RETURN_VALUE_r11 1433 -#define _SAVE_RETURN_OFFSET_r00 1434 -#define _SAVE_RETURN_OFFSET_r11 1435 -#define _SAVE_RETURN_OFFSET_r22 1436 -#define _SAVE_RETURN_OFFSET_r33 1437 -#define _SEND_r33 1438 -#define _SEND_GEN_FRAME_r33 1439 -#define _SETUP_ANNOTATIONS_r00 1440 -#define _SET_ADD_r10 1441 -#define _SET_FUNCTION_ATTRIBUTE_r01 1442 -#define _SET_FUNCTION_ATTRIBUTE_r11 1443 -#define _SET_FUNCTION_ATTRIBUTE_r21 1444 -#define _SET_FUNCTION_ATTRIBUTE_r32 1445 -#define _SET_IP_r00 1446 -#define _SET_IP_r11 1447 -#define _SET_IP_r22 1448 -#define _SET_IP_r33 1449 -#define _SET_UPDATE_r11 1450 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1451 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1452 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1453 -#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1454 -#define _SPILL_OR_RELOAD_r01 1455 -#define _SPILL_OR_RELOAD_r02 1456 -#define _SPILL_OR_RELOAD_r03 1457 -#define _SPILL_OR_RELOAD_r10 1458 -#define _SPILL_OR_RELOAD_r12 1459 -#define _SPILL_OR_RELOAD_r13 1460 -#define _SPILL_OR_RELOAD_r20 1461 -#define _SPILL_OR_RELOAD_r21 1462 -#define _SPILL_OR_RELOAD_r23 1463 -#define _SPILL_OR_RELOAD_r30 1464 -#define _SPILL_OR_RELOAD_r31 1465 -#define _SPILL_OR_RELOAD_r32 1466 -#define _START_EXECUTOR_r00 1467 -#define _STORE_ATTR_r20 1468 -#define _STORE_ATTR_INSTANCE_VALUE_r21 1469 -#define _STORE_ATTR_SLOT_r21 1470 -#define _STORE_ATTR_WITH_HINT_r21 1471 -#define _STORE_DEREF_r10 1472 -#define _STORE_FAST_LOAD_FAST_r11 1473 -#define _STORE_FAST_STORE_FAST_r20 1474 -#define _STORE_GLOBAL_r10 1475 -#define _STORE_NAME_r10 1476 -#define _STORE_SLICE_r30 1477 -#define _STORE_SUBSCR_r30 1478 -#define _STORE_SUBSCR_DICT_r31 1479 -#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1480 -#define _STORE_SUBSCR_LIST_INT_r32 1481 -#define _SWAP_r11 1482 -#define _SWAP_2_r02 1483 -#define _SWAP_2_r12 1484 -#define _SWAP_2_r22 1485 -#define _SWAP_2_r33 1486 -#define _SWAP_3_r03 1487 -#define _SWAP_3_r13 1488 -#define _SWAP_3_r23 1489 -#define _SWAP_3_r33 1490 -#define _SWAP_FAST_r01 1491 -#define _SWAP_FAST_r11 1492 -#define _SWAP_FAST_r22 1493 -#define _SWAP_FAST_r33 1494 -#define _SWAP_FAST_0_r01 1495 -#define _SWAP_FAST_0_r11 1496 -#define _SWAP_FAST_0_r22 1497 -#define _SWAP_FAST_0_r33 1498 -#define _SWAP_FAST_1_r01 1499 -#define _SWAP_FAST_1_r11 1500 -#define _SWAP_FAST_1_r22 1501 -#define _SWAP_FAST_1_r33 1502 -#define _SWAP_FAST_2_r01 1503 -#define _SWAP_FAST_2_r11 1504 -#define _SWAP_FAST_2_r22 1505 -#define _SWAP_FAST_2_r33 1506 -#define _SWAP_FAST_3_r01 1507 -#define _SWAP_FAST_3_r11 1508 -#define _SWAP_FAST_3_r22 1509 -#define _SWAP_FAST_3_r33 1510 -#define _SWAP_FAST_4_r01 1511 -#define _SWAP_FAST_4_r11 1512 -#define _SWAP_FAST_4_r22 1513 -#define _SWAP_FAST_4_r33 1514 -#define _SWAP_FAST_5_r01 1515 -#define _SWAP_FAST_5_r11 1516 -#define _SWAP_FAST_5_r22 1517 -#define _SWAP_FAST_5_r33 1518 -#define _SWAP_FAST_6_r01 1519 -#define _SWAP_FAST_6_r11 1520 -#define _SWAP_FAST_6_r22 1521 -#define _SWAP_FAST_6_r33 1522 -#define _SWAP_FAST_7_r01 1523 -#define _SWAP_FAST_7_r11 1524 -#define _SWAP_FAST_7_r22 1525 -#define _SWAP_FAST_7_r33 1526 -#define _TIER2_RESUME_CHECK_r00 1527 -#define _TIER2_RESUME_CHECK_r11 1528 -#define _TIER2_RESUME_CHECK_r22 1529 -#define _TIER2_RESUME_CHECK_r33 1530 -#define _TO_BOOL_r11 1531 -#define _TO_BOOL_BOOL_r01 1532 -#define _TO_BOOL_BOOL_r11 1533 -#define _TO_BOOL_BOOL_r22 1534 -#define _TO_BOOL_BOOL_r33 1535 -#define _TO_BOOL_INT_r02 1536 -#define _TO_BOOL_INT_r12 1537 -#define _TO_BOOL_INT_r23 1538 -#define _TO_BOOL_LIST_r02 1539 -#define _TO_BOOL_LIST_r12 1540 -#define _TO_BOOL_LIST_r23 1541 -#define _TO_BOOL_NONE_r01 1542 -#define _TO_BOOL_NONE_r11 1543 -#define _TO_BOOL_NONE_r22 1544 -#define _TO_BOOL_NONE_r33 1545 -#define _TO_BOOL_STR_r02 1546 -#define _TO_BOOL_STR_r12 1547 -#define _TO_BOOL_STR_r23 1548 -#define _TRACE_RECORD_r00 1549 -#define _UNARY_INVERT_r12 1550 -#define _UNARY_NEGATIVE_r12 1551 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1552 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1553 -#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1554 -#define _UNARY_NOT_r01 1555 -#define _UNARY_NOT_r11 1556 -#define _UNARY_NOT_r22 1557 -#define _UNARY_NOT_r33 1558 -#define _UNPACK_EX_r10 1559 -#define _UNPACK_SEQUENCE_r10 1560 -#define _UNPACK_SEQUENCE_LIST_r10 1561 -#define _UNPACK_SEQUENCE_TUPLE_r10 1562 -#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1563 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1564 -#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1565 -#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1566 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1567 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1568 -#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1569 -#define _WITH_EXCEPT_START_r33 1570 -#define _YIELD_VALUE_r11 1571 -#define MAX_UOP_REGS_ID 1571 +#define _LOAD_ATTR_PROPERTY_FRAME_r01 1238 +#define _LOAD_ATTR_PROPERTY_FRAME_r11 1239 +#define _LOAD_ATTR_PROPERTY_FRAME_r22 1240 +#define _LOAD_ATTR_PROPERTY_FRAME_r33 1241 +#define _LOAD_ATTR_SLOT_r02 1242 +#define _LOAD_ATTR_SLOT_r12 1243 +#define _LOAD_ATTR_SLOT_r23 1244 +#define _LOAD_ATTR_WITH_HINT_r12 1245 +#define _LOAD_BUILD_CLASS_r01 1246 +#define _LOAD_BYTECODE_r00 1247 +#define _LOAD_COMMON_CONSTANT_r01 1248 +#define _LOAD_COMMON_CONSTANT_r12 1249 +#define _LOAD_COMMON_CONSTANT_r23 1250 +#define _LOAD_CONST_r01 1251 +#define _LOAD_CONST_r12 1252 +#define _LOAD_CONST_r23 1253 +#define _LOAD_CONST_INLINE_r01 1254 +#define _LOAD_CONST_INLINE_r12 1255 +#define _LOAD_CONST_INLINE_r23 1256 +#define _LOAD_CONST_INLINE_BORROW_r01 1257 +#define _LOAD_CONST_INLINE_BORROW_r12 1258 +#define _LOAD_CONST_INLINE_BORROW_r23 1259 +#define _LOAD_DEREF_r01 1260 +#define _LOAD_FAST_r01 1261 +#define _LOAD_FAST_r12 1262 +#define _LOAD_FAST_r23 1263 +#define _LOAD_FAST_0_r01 1264 +#define _LOAD_FAST_0_r12 1265 +#define _LOAD_FAST_0_r23 1266 +#define _LOAD_FAST_1_r01 1267 +#define _LOAD_FAST_1_r12 1268 +#define _LOAD_FAST_1_r23 1269 +#define _LOAD_FAST_2_r01 1270 +#define _LOAD_FAST_2_r12 1271 +#define _LOAD_FAST_2_r23 1272 +#define _LOAD_FAST_3_r01 1273 +#define _LOAD_FAST_3_r12 1274 +#define _LOAD_FAST_3_r23 1275 +#define _LOAD_FAST_4_r01 1276 +#define _LOAD_FAST_4_r12 1277 +#define _LOAD_FAST_4_r23 1278 +#define _LOAD_FAST_5_r01 1279 +#define _LOAD_FAST_5_r12 1280 +#define _LOAD_FAST_5_r23 1281 +#define _LOAD_FAST_6_r01 1282 +#define _LOAD_FAST_6_r12 1283 +#define _LOAD_FAST_6_r23 1284 +#define _LOAD_FAST_7_r01 1285 +#define _LOAD_FAST_7_r12 1286 +#define _LOAD_FAST_7_r23 1287 +#define _LOAD_FAST_AND_CLEAR_r01 1288 +#define _LOAD_FAST_AND_CLEAR_r12 1289 +#define _LOAD_FAST_AND_CLEAR_r23 1290 +#define _LOAD_FAST_BORROW_r01 1291 +#define _LOAD_FAST_BORROW_r12 1292 +#define _LOAD_FAST_BORROW_r23 1293 +#define _LOAD_FAST_BORROW_0_r01 1294 +#define _LOAD_FAST_BORROW_0_r12 1295 +#define _LOAD_FAST_BORROW_0_r23 1296 +#define _LOAD_FAST_BORROW_1_r01 1297 +#define _LOAD_FAST_BORROW_1_r12 1298 +#define _LOAD_FAST_BORROW_1_r23 1299 +#define _LOAD_FAST_BORROW_2_r01 1300 +#define _LOAD_FAST_BORROW_2_r12 1301 +#define _LOAD_FAST_BORROW_2_r23 1302 +#define _LOAD_FAST_BORROW_3_r01 1303 +#define _LOAD_FAST_BORROW_3_r12 1304 +#define _LOAD_FAST_BORROW_3_r23 1305 +#define _LOAD_FAST_BORROW_4_r01 1306 +#define _LOAD_FAST_BORROW_4_r12 1307 +#define _LOAD_FAST_BORROW_4_r23 1308 +#define _LOAD_FAST_BORROW_5_r01 1309 +#define _LOAD_FAST_BORROW_5_r12 1310 +#define _LOAD_FAST_BORROW_5_r23 1311 +#define _LOAD_FAST_BORROW_6_r01 1312 +#define _LOAD_FAST_BORROW_6_r12 1313 +#define _LOAD_FAST_BORROW_6_r23 1314 +#define _LOAD_FAST_BORROW_7_r01 1315 +#define _LOAD_FAST_BORROW_7_r12 1316 +#define _LOAD_FAST_BORROW_7_r23 1317 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r02 1318 +#define _LOAD_FAST_BORROW_LOAD_FAST_BORROW_r13 1319 +#define _LOAD_FAST_CHECK_r01 1320 +#define _LOAD_FAST_CHECK_r12 1321 +#define _LOAD_FAST_CHECK_r23 1322 +#define _LOAD_FAST_LOAD_FAST_r02 1323 +#define _LOAD_FAST_LOAD_FAST_r13 1324 +#define _LOAD_FROM_DICT_OR_DEREF_r11 1325 +#define _LOAD_FROM_DICT_OR_GLOBALS_r11 1326 +#define _LOAD_GLOBAL_r00 1327 +#define _LOAD_GLOBAL_BUILTINS_r01 1328 +#define _LOAD_GLOBAL_MODULE_r01 1329 +#define _LOAD_LOCALS_r01 1330 +#define _LOAD_LOCALS_r12 1331 +#define _LOAD_LOCALS_r23 1332 +#define _LOAD_NAME_r01 1333 +#define _LOAD_SMALL_INT_r01 1334 +#define _LOAD_SMALL_INT_r12 1335 +#define _LOAD_SMALL_INT_r23 1336 +#define _LOAD_SMALL_INT_0_r01 1337 +#define _LOAD_SMALL_INT_0_r12 1338 +#define _LOAD_SMALL_INT_0_r23 1339 +#define _LOAD_SMALL_INT_1_r01 1340 +#define _LOAD_SMALL_INT_1_r12 1341 +#define _LOAD_SMALL_INT_1_r23 1342 +#define _LOAD_SMALL_INT_2_r01 1343 +#define _LOAD_SMALL_INT_2_r12 1344 +#define _LOAD_SMALL_INT_2_r23 1345 +#define _LOAD_SMALL_INT_3_r01 1346 +#define _LOAD_SMALL_INT_3_r12 1347 +#define _LOAD_SMALL_INT_3_r23 1348 +#define _LOAD_SPECIAL_r00 1349 +#define _LOAD_SUPER_ATTR_ATTR_r31 1350 +#define _LOAD_SUPER_ATTR_METHOD_r32 1351 +#define _LOCK_OBJECT_r01 1352 +#define _LOCK_OBJECT_r11 1353 +#define _LOCK_OBJECT_r22 1354 +#define _LOCK_OBJECT_r33 1355 +#define _MAKE_CALLARGS_A_TUPLE_r33 1356 +#define _MAKE_CELL_r00 1357 +#define _MAKE_FUNCTION_r12 1358 +#define _MAKE_HEAP_SAFE_r01 1359 +#define _MAKE_HEAP_SAFE_r11 1360 +#define _MAKE_HEAP_SAFE_r22 1361 +#define _MAKE_HEAP_SAFE_r33 1362 +#define _MAKE_WARM_r00 1363 +#define _MAKE_WARM_r11 1364 +#define _MAKE_WARM_r22 1365 +#define _MAKE_WARM_r33 1366 +#define _MAP_ADD_r20 1367 +#define _MATCH_CLASS_r33 1368 +#define _MATCH_KEYS_r23 1369 +#define _MATCH_MAPPING_r02 1370 +#define _MATCH_MAPPING_r12 1371 +#define _MATCH_MAPPING_r23 1372 +#define _MATCH_SEQUENCE_r02 1373 +#define _MATCH_SEQUENCE_r12 1374 +#define _MATCH_SEQUENCE_r23 1375 +#define _MAYBE_EXPAND_METHOD_r00 1376 +#define _MAYBE_EXPAND_METHOD_KW_r11 1377 +#define _MONITOR_CALL_r00 1378 +#define _MONITOR_CALL_KW_r11 1379 +#define _MONITOR_JUMP_BACKWARD_r00 1380 +#define _MONITOR_JUMP_BACKWARD_r11 1381 +#define _MONITOR_JUMP_BACKWARD_r22 1382 +#define _MONITOR_JUMP_BACKWARD_r33 1383 +#define _MONITOR_RESUME_r00 1384 +#define _NOP_r00 1385 +#define _NOP_r11 1386 +#define _NOP_r22 1387 +#define _NOP_r33 1388 +#define _POP_EXCEPT_r10 1389 +#define _POP_ITER_r20 1390 +#define _POP_JUMP_IF_FALSE_r00 1391 +#define _POP_JUMP_IF_FALSE_r10 1392 +#define _POP_JUMP_IF_FALSE_r21 1393 +#define _POP_JUMP_IF_FALSE_r32 1394 +#define _POP_JUMP_IF_TRUE_r00 1395 +#define _POP_JUMP_IF_TRUE_r10 1396 +#define _POP_JUMP_IF_TRUE_r21 1397 +#define _POP_JUMP_IF_TRUE_r32 1398 +#define _POP_TOP_r10 1399 +#define _POP_TOP_FLOAT_r00 1400 +#define _POP_TOP_FLOAT_r10 1401 +#define _POP_TOP_FLOAT_r21 1402 +#define _POP_TOP_FLOAT_r32 1403 +#define _POP_TOP_INT_r00 1404 +#define _POP_TOP_INT_r10 1405 +#define _POP_TOP_INT_r21 1406 +#define _POP_TOP_INT_r32 1407 +#define _POP_TOP_NOP_r00 1408 +#define _POP_TOP_NOP_r10 1409 +#define _POP_TOP_NOP_r21 1410 +#define _POP_TOP_NOP_r32 1411 +#define _POP_TOP_OPARG_r00 1412 +#define _POP_TOP_UNICODE_r00 1413 +#define _POP_TOP_UNICODE_r10 1414 +#define _POP_TOP_UNICODE_r21 1415 +#define _POP_TOP_UNICODE_r32 1416 +#define _PUSH_EXC_INFO_r02 1417 +#define _PUSH_EXC_INFO_r12 1418 +#define _PUSH_EXC_INFO_r23 1419 +#define _PUSH_FRAME_r10 1420 +#define _PUSH_NULL_r01 1421 +#define _PUSH_NULL_r12 1422 +#define _PUSH_NULL_r23 1423 +#define _PUSH_NULL_CONDITIONAL_r00 1424 +#define _PY_FRAME_EX_r31 1425 +#define _PY_FRAME_GENERAL_r01 1426 +#define _PY_FRAME_KW_r11 1427 +#define _REPLACE_WITH_TRUE_r02 1428 +#define _REPLACE_WITH_TRUE_r12 1429 +#define _REPLACE_WITH_TRUE_r23 1430 +#define _RESUME_CHECK_r00 1431 +#define _RESUME_CHECK_r11 1432 +#define _RESUME_CHECK_r22 1433 +#define _RESUME_CHECK_r33 1434 +#define _RETURN_GENERATOR_r01 1435 +#define _RETURN_VALUE_r11 1436 +#define _SAVE_RETURN_OFFSET_r00 1437 +#define _SAVE_RETURN_OFFSET_r11 1438 +#define _SAVE_RETURN_OFFSET_r22 1439 +#define _SAVE_RETURN_OFFSET_r33 1440 +#define _SEND_r33 1441 +#define _SEND_GEN_FRAME_r33 1442 +#define _SETUP_ANNOTATIONS_r00 1443 +#define _SET_ADD_r10 1444 +#define _SET_FUNCTION_ATTRIBUTE_r01 1445 +#define _SET_FUNCTION_ATTRIBUTE_r11 1446 +#define _SET_FUNCTION_ATTRIBUTE_r21 1447 +#define _SET_FUNCTION_ATTRIBUTE_r32 1448 +#define _SET_IP_r00 1449 +#define _SET_IP_r11 1450 +#define _SET_IP_r22 1451 +#define _SET_IP_r33 1452 +#define _SET_UPDATE_r11 1453 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r03 1454 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r13 1455 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r23 1456 +#define _SHUFFLE_3_LOAD_CONST_INLINE_BORROW_r33 1457 +#define _SPILL_OR_RELOAD_r01 1458 +#define _SPILL_OR_RELOAD_r02 1459 +#define _SPILL_OR_RELOAD_r03 1460 +#define _SPILL_OR_RELOAD_r10 1461 +#define _SPILL_OR_RELOAD_r12 1462 +#define _SPILL_OR_RELOAD_r13 1463 +#define _SPILL_OR_RELOAD_r20 1464 +#define _SPILL_OR_RELOAD_r21 1465 +#define _SPILL_OR_RELOAD_r23 1466 +#define _SPILL_OR_RELOAD_r30 1467 +#define _SPILL_OR_RELOAD_r31 1468 +#define _SPILL_OR_RELOAD_r32 1469 +#define _START_EXECUTOR_r00 1470 +#define _STORE_ATTR_r20 1471 +#define _STORE_ATTR_INSTANCE_VALUE_r21 1472 +#define _STORE_ATTR_SLOT_r21 1473 +#define _STORE_ATTR_WITH_HINT_r21 1474 +#define _STORE_DEREF_r10 1475 +#define _STORE_FAST_LOAD_FAST_r11 1476 +#define _STORE_FAST_STORE_FAST_r20 1477 +#define _STORE_GLOBAL_r10 1478 +#define _STORE_NAME_r10 1479 +#define _STORE_SLICE_r30 1480 +#define _STORE_SUBSCR_r30 1481 +#define _STORE_SUBSCR_DICT_r31 1482 +#define _STORE_SUBSCR_DICT_KNOWN_HASH_r31 1483 +#define _STORE_SUBSCR_LIST_INT_r32 1484 +#define _SWAP_r11 1485 +#define _SWAP_2_r02 1486 +#define _SWAP_2_r12 1487 +#define _SWAP_2_r22 1488 +#define _SWAP_2_r33 1489 +#define _SWAP_3_r03 1490 +#define _SWAP_3_r13 1491 +#define _SWAP_3_r23 1492 +#define _SWAP_3_r33 1493 +#define _SWAP_FAST_r01 1494 +#define _SWAP_FAST_r11 1495 +#define _SWAP_FAST_r22 1496 +#define _SWAP_FAST_r33 1497 +#define _SWAP_FAST_0_r01 1498 +#define _SWAP_FAST_0_r11 1499 +#define _SWAP_FAST_0_r22 1500 +#define _SWAP_FAST_0_r33 1501 +#define _SWAP_FAST_1_r01 1502 +#define _SWAP_FAST_1_r11 1503 +#define _SWAP_FAST_1_r22 1504 +#define _SWAP_FAST_1_r33 1505 +#define _SWAP_FAST_2_r01 1506 +#define _SWAP_FAST_2_r11 1507 +#define _SWAP_FAST_2_r22 1508 +#define _SWAP_FAST_2_r33 1509 +#define _SWAP_FAST_3_r01 1510 +#define _SWAP_FAST_3_r11 1511 +#define _SWAP_FAST_3_r22 1512 +#define _SWAP_FAST_3_r33 1513 +#define _SWAP_FAST_4_r01 1514 +#define _SWAP_FAST_4_r11 1515 +#define _SWAP_FAST_4_r22 1516 +#define _SWAP_FAST_4_r33 1517 +#define _SWAP_FAST_5_r01 1518 +#define _SWAP_FAST_5_r11 1519 +#define _SWAP_FAST_5_r22 1520 +#define _SWAP_FAST_5_r33 1521 +#define _SWAP_FAST_6_r01 1522 +#define _SWAP_FAST_6_r11 1523 +#define _SWAP_FAST_6_r22 1524 +#define _SWAP_FAST_6_r33 1525 +#define _SWAP_FAST_7_r01 1526 +#define _SWAP_FAST_7_r11 1527 +#define _SWAP_FAST_7_r22 1528 +#define _SWAP_FAST_7_r33 1529 +#define _TIER2_RESUME_CHECK_r00 1530 +#define _TIER2_RESUME_CHECK_r11 1531 +#define _TIER2_RESUME_CHECK_r22 1532 +#define _TIER2_RESUME_CHECK_r33 1533 +#define _TO_BOOL_r11 1534 +#define _TO_BOOL_BOOL_r01 1535 +#define _TO_BOOL_BOOL_r11 1536 +#define _TO_BOOL_BOOL_r22 1537 +#define _TO_BOOL_BOOL_r33 1538 +#define _TO_BOOL_INT_r02 1539 +#define _TO_BOOL_INT_r12 1540 +#define _TO_BOOL_INT_r23 1541 +#define _TO_BOOL_LIST_r02 1542 +#define _TO_BOOL_LIST_r12 1543 +#define _TO_BOOL_LIST_r23 1544 +#define _TO_BOOL_NONE_r01 1545 +#define _TO_BOOL_NONE_r11 1546 +#define _TO_BOOL_NONE_r22 1547 +#define _TO_BOOL_NONE_r33 1548 +#define _TO_BOOL_STR_r02 1549 +#define _TO_BOOL_STR_r12 1550 +#define _TO_BOOL_STR_r23 1551 +#define _TRACE_RECORD_r00 1552 +#define _UNARY_INVERT_r12 1553 +#define _UNARY_NEGATIVE_r12 1554 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r02 1555 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r12 1556 +#define _UNARY_NEGATIVE_FLOAT_INPLACE_r23 1557 +#define _UNARY_NOT_r01 1558 +#define _UNARY_NOT_r11 1559 +#define _UNARY_NOT_r22 1560 +#define _UNARY_NOT_r33 1561 +#define _UNPACK_EX_r10 1562 +#define _UNPACK_SEQUENCE_r10 1563 +#define _UNPACK_SEQUENCE_LIST_r10 1564 +#define _UNPACK_SEQUENCE_TUPLE_r10 1565 +#define _UNPACK_SEQUENCE_TWO_TUPLE_r12 1566 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r03 1567 +#define _UNPACK_SEQUENCE_UNIQUE_THREE_TUPLE_r13 1568 +#define _UNPACK_SEQUENCE_UNIQUE_TUPLE_r10 1569 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r02 1570 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r12 1571 +#define _UNPACK_SEQUENCE_UNIQUE_TWO_TUPLE_r23 1572 +#define _WITH_EXCEPT_START_r33 1573 +#define _YIELD_VALUE_r11 1574 +#define MAX_UOP_REGS_ID 1574 #ifdef __cplusplus } diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 6e0e42d2542b..bb3e3b9950c5 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -2112,12 +2112,12 @@ const _PyUopCachingInfo _PyUop_Caching[MAX_UOP_ID+1] = { }, }, [_LOAD_ATTR_PROPERTY_FRAME] = { - .best = { 1, 1, 1, 1 }, + .best = { 0, 1, 2, 3 }, .entries = { - { -1, -1, -1 }, + { 1, 0, _LOAD_ATTR_PROPERTY_FRAME_r01 }, { 1, 1, _LOAD_ATTR_PROPERTY_FRAME_r11 }, - { -1, -1, -1 }, - { -1, -1, -1 }, + { 2, 2, _LOAD_ATTR_PROPERTY_FRAME_r22 }, + { 3, 3, _LOAD_ATTR_PROPERTY_FRAME_r33 }, }, }, [_GUARD_DORV_NO_DICT] = { @@ -4180,7 +4180,10 @@ const uint16_t _PyUop_Uncached[MAX_UOP_REGS_ID+1] = { [_CHECK_ATTR_CLASS_r22] = _CHECK_ATTR_CLASS, [_CHECK_ATTR_CLASS_r33] = _CHECK_ATTR_CLASS, [_LOAD_ATTR_CLASS_r11] = _LOAD_ATTR_CLASS, + [_LOAD_ATTR_PROPERTY_FRAME_r01] = _LOAD_ATTR_PROPERTY_FRAME, [_LOAD_ATTR_PROPERTY_FRAME_r11] = _LOAD_ATTR_PROPERTY_FRAME, + [_LOAD_ATTR_PROPERTY_FRAME_r22] = _LOAD_ATTR_PROPERTY_FRAME, + [_LOAD_ATTR_PROPERTY_FRAME_r33] = _LOAD_ATTR_PROPERTY_FRAME, [_GUARD_DORV_NO_DICT_r01] = _GUARD_DORV_NO_DICT, [_GUARD_DORV_NO_DICT_r11] = _GUARD_DORV_NO_DICT, [_GUARD_DORV_NO_DICT_r22] = _GUARD_DORV_NO_DICT, @@ -5425,7 +5428,10 @@ const char *const _PyOpcode_uop_name[MAX_UOP_REGS_ID+1] = { [_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES] = "_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES", [_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11] = "_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES_r11", [_LOAD_ATTR_PROPERTY_FRAME] = "_LOAD_ATTR_PROPERTY_FRAME", + [_LOAD_ATTR_PROPERTY_FRAME_r01] = "_LOAD_ATTR_PROPERTY_FRAME_r01", [_LOAD_ATTR_PROPERTY_FRAME_r11] = "_LOAD_ATTR_PROPERTY_FRAME_r11", + [_LOAD_ATTR_PROPERTY_FRAME_r22] = "_LOAD_ATTR_PROPERTY_FRAME_r22", + [_LOAD_ATTR_PROPERTY_FRAME_r33] = "_LOAD_ATTR_PROPERTY_FRAME_r33", [_LOAD_ATTR_SLOT] = "_LOAD_ATTR_SLOT", [_LOAD_ATTR_SLOT_r02] = "_LOAD_ATTR_SLOT_r02", [_LOAD_ATTR_SLOT_r12] = "_LOAD_ATTR_SLOT_r12", diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 0b112afb8181..f9cd37c4e1c8 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -4896,6 +4896,38 @@ class TestUopsOptimization(unittest.TestCase): # This is a sign the optimizer ran and didn't hit contradiction. self.assertIn("_LOAD_CONST_INLINE_BORROW", uops) + def test_load_attr_property_frame_invalidates_on_code_change(self): + class C: + @property + def val(self): + return int(1) + + fget = C.val.fget + + def testfunc(*args): + n, c = args[0] + total = 0 + for _ in range(n): + total += c.val + return total + + testfunc((3, C())) + res, ex = self._run_with_optimizer(testfunc, (TIER2_THRESHOLD, C())) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_LOAD_ATTR_PROPERTY_FRAME", uops) + # Check the optimizer traced through the property call. + self.assertNotIn("_LOAD_GLOBAL_BUILTINS", uops) + self.assertIn("_CALL_BUILTIN_CLASS", uops) + + fget.__code__ = (lambda self: 2).__code__ + _testinternalcapi.clear_executor_deletion_list() + ex = get_first_executor(testfunc) + self.assertIsNone(ex) + res = testfunc((TIER2_THRESHOLD, C())) + self.assertEqual(res, TIER2_THRESHOLD * 2) + def test_unary_negative(self): def testfunc(n): a = 3 diff --git a/Modules/_testinternalcapi/test_cases.c.h b/Modules/_testinternalcapi/test_cases.c.h index 8bf751026bd3..afbc88381d65 100644 --- a/Modules/_testinternalcapi/test_cases.c.h +++ b/Modules/_testinternalcapi/test_cases.c.h @@ -8840,29 +8840,19 @@ JUMP_TO_PREDICTED(LOAD_ATTR); } } - /* Skip 2 cache entries */ // _LOAD_ATTR_PROPERTY_FRAME { + uint32_t func_version = read_u32(&this_instr[4].cache); PyObject *fget = read_obj(&this_instr[6].cache); assert((oparg & 1) == 0); assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; - PyCodeObject *code = (PyCodeObject *)f->func_code; - if ((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } - if (code->co_kwonlyargcount) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } - if (code->co_argcount != 1) { + if (f->func_version != func_version) { UPDATE_MISS_STATS(LOAD_ATTR); assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); JUMP_TO_PREDICTED(LOAD_ATTR); } + PyCodeObject *code = (PyCodeObject *)f->func_code; if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { UPDATE_MISS_STATS(LOAD_ATTR); assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 57731fc65ed3..1ae6610774e2 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -2919,14 +2919,12 @@ dummy_func( _LOAD_ATTR_CLASS + _PUSH_NULL_CONDITIONAL; - op(_LOAD_ATTR_PROPERTY_FRAME, (fget/4, owner -- new_frame)) { + op(_LOAD_ATTR_PROPERTY_FRAME, (func_version/2, fget/4, owner -- new_frame)) { assert((oparg & 1) == 0); assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; + EXIT_IF(f->func_version != func_version); PyCodeObject *code = (PyCodeObject *)f->func_code; - EXIT_IF((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED); - EXIT_IF(code->co_kwonlyargcount); - EXIT_IF(code->co_argcount != 1); EXIT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize)); STAT_INC(LOAD_ATTR, hit); _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame); @@ -2940,7 +2938,6 @@ dummy_func( _RECORD_TOS_TYPE + _GUARD_TYPE_VERSION + _CHECK_PEP_523 + - unused/2 + _LOAD_ATTR_PROPERTY_FRAME + _SAVE_RETURN_OFFSET + _PUSH_FRAME; diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index d54afe34f202..3614839499b7 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -11450,6 +11450,41 @@ break; } + case _LOAD_ATTR_PROPERTY_FRAME_r01: { + CHECK_CURRENT_CACHED_VALUES(0); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + _PyStackRef new_frame; + oparg = CURRENT_OPARG(); + owner = stack_pointer[-1]; + uint32_t func_version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *fget = (PyObject *)CURRENT_OPERAND1_64(); + assert((oparg & 1) == 0); + assert(Py_IS_TYPE(fget, &PyFunction_Type)); + PyFunctionObject *f = (PyFunctionObject *)fget; + if (f->func_version != func_version) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + PyCodeObject *code = (PyCodeObject *)f->func_code; + if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { + UOP_STAT_INC(uopcode, miss); + SET_CURRENT_CACHED_VALUES(0); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(LOAD_ATTR, hit); + _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame); + pushed_frame->localsplus[0] = owner; + new_frame = PyStackRef_Wrap(pushed_frame); + _tos_cache0 = new_frame; + SET_CURRENT_CACHED_VALUES(1); + stack_pointer += -1; + ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + case _LOAD_ATTR_PROPERTY_FRAME_r11: { CHECK_CURRENT_CACHED_VALUES(1); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); @@ -11458,43 +11493,114 @@ _PyStackRef _stack_item_0 = _tos_cache0; oparg = CURRENT_OPARG(); owner = _stack_item_0; - PyObject *fget = (PyObject *)CURRENT_OPERAND0_64(); + uint32_t func_version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *fget = (PyObject *)CURRENT_OPERAND1_64(); assert((oparg & 1) == 0); assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; - PyCodeObject *code = (PyCodeObject *)f->func_code; - if ((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED) { + if (f->func_version != func_version) { UOP_STAT_INC(uopcode, miss); _tos_cache0 = owner; SET_CURRENT_CACHED_VALUES(1); JUMP_TO_JUMP_TARGET(); } - if (code->co_kwonlyargcount) { + PyCodeObject *code = (PyCodeObject *)f->func_code; + if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { UOP_STAT_INC(uopcode, miss); _tos_cache0 = owner; SET_CURRENT_CACHED_VALUES(1); JUMP_TO_JUMP_TARGET(); } - if (code->co_argcount != 1) { + STAT_INC(LOAD_ATTR, hit); + _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame); + pushed_frame->localsplus[0] = owner; + new_frame = PyStackRef_Wrap(pushed_frame); + _tos_cache0 = new_frame; + SET_CURRENT_CACHED_VALUES(1); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _LOAD_ATTR_PROPERTY_FRAME_r22: { + CHECK_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + _PyStackRef new_frame; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + oparg = CURRENT_OPARG(); + owner = _stack_item_1; + uint32_t func_version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *fget = (PyObject *)CURRENT_OPERAND1_64(); + assert((oparg & 1) == 0); + assert(Py_IS_TYPE(fget, &PyFunction_Type)); + PyFunctionObject *f = (PyFunctionObject *)fget; + if (f->func_version != func_version) { UOP_STAT_INC(uopcode, miss); - _tos_cache0 = owner; - SET_CURRENT_CACHED_VALUES(1); + _tos_cache1 = owner; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); JUMP_TO_JUMP_TARGET(); } + PyCodeObject *code = (PyCodeObject *)f->func_code; if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { UOP_STAT_INC(uopcode, miss); - _tos_cache0 = owner; - SET_CURRENT_CACHED_VALUES(1); + _tos_cache1 = owner; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); JUMP_TO_JUMP_TARGET(); } STAT_INC(LOAD_ATTR, hit); _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame); pushed_frame->localsplus[0] = owner; new_frame = PyStackRef_Wrap(pushed_frame); - _tos_cache0 = new_frame; - _tos_cache1 = PyStackRef_ZERO_BITS; - _tos_cache2 = PyStackRef_ZERO_BITS; - SET_CURRENT_CACHED_VALUES(1); + _tos_cache1 = new_frame; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(2); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + break; + } + + case _LOAD_ATTR_PROPERTY_FRAME_r33: { + CHECK_CURRENT_CACHED_VALUES(3); + assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); + _PyStackRef owner; + _PyStackRef new_frame; + _PyStackRef _stack_item_0 = _tos_cache0; + _PyStackRef _stack_item_1 = _tos_cache1; + _PyStackRef _stack_item_2 = _tos_cache2; + oparg = CURRENT_OPARG(); + owner = _stack_item_2; + uint32_t func_version = (uint32_t)CURRENT_OPERAND0_32(); + PyObject *fget = (PyObject *)CURRENT_OPERAND1_64(); + assert((oparg & 1) == 0); + assert(Py_IS_TYPE(fget, &PyFunction_Type)); + PyFunctionObject *f = (PyFunctionObject *)fget; + if (f->func_version != func_version) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = owner; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + PyCodeObject *code = (PyCodeObject *)f->func_code; + if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { + UOP_STAT_INC(uopcode, miss); + _tos_cache2 = owner; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); + JUMP_TO_JUMP_TARGET(); + } + STAT_INC(LOAD_ATTR, hit); + _PyInterpreterFrame *pushed_frame = _PyFrame_PushUnchecked(tstate, PyStackRef_FromPyObjectNew(fget), 1, frame); + pushed_frame->localsplus[0] = owner; + new_frame = PyStackRef_Wrap(pushed_frame); + _tos_cache2 = new_frame; + _tos_cache1 = _stack_item_1; + _tos_cache0 = _stack_item_0; + SET_CURRENT_CACHED_VALUES(3); assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE()); break; } diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index d710e82a306a..cd5131c0f1b6 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -8839,29 +8839,19 @@ JUMP_TO_PREDICTED(LOAD_ATTR); } } - /* Skip 2 cache entries */ // _LOAD_ATTR_PROPERTY_FRAME { + uint32_t func_version = read_u32(&this_instr[4].cache); PyObject *fget = read_obj(&this_instr[6].cache); assert((oparg & 1) == 0); assert(Py_IS_TYPE(fget, &PyFunction_Type)); PyFunctionObject *f = (PyFunctionObject *)fget; - PyCodeObject *code = (PyCodeObject *)f->func_code; - if ((code->co_flags & (CO_VARKEYWORDS | CO_VARARGS | CO_OPTIMIZED)) != CO_OPTIMIZED) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } - if (code->co_kwonlyargcount) { - UPDATE_MISS_STATS(LOAD_ATTR); - assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); - JUMP_TO_PREDICTED(LOAD_ATTR); - } - if (code->co_argcount != 1) { + if (f->func_version != func_version) { UPDATE_MISS_STATS(LOAD_ATTR); assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); JUMP_TO_PREDICTED(LOAD_ATTR); } + PyCodeObject *code = (PyCodeObject *)f->func_code; if (!_PyThreadState_HasStackSpace(tstate, code->co_framesize)) { UPDATE_MISS_STATS(LOAD_ATTR); assert(_PyOpcode_Deopt[opcode] == (LOAD_ATTR)); diff --git a/Python/optimizer_analysis.c b/Python/optimizer_analysis.c index 6b48f89510ef..095bcfc639bc 100644 --- a/Python/optimizer_analysis.c +++ b/Python/optimizer_analysis.c @@ -257,6 +257,7 @@ add_op(JitOptContext *ctx, _PyUOpInstruction *this_instr, #define sym_get_probable_type _Py_uop_sym_get_probable_type #define sym_matches_type _Py_uop_sym_matches_type #define sym_matches_type_version _Py_uop_sym_matches_type_version +#define sym_get_type_version _Py_uop_sym_get_type_version #define sym_set_null(SYM) _Py_uop_sym_set_null(ctx, SYM) #define sym_set_non_null(SYM) _Py_uop_sym_set_non_null(ctx, SYM) #define sym_set_type(SYM, TYPE) _Py_uop_sym_set_type(ctx, SYM, TYPE) diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 3332a9627c15..d50e32e590bd 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -20,6 +20,7 @@ typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame; #define sym_new_null _Py_uop_sym_new_null #define sym_matches_type _Py_uop_sym_matches_type #define sym_matches_type_version _Py_uop_sym_matches_type_version +#define sym_get_type_version _Py_uop_sym_get_type_version #define sym_get_type _Py_uop_sym_get_type #define sym_has_type _Py_uop_sym_has_type #define sym_set_null(SYM) _Py_uop_sym_set_null(ctx, SYM) @@ -138,15 +139,24 @@ dummy_func(void) { assert(type_version); if (sym_matches_type_version(owner, type_version)) { ADD_OP(_NOP, 0, 0); - } else { + } + else { PyTypeObject *probable_type = sym_get_probable_type(owner); - if (probable_type->tp_version_tag == type_version && sym_set_type_version(owner, type_version)) { + if (probable_type != NULL && + probable_type->tp_version_tag == type_version) { // Promote the probable type version to a known one. + sym_set_type(owner, probable_type); + sym_set_type_version(owner, type_version); if ((probable_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type); _Py_BloomFilter_Add(dependencies, probable_type); } } + else { + ctx->contradiction = true; + ctx->done = true; + break; + } } } @@ -239,20 +249,20 @@ dummy_func(void) { assert(this_instr[-1].opcode == _RECORD_TOS_TYPE); if (sym_matches_type_version(owner, type_version)) { ADD_OP(_NOP, 0, 0); - } else { - // add watcher so that whenever the type changes we invalidate this - PyTypeObject *type = _PyType_LookupByVersion(type_version); - // if the type is null, it was not found in the cache (there was a conflict) - // with the key, in which case we can't trust the version - if (type) { - // if the type version was set properly, then add a watcher - // if it wasn't this means that the type version was previously set to something else - // and we set the owner to bottom, so we don't need to add a watcher because we must have - // already added one earlier. - if (sym_set_type_version(owner, type_version)) { - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); - _Py_BloomFilter_Add(dependencies, type); - } + } + else { + PyTypeObject *probable_type = sym_get_probable_type(owner); + if (probable_type != NULL && + probable_type->tp_version_tag == type_version) { + sym_set_type(owner, probable_type); + sym_set_type_version(owner, type_version); + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type); + _Py_BloomFilter_Add(dependencies, probable_type); + } + else { + ctx->contradiction = true; + ctx->done = true; + break; } } } @@ -983,15 +993,22 @@ dummy_func(void) { _LOAD_CONST_INLINE, _SWAP); } - op(_LOAD_ATTR_PROPERTY_FRAME, (fget/4, owner -- new_frame)) { - // + 1 for _SAVE_RETURN_OFFSET - // FIX ME -- This needs a version check and function watcher - PyCodeObject *co = (PyCodeObject *)((PyFunctionObject *)fget)->func_code; + op(_LOAD_ATTR_PROPERTY_FRAME, (func_version/2, fget/4, owner -- new_frame)) { + PyFunctionObject *func = (PyFunctionObject *)fget; + if (sym_get_type_version(owner) == 0 || + func->func_version != func_version) { + ctx->contradiction = true; + ctx->done = true; + break; + } + _Py_BloomFilter_Add(dependencies, fget); + PyCodeObject *co = (PyCodeObject *)func->func_code; _Py_UOpsAbstractFrame *f = frame_new(ctx, co, NULL, 0); if (f == NULL) { break; } f->locals[0] = owner; + f->func = func; new_frame = PyJitRef_WrapInvalid(f); } diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 2547c959ed50..fcea042a585e 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -2429,13 +2429,20 @@ assert(this_instr[-1].opcode == _RECORD_TOS_TYPE); if (sym_matches_type_version(owner, type_version)) { ADD_OP(_NOP, 0, 0); - } else { - PyTypeObject *type = _PyType_LookupByVersion(type_version); - if (type) { - if (sym_set_type_version(owner, type_version)) { - PyType_Watch(TYPE_WATCHER_ID, (PyObject *)type); - _Py_BloomFilter_Add(dependencies, type); - } + } + else { + PyTypeObject *probable_type = sym_get_probable_type(owner); + if (probable_type != NULL && + probable_type->tp_version_tag == type_version) { + sym_set_type(owner, probable_type); + sym_set_type_version(owner, type_version); + PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type); + _Py_BloomFilter_Add(dependencies, probable_type); + } + else { + ctx->contradiction = true; + ctx->done = true; + break; } } break; @@ -2448,14 +2455,23 @@ assert(type_version); if (sym_matches_type_version(owner, type_version)) { ADD_OP(_NOP, 0, 0); - } else { + } + else { PyTypeObject *probable_type = sym_get_probable_type(owner); - if (probable_type->tp_version_tag == type_version && sym_set_type_version(owner, type_version)) { + if (probable_type != NULL && + probable_type->tp_version_tag == type_version) { + sym_set_type(owner, probable_type); + sym_set_type_version(owner, type_version); if ((probable_type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE) == 0) { PyType_Watch(TYPE_WATCHER_ID, (PyObject *)probable_type); _Py_BloomFilter_Add(dependencies, probable_type); } } + else { + ctx->contradiction = true; + ctx->done = true; + break; + } } break; } @@ -2598,13 +2614,23 @@ JitOptRef owner; JitOptRef new_frame; owner = stack_pointer[-1]; - PyObject *fget = (PyObject *)this_instr->operand0; - PyCodeObject *co = (PyCodeObject *)((PyFunctionObject *)fget)->func_code; + uint32_t func_version = (uint32_t)this_instr->operand0; + PyObject *fget = (PyObject *)this_instr->operand1; + PyFunctionObject *func = (PyFunctionObject *)fget; + if (sym_get_type_version(owner) == 0 || + func->func_version != func_version) { + ctx->contradiction = true; + ctx->done = true; + break; + } + _Py_BloomFilter_Add(dependencies, fget); + PyCodeObject *co = (PyCodeObject *)func->func_code; _Py_UOpsAbstractFrame *f = frame_new(ctx, co, NULL, 0); if (f == NULL) { break; } f->locals[0] = owner; + f->func = func; new_frame = PyJitRef_WrapInvalid(f); stack_pointer[-1] = new_frame; break; diff --git a/Python/specialize.c b/Python/specialize.c index bfa7b8148e46..e42e1a8faa8a 100644 --- a/Python/specialize.c +++ b/Python/specialize.c @@ -846,8 +846,13 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* return -1; } #endif + uint32_t func_version = function_get_version(fget, LOAD_ATTR); + if (func_version == 0) { + return -1; + } assert(tp_version != 0); write_u32(lm_cache->type_version, tp_version); + write_u32(lm_cache->keys_version, func_version); /* borrowed */ write_ptr(lm_cache->descr, fget); specialize(instr, LOAD_ATTR_PROPERTY);