diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
commit | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (patch) | |
tree | 012bb94d777798f1f56ac1cec429509766d05181 /contrib/tools/python3/src/Objects/methodobject.c | |
parent | 6751af0b0c1b952fede40b19b71da8025b5d8bcf (diff) | |
download | ydb-2598ef1d0aee359b4b6d5fdd1758916d5907d04f.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/python3/src/Objects/methodobject.c')
-rw-r--r-- | contrib/tools/python3/src/Objects/methodobject.c | 602 |
1 files changed, 301 insertions, 301 deletions
diff --git a/contrib/tools/python3/src/Objects/methodobject.c b/contrib/tools/python3/src/Objects/methodobject.c index 2df63cfdf6..bae0664d8d 100644 --- a/contrib/tools/python3/src/Objects/methodobject.c +++ b/contrib/tools/python3/src/Objects/methodobject.c @@ -2,33 +2,33 @@ /* Method object implementation */ #include "Python.h" -#include "pycore_ceval.h" // _Py_EnterRecursiveCall() -#include "pycore_object.h" -#include "pycore_pyerrors.h" -#include "pycore_pystate.h" // _PyThreadState_GET() -#include "structmember.h" // PyMemberDef +#include "pycore_ceval.h" // _Py_EnterRecursiveCall() +#include "pycore_object.h" +#include "pycore_pyerrors.h" +#include "pycore_pystate.h" // _PyThreadState_GET() +#include "structmember.h" // PyMemberDef /* undefine macro trampoline to PyCFunction_NewEx */ #undef PyCFunction_New -/* undefine macro trampoline to PyCMethod_New */ -#undef PyCFunction_NewEx - -/* Forward declarations */ -static PyObject * cfunction_vectorcall_FASTCALL( - PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); -static PyObject * cfunction_vectorcall_FASTCALL_KEYWORDS( - PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); -static PyObject * cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD( - PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); -static PyObject * cfunction_vectorcall_NOARGS( - PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); -static PyObject * cfunction_vectorcall_O( - PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); -static PyObject * cfunction_call( - PyObject *func, PyObject *args, PyObject *kwargs); - - -PyObject * +/* undefine macro trampoline to PyCMethod_New */ +#undef PyCFunction_NewEx + +/* Forward declarations */ +static PyObject * cfunction_vectorcall_FASTCALL( + PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); +static PyObject * cfunction_vectorcall_FASTCALL_KEYWORDS( + PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); +static PyObject * cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD( + PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); +static PyObject * cfunction_vectorcall_NOARGS( + PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); +static PyObject * cfunction_vectorcall_O( + PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); +static PyObject * cfunction_call( + PyObject *func, PyObject *args, PyObject *kwargs); + + +PyObject * PyCFunction_New(PyMethodDef *ml, PyObject *self) { return PyCFunction_NewEx(ml, self, NULL); @@ -37,80 +37,80 @@ PyCFunction_New(PyMethodDef *ml, PyObject *self) PyObject * PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) { - return PyCMethod_New(ml, self, module, NULL); -} - -PyObject * -PyCMethod_New(PyMethodDef *ml, PyObject *self, PyObject *module, PyTypeObject *cls) -{ - /* Figure out correct vectorcall function to use */ - vectorcallfunc vectorcall; - switch (ml->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | - METH_O | METH_KEYWORDS | METH_METHOD)) - { - case METH_VARARGS: - case METH_VARARGS | METH_KEYWORDS: - /* For METH_VARARGS functions, it's more efficient to use tp_call - * instead of vectorcall. */ - vectorcall = NULL; - break; - case METH_FASTCALL: - vectorcall = cfunction_vectorcall_FASTCALL; - break; - case METH_FASTCALL | METH_KEYWORDS: - vectorcall = cfunction_vectorcall_FASTCALL_KEYWORDS; - break; - case METH_NOARGS: - vectorcall = cfunction_vectorcall_NOARGS; - break; - case METH_O: - vectorcall = cfunction_vectorcall_O; - break; - case METH_METHOD | METH_FASTCALL | METH_KEYWORDS: - vectorcall = cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD; - break; - default: - PyErr_Format(PyExc_SystemError, - "%s() method: bad call flags", ml->ml_name); - return NULL; - } - - PyCFunctionObject *op = NULL; - - if (ml->ml_flags & METH_METHOD) { - if (!cls) { - PyErr_SetString(PyExc_SystemError, - "attempting to create PyCMethod with a METH_METHOD " - "flag but no class"); - return NULL; - } - PyCMethodObject *om = PyObject_GC_New(PyCMethodObject, &PyCMethod_Type); - if (om == NULL) { - return NULL; - } - Py_INCREF(cls); - om->mm_class = cls; - op = (PyCFunctionObject *)om; - } else { - if (cls) { - PyErr_SetString(PyExc_SystemError, - "attempting to create PyCFunction with class " - "but no METH_METHOD flag"); - return NULL; - } + return PyCMethod_New(ml, self, module, NULL); +} + +PyObject * +PyCMethod_New(PyMethodDef *ml, PyObject *self, PyObject *module, PyTypeObject *cls) +{ + /* Figure out correct vectorcall function to use */ + vectorcallfunc vectorcall; + switch (ml->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | + METH_O | METH_KEYWORDS | METH_METHOD)) + { + case METH_VARARGS: + case METH_VARARGS | METH_KEYWORDS: + /* For METH_VARARGS functions, it's more efficient to use tp_call + * instead of vectorcall. */ + vectorcall = NULL; + break; + case METH_FASTCALL: + vectorcall = cfunction_vectorcall_FASTCALL; + break; + case METH_FASTCALL | METH_KEYWORDS: + vectorcall = cfunction_vectorcall_FASTCALL_KEYWORDS; + break; + case METH_NOARGS: + vectorcall = cfunction_vectorcall_NOARGS; + break; + case METH_O: + vectorcall = cfunction_vectorcall_O; + break; + case METH_METHOD | METH_FASTCALL | METH_KEYWORDS: + vectorcall = cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD; + break; + default: + PyErr_Format(PyExc_SystemError, + "%s() method: bad call flags", ml->ml_name); + return NULL; + } + + PyCFunctionObject *op = NULL; + + if (ml->ml_flags & METH_METHOD) { + if (!cls) { + PyErr_SetString(PyExc_SystemError, + "attempting to create PyCMethod with a METH_METHOD " + "flag but no class"); + return NULL; + } + PyCMethodObject *om = PyObject_GC_New(PyCMethodObject, &PyCMethod_Type); + if (om == NULL) { + return NULL; + } + Py_INCREF(cls); + om->mm_class = cls; + op = (PyCFunctionObject *)om; + } else { + if (cls) { + PyErr_SetString(PyExc_SystemError, + "attempting to create PyCFunction with class " + "but no METH_METHOD flag"); + return NULL; + } op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type); - if (op == NULL) { + if (op == NULL) { return NULL; - } + } } - + op->m_weakreflist = NULL; op->m_ml = ml; Py_XINCREF(self); op->m_self = self; Py_XINCREF(module); op->m_module = module; - op->vectorcall = vectorcall; + op->vectorcall = vectorcall; _PyObject_GC_TRACK(op); return (PyObject *)op; } @@ -145,39 +145,39 @@ PyCFunction_GetFlags(PyObject *op) return PyCFunction_GET_FLAGS(op); } -PyTypeObject * -PyCMethod_GetClass(PyObject *op) -{ - if (!PyCFunction_Check(op)) { - PyErr_BadInternalCall(); - return NULL; - } - return PyCFunction_GET_CLASS(op); -} - +PyTypeObject * +PyCMethod_GetClass(PyObject *op) +{ + if (!PyCFunction_Check(op)) { + PyErr_BadInternalCall(); + return NULL; + } + return PyCFunction_GET_CLASS(op); +} + /* Methods (the standard built-in methods, that is) */ static void meth_dealloc(PyCFunctionObject *m) { - // The Py_TRASHCAN mechanism requires that we be able to - // call PyObject_GC_UnTrack twice on an object. - PyObject_GC_UnTrack(m); - Py_TRASHCAN_BEGIN(m, meth_dealloc); + // The Py_TRASHCAN mechanism requires that we be able to + // call PyObject_GC_UnTrack twice on an object. + PyObject_GC_UnTrack(m); + Py_TRASHCAN_BEGIN(m, meth_dealloc); if (m->m_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject*) m); } - // Dereference class before m_self: PyCFunction_GET_CLASS accesses - // PyMethodDef m_ml, which could be kept alive by m_self - Py_XDECREF(PyCFunction_GET_CLASS(m)); + // Dereference class before m_self: PyCFunction_GET_CLASS accesses + // PyMethodDef m_ml, which could be kept alive by m_self + Py_XDECREF(PyCFunction_GET_CLASS(m)); Py_XDECREF(m->m_self); Py_XDECREF(m->m_module); - PyObject_GC_Del(m); - Py_TRASHCAN_END; + PyObject_GC_Del(m); + Py_TRASHCAN_END; } static PyObject * -meth_reduce(PyCFunctionObject *m, PyObject *Py_UNUSED(ignored)) +meth_reduce(PyCFunctionObject *m, PyObject *Py_UNUSED(ignored)) { _Py_IDENTIFIER(getattr); @@ -249,7 +249,7 @@ meth_get__qualname__(PyCFunctionObject *m, void *closure) static int meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg) { - Py_VISIT(PyCFunction_GET_CLASS(m)); + Py_VISIT(PyCFunction_GET_CLASS(m)); Py_VISIT(m->m_self); Py_VISIT(m->m_module); return 0; @@ -279,7 +279,7 @@ static PyGetSetDef meth_getsets [] = { #define OFF(x) offsetof(PyCFunctionObject, x) static PyMemberDef meth_members[] = { - {"__module__", T_OBJECT, OFF(m_module), 0}, + {"__module__", T_OBJECT, OFF(m_module), 0}, {NULL} }; @@ -291,7 +291,7 @@ meth_repr(PyCFunctionObject *m) m->m_ml->ml_name); return PyUnicode_FromFormat("<built-in method %s of %s object at %p>", m->m_ml->ml_name, - Py_TYPE(m->m_self)->tp_name, + Py_TYPE(m->m_self)->tp_name, m->m_self); } @@ -325,7 +325,7 @@ static Py_hash_t meth_hash(PyCFunctionObject *a) { Py_hash_t x, y; - x = _Py_HashPointer(a->m_self); + x = _Py_HashPointer(a->m_self); y = _Py_HashPointer((void*)(a->m_ml->ml_meth)); x ^= y; if (x == -1) @@ -340,22 +340,22 @@ PyTypeObject PyCFunction_Type = { sizeof(PyCFunctionObject), 0, (destructor)meth_dealloc, /* tp_dealloc */ - offsetof(PyCFunctionObject, vectorcall), /* tp_vectorcall_offset */ + offsetof(PyCFunctionObject, vectorcall), /* tp_vectorcall_offset */ 0, /* tp_getattr */ 0, /* tp_setattr */ - 0, /* tp_as_async */ + 0, /* tp_as_async */ (reprfunc)meth_repr, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc)meth_hash, /* tp_hash */ - cfunction_call, /* tp_call */ + cfunction_call, /* tp_call */ 0, /* tp_str */ PyObject_GenericGetAttr, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_HAVE_VECTORCALL, /* tp_flags */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_HAVE_VECTORCALL, /* tp_flags */ 0, /* tp_doc */ (traverseproc)meth_traverse, /* tp_traverse */ 0, /* tp_clear */ @@ -370,186 +370,186 @@ PyTypeObject PyCFunction_Type = { 0, /* tp_dict */ }; -PyTypeObject PyCMethod_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - .tp_name = "builtin_method", - .tp_basicsize = sizeof(PyCMethodObject), - .tp_base = &PyCFunction_Type, -}; - -/* Vectorcall functions for each of the PyCFunction calling conventions, - * except for METH_VARARGS (possibly combined with METH_KEYWORDS) which - * doesn't use vectorcall. - * - * First, common helpers - */ - -static inline int -cfunction_check_kwargs(PyThreadState *tstate, PyObject *func, PyObject *kwnames) -{ - assert(!_PyErr_Occurred(tstate)); - assert(PyCFunction_Check(func)); - if (kwnames && PyTuple_GET_SIZE(kwnames)) { - PyObject *funcstr = _PyObject_FunctionStr(func); - if (funcstr != NULL) { - _PyErr_Format(tstate, PyExc_TypeError, - "%U takes no keyword arguments", funcstr); - Py_DECREF(funcstr); - } - return -1; - } - return 0; -} - -typedef void (*funcptr)(void); - -static inline funcptr -cfunction_enter_call(PyThreadState *tstate, PyObject *func) -{ - if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) { - return NULL; - } - return (funcptr)PyCFunction_GET_FUNCTION(func); -} - -/* Now the actual vectorcall functions */ -static PyObject * -cfunction_vectorcall_FASTCALL( - PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) -{ - PyThreadState *tstate = _PyThreadState_GET(); - if (cfunction_check_kwargs(tstate, func, kwnames)) { - return NULL; - } - Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); - _PyCFunctionFast meth = (_PyCFunctionFast) - cfunction_enter_call(tstate, func); - if (meth == NULL) { - return NULL; - } - PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs); - _Py_LeaveRecursiveCall(tstate); - return result; -} - -static PyObject * -cfunction_vectorcall_FASTCALL_KEYWORDS( - PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) -{ - PyThreadState *tstate = _PyThreadState_GET(); - Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); - _PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords) - cfunction_enter_call(tstate, func); - if (meth == NULL) { - return NULL; - } - PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs, kwnames); - _Py_LeaveRecursiveCall(tstate); - return result; -} - -static PyObject * -cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD( - PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) -{ - PyThreadState *tstate = _PyThreadState_GET(); - PyTypeObject *cls = PyCFunction_GET_CLASS(func); - Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); - PyCMethod meth = (PyCMethod)cfunction_enter_call(tstate, func); - if (meth == NULL) { - return NULL; - } - PyObject *result = meth(PyCFunction_GET_SELF(func), cls, args, nargs, kwnames); - _Py_LeaveRecursiveCall(tstate); - return result; -} - -static PyObject * -cfunction_vectorcall_NOARGS( - PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) -{ - PyThreadState *tstate = _PyThreadState_GET(); - if (cfunction_check_kwargs(tstate, func, kwnames)) { - return NULL; - } - Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); - if (nargs != 0) { - PyObject *funcstr = _PyObject_FunctionStr(func); - if (funcstr != NULL) { - _PyErr_Format(tstate, PyExc_TypeError, - "%U takes no arguments (%zd given)", funcstr, nargs); - Py_DECREF(funcstr); - } - return NULL; - } - PyCFunction meth = (PyCFunction)cfunction_enter_call(tstate, func); - if (meth == NULL) { - return NULL; - } - PyObject *result = meth(PyCFunction_GET_SELF(func), NULL); - _Py_LeaveRecursiveCall(tstate); - return result; -} - -static PyObject * -cfunction_vectorcall_O( - PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) -{ - PyThreadState *tstate = _PyThreadState_GET(); - if (cfunction_check_kwargs(tstate, func, kwnames)) { - return NULL; - } - Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); - if (nargs != 1) { - PyObject *funcstr = _PyObject_FunctionStr(func); - if (funcstr != NULL) { - _PyErr_Format(tstate, PyExc_TypeError, - "%U takes exactly one argument (%zd given)", funcstr, nargs); - Py_DECREF(funcstr); - } - return NULL; - } - PyCFunction meth = (PyCFunction)cfunction_enter_call(tstate, func); - if (meth == NULL) { - return NULL; - } - PyObject *result = meth(PyCFunction_GET_SELF(func), args[0]); - _Py_LeaveRecursiveCall(tstate); - return result; -} - - -static PyObject * -cfunction_call(PyObject *func, PyObject *args, PyObject *kwargs) -{ - assert(kwargs == NULL || PyDict_Check(kwargs)); - - PyThreadState *tstate = _PyThreadState_GET(); - assert(!_PyErr_Occurred(tstate)); - - int flags = PyCFunction_GET_FLAGS(func); - if (!(flags & METH_VARARGS)) { - /* If this is not a METH_VARARGS function, delegate to vectorcall */ - return PyVectorcall_Call(func, args, kwargs); - } - - /* For METH_VARARGS, we cannot use vectorcall as the vectorcall pointer - * is NULL. This is intentional, since vectorcall would be slower. */ - PyCFunction meth = PyCFunction_GET_FUNCTION(func); - PyObject *self = PyCFunction_GET_SELF(func); - - PyObject *result; - if (flags & METH_KEYWORDS) { - result = (*(PyCFunctionWithKeywords)(void(*)(void))meth)(self, args, kwargs); - } - else { - if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) { - _PyErr_Format(tstate, PyExc_TypeError, - "%.200s() takes no keyword arguments", - ((PyCFunctionObject*)func)->m_ml->ml_name); - return NULL; - } - result = meth(self, args); - } - return _Py_CheckFunctionResult(tstate, func, result, NULL); -} +PyTypeObject PyCMethod_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + .tp_name = "builtin_method", + .tp_basicsize = sizeof(PyCMethodObject), + .tp_base = &PyCFunction_Type, +}; + +/* Vectorcall functions for each of the PyCFunction calling conventions, + * except for METH_VARARGS (possibly combined with METH_KEYWORDS) which + * doesn't use vectorcall. + * + * First, common helpers + */ + +static inline int +cfunction_check_kwargs(PyThreadState *tstate, PyObject *func, PyObject *kwnames) +{ + assert(!_PyErr_Occurred(tstate)); + assert(PyCFunction_Check(func)); + if (kwnames && PyTuple_GET_SIZE(kwnames)) { + PyObject *funcstr = _PyObject_FunctionStr(func); + if (funcstr != NULL) { + _PyErr_Format(tstate, PyExc_TypeError, + "%U takes no keyword arguments", funcstr); + Py_DECREF(funcstr); + } + return -1; + } + return 0; +} + +typedef void (*funcptr)(void); + +static inline funcptr +cfunction_enter_call(PyThreadState *tstate, PyObject *func) +{ + if (_Py_EnterRecursiveCall(tstate, " while calling a Python object")) { + return NULL; + } + return (funcptr)PyCFunction_GET_FUNCTION(func); +} + +/* Now the actual vectorcall functions */ +static PyObject * +cfunction_vectorcall_FASTCALL( + PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) +{ + PyThreadState *tstate = _PyThreadState_GET(); + if (cfunction_check_kwargs(tstate, func, kwnames)) { + return NULL; + } + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + _PyCFunctionFast meth = (_PyCFunctionFast) + cfunction_enter_call(tstate, func); + if (meth == NULL) { + return NULL; + } + PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs); + _Py_LeaveRecursiveCall(tstate); + return result; +} + +static PyObject * +cfunction_vectorcall_FASTCALL_KEYWORDS( + PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) +{ + PyThreadState *tstate = _PyThreadState_GET(); + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + _PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords) + cfunction_enter_call(tstate, func); + if (meth == NULL) { + return NULL; + } + PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs, kwnames); + _Py_LeaveRecursiveCall(tstate); + return result; +} + +static PyObject * +cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD( + PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) +{ + PyThreadState *tstate = _PyThreadState_GET(); + PyTypeObject *cls = PyCFunction_GET_CLASS(func); + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + PyCMethod meth = (PyCMethod)cfunction_enter_call(tstate, func); + if (meth == NULL) { + return NULL; + } + PyObject *result = meth(PyCFunction_GET_SELF(func), cls, args, nargs, kwnames); + _Py_LeaveRecursiveCall(tstate); + return result; +} + +static PyObject * +cfunction_vectorcall_NOARGS( + PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) +{ + PyThreadState *tstate = _PyThreadState_GET(); + if (cfunction_check_kwargs(tstate, func, kwnames)) { + return NULL; + } + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + if (nargs != 0) { + PyObject *funcstr = _PyObject_FunctionStr(func); + if (funcstr != NULL) { + _PyErr_Format(tstate, PyExc_TypeError, + "%U takes no arguments (%zd given)", funcstr, nargs); + Py_DECREF(funcstr); + } + return NULL; + } + PyCFunction meth = (PyCFunction)cfunction_enter_call(tstate, func); + if (meth == NULL) { + return NULL; + } + PyObject *result = meth(PyCFunction_GET_SELF(func), NULL); + _Py_LeaveRecursiveCall(tstate); + return result; +} + +static PyObject * +cfunction_vectorcall_O( + PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) +{ + PyThreadState *tstate = _PyThreadState_GET(); + if (cfunction_check_kwargs(tstate, func, kwnames)) { + return NULL; + } + Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); + if (nargs != 1) { + PyObject *funcstr = _PyObject_FunctionStr(func); + if (funcstr != NULL) { + _PyErr_Format(tstate, PyExc_TypeError, + "%U takes exactly one argument (%zd given)", funcstr, nargs); + Py_DECREF(funcstr); + } + return NULL; + } + PyCFunction meth = (PyCFunction)cfunction_enter_call(tstate, func); + if (meth == NULL) { + return NULL; + } + PyObject *result = meth(PyCFunction_GET_SELF(func), args[0]); + _Py_LeaveRecursiveCall(tstate); + return result; +} + + +static PyObject * +cfunction_call(PyObject *func, PyObject *args, PyObject *kwargs) +{ + assert(kwargs == NULL || PyDict_Check(kwargs)); + + PyThreadState *tstate = _PyThreadState_GET(); + assert(!_PyErr_Occurred(tstate)); + + int flags = PyCFunction_GET_FLAGS(func); + if (!(flags & METH_VARARGS)) { + /* If this is not a METH_VARARGS function, delegate to vectorcall */ + return PyVectorcall_Call(func, args, kwargs); + } + + /* For METH_VARARGS, we cannot use vectorcall as the vectorcall pointer + * is NULL. This is intentional, since vectorcall would be slower. */ + PyCFunction meth = PyCFunction_GET_FUNCTION(func); + PyObject *self = PyCFunction_GET_SELF(func); + + PyObject *result; + if (flags & METH_KEYWORDS) { + result = (*(PyCFunctionWithKeywords)(void(*)(void))meth)(self, args, kwargs); + } + else { + if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) { + _PyErr_Format(tstate, PyExc_TypeError, + "%.200s() takes no keyword arguments", + ((PyCFunctionObject*)func)->m_ml->ml_name); + return NULL; + } + result = meth(self, args); + } + return _Py_CheckFunctionResult(tstate, func, result, NULL); +} |