Skip to content

Commit

Permalink
remove _PyCounterOptimizer_Type and _PyOptimizer_NewCounter
Browse files Browse the repository at this point in the history
  • Loading branch information
xuantengh committed Jan 1, 2025
1 parent 910be98 commit 3f89146
Show file tree
Hide file tree
Showing 7 changed files with 7 additions and 118 deletions.
2 changes: 0 additions & 2 deletions Include/internal/pycore_optimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ PyAPI_FUNC(void) _Py_Executor_DependsOn(_PyExecutorObject *executor, void *obj);
// Export for '_testinternalcapi' shared extension.
PyAPI_FUNC(_PyOptimizerObject *) _Py_GetOptimizer(void);
PyAPI_FUNC(int) _Py_SetTier2Optimizer(_PyOptimizerObject* optimizer);
PyAPI_FUNC(PyObject *) _PyOptimizer_NewCounter(void);
PyAPI_FUNC(PyObject *) _PyOptimizer_NewUOpOptimizer(void);

#define _Py_MAX_ALLOWED_BUILTINS_MODIFICATIONS 3
Expand Down Expand Up @@ -153,7 +152,6 @@ int _Py_uop_analyze_and_optimize(struct _PyInterpreterFrame *frame,
_PyBloomFilter *dependencies);

extern PyTypeObject _PyCounterExecutor_Type;
extern PyTypeObject _PyCounterOptimizer_Type;
extern PyTypeObject _PyDefaultOptimizer_Type;
extern PyTypeObject _PyUOpExecutor_Type;
extern PyTypeObject _PyUOpOptimizer_Type;
Expand Down
88 changes: 4 additions & 84 deletions Lib/test/test_capi/test_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ def clear_executors(func):

