https://github.com/python/cpython/commit/ff0cf0af10a775ea03dc2546b6a5506a708c2ab7
commit: ff0cf0af10a775ea03dc2546b6a5506a708c2ab7
branch: main
author: Dino Viehland <[email protected]>
committer: DinoV <[email protected]>
date: 2025-10-03T09:58:32-07:00
summary:
gh-139525: Don't specialize functions which have a modified vectorcall (#139524)
Don't specialize functions which have a modified vectorcall
files:
M Lib/test/test_opcache.py
M Modules/_testinternalcapi.c
M Python/specialize.c
diff --git a/Lib/test/test_opcache.py b/Lib/test/test_opcache.py
index f1271fc540ebd8..f23f8c053e8431 100644
--- a/Lib/test/test_opcache.py
+++ b/Lib/test/test_opcache.py
@@ -567,6 +567,14 @@ def test(default=None):
with self.assertRaises(RecursionError):
test()
+ def test_dont_specialize_custom_vectorcall(self):
+ def f():
+ raise Exception("no way")
+
+ _testinternalcapi.set_vectorcall_nop(f)
+ for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
+ f()
+
def make_deferred_ref_count_obj():
"""Create an object that uses deferred reference counting.
diff --git a/Modules/_testinternalcapi.c b/Modules/_testinternalcapi.c
index a4348e7e1497cd..c2647d405e25bc 100644
--- a/Modules/_testinternalcapi.c
+++ b/Modules/_testinternalcapi.c
@@ -2399,6 +2399,25 @@ simple_pending_call(PyObject *self, PyObject *callable)
Py_RETURN_NONE;
}
+static PyObject *
+vectorcall_nop(PyObject *callable, PyObject *const *args,
+ size_t nargsf, PyObject *kwnames)
+{
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+set_vectorcall_nop(PyObject *self, PyObject *func)
+{
+ if (!PyFunction_Check(func)) {
+ PyErr_SetString(PyExc_TypeError, "expected function");
+ return NULL;
+ }
+
+ ((PyFunctionObject*)func)->vectorcall = vectorcall_nop;
+ Py_RETURN_NONE;
+}
+
static PyMethodDef module_functions[] = {
{"get_configs", get_configs, METH_NOARGS},
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
@@ -2507,6 +2526,7 @@ static PyMethodDef module_functions[] = {
{"emscripten_set_up_async_input_device",
emscripten_set_up_async_input_device, METH_NOARGS},
#endif
{"simple_pending_call", simple_pending_call, METH_O},
+ {"set_vectorcall_nop", set_vectorcall_nop, METH_O},
{NULL, NULL} /* sentinel */
};
diff --git a/Python/specialize.c b/Python/specialize.c
index 47f7b27b4908fd..a1c5dedd61563b 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -630,6 +630,7 @@ _PyCode_Quicken(_Py_CODEUNIT *instructions, Py_ssize_t
size, int enable_counters
#define SPEC_FAIL_CALL_INIT_NOT_PYTHON 21
#define SPEC_FAIL_CALL_PEP_523 22
#define SPEC_FAIL_CALL_BOUND_METHOD 23
+#define SPEC_FAIL_CALL_VECTORCALL 24
#define SPEC_FAIL_CALL_CLASS_MUTABLE 26
#define SPEC_FAIL_CALL_METHOD_WRAPPER 28
#define SPEC_FAIL_CALL_OPERATOR_WRAPPER 29
@@ -2071,6 +2072,10 @@ specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT
*instr, int nargs,
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
return -1;
}
+ if (func->vectorcall != _PyFunction_Vectorcall) {
+ SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_VECTORCALL);
+ return -1;
+ }
int argcount = -1;
if (kind == SPEC_FAIL_CODE_NOT_OPTIMIZED) {
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CODE_NOT_OPTIMIZED);
@@ -2110,6 +2115,10 @@ specialize_py_call_kw(PyFunctionObject *func,
_Py_CODEUNIT *instr, int nargs,
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
return -1;
}
+ if (func->vectorcall != _PyFunction_Vectorcall) {
+ SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_VECTORCALL);
+ return -1;
+ }
if (kind == SPEC_FAIL_CODE_NOT_OPTIMIZED) {
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CODE_NOT_OPTIMIZED);
return -1;
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]