Skip to content

Commit f26c10d

Browse files
committed
pythongh-139525: Don't specialize functions which have a modified vectorcall (python#139524)
Don't specialize functions which have a modified vectorcall
1 parent 9e091db commit f26c10d

File tree

3 files changed

+37
-0
lines changed

3 files changed

+37
-0
lines changed

Lib/test/test_opcache.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,14 @@ def test(default=None):
567567
with self.assertRaises(RecursionError):
568568
test()
569569

570+
def test_dont_specialize_custom_vectorcall(self):
571+
def f():
572+
raise Exception("no way")
573+
574+
_testinternalcapi.set_vectorcall_nop(f)
575+
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
576+
f()
577+
570578

571579
def make_deferred_ref_count_obj():
572580
"""Create an object that uses deferred reference counting.

Modules/_testinternalcapi.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2377,6 +2377,25 @@ emscripten_set_up_async_input_device(PyObject *self, PyObject *Py_UNUSED(ignored
23772377
}
23782378
#endif
23792379

2380+
static PyObject *
2381+
vectorcall_nop(PyObject *callable, PyObject *const *args,
2382+
size_t nargsf, PyObject *kwnames)
2383+
{
2384+
Py_RETURN_NONE;
2385+
}
2386+
2387+
static PyObject *
2388+
set_vectorcall_nop(PyObject *self, PyObject *func)
2389+
{
2390+
if (!PyFunction_Check(func)) {
2391+
PyErr_SetString(PyExc_TypeError, "expected function");
2392+
return NULL;
2393+
}
2394+
2395+
((PyFunctionObject*)func)->vectorcall = vectorcall_nop;
2396+
Py_RETURN_NONE;
2397+
}
2398+
23802399
static PyMethodDef module_functions[] = {
23812400
{"get_configs", get_configs, METH_NOARGS},
23822401
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
@@ -2482,6 +2501,7 @@ static PyMethodDef module_functions[] = {
24822501
#ifdef __EMSCRIPTEN__
24832502
{"emscripten_set_up_async_input_device", emscripten_set_up_async_input_device, METH_NOARGS},
24842503
#endif
2504+
{"set_vectorcall_nop", set_vectorcall_nop, METH_O},
24852505
{NULL, NULL} /* sentinel */
24862506
};
24872507

Python/specialize.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,7 @@ _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t size, int enable_counters
630630
#define SPEC_FAIL_CALL_INIT_NOT_PYTHON 21
631631
#define SPEC_FAIL_CALL_PEP_523 22
632632
#define SPEC_FAIL_CALL_BOUND_METHOD 23
633+
#define SPEC_FAIL_CALL_VECTORCALL 24
633634
#define SPEC_FAIL_CALL_CLASS_MUTABLE 26
634635
#define SPEC_FAIL_CALL_METHOD_WRAPPER 28
635636
#define SPEC_FAIL_CALL_OPERATOR_WRAPPER 29
@@ -2078,6 +2079,10 @@ specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
20782079
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
20792080
return -1;
20802081
}
2082+
if (func->vectorcall != _PyFunction_Vectorcall) {
2083+
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_VECTORCALL);
2084+
return -1;
2085+
}
20812086
int argcount = -1;
20822087
if (kind == SPEC_FAIL_CODE_NOT_OPTIMIZED) {
20832088
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CODE_NOT_OPTIMIZED);
@@ -2117,6 +2122,10 @@ specialize_py_call_kw(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
21172122
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
21182123
return -1;
21192124
}
2125+
if (func->vectorcall != _PyFunction_Vectorcall) {
2126+
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_VECTORCALL);
2127+
return -1;
2128+
}
21202129
if (kind == SPEC_FAIL_CODE_NOT_OPTIMIZED) {
21212130
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CODE_NOT_OPTIMIZED);
21222131
return -1;

0 commit comments

Comments
 (0)