@@ -34,91 +34,6 @@ def clear_executors(func):
34
34
func .__code__ = func .__code__ .replace ()
35
35
36
36
37
- @requires_specialization
38
- @unittest .skipIf (Py_GIL_DISABLED , "optimizer not yet supported in free-threaded builds" )
39
- @unittest .skipUnless (hasattr (_testinternalcapi , "get_optimizer" ) and
40
- hasattr (_testinternalcapi , "new_counter_optimizer" ),
41
- "Requires optimizer infrastructure" )
42
- class TestOptimizerAPI (unittest .TestCase ):
43
-
44
- def test_new_counter_optimizer_dealloc (self ):
45
- # See gh-108727
46
- def f ():
47
- _testinternalcapi .new_counter_optimizer ()
48
-
49
- f ()
50
-
51
- def test_get_set_optimizer (self ):
52
- old = _testinternalcapi .get_optimizer ()
53
- opt = _testinternalcapi .new_counter_optimizer ()
54
- try :
55
- _testinternalcapi .set_optimizer (opt )
56
- self .assertEqual (_testinternalcapi .get_optimizer (), opt )
57
- _testinternalcapi .set_optimizer (None )
58
- self .assertEqual (_testinternalcapi .get_optimizer (), None )
59
- finally :
60
- _testinternalcapi .set_optimizer (old )
61
-
62
-
63
- def test_counter_optimizer (self ):
64
- # Generate a new function at each call
65
- ns = {}
66
- exec (textwrap .dedent (f"""
67
- def loop():
68
- for _ in range({ TIER2_THRESHOLD + 1000 } ):
69
- pass
70
- """ ), ns , ns )
71
- loop = ns ['loop' ]
72
-
73
- for repeat in range (5 ):
74
- opt = _testinternalcapi .new_counter_optimizer ()
75
- with temporary_optimizer (opt ):
76
- self .assertEqual (opt .get_count (), 0 )
77
- with clear_executors (loop ):
78
- loop ()
79
- self .assertEqual (opt .get_count (), 1001 )
80
-
81
- def test_long_loop (self ):
82
- "Check that we aren't confused by EXTENDED_ARG"
83
-
84
- # Generate a new function at each call
85
- ns = {}
86
- exec (textwrap .dedent (f"""
87
- def nop():
88
- pass
89
-
90
- def long_loop():
91
- for _ in range({ TIER2_THRESHOLD + 20 } ):
92
- nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();
93
- nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();
94
- nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();
95
- nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();
96
- nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();
97
- nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();
98
- nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();
99
- """ ), ns , ns )
100
- long_loop = ns ['long_loop' ]
101
-
102
- opt = _testinternalcapi .new_counter_optimizer ()
103
- with temporary_optimizer (opt ):
104
- self .assertEqual (opt .get_count (), 0 )
105
- long_loop ()
106
- self .assertEqual (opt .get_count (), 21 ) # Need iterations to warm up
107
-
108
- def test_code_restore_for_ENTER_EXECUTOR (self ):
109
- def testfunc (x ):
110
- i = 0
111
- while i < x :
112
- i += 1
113
-
114
- opt = _testinternalcapi .new_counter_optimizer ()
115
- with temporary_optimizer (opt ):
116
- testfunc (1000 )
117
- code , replace_code = testfunc .__code__ , testfunc .__code__ .replace ()
118
- self .assertEqual (code , replace_code )
119
- self .assertEqual (hash (code ), hash (replace_code ))
120
-
121
-
122
37
def get_first_executor (func ):
123
38
code = func .__code__
124
39
co_code = code .co_code
@@ -139,89 +54,6 @@ def get_opnames(ex):
139
54
return list (iter_opnames (ex ))
140
55
141
56
142
- @requires_specialization
143
- @unittest .skipIf (Py_GIL_DISABLED , "optimizer not yet supported in free-threaded builds" )
144
- @unittest .skipUnless (hasattr (_testinternalcapi , "get_optimizer" ) and
145
- hasattr (_testinternalcapi , "new_counter_optimizer" ),
146
- "Requires optimizer infrastructure" )
147
- class TestExecutorInvalidation (unittest .TestCase ):
148
-
149
- def setUp (self ):
150
- self .old = _testinternalcapi .get_optimizer ()
151
- self .opt = _testinternalcapi .new_counter_optimizer ()
152
- _testinternalcapi .set_optimizer (self .opt )
153
-
154
- def tearDown (self ):
155
- _testinternalcapi .set_optimizer (self .old )
156
-
157
- def test_invalidate_object (self ):
158
- # Generate a new set of functions at each call
159
- ns = {}
160
- func_src = "\n " .join (
161
- f"""
162
- def f{ n } ():
163
- for _ in range({ TIER2_THRESHOLD } ):
164
- pass
165
- """ for n in range (5 )
166
- )
167
- exec (textwrap .dedent (func_src ), ns , ns )
168
- funcs = [ ns [f'f{ n } ' ] for n in range (5 )]
169
- objects = [object () for _ in range (5 )]
170
-
171
- for f in funcs :
172
- f ()
173
- executors = [get_first_executor (f ) for f in funcs ]
174
- # Set things up so each executor depends on the objects
175
- # with an equal or lower index.
176
- for i , exe in enumerate (executors ):
177
- self .assertTrue (exe .is_valid ())
178
- for obj in objects [:i + 1 ]:
179
- _testinternalcapi .add_executor_dependency (exe , obj )
180
- self .assertTrue (exe .is_valid ())
181
- # Assert that the correct executors are invalidated
182
- # and check that nothing crashes when we invalidate
183
- # an executor multiple times.
184
- for i in (4 ,3 ,2 ,1 ,0 ):
185
- _testinternalcapi .invalidate_executors (objects [i ])
186
- for exe in executors [i :]:
187
- self .assertFalse (exe .is_valid ())
188
- for exe in executors [:i ]:
189
- self .assertTrue (exe .is_valid ())
190
-
191
- def test_uop_optimizer_invalidation (self ):
192
- # Generate a new function at each call
193
- ns = {}
194
- exec (textwrap .dedent (f"""
195
- def f():
196
- for i in range({ TIER2_THRESHOLD } ):
197
- pass
198
- """ ), ns , ns )
199
- f = ns ['f' ]
200
- opt = _testinternalcapi .new_uop_optimizer ()
201
- with temporary_optimizer (opt ):
202
- f ()
203
- exe = get_first_executor (f )
204
- self .assertIsNotNone (exe )
205
- self .assertTrue (exe .is_valid ())
206
- _testinternalcapi .invalidate_executors (f .__code__ )
207
- self .assertFalse (exe .is_valid ())
208
-
209
- def test_sys__clear_internal_caches (self ):
210
- def f ():
211
- for _ in range (TIER2_THRESHOLD ):
212
- pass
213
- opt = _testinternalcapi .new_uop_optimizer ()
214
- with temporary_optimizer (opt ):
215
- f ()
216
- exe = get_first_executor (f )
217
- self .assertIsNotNone (exe )
218
- self .assertTrue (exe .is_valid ())
219
- sys ._clear_internal_caches ()
220
- self .assertFalse (exe .is_valid ())
221
- exe = get_first_executor (f )
222
- self .assertIsNone (exe )
223
-
224
-
225
57
@requires_specialization
226
58
@unittest .skipIf (Py_GIL_DISABLED , "optimizer not yet supported in free-threaded builds" )
227
59
@unittest .skipUnless (hasattr (_testinternalcapi , "get_optimizer" ),
0 commit comments