@@ -1168,22 +1168,6 @@ def testfunc(n):
11681168 self .assertIsNotNone (ex )
11691169 self .assertIn ("_FOR_ITER_TIER_TWO" , get_opnames (ex ))
11701170
1171- @unittest .skip ("Tracing into generators currently isn't supported." )
1172- def test_for_iter_gen (self ):
1173- def gen (n ):
1174- for i in range (n ):
1175- yield i
1176- def testfunc (n ):
1177- g = gen (n )
1178- s = 0
1179- for i in g :
1180- s += i
1181- return s
1182- res , ex = self ._run_with_optimizer (testfunc , TIER2_THRESHOLD )
1183- self .assertEqual (res , sum (range (TIER2_THRESHOLD )))
1184- self .assertIsNotNone (ex )
1185- self .assertIn ("_FOR_ITER_GEN_FRAME" , get_opnames (ex ))
1186-
11871171 def test_modified_local_is_seen_by_optimized_code (self ):
11881172 l = sys ._getframe ().f_locals
11891173 a = 1
@@ -3404,6 +3388,47 @@ def test_is_none(n):
34043388 self .assertIn ("_POP_TOP_NOP" , uops )
34053389 self .assertLessEqual (count_ops (ex , "_POP_TOP" ), 2 )
34063390
3391+ def test_for_iter_gen_frame (self ):
3392+ def f (n ):
3393+ for i in range (n ):
3394+ # Should be optimized to POP_TOP_NOP
3395+ yield i + i
3396+ def testfunc (n ):
3397+ for _ in f (n ):
3398+ pass
3399+
3400+ res , ex = self ._run_with_optimizer (testfunc , TIER2_THRESHOLD * 2 )
3401+ self .assertIsNotNone (ex )
3402+ uops = get_opnames (ex )
3403+
3404+ self .assertIn ("_FOR_ITER_GEN_FRAME" , uops )
3405+ # _POP_TOP_NOP is a sign the optimizer ran and didn't hit bottom.
3406+ self .assertGreaterEqual (count_ops (ex , "_POP_TOP_NOP" ), 1 )
3407+
3408+ def test_send_gen_frame (self ):
3409+
3410+ def gen (n ):
3411+ for i in range (n ):
3412+ yield i + i
3413+ def send_gen (n ):
3414+ yield from gen (n )
3415+ def testfunc (n ):
3416+ for _ in send_gen (n ):
3417+ pass
3418+
3419+ for _ in range (_testinternalcapi .SPECIALIZATION_THRESHOLD ):
3420+ # Ensure SEND is specialized to SEND_GEN
3421+ send_gen (10 )
3422+
3423+ res , ex = self ._run_with_optimizer (testfunc , TIER2_THRESHOLD * 2 )
3424+ self .assertIsNotNone (ex )
3425+ uops = get_opnames (ex )
3426+
3427+ self .assertIn ("_FOR_ITER_GEN_FRAME" , uops )
3428+ self .assertIn ("_SEND_GEN_FRAME" , uops )
3429+ # _POP_TOP_NOP is a sign the optimizer ran and didn't hit bottom.
3430+ self .assertGreaterEqual (count_ops (ex , "_POP_TOP_NOP" ), 1 )
3431+
34073432 def test_143026 (self ):
34083433 # https://github.com/python/cpython/issues/143026
34093434
0 commit comments