@@ -625,22 +625,83 @@ _PyMethodDef_RawFastCallKeywords(PyMethodDef *method, PyObject *self,
625
625
}
626
626
627
627
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 */
628
659
PyObject *
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 )
632
662
{
633
- PyObject * result ;
663
+ PyCFunction_VECTORCALL_BEGIN (0 )
664
+ result = ((_PyCFunctionFast )meth )(self , args , nargs );
665
+ PyCFunction_VECTORCALL_END
666
+ }
634
667
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
+ }
638
676
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
644
705
}
645
706
646
707
0 commit comments