Skip to content
Merged
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
14 changes: 0 additions & 14 deletions Include/methodobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,20 +95,6 @@ typedef struct {
PyObject *m_weakreflist; /* List of weak references */
vectorcallfunc vectorcall;
} PyCFunctionObject;

PyAPI_FUNC(PyObject *) _PyMethodDef_RawFastCallDict(
PyMethodDef *method,
PyObject *self,
PyObject *const *args,
Py_ssize_t nargs,
PyObject *kwargs);

PyAPI_FUNC(PyObject *) _PyMethodDef_RawFastCallKeywords(
PyMethodDef *method,
PyObject *self,
PyObject *const *args,
Py_ssize_t nargs,
PyObject *kwnames);
#endif

PyAPI_FUNC(int) PyCFunction_ClearFreeList(void);
Expand Down
259 changes: 0 additions & 259 deletions Objects/call.c
Original file line number Diff line number Diff line change
Expand Up @@ -366,265 +366,6 @@ _PyFunction_Vectorcall(PyObject *func, PyObject* const* stack,

/* --- PyCFunction call functions --------------------------------- */

PyObject *
_PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self,
PyObject *const *args, Py_ssize_t nargs,
PyObject *kwargs)
{
/* _PyMethodDef_RawFastCallDict() must not be called with an exception set,
because it can clear it (directly or indirectly) and so the
caller loses its exception */
assert(!PyErr_Occurred());

assert(method != NULL);
assert(nargs >= 0);
assert(nargs == 0 || args != NULL);
assert(kwargs == NULL || PyDict_Check(kwargs));

PyCFunction meth = method->ml_meth;
int flags = method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST);
PyObject *result = NULL;

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

switch (flags)
{
case METH_NOARGS:
if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
goto no_keyword_error;
}

if (nargs != 0) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes no arguments (%zd given)",
method->ml_name, nargs);
goto exit;
}

result = (*meth) (self, NULL);
break;

case METH_O:
if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
goto no_keyword_error;
}

if (nargs != 1) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes exactly one argument (%zd given)",
method->ml_name, nargs);
goto exit;
}

result = (*meth) (self, args[0]);
break;

case METH_VARARGS:
if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
goto no_keyword_error;
}
/* fall through */

case METH_VARARGS | METH_KEYWORDS:
{
/* Slow-path: create a temporary tuple for positional arguments */
PyObject *argstuple = _PyTuple_FromArray(args, nargs);
if (argstuple == NULL) {
goto exit;
}

if (flags & METH_KEYWORDS) {
result = (*(PyCFunctionWithKeywords)(void(*)(void))meth) (self, argstuple, kwargs);
}
else {
result = (*meth) (self, argstuple);
}
Py_DECREF(argstuple);
break;
}

case METH_FASTCALL:
{
if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
goto no_keyword_error;
}

result = (*(_PyCFunctionFast)(void(*)(void))meth) (self, args, nargs);
break;
}

case METH_FASTCALL | METH_KEYWORDS:
{
_PyCFunctionFastWithKeywords fastmeth = (_PyCFunctionFastWithKeywords)(void(*)(void))meth;

/* Fast path for no keywords */
if (kwargs == NULL || PyDict_GET_SIZE(kwargs) == 0) {
result = (*fastmeth) (self, args, nargs, NULL);
break;
}

PyObject *const *stack;
PyObject *kwnames;
stack = _PyStack_UnpackDict(args, nargs, kwargs, &kwnames);
if (stack == NULL) {
goto exit;
}
result = (*fastmeth) (self, stack, nargs, kwnames);
_PyStack_UnpackDict_Free(stack, nargs, kwnames);
break;
}

default:
PyErr_SetString(PyExc_SystemError,
"Bad call flags in _PyMethodDef_RawFastCallDict. "
"METH_OLDARGS is no longer supported!");
goto exit;
}

goto exit;

no_keyword_error:
PyErr_Format(PyExc_TypeError,
"%.200s() takes no keyword arguments",
method->ml_name);

exit:
Py_LeaveRecursiveCall();
return result;
}


PyObject *
_PyMethodDef_RawFastCallKeywords(PyMethodDef *method, PyObject *self,
PyObject *const *args, Py_ssize_t nargs,
PyObject *kwnames)
{
/* _PyMethodDef_RawFastCallKeywords() must not be called with an exception set,
because it can clear it (directly or indirectly) and so the
caller loses its exception */
assert(!PyErr_Occurred());

assert(method != NULL);
assert(nargs >= 0);
assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
/* kwnames must only contains str strings, no subclass, and all keys must
be unique */

PyCFunction meth = method->ml_meth;
int flags = method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST);
Py_ssize_t nkwargs = kwnames == NULL ? 0 : PyTuple_GET_SIZE(kwnames);
PyObject *result = NULL;

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

switch (flags)
{
case METH_NOARGS:
if (nkwargs) {
goto no_keyword_error;
}

if (nargs != 0) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes no arguments (%zd given)",
method->ml_name, nargs);
goto exit;
}

result = (*meth) (self, NULL);
break;

case METH_O:
if (nkwargs) {
goto no_keyword_error;
}

if (nargs != 1) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes exactly one argument (%zd given)",
method->ml_name, nargs);
goto exit;
}

result = (*meth) (self, args[0]);
break;

case METH_FASTCALL:
if (nkwargs) {
goto no_keyword_error;
}
result = ((_PyCFunctionFast)(void(*)(void))meth) (self, args, nargs);
break;

case METH_FASTCALL | METH_KEYWORDS:
/* Fast-path: avoid temporary dict to pass keyword arguments */
result = ((_PyCFunctionFastWithKeywords)(void(*)(void))meth) (self, args, nargs, kwnames);
break;

case METH_VARARGS:
if (nkwargs) {
goto no_keyword_error;
}
/* fall through */

case METH_VARARGS | METH_KEYWORDS:
{
/* Slow-path: create a temporary tuple for positional arguments
and a temporary dict for keyword arguments */
PyObject *argtuple;

argtuple = _PyTuple_FromArray(args, nargs);
if (argtuple == NULL) {
goto exit;
}

if (flags & METH_KEYWORDS) {
PyObject *kwdict;

if (nkwargs > 0) {
kwdict = _PyStack_AsDict(args + nargs, kwnames);
if (kwdict == NULL) {
Py_DECREF(argtuple);
goto exit;
}
}
else {
kwdict = NULL;
}

result = (*(PyCFunctionWithKeywords)(void(*)(void))meth) (self, argtuple, kwdict);
Py_XDECREF(kwdict);
}
else {
result = (*meth) (self, argtuple);
}
Py_DECREF(argtuple);
break;
}

default:
PyErr_SetString(PyExc_SystemError,
"Bad call flags in _PyMethodDef_RawFastCallKeywords. "
"METH_OLDARGS is no longer supported!");
goto exit;
}

goto exit;

no_keyword_error:
PyErr_Format(PyExc_TypeError,
"%.200s() takes no keyword arguments",
method->ml_name);

exit:
Py_LeaveRecursiveCall();
return result;
}

static PyObject *
cfunction_call_varargs(PyObject *func, PyObject *args, PyObject *kwargs)
{
Expand Down