Skip to content

Commit 0c4e6b5

Browse files
committed
remove _PyCounterOptimizerObject
1 parent 244bf39 commit 0c4e6b5

File tree

7 files changed

+0
-281
lines changed

7 files changed

+0
-281
lines changed

Include/internal/pycore_optimizer.h

-7
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,6 @@ struct _PyOptimizerObject {
9797
/* Data needed by the optimizer goes here, but is opaque to the VM */
9898
};
9999

100-
/** Test support **/
101-
typedef struct {
102-
_PyOptimizerObject base;
103-
int64_t count;
104-
} _PyCounterOptimizerObject;
105-
106100
_PyOptimizerObject *_Py_SetOptimizer(PyInterpreterState *interp, _PyOptimizerObject* optimizer);
107101

108102

@@ -151,7 +145,6 @@ int _Py_uop_analyze_and_optimize(struct _PyInterpreterFrame *frame,
151145
_PyBloomFilter *dependencies);
152146

153147
extern PyTypeObject _PyCounterExecutor_Type;
154-
extern PyTypeObject _PyCounterOptimizer_Type;
155148
extern PyTypeObject _PyDefaultOptimizer_Type;
156149
extern PyTypeObject _PyUOpExecutor_Type;
157150
extern PyTypeObject _PyUOpOptimizer_Type;

Lib/test/test_capi/test_opt.py

-166
Original file line numberDiff line numberDiff line change
@@ -35,90 +35,6 @@ def clear_executors(func):
3535
func.__code__ = func.__code__.replace()
3636

3737

