@@ -1385,20 +1385,17 @@ class Foo:
1385
1385
guard_type_version_count = opnames .count ("_GUARD_TYPE_VERSION" )
1386
1386
self .assertEqual (guard_type_version_count , 1 )
1387
1387
1388
- def test_guard_type_version_not_removed (self ):
1389
- """
1390
- Verify that the guard type version is not removed if we modify the class
1391
- """
1388
+ def test_guard_type_version_removed_invalidation (self ):
1392
1389
1393
1390
def thing (a ):
1394
1391
x = 0
1395
- for i in range (TIER2_THRESHOLD + 100 ):
1392
+ for i in range (TIER2_THRESHOLD * 2 + 1 ):
1396
1393
x += a .attr
1397
- # for the first ( TIER2_THRESHOLD + 90) iterations we set the attribute on this dummy function which shouldn't
1398
- # trigger the type watcher
1399
- # then after for the next 10 it should trigger it and stop optimizing
1400
- # Note that the code needs to be in this weird form so it's optimized inline without any control flow
1401
- setattr ((Foo , Bar )[i < TIER2_THRESHOLD + 90 ], "attr" , 2 )
1394
+ # The first TIER2_THRESHOLD iterations we set the attribute on
1395
+ # this dummy class, which shouldn't trigger the type watcher.
1396
+ # Note that the code needs to be in this weird form so it's
1397
+ # optimized inline without any control flow:
1398
+ setattr ((Bar , Foo )[i == TIER2_THRESHOLD + 1 ], "attr" , 2 )
1402
1399
x += a .attr
1403
1400
return x
1404
1401
@@ -1410,24 +1407,21 @@ class Bar:
1410
1407
1411
1408
res , ex = self ._run_with_optimizer (thing , Foo ())
1412
1409
opnames = list (iter_opnames (ex ))
1413
-
1414
1410
self .assertIsNotNone (ex )
1415
- self .assertEqual (res , (TIER2_THRESHOLD * 2 ) + 219 )
1416
- guard_type_version_count = opnames .count ("_GUARD_TYPE_VERSION" )
1417
- self .assertEqual (guard_type_version_count , 2 )
1411
+ self .assertEqual (res , TIER2_THRESHOLD * 6 + 1 )
1412
+ call = opnames .index ("_CALL_BUILTIN_FAST" )
1413
+ load_attr_top = opnames .index ("_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES" , 0 , call )
1414
+ load_attr_bottom = opnames .index ("_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES" , call )
1415
+ self .assertEqual (opnames [:load_attr_top ].count ("_GUARD_TYPE_VERSION" ), 1 )
1416
+ self .assertEqual (opnames [call :load_attr_bottom ].count ("_CHECK_VALIDITY" ), 1 )
1418
1417
1419
-
1420
- @unittest .expectedFailure
1421
- def test_guard_type_version_not_removed_escaping (self ):
1422
- """
1423
- Verify that the guard type version is not removed if have an escaping function
1424
- """
1418
+ def test_guard_type_version_removed_escaping (self ):
1425
1419
1426
1420
def thing (a ):
1427
1421
x = 0
1428
- for i in range (100 ):
1422
+ for i in range (TIER2_THRESHOLD ):
1429
1423
x += a .attr
1430
- # eval should be escaping and so should cause optimization to stop and preserve both type versions
1424
+ # eval should be escaping
1431
1425
eval ("None" )
1432
1426
x += a .attr
1433
1427
return x
@@ -1437,12 +1431,12 @@ class Foo:
1437
1431
res , ex = self ._run_with_optimizer (thing , Foo ())
1438
1432
opnames = list (iter_opnames (ex ))
1439
1433
self .assertIsNotNone (ex )
1440
- self .assertEqual (res , 200 )
1441
- guard_type_version_count = opnames .count ( "_GUARD_TYPE_VERSION " )
1442
- # Note: This will actually be 1 for noe
1443
- # https://github.com/python/cpython/pull/119365#discussion_r1626220129
1444
- self .assertEqual (guard_type_version_count , 2 )
1445
-
1434
+ self .assertEqual (res , TIER2_THRESHOLD * 2 )
1435
+ call = opnames .index ( "_CALL_BUILTIN_FAST_WITH_KEYWORDS " )
1436
+ load_attr_top = opnames . index ( "_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES" , 0 , call )
1437
+ load_attr_bottom = opnames . index ( "_LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES" , call )
1438
+ self .assertEqual (opnames [: load_attr_top ]. count ( "_GUARD_TYPE_VERSION" ), 1 )
1439
+ self . assertEqual ( opnames [ call : load_attr_bottom ]. count ( "_CHECK_VALIDITY" ), 1 )
1446
1440
1447
1441
def test_guard_type_version_executor_invalidated (self ):
1448
1442
"""
0 commit comments