@requires_specialization
@unittest.skipIf(Py_GIL_DISABLED, "optimizer not yet supported in free-threaded builds")
@unittest.skipUnless(hasattr(_testinternalcapi, "get_optimizer"),
@unittest.skipUnless(hasattr(_testinternalcapi, "get_optimizer") and
hasattr(_testinternalcapi, "new_counter_optimizer"),
"Requires optimizer infrastructure")
class TestOptimizerAPI(unittest.TestCase):

Expand Down Expand Up @@ -140,89 +141,8 @@ def get_opnames(ex):

@requires_specialization
@unittest.skipIf(Py_GIL_DISABLED, "optimizer not yet supported in free-threaded builds")
@unittest.skipUnless(hasattr(_testinternalcapi, "get_optimizer"),
"Requires optimizer infrastructure")
class TestExecutorInvalidation(unittest.TestCase):

def setUp(self):
self.old = _testinternalcapi.get_optimizer()
self.opt = _testinternalcapi.new_counter_optimizer()
_testinternalcapi.set_optimizer(self.opt)

def tearDown(self):
_testinternalcapi.set_optimizer(self.old)

def test_invalidate_object(self):
# Generate a new set of functions at each call
ns = {}
func_src = "\n".join(
f"""
def f{n}():
for _ in range(1000):
pass
""" for n in range(5)
)
exec(textwrap.dedent(func_src), ns, ns)
funcs = [ ns[f'f{n}'] for n in range(5)]
objects = [object() for _ in range(5)]

for f in funcs:
f()
executors = [get_first_executor(f) for f in funcs]
# Set things up so each executor depends on the objects
# with an equal or lower index.
for i, exe in enumerate(executors):
self.assertTrue(exe.is_valid())
for obj in objects[:i+1]:
_testinternalcapi.add_executor_dependency(exe, obj)
self.assertTrue(exe.is_valid())
# Assert that the correct executors are invalidated
# and check that nothing crashes when we invalidate
# an executor multiple times.
for i in (4,3,2,1,0):
_testinternalcapi.invalidate_executors(objects[i])
for exe in executors[i:]:
self.assertFalse(exe.is_valid())
for exe in executors[:i]:
self.assertTrue(exe.is_valid())

def test_uop_optimizer_invalidation(self):
# Generate a new function at each call
ns = {}
exec(textwrap.dedent("""
def f():
for i in range(1000):
pass
"""), ns, ns)
f = ns['f']
opt = _testinternalcapi.new_uop_optimizer()
with temporary_optimizer(opt):
f()
exe = get_first_executor(f)
self.assertIsNotNone(exe)
self.assertTrue(exe.is_valid())
_testinternalcapi.invalidate_executors(f.__code__)
self.assertFalse(exe.is_valid())

def test_sys__clear_internal_caches(self):
def f():
for _ in range(1000):
pass
opt = _testinternalcapi.new_uop_optimizer()
with temporary_optimizer(opt):
f()
exe = get_first_executor(f)
self.assertIsNotNone(exe)
self.assertTrue(exe.is_valid())
sys._clear_internal_caches()
self.assertFalse(exe.is_valid())
exe = get_first_executor(f)
self.assertIsNone(exe)


@requires_specialization
@unittest.skipIf(Py_GIL_DISABLED, "optimizer not yet supported in free-threaded builds")
@unittest.skipUnless(hasattr(_testinternalcapi, "get_optimizer"),
@unittest.skipUnless(hasattr(_testinternalcapi, "get_optimizer") and
hasattr(_testinternalcapi, "new_counter_optimizer"),
"Requires optimizer infrastructure")
class TestExecutorInvalidation(unittest.TestCase):

Expand Down
4 changes: 3 additions & 1 deletion Lib/test/test_monitoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from test.support.import_helper import import_module

_testcapi = test.support.import_helper.import_module("_testcapi")
_testinternalcapi = test.support.import_helper.import_module("_testinternalcapi")

PAIR = (0,1)

Expand Down Expand Up @@ -2003,10 +2004,11 @@ def callback(code, instruction_offset):
sys.monitoring.set_events(0, 0)


@unittest.skipUnless(hasattr(_testinternalcapi, "new_counter_optimizer"),
"Requires counter optimizer")
class TestOptimizer(MonitoringTestBase, unittest.TestCase):

def setUp(self):
_testinternalcapi = import_module("_testinternalcapi")
if hasattr(_testinternalcapi, "get_optimizer"):
self.old_opt = _testinternalcapi.get_optimizer()
opt = _testinternalcapi.new_counter_optimizer()
Expand Down
7 changes: 0 additions & 7 deletions Modules/_testinternalcapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -989,12 +989,6 @@ get_co_framesize(PyObject *self, PyObject *arg)

#ifdef _Py_TIER2

static PyObject *
new_counter_optimizer(PyObject *self, PyObject *arg)
{
return _PyOptimizer_NewCounter();
}

static PyObject *
new_uop_optimizer(PyObject *self, PyObject *arg)
{
Expand Down Expand Up @@ -2101,7 +2095,6 @@ static PyMethodDef module_functions[] = {
#ifdef _Py_TIER2
{"get_optimizer", get_optimizer, METH_NOARGS, NULL},
{"set_optimizer", set_optimizer, METH_O, NULL},
{"new_counter_optimizer", new_counter_optimizer, METH_NOARGS, NULL},
{"new_uop_optimizer", new_uop_optimizer, METH_NOARGS, NULL},
{"add_executor_dependency", add_executor_dependency, METH_VARARGS, NULL},
{"invalidate_executors", invalidate_executors, METH_O, NULL},
Expand Down
1 change: 0 additions & 1 deletion Objects/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -2380,7 +2380,6 @@ static PyTypeObject* static_types[] = {
&_PyCoroWrapper_Type,
#ifdef _Py_TIER2
&_PyCounterExecutor_Type,
&_PyCounterOptimizer_Type,
&_PyDefaultOptimizer_Type,
#endif
&_Py_GenericAliasIterType,
Expand Down
22 changes: 0 additions & 22 deletions Python/optimizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1394,28 +1394,6 @@ static PyMethodDef counter_optimizer_methods[] = {
{ NULL, NULL },
};

PyTypeObject _PyCounterOptimizer_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
.tp_name = "Counter optimizer",
.tp_basicsize = sizeof(_PyCounterOptimizerObject),
.tp_itemsize = 0,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
.tp_methods = counter_optimizer_methods,
.tp_dealloc = (destructor)PyObject_Free,
};

PyObject *
_PyOptimizer_NewCounter(void)
{
_PyCounterOptimizerObject *opt = (_PyCounterOptimizerObject *)_PyObject_New(&_PyCounterOptimizer_Type);
if (opt == NULL) {
return NULL;
}
opt->base.optimize = counter_optimize;
opt->count = 0;
return (PyObject *)opt;
}


/*****************************************
* Executor management
Expand Down
1 change: 0 additions & 1 deletion Tools/c-analyzer/cpython/ignored.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,6 @@ Python/sysmodule.c - _PySys_ImplName -
Python/sysmodule.c - whatstrings -
Python/optimizer.c - _PyDefaultOptimizer_Type -
Python/optimizer.c - _PyCounterExecutor_Type -
Python/optimizer.c - _PyCounterOptimizer_Type -
Python/optimizer.c - _PyUOpExecutor_Type -
Python/optimizer.c - _PyUOpOptimizer_Type -
Python/optimizer.c - _PyOptimizer_Default -
Expand Down

0 comments on commit 3f89146

Please sign in to comment.