1
1
#include "Python.h"
2
2
#include "pycore_moduleobject.h" // _PyModule_GetState()
3
+ #include "structmember.h"
3
4
#include "clinic/_operator.c.h"
4
5
5
6
typedef struct {
@@ -1478,14 +1479,33 @@ typedef struct {
1478
1479
PyObject * name ;
1479
1480
PyObject * args ;
1480
1481
PyObject * kwds ;
1482
+ PyObject * * vectorcall_args ; /* Borrowed references */
1483
+ PyObject * vectorcall_kwnames ;
1484
+ vectorcallfunc vectorcall ;
1481
1485
} methodcallerobject ;
1482
1486
1487
+ static PyObject *
1488
+ methodcaller_vectorcall (
1489
+ methodcallerobject * mc , PyObject * const * args , size_t nargsf , PyObject * kwnames )
1490
+ {
1491
+ if (!_PyArg_CheckPositional ("methodcaller" , PyVectorcall_NARGS (nargsf ), 1 , 1 )
1492
+ || !_PyArg_NoKwnames ("methodcaller" , kwnames )) {
1493
+ return NULL ;
1494
+ }
1495
+ mc -> vectorcall_args [0 ] = args [0 ];
1496
+ return PyObject_VectorcallMethod (
1497
+ mc -> name , mc -> vectorcall_args ,
1498
+ (1 + PyTuple_GET_SIZE (mc -> args )) | PY_VECTORCALL_ARGUMENTS_OFFSET ,
1499
+ mc -> vectorcall_kwnames );
1500
+ }
1501
+
1483
1502
/* AC 3.5: variable number of arguments, not currently support by AC */
1484
1503
static PyObject *
1485
1504
methodcaller_new (PyTypeObject * type , PyObject * args , PyObject * kwds )
1486
1505
{
1487
1506
methodcallerobject * mc ;
1488
- PyObject * name ;
1507
+ PyObject * name , * key , * value ;
1508
+ Py_ssize_t nargs , i , ppos ;
1489
1509
1490
1510
if (PyTuple_GET_SIZE (args ) < 1 ) {
1491
1511
PyErr_SetString (PyExc_TypeError , "methodcaller needs at least "
@@ -1521,6 +1541,32 @@ methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1521
1541
return NULL ;
1522
1542
}
1523
1543
1544
+ nargs = PyTuple_GET_SIZE (args ) - 1 ;
1545
+ mc -> vectorcall_args = PyMem_Calloc (
1546
+ 1 + nargs + (kwds ? PyDict_Size (kwds ) : 0 ),
1547
+ sizeof (PyObject * ));
1548
+ if (!mc -> vectorcall_args ) {
1549
+ return PyErr_NoMemory ();
1550
+ }
1551
+ /* The first item of vectorcall_args will be filled with obj. */
1552
+ memcpy (mc -> vectorcall_args + 1 , PySequence_Fast_ITEMS (mc -> args ),
1553
+ nargs * sizeof (PyObject * ));
1554
+ if (kwds ) {
1555
+ mc -> vectorcall_kwnames = PySequence_Tuple (kwds );
1556
+ if (!mc -> vectorcall_kwnames ) {
1557
+ return NULL ;
1558
+ }
1559
+ i = ppos = 0 ;
1560
+ while (PyDict_Next (kwds , & ppos , & key , & value )) {
1561
+ mc -> vectorcall_args [1 + nargs + i ] = value ;
1562
+ ++ i ;
1563
+ }
1564
+ }
1565
+ else {
1566
+ mc -> vectorcall_kwnames = NULL ;
1567
+ }
1568
+ mc -> vectorcall = (vectorcallfunc )methodcaller_vectorcall ;
1569
+
1524
1570
PyObject_GC_Track (mc );
1525
1571
return (PyObject * )mc ;
1526
1572
}
@@ -1531,6 +1577,7 @@ methodcaller_clear(methodcallerobject *mc)
1531
1577
Py_CLEAR (mc -> name );
1532
1578
Py_CLEAR (mc -> args );
1533
1579
Py_CLEAR (mc -> kwds );
1580
+ Py_CLEAR (mc -> vectorcall_kwnames );
1534
1581
return 0 ;
1535
1582
}
1536
1583
@@ -1540,6 +1587,7 @@ methodcaller_dealloc(methodcallerobject *mc)
1540
1587
PyTypeObject * tp = Py_TYPE (mc );
1541
1588
PyObject_GC_UnTrack (mc );
1542
1589
(void )methodcaller_clear (mc );
1590
+ PyMem_Free (mc -> vectorcall_args );
1543
1591
tp -> tp_free (mc );
1544
1592
Py_DECREF (tp );
1545
1593
}
@@ -1696,6 +1744,12 @@ static PyMethodDef methodcaller_methods[] = {
1696
1744
reduce_doc },
1697
1745
{NULL }
1698
1746
};
1747
+
1748
+ static PyMemberDef methodcaller_members [] = {
1749
+ {"__vectorcalloffset__" , T_PYSSIZET , offsetof(methodcallerobject , vectorcall ), READONLY },
1750
+ {NULL }
1751
+ };
1752
+
1699
1753
PyDoc_STRVAR (methodcaller_doc ,
1700
1754
"methodcaller(name, ...) --> methodcaller object\n\
1701
1755
\n\
@@ -1711,6 +1765,7 @@ static PyType_Slot methodcaller_type_slots[] = {
1711
1765
{Py_tp_traverse , methodcaller_traverse },
1712
1766
{Py_tp_clear , methodcaller_clear },
1713
1767
{Py_tp_methods , methodcaller_methods },
1768
+ {Py_tp_members , methodcaller_members },
1714
1769
{Py_tp_new , methodcaller_new },
1715
1770
{Py_tp_getattro , PyObject_GenericGetAttr },
1716
1771
{Py_tp_repr , methodcaller_repr },
@@ -1722,7 +1777,7 @@ static PyType_Spec methodcaller_type_spec = {
1722
1777
.basicsize = sizeof (methodcallerobject ),
1723
1778
.itemsize = 0 ,
1724
1779
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1725
- Py_TPFLAGS_IMMUTABLETYPE ),
1780
+ Py_TPFLAGS_HAVE_VECTORCALL | Py_TPFLAGS_IMMUTABLETYPE ),
1726
1781
.slots = methodcaller_type_slots ,
1727
1782
};
1728
1783
0 commit comments