@@ -625,22 +625,83 @@ _PyMethodDef_RawFastCallKeywords(PyMethodDef *method, PyObject *self,
625625}
626626
627627
628+ /* Vectorcall functions for each of the PyCFunction calling conventions,
629+ * except for METH_VARARGS (possibly combined with METH_KEYWORDS) which
630+ * doesn't use vectorcall.
631+ *
632+ * First two macros to define common boilerplate
633+ */
634+ #define PyCFunction_VECTORCALL_BEGIN (ALLOW_KWARGS ) \
635+ assert(!PyErr_Occurred()); \
636+ assert(PyCFunction_Check(func)); \
637+ PyCFunctionObject *f = (PyCFunctionObject *)func; \
638+ Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); \
639+ PyObject *self = f->m_self; \
640+ PyMethodDef *method = f->m_ml; \
641+ const char *name = method->ml_name; \
642+ void(*meth)(void) = (void(*)(void))method->ml_meth; \
643+ PyObject *result = NULL; \
644+ \
645+ if (!ALLOW_KWARGS && kwnames && PyTuple_GET_SIZE(kwnames) > 0) { \
646+ PyErr_Format(PyExc_TypeError, \
647+ "%.200s() takes no keyword arguments", name); \
648+ return NULL; \
649+ } \
650+ if (Py_EnterRecursiveCall(" while calling a Python object")) { \
651+ return NULL; \
652+ }
653+
654+ #define PyCFunction_VECTORCALL_END \
655+ Py_LeaveRecursiveCall(); \
656+ return _Py_CheckFunctionResult(func, result, NULL);
657+
658+ /* Now the actual vectorcall functions */
628659PyObject *
629- _PyCFunction_Vectorcall (PyObject * func ,
630- PyObject * const * args , size_t nargsf ,
631- PyObject * kwnames )
660+ _PyCFunction_Vectorcall_FASTCALL (
661+ PyObject * func , PyObject * const * args , size_t nargsf , PyObject * kwnames )
632662{
633- PyObject * result ;
663+ PyCFunction_VECTORCALL_BEGIN (0 )
664+ result = ((_PyCFunctionFast )meth )(self , args , nargs );
665+ PyCFunction_VECTORCALL_END
666+ }
634667
635- assert (func != NULL );
636- assert (PyCFunction_Check (func ));
637- Py_ssize_t nargs = PyVectorcall_NARGS (nargsf );
668+ PyObject *
669+ _PyCFunction_Vectorcall_FASTCALL_KEYWORDS (
670+ PyObject * func , PyObject * const * args , size_t nargsf , PyObject * kwnames )
671+ {
672+ PyCFunction_VECTORCALL_BEGIN (1 )
673+ result = ((_PyCFunctionFastWithKeywords )meth )(self , args , nargs , kwnames );
674+ PyCFunction_VECTORCALL_END
675+ }
638676
639- result = _PyMethodDef_RawFastCallKeywords (((PyCFunctionObject * )func )-> m_ml ,
640- PyCFunction_GET_SELF (func ),
641- args , nargs , kwnames );
642- result = _Py_CheckFunctionResult (func , result , NULL );
643- return result ;
677+ PyObject *
678+ _PyCFunction_Vectorcall_NOARGS (
679+ PyObject * func , PyObject * const * args , size_t nargsf , PyObject * kwnames )
680+ {
681+ PyCFunction_VECTORCALL_BEGIN (0 )
682+ if (nargs != 0 ) {
683+ PyErr_Format (PyExc_TypeError ,
684+ "%.200s() takes no arguments (%zd given)" , name , nargs );
685+ }
686+ else {
687+ result = ((PyCFunction )meth )(self , NULL );
688+ }
689+ PyCFunction_VECTORCALL_END
690+ }
691+
692+ PyObject *
693+ _PyCFunction_Vectorcall_O (
694+ PyObject * func , PyObject * const * args , size_t nargsf , PyObject * kwnames )
695+ {
696+ PyCFunction_VECTORCALL_BEGIN (0 )
697+ if (nargs != 1 ) {
698+ PyErr_Format (PyExc_TypeError ,
699+ "%.200s() takes exactly one argument (%zd given)" , name , nargs );
700+ }
701+ else {
702+ result = ((PyCFunction )meth )(self , args [0 ]);
703+ }
704+ PyCFunction_VECTORCALL_END
644705}
645706
646707
0 commit comments