38-
@requires_specialization
39-
@unittest.skipIf(Py_GIL_DISABLED, "optimizer not yet supported in free-threaded builds")
40-
@unittest.skipUnless(hasattr(_testinternalcapi, "get_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-
12238
def get_first_executor(func):
12339
code = func.__code__
12440
co_code = code.co_code
@@ -139,88 +55,6 @@ def get_opnames(ex):
13955
return list(iter_opnames(ex))
14056

14157

142-
@requires_specialization
143-
@unittest.skipIf(Py_GIL_DISABLED, "optimizer not yet supported in free-threaded builds")
144-
@unittest.skipUnless(hasattr(_testinternalcapi, "get_optimizer"),
145-
"Requires optimizer infrastructure")
146-
class TestExecutorInvalidation(unittest.TestCase):
147-
148-
def setUp(self):
149-
self.old = _testinternalcapi.get_optimizer()
150-
self.opt = _testinternalcapi.new_counter_optimizer()
151-
_testinternalcapi.set_optimizer(self.opt)
152-
153-
def tearDown(self):
154-
_testinternalcapi.set_optimizer(self.old)
155-
156-
def test_invalidate_object(self):
157-
# Generate a new set of functions at each call
158-
ns = {}
159-
func_src = "\n".join(
160-
f"""
161-
def f{n}():
162-
for _ in range({TIER2_THRESHOLD}):
163-
pass
164-
""" for n in range(5)
165-
)
166-
exec(textwrap.dedent(func_src), ns, ns)
167-
funcs = [ ns[f'f{n}'] for n in range(5)]
168-
objects = [object() for _ in range(5)]
169-
170-
for f in funcs:
171-
f()
172-
executors = [get_first_executor(f) for f in funcs]
173-
# Set things up so each executor depends on the objects
174-
# with an equal or lower index.
175-
for i, exe in enumerate(executors):
176-
self.assertTrue(exe.is_valid())
177-
for obj in objects[:i+1]:
178-
_testinternalcapi.add_executor_dependency(exe, obj)
179-
self.assertTrue(exe.is_valid())
180-
# Assert that the correct executors are invalidated
181-
# and check that nothing crashes when we invalidate
182-
# an executor multiple times.
183-
for i in (4,3,2,1,0):
184-
_testinternalcapi.invalidate_executors(objects[i])
185-
for exe in executors[i:]:
186-
self.assertFalse(exe.is_valid())
187-
for exe in executors[:i]:
188-
self.assertTrue(exe.is_valid())
189-
190-
def test_uop_optimizer_invalidation(self):
191-
# Generate a new function at each call
192-
ns = {}
193-
exec(textwrap.dedent(f"""
194-
def f():
195-
for i in range({TIER2_THRESHOLD}):
196-
pass
197-
"""), ns, ns)
198-
f = ns['f']
199-
opt = _testinternalcapi.new_uop_optimizer()
200-
with temporary_optimizer(opt):
201-
f()
202-
exe = get_first_executor(f)
203-
self.assertIsNotNone(exe)
204-
self.assertTrue(exe.is_valid())
205-
_testinternalcapi.invalidate_executors(f.__code__)
206-
self.assertFalse(exe.is_valid())
207-
208-
def test_sys__clear_internal_caches(self):
209-
def f():
210-
for _ in range(TIER2_THRESHOLD):
211-
pass
212-
opt = _testinternalcapi.new_uop_optimizer()
213-
with temporary_optimizer(opt):
214-
f()
215-
exe = get_first_executor(f)
216-
self.assertIsNotNone(exe)
217-
self.assertTrue(exe.is_valid())
218-
sys._clear_internal_caches()
219-
self.assertFalse(exe.is_valid())
220-
exe = get_first_executor(f)
221-
self.assertIsNone(exe)
222-
223-
22458
@requires_specialization
22559
@unittest.skipIf(Py_GIL_DISABLED, "optimizer not yet supported in free-threaded builds")
22660
@unittest.skipUnless(hasattr(_testinternalcapi, "get_optimizer"),

Lib/test/test_monitoring.py

-29
Original file line numberDiff line numberDiff line change
@@ -2085,35 +2085,6 @@ def callback(code, instruction_offset):
20852085
sys.monitoring.set_events(0, 0)
20862086

20872087

2088-
class TestOptimizer(MonitoringTestBase, unittest.TestCase):
2089-
2090-
def setUp(self):
2091-
_testinternalcapi = import_module("_testinternalcapi")
2092-
if hasattr(_testinternalcapi, "get_optimizer"):
2093-
self.old_opt = _testinternalcapi.get_optimizer()
2094-
opt = _testinternalcapi.new_counter_optimizer()
2095-
_testinternalcapi.set_optimizer(opt)
2096-
super(TestOptimizer, self).setUp()
2097-
2098-
def tearDown(self):
2099-
super(TestOptimizer, self).tearDown()
2100-
import _testinternalcapi
2101-
if hasattr(_testinternalcapi, "get_optimizer"):
2102-
_testinternalcapi.set_optimizer(self.old_opt)
2103-
2104-
def test_for_loop(self):
2105-
def test_func(x):
2106-
i = 0
2107-
while i < x:
2108-
i += 1
2109-
2110-
code = test_func.__code__
2111-
sys.monitoring.set_local_events(TEST_TOOL, code, E.PY_START)
2112-
self.assertEqual(sys.monitoring.get_local_events(TEST_TOOL, code), E.PY_START)
2113-
test_func(1000)
2114-
sys.monitoring.set_local_events(TEST_TOOL, code, 0)
2115-
self.assertEqual(sys.monitoring.get_local_events(TEST_TOOL, code), 0)
2116-
21172088
class TestTier2Optimizer(CheckEvents):
21182089

21192090
def test_monitoring_already_opimized_loop(self):

Modules/_testinternalcapi.c

-7
Original file line numberDiff line numberDiff line change
@@ -989,12 +989,6 @@ get_co_framesize(PyObject *self, PyObject *arg)
989989

990990
#ifdef _Py_TIER2
991991

992-
static PyObject *
993-
new_counter_optimizer(PyObject *self, PyObject *arg)
994-
{
995-
return _PyOptimizer_NewCounter();
996-
}
997-
998992
static PyObject *
999993
new_uop_optimizer(PyObject *self, PyObject *arg)
1000994
{
@@ -2101,7 +2095,6 @@ static PyMethodDef module_functions[] = {
21012095
#ifdef _Py_TIER2
21022096
{"get_optimizer", get_optimizer, METH_NOARGS, NULL},
21032097
{"set_optimizer", set_optimizer, METH_O, NULL},
2104-
{"new_counter_optimizer", new_counter_optimizer, METH_NOARGS, NULL},
21052098
{"new_uop_optimizer", new_uop_optimizer, METH_NOARGS, NULL},
21062099
{"add_executor_dependency", add_executor_dependency, METH_VARARGS, NULL},
21072100
{"invalidate_executors", invalidate_executors, METH_O, NULL},

Objects/object.c

-1
Original file line numberDiff line numberDiff line change
@@ -2380,7 +2380,6 @@ static PyTypeObject* static_types[] = {
23802380
&_PyCoroWrapper_Type,
23812381
#ifdef _Py_TIER2
23822382
&_PyCounterExecutor_Type,
2383-
&_PyCounterOptimizer_Type,
23842383
&_PyDefaultOptimizer_Type,
23852384
#endif
23862385
&_Py_GenericAliasIterType,

Python/optimizer.c

-70
Original file line numberDiff line numberDiff line change
@@ -1352,76 +1352,6 @@ PyTypeObject _PyCounterExecutor_Type = {
13521352
.tp_clear = (inquiry)executor_clear,
13531353
};
13541354

1355-
static int
1356-
counter_optimize(
1357-
_PyOptimizerObject* self,
1358-
_PyInterpreterFrame *frame,
1359-
_Py_CODEUNIT *instr,
1360-
_PyExecutorObject **exec_ptr,
1361-
int Py_UNUSED(curr_stackentries),
1362-
bool Py_UNUSED(progress_needed)
1363-
)
1364-
{
1365-
PyCodeObject *code = _PyFrame_GetCode(frame);
1366-
int oparg = instr->op.arg;
1367-
while (instr->op.code == EXTENDED_ARG) {
1368-
instr++;
1369-
oparg = (oparg << 8) | instr->op.arg;
1370-
}
1371-
if (instr->op.code != JUMP_BACKWARD) {
1372-
/* Counter optimizer can only handle backward edges */
1373-
return 0;
1374-
}
1375-
_Py_CODEUNIT *target = instr + 1 + _PyOpcode_Caches[JUMP_BACKWARD] - oparg;
1376-
_PyUOpInstruction buffer[4] = {
1377-
{ .opcode = _START_EXECUTOR, .jump_target = 3, .format=UOP_FORMAT_JUMP },
1378-
{ .opcode = _LOAD_CONST_INLINE, .operand0 = (uintptr_t)self },
1379-
{ .opcode = _EXIT_TRACE, .target = (uint32_t)(target - _PyCode_CODE(code)), .format=UOP_FORMAT_TARGET }
1380-
};
1381-
_PyExecutorObject *executor = make_executor_from_uops(buffer, 4, &EMPTY_FILTER);
1382-
if (executor == NULL) {
1383-
return -1;
1384-
}
1385-
Py_INCREF(self);
1386-
Py_SET_TYPE(executor, &_PyCounterExecutor_Type);
1387-
*exec_ptr = executor;
1388-
return 1;
1389-
}
1390-
1391-
static PyObject *
1392-
counter_get_counter(PyObject *self, PyObject *args)
1393-
{
1394-
return PyLong_FromLongLong(((_PyCounterOptimizerObject *)self)->count);
1395-
}
1396-
1397-
static PyMethodDef counter_optimizer_methods[] = {
1398-
{ "get_count", counter_get_counter, METH_NOARGS, NULL },
1399-
{ NULL, NULL },
1400-
};
1401-
1402-
PyTypeObject _PyCounterOptimizer_Type = {
1403-
PyVarObject_HEAD_INIT(&PyType_Type, 0)
1404-
.tp_name = "Counter optimizer",
1405-
.tp_basicsize = sizeof(_PyCounterOptimizerObject),
1406-
.tp_itemsize = 0,
1407-
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
1408-
.tp_methods = counter_optimizer_methods,
1409-
.tp_dealloc = (destructor)PyObject_Free,
1410-
};
1411-
1412-
PyObject *
1413-
_PyOptimizer_NewCounter(void)
1414-
{
1415-
_PyCounterOptimizerObject *opt = (_PyCounterOptimizerObject *)_PyObject_New(&_PyCounterOptimizer_Type);
1416-
if (opt == NULL) {
1417-
return NULL;
1418-
}
1419-
opt->base.optimize = counter_optimize;
1420-
opt->count = 0;
1421-
return (PyObject *)opt;
1422-
}
1423-
1424-
14251355
/*****************************************
14261356
* Executor management
14271357
****************************************/

Tools/c-analyzer/cpython/ignored.tsv

-1
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,6 @@ Python/sysmodule.c - _PySys_ImplName -
385385
Python/sysmodule.c - whatstrings -
386386
Python/optimizer.c - _PyDefaultOptimizer_Type -
387387
Python/optimizer.c - _PyCounterExecutor_Type -
388-
Python/optimizer.c - _PyCounterOptimizer_Type -
389388
Python/optimizer.c - _PyUOpExecutor_Type -
390389
Python/optimizer.c - _PyUOpOptimizer_Type -
391390
Python/optimizer.c - _PyOptimizer_Default -

0 commit comments

Comments
 (0)