]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-148510: restore `func_version` check in `_LOAD_ATTR_PROPERTY_FRAME` (GH-148528)
authorNeko Asakura <neko.asakura@outlook.com>
Tue, 14 Apr 2026 14:44:39 +0000 (10:44 -0400)
committerGitHub <noreply@github.com>
Tue, 14 Apr 2026 14:44:39 +0000 (22:44 +0800)
13 files changed:
Include/internal/pycore_opcode_metadata.h
Include/internal/pycore_optimizer.h
Include/internal/pycore_uop_ids.h
Include/internal/pycore_uop_metadata.h
Lib/test/test_capi/test_opt.py
Modules/_testinternalcapi/test_cases.c.h
Python/bytecodes.c
Python/executor_cases.c.h
Python/generated_cases.c.h
Python/optimizer_analysis.c
Python/optimizer_bytecodes.c
Python/optimizer_cases.c.h
Python/specialize.c

index aa7b44d9e7f16b275bde55970e00b5fef6ce3aad..ce07b71192bf3b22e74a9807801e89c585456b90 100644 (file)
@@ -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 } } },
index 78bbdc2026e9d2d71293ce282672683b17bc1136..a809a7e25526f63c9b4e8ff198edbf81de745740 100644 (file)
@@ -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);
index 390bfa27c100c3f7b63e5d0a41867905a24c962f..105878aef3ae9b3dd8db6d12e69d477dd247de16 100644 (file)
@@ -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
 }
index 6e0e42d2542b8a1e73ac2ae5c41f90c10bd650be..bb3e3b9950c577f26e98d0d6263eb0afb2ec903a 100644 (file)
@@ -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",
index 0b112afb8181b129cb6023dd97b878cec0f88f73..f9cd37c4e1c86b2f83b1c4ae0b17db67dd492ede 100644 (file)
@@ -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
index 8bf751026bd35c7d6d98ce1b2ba9be7d207cc965..afbc88381d65b48232529b9a982945fe07c3cb38 100644 (file)
                     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));
index 57731fc65ed35c3bcd4eb37b0b185f4d73b5116d..1ae6610774e2745216e6f1bc34e40c5ea3811829 100644 (file)
@@ -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;
index d54afe34f202b2f7a52f9d957389093747ab3c80..3614839499b7abd2b350884be50df19f7e8587cb 100644 (file)
             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());
             _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;
         }
index d710e82a306ab440902ec196e1034121fbe77ad5..cd5131c0f1b68cc87802cb2ce4b36691ee40cda0 100644 (file)
                     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));
index 6b48f89510ef2879169c1a7e986a5290806db69d..095bcfc639bc658010f32ee8041db82ef5623535 100644 (file)
@@ -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)
index 3332a9627c1523c3b48fbb9c738d1138c6ca4192..d50e32e590bdb9ef71795cecb9bbcca9d422e6f0 100644 (file)
@@ -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);
     }
 
index 2547c959ed50ae447f8fdc10f622020dc97bf20e..fcea042a585e8018a0b0bd9d097d18d4043067de 100644 (file)
             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;
             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;
         }
             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;
index bfa7b8148e46de35b919809a5ef0bbe0038148be..e42e1a8faa8a238ef942213f05f05671a854f49f 100644 (file)
@@ -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);