Skip to content

bpo-36926: implement methoddescr_call without _PyMethodDef_RawFastCallDict #13342

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Objects/call.c
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,7 @@ cfunction_call_varargs(PyObject *func, PyObject *args, PyObject *kwargs)
{
assert(!PyErr_Occurred());
assert(kwargs == NULL || PyDict_Check(kwargs));
assert(PyCFunction_GET_FLAGS(func) & METH_VARARGS);

PyCFunction meth = PyCFunction_GET_FUNCTION(func);
PyObject *self = PyCFunction_GET_SELF(func);
Expand Down
62 changes: 52 additions & 10 deletions Objects/descrobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,14 +227,15 @@ getset_set(PyGetSetDescrObject *descr, PyObject *obj, PyObject *value)
}

static PyObject *
methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwargs)
methoddescr_call_varargs_keywords(PyMethodDescrObject *descr, PyObject *args, PyObject *kwargs)
{
Py_ssize_t nargs;
PyObject *self, *result;
assert(!PyErr_Occurred());
assert(kwargs == NULL || PyDict_Check(kwargs));
assert(descr->d_method->ml_flags & METH_VARARGS);
assert(descr->d_method->ml_flags & METH_KEYWORDS);

/* Make sure that the first argument is acceptable as 'self' */
assert(PyTuple_Check(args));
nargs = PyTuple_GET_SIZE(args);
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
if (nargs < 1) {
PyErr_Format(PyExc_TypeError,
"descriptor '%V' of '%.100s' "
Expand All @@ -243,7 +244,7 @@ methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwargs)
PyDescr_TYPE(descr)->tp_name);
return NULL;
}
self = PyTuple_GET_ITEM(args, 0);
PyObject *self = PyTuple_GET_ITEM(args, 0);
if (!_PyObject_RealIsSubclass((PyObject *)Py_TYPE(self),
(PyObject *)PyDescr_TYPE(descr))) {
PyErr_Format(PyExc_TypeError,
Expand All @@ -255,10 +256,51 @@ methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwargs)
return NULL;
}

result = _PyMethodDef_RawFastCallDict(descr->d_method, self,
&_PyTuple_ITEMS(args)[1], nargs - 1,
kwargs);
result = _Py_CheckFunctionResult((PyObject *)descr, result, NULL);
/* Remove self from args */
PyObject *slicedargs = _PyTuple_FromArray(_PyTuple_ITEMS(args) + 1, nargs - 1);
if (slicedargs == NULL) {
return NULL;
}

if (Py_EnterRecursiveCall(" while calling a Python object")) {
Py_DECREF(slicedargs);
return NULL;
}

PyCFunctionWithKeywords meth = (PyCFunctionWithKeywords)(void(*)(void))descr->d_method->ml_meth;
PyObject *result = meth(self, slicedargs, kwargs);

Py_LeaveRecursiveCall();
Py_DECREF(slicedargs);

return _Py_CheckFunctionResult((PyObject *)descr, result, NULL);
}

static PyObject *
methoddescr_call(PyMethodDescrObject *descr, PyObject *args, PyObject *kwargs)
{
int flags = descr->d_method->ml_flags;
if ((flags & (METH_VARARGS|METH_KEYWORDS)) == (METH_VARARGS|METH_KEYWORDS)) {
/* For METH_VARARGS|METH_KEYWORDS, using FastCallKeywords would
* be less optimal because the kwargs dict would be converted
* to a tuple and then back to a dict. */
return methoddescr_call_varargs_keywords(descr, args, kwargs);
}

/* Use FastCallKeywords instead */
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
PyObject *const *stack;
PyObject *kwnames;
if (_PyStack_UnpackDict(_PyTuple_ITEMS(args), nargs, kwargs, &stack, &kwnames) < 0) {
return NULL;
}

PyObject *result = _PyMethodDescr_FastCallKeywords((PyObject *)descr,
stack, nargs, kwnames);
if (stack != _PyTuple_ITEMS(args)) {
PyMem_Free((PyObject **)stack);
}
Py_XDECREF(kwnames);
return result;
}

Expand Down