bpo-36974: implement PEP 590 (GH-13185)
Co-authored-by: Jeroen Demeyer <J.Demeyer@UGent.be> Co-authored-by: Mark Shannon <mark@hotpy.org>
This commit is contained in:
committed by
Petr Viktorin
parent
d30da5dd9a
commit
aacc77fbd7
@@ -40,6 +40,45 @@ PyMethod_Self(PyObject *im)
|
||||
return ((PyMethodObject *)im)->im_self;
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
method_vectorcall(PyObject *method, PyObject *const *args,
|
||||
size_t nargsf, PyObject *kwnames)
|
||||
{
|
||||
assert(Py_TYPE(method) == &PyMethod_Type);
|
||||
PyObject *self, *func, *result;
|
||||
self = PyMethod_GET_SELF(method);
|
||||
func = PyMethod_GET_FUNCTION(method);
|
||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||
|
||||
if (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET) {
|
||||
/* PY_VECTORCALL_ARGUMENTS_OFFSET is set, so we are allowed to mutate the vector */
|
||||
PyObject **newargs = (PyObject**)args - 1;
|
||||
nargs += 1;
|
||||
PyObject *tmp = newargs[0];
|
||||
newargs[0] = self;
|
||||
result = _PyObject_Vectorcall(func, newargs, nargs, kwnames);
|
||||
newargs[0] = tmp;
|
||||
}
|
||||
else {
|
||||
Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
|
||||
PyObject **newargs;
|
||||
Py_ssize_t totalargs = nargs + nkwargs;
|
||||
newargs = PyMem_Malloc((totalargs+1) * sizeof(PyObject *));
|
||||
if (newargs == NULL) {
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
/* use borrowed references */
|
||||
newargs[0] = self;
|
||||
memcpy(newargs + 1, args, totalargs * sizeof(PyObject *));
|
||||
result = _PyObject_Vectorcall(func, newargs, nargs+1, kwnames);
|
||||
PyMem_Free(newargs);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Method objects are used for bound instance methods returned by
|
||||
instancename.methodname. ClassName.methodname returns an ordinary
|
||||
function.
|
||||
@@ -69,6 +108,7 @@ PyMethod_New(PyObject *func, PyObject *self)
|
||||
im->im_func = func;
|
||||
Py_XINCREF(self);
|
||||
im->im_self = self;
|
||||
im->vectorcall = method_vectorcall;
|
||||
_PyObject_GC_TRACK(im);
|
||||
return (PyObject *)im;
|
||||
}
|
||||
@@ -309,7 +349,7 @@ PyTypeObject PyMethod_Type = {
|
||||
sizeof(PyMethodObject),
|
||||
0,
|
||||
(destructor)method_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
offsetof(PyMethodObject, vectorcall), /* tp_vectorcall_offset */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_reserved */
|
||||
@@ -323,7 +363,8 @@ PyTypeObject PyMethod_Type = {
|
||||
method_getattro, /* tp_getattro */
|
||||
PyObject_GenericSetAttr, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
|
||||
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
|
||||
_Py_TPFLAGS_HAVE_VECTORCALL, /* tp_flags */
|
||||
method_doc, /* tp_doc */
|
||||
(traverseproc)method_traverse, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
|
||||
Reference in New Issue
Block a user