@@ -1385,20 +1385,17 @@ class Foo:
13851385 guard_type_version_count = opnames .count ("_GUARD_TYPE_VERSION" )
13861386 self .assertEqual (guard_type_version_count , 1 )
13871387
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 ):
13921389
13931390 def thing (a ):
13941391 x = 0
1395- for i in range (TIER2_THRESHOLD + 100 ):
1392+ for i in range (TIER2_THRESHOLD * 2 + 1 ):
13961393 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 )
14021399 x += a .attr
14031400 return x
14041401
@@ -1410,24 +1407,21 @@ class Bar:
14101407
14111408 res , ex = self ._run_with_optimizer (thing , Foo ())
14121409 opnames = list (iter_opnames (ex ))
1413-
14141410 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 )
14181417
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 ):
14251419
14261420 def thing (a ):
14271421 x = 0
1428- for i in range (100 ):
1422+ for i in range (TIER2_THRESHOLD ):
14291423 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
14311425 eval ("None" )
14321426 x += a .attr
14331427 return x
@@ -1437,12 +1431,12 @@ class Foo:
14371431 res , ex = self ._run_with_optimizer (thing , Foo ())
14381432 opnames = list (iter_opnames (ex ))
14391433 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 )
14461440
14471441 def test_guard_type_version_executor_invalidated (self ):
14481442 """
0 commit comments