@@ -60,6 +60,13 @@ def iter_opnames(ex):
6060def get_opnames (ex ):
6161 return list (iter_opnames (ex ))
6262
63+ def iter_ops (ex ):
64+ for item in ex :
65+ yield item
66+
67+ def get_ops (ex ):
68+ return list (iter_ops (ex ))
69+
6370
6471@requires_specialization
6572@unittest .skipIf (Py_GIL_DISABLED , "optimizer not yet supported in free-threaded builds" )
@@ -3003,14 +3010,25 @@ def f():
30033010 # Outer loop warms up later, linking to the inner one.
30043011 # Therefore, we have at least two executors.
30053012 self .assertGreaterEqual (len (all_executors ), 2 )
3013+ executor_ids = [id (e ) for e in all_executors ]
30063014 for executor in all_executors :
3007- opnames = list ( get_opnames ( executor ) )
3015+ ops = get_ops ( executor )
30083016 # Assert all executors first terminator ends in
30093017 # _EXIT_TRACE or _JUMP_TO_TOP, not _DEOPT
3010- for idx , op in enumerate (opnames ):
3011- if op == "_EXIT_TRACE" or op == "_JUMP_TO_TOP" :
3018+ for idx , op in enumerate (ops ):
3019+ opname = op [0 ]
3020+ if opname == "_EXIT_TRACE" :
3021+ # As this is a link outer executor to inner
3022+ # executor problem, all executors exits should point to
3023+ # another valid executor. In this case, none of them
3024+ # should be the cold executor.
3025+ exit = op [3 ]
3026+ link_to = _testinternalcapi .get_exit_executor (exit )
3027+ self .assertIn (id (link_to ), executor_ids )
3028+ break
3029+ elif opname == "_JUMP_TO_TOP" :
30123030 break
3013- elif op == "_DEOPT" :
3031+ elif opname == "_DEOPT" :
30143032 self .fail (f"_DEOPT encountered first at executor"
30153033 f" { executor } at offset { idx } rather"
30163034 f" than expected _EXIT_TRACE" )
0 commit comments