cleanup _PyMethodDef_RawFastCallDict

refer python/cpython@0a2e46835d
refer python/cpython@98ccba8344
refer python/cpython@c89ef828cf
refer python/cpython@250e4b0063
This commit is contained in:
ahgamut 2021-11-05 01:45:44 +05:30
parent 9220b67b3e
commit 7fb46fb510
2 changed files with 39 additions and 97 deletions

View file

@ -2255,7 +2255,7 @@ PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs)
PyObject *result;
/* PyObject_Call() must not be called with an exception set,
because it may clear it (directly or indirectly) and so the
because it can clear it (directly or indirectly) and so the
caller loses its exception */
assert(!PyErr_Occurred());
assert(PyTuple_Check(args));
@ -2332,7 +2332,7 @@ _PyObject_FastCallDict(PyObject *callable, PyObject **args, Py_ssize_t nargs,
PyObject *result = NULL;
/* _PyObject_FastCallDict() must not be called with an exception set,
because it may clear it (directly or indirectly) and so the
because it can clear it (directly or indirectly) and so the
caller loses its exception */
assert(!PyErr_Occurred());
@ -2505,6 +2505,11 @@ PyObject *
_PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t nargs,
PyObject *kwnames)
{
/* _PyObject_FastCallKeywords() 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(nargs >= 0);
assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
@ -2562,6 +2567,8 @@ _PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t narg
Py_DECREF(argtuple);
Py_XDECREF(kwdict);
result = _Py_CheckFunctionResult(callable, result, NULL);
exit:
Py_LeaveRecursiveCall();
return result;

View file

@ -91,77 +91,12 @@ PyCFunction_GetFlags(PyObject *op)
}
PyObject *
PyCFunction_Call(PyObject *func, PyObject *args, PyObject *kwds)
PyCFunction_Call(PyObject *func, PyObject *args, PyObject *kwargs)
{
PyCFunctionObject* f = (PyCFunctionObject*)func;
PyCFunction meth = PyCFunction_GET_FUNCTION(func);
PyObject *self = PyCFunction_GET_SELF(func);
PyObject *arg, *res;
Py_ssize_t size;
int flags;
assert(kwds == NULL || PyDict_Check(kwds));
/* PyCFunction_Call() 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());
flags = PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST);
if (flags == (METH_VARARGS | METH_KEYWORDS)) {
res = (*(PyCFunctionWithKeywords)meth)(self, args, kwds);
}
else if (flags == METH_FASTCALL) {
PyObject **stack = &PyTuple_GET_ITEM(args, 0);
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
res = _PyCFunction_FastCallDict(func, stack, nargs, kwds);
}
else {
if (kwds != NULL && PyDict_GET_SIZE(kwds) != 0) {
PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
f->m_ml->ml_name);
return NULL;
}
switch (flags) {
case METH_VARARGS:
res = (*meth)(self, args);
break;
case METH_NOARGS:
size = PyTuple_GET_SIZE(args);
if (size != 0) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes no arguments (%zd given)",
f->m_ml->ml_name, size);
return NULL;
}
res = (*meth)(self, NULL);
break;
case METH_O:
size = PyTuple_GET_SIZE(args);
if (size != 1) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes exactly one argument (%zd given)",
f->m_ml->ml_name, size);
return NULL;
}
arg = PyTuple_GET_ITEM(args, 0);
res = (*meth)(self, arg);
break;
default:
PyErr_SetString(PyExc_SystemError,
"Bad call flags in PyCFunction_Call. "
"METH_OLDARGS is no longer supported!");
return NULL;
}
}
return _Py_CheckFunctionResult(func, res, NULL);
return _PyCFunction_FastCallDict(func,
&PyTuple_GET_ITEM(args, 0),
PyTuple_GET_SIZE(args),
kwargs);
}
PyObject *
@ -171,17 +106,18 @@ _PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **arg
PyCFunction meth;
PyObject *result;
int flags;
PyObject *argstuple;
/* _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_FastCallDict() must not be called with an exception set,
because it may clear it (directly or indirectly) and so the
caller loses its exception */
assert(!PyErr_Occurred());
meth = method->ml_meth;
flags = method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST);
@ -189,13 +125,14 @@ _PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **arg
{
case METH_NOARGS:
if (nargs != 0) {
goto no_keyword_error;
PyErr_Format(PyExc_TypeError,
"%.200s() takes no arguments (%zd given)",
method->ml_name, nargs);
return NULL;
}
if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
method->ml_name);
return NULL;
goto no_keyword_error;
}
result = (*meth) (self, NULL);
@ -217,30 +154,27 @@ _PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **arg
break;
case METH_VARARGS:
case METH_VARARGS | METH_KEYWORDS:
{
/* Slow-path: create a temporary tuple for positional arguments */
PyObject *tuple;
if (!(flags & METH_KEYWORDS)
&& kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
goto no_keyword_error;
}
/* fall through next case */
tuple = _PyStack_AsTuple(args, nargs);
if (tuple == NULL) {
case METH_VARARGS | METH_KEYWORDS:
/* Slow-path: create a temporary tuple for positional arguments */
argstuple = _PyStack_AsTuple(args, nargs);
if (argstuple == NULL) {
return NULL;
}
if (flags & METH_KEYWORDS) {
result = (*(PyCFunctionWithKeywords)meth) (self, tuple, kwargs);
result = (*(PyCFunctionWithKeywords)meth) (self, argstuple, kwargs);
}
else {
result = (*meth) (self, tuple);
result = (*meth) (self, argstuple);
}
Py_DECREF(tuple);
Py_DECREF(argstuple);
break;
}
case METH_FASTCALL:
{
@ -262,7 +196,7 @@ _PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **arg
default:
PyErr_SetString(PyExc_SystemError,
"Bad call flags in PyCFunction_Call. "
"Bad call flags in _PyMethodDef_RawFastCallDict. "
"METH_OLDARGS is no longer supported!");
return NULL;
}
@ -271,8 +205,9 @@ _PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **arg
no_keyword_error:
PyErr_Format(PyExc_TypeError,
"%.200s() takes no arguments (%zd given)",
"%.200s() takes no keyword arguments",
method->ml_name, nargs);
return NULL;
}