diff options
author | Jeroen Demeyer <J.Demeyer@UGent.be> | 2019-05-29 18:31:52 (GMT) |
---|---|---|
committer | Petr Viktorin <encukou@gmail.com> | 2019-05-29 18:31:52 (GMT) |
commit | aacc77fbd77640a8f03638216fa09372cc21673d (patch) | |
tree | fd64be1c4c1167a8bf708d1fd22c733cf3a9a30f /Objects/classobject.c | |
parent | d30da5dd9a8a965cf24a22bbaff8a5b1341c2944 (diff) | |
download | cpython-aacc77fbd77640a8f03638216fa09372cc21673d.zip cpython-aacc77fbd77640a8f03638216fa09372cc21673d.tar.gz cpython-aacc77fbd77640a8f03638216fa09372cc21673d.tar.bz2 |
bpo-36974: implement PEP 590 (GH-13185)
Co-authored-by: Jeroen Demeyer <J.Demeyer@UGent.be>
Co-authored-by: Mark Shannon <mark@hotpy.org>
Diffstat (limited to 'Objects/classobject.c')
-rw-r--r-- | Objects/classobject.c | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/Objects/classobject.c b/Objects/classobject.c index 1ee8978..cfc2446 100644 --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -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 */ |