Skip to content

Commit ff0cf0a

Browse files
authored
gh-139525: Don't specialize functions which have a modified vectorcall (#139524)
Don't specialize functions which have a modified vectorcall
1 parent 12805ef commit ff0cf0a

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
@@ -2399,6 +2399,25 @@ simple_pending_call(PyObject *self, PyObject *callable)
23992399
Py_RETURN_NONE;
24002400
}
24012401

2402+
static PyObject *
2403+
vectorcall_nop(PyObject *callable, PyObject *const *args,
2404+
size_t nargsf, PyObject *kwnames)
2405+
{
2406+
Py_RETURN_NONE;
2407+
}
2408+
2409+
static PyObject *
2410+
set_vectorcall_nop(PyObject *self, PyObject *func)
2411+
{
2412+
if (!PyFunction_Check(func)) {
2413+
PyErr_SetString(PyExc_TypeError, "expected function");
2414+
return NULL;
2415+
}
2416+
2417+
((PyFunctionObject*)func)->vectorcall = vectorcall_nop;
2418+
Py_RETURN_NONE;
2419+
}
2420+
24022421
static PyMethodDef module_functions[] = {
24032422
{"get_configs", get_configs, METH_NOARGS},
24042423
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
@@ -2507,6 +2526,7 @@ static PyMethodDef module_functions[] = {
25072526
{"emscripten_set_up_async_input_device", emscripten_set_up_async_input_device, METH_NOARGS},
25082527
#endif
25092528
{"simple_pending_call", simple_pending_call, METH_O},
2529+
{"set_vectorcall_nop", set_vectorcall_nop, METH_O},
25102530
{NULL, NULL} /* sentinel */
25112531
};
25122532

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
@@ -2071,6 +2072,10 @@ specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
20712072
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
20722073
return -1;
20732074
}
2075+
if (func->vectorcall != _PyFunction_Vectorcall) {
2076+
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_VECTORCALL);
2077+
return -1;
2078+
}
20742079
int argcount = -1;
20752080
if (kind == SPEC_FAIL_CODE_NOT_OPTIMIZED) {
20762081
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CODE_NOT_OPTIMIZED);
@@ -2110,6 +2115,10 @@ specialize_py_call_kw(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
21102115
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
21112116
return -1;
21122117
}
2118+
if (func->vectorcall != _PyFunction_Vectorcall) {
2119+
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_VECTORCALL);
2120+
return -1;
2121+
}
21132122
if (kind == SPEC_FAIL_CODE_NOT_OPTIMIZED) {
21142123
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CODE_NOT_OPTIMIZED);
21152124
return -1;

0 commit comments

Comments
 (0)