@@ -1595,21 +1595,51 @@ static PyType_Spec attrgetter_type_spec = {
15951595typedef struct {
15961596 PyObject_HEAD
15971597 PyObject * name ;
1598- PyObject * xargs ; // reference to arguments passed in constructor
1598+ PyObject * args ;
15991599 PyObject * kwds ;
16001600 PyObject * * vectorcall_args ; /* Borrowed references */
16011601 PyObject * vectorcall_kwnames ;
16021602 vectorcallfunc vectorcall ;
16031603} methodcallerobject ;
16041604
16051605
1606+ #define _METHODCALLER_MAX_ARGS 8
1607+
1608+ static PyObject *
1609+ methodcaller_vectorcall (
1610+ methodcallerobject * mc , PyObject * const * args , size_t nargsf , PyObject * kwnames )
1611+ {
1612+ printf ("methodcaller_vectorcall\n" );
1613+ if (!_PyArg_CheckPositional ("methodcaller" , PyVectorcall_NARGS (nargsf ), 1 , 1 )
1614+ || !_PyArg_NoKwnames ("methodcaller" , kwnames )) {
1615+ return NULL ;
1616+ }
1617+ assert (mc -> vectorcall_args != NULL );
1618+
1619+ Py_ssize_t number_of_arguments = 1 + PyTuple_GET_SIZE (mc -> args ) +
1620+ (mc -> vectorcall_kwnames ? PyTuple_GET_SIZE (mc -> vectorcall_kwnames ):0 ) + 1 ;
1621+
1622+ PyObject * tmp_args [_METHODCALLER_MAX_ARGS ];
1623+ tmp_args [0 ] = args [0 ];
1624+ if (number_of_arguments ) {
1625+ assert (1 + number_of_arguments <= _METHODCALLER_MAX_ARGS );
1626+ memcpy (tmp_args + 1 , mc -> vectorcall_args , sizeof (PyObject * ) * number_of_arguments );
1627+ }
1628+ PyObject * result = PyObject_VectorcallMethod (
1629+ mc -> name , tmp_args ,
1630+ (1 + PyTuple_GET_SIZE (mc -> args )) | PY_VECTORCALL_ARGUMENTS_OFFSET ,
1631+ mc -> vectorcall_kwnames );
1632+
1633+ PyMem_Free (tmp_args );
1634+ return result ;
1635+ }
1636+
16061637static int _methodcaller_initialize_vectorcall (methodcallerobject * mc )
16071638{
1608- PyObject * args = mc -> xargs ;
1639+ PyObject * args = mc -> args ;
16091640 PyObject * kwds = mc -> kwds ;
16101641
1611- Py_ssize_t nargs = PyTuple_GET_SIZE (args );
1612- assert (nargs > 0 );
1642+ Py_ssize_t nargs = 1 + PyTuple_GET_SIZE (args );
16131643 mc -> vectorcall_args = PyMem_Calloc (
16141644 nargs + (kwds ? PyDict_Size (kwds ) : 0 ),
16151645 sizeof (PyObject * ));
@@ -1619,8 +1649,8 @@ static int _methodcaller_initialize_vectorcall(methodcallerobject* mc)
16191649 }
16201650 /* The first item of vectorcall_args will be filled with obj later */
16211651 if (nargs > 1 ) {
1622- memcpy (mc -> vectorcall_args , PySequence_Fast_ITEMS (args ),
1623- nargs * sizeof (PyObject * ));
1652+ memcpy (mc -> vectorcall_args + 1 , PySequence_Fast_ITEMS (args ),
1653+ ( nargs - 1 ) * sizeof (PyObject * ));
16241654 }
16251655 if (kwds ) {
16261656 const Py_ssize_t nkwds = PyDict_Size (kwds );
@@ -1640,47 +1670,11 @@ static int _methodcaller_initialize_vectorcall(methodcallerobject* mc)
16401670 else {
16411671 mc -> vectorcall_kwnames = NULL ;
16421672 }
1643- return 1 ;
1644- }
1673+ //mc->vectorcall = (vectorcallfunc)methodcaller_vectorcall;
16451674
1646-
1647- static PyObject *
1648- methodcaller_vectorcall (
1649- methodcallerobject * mc , PyObject * const * args , size_t nargsf , PyObject * kwnames )
1650- {
1651- if (!_PyArg_CheckPositional ("methodcaller" , PyVectorcall_NARGS (nargsf ), 1 , 1 )
1652- || !_PyArg_NoKwnames ("methodcaller" , kwnames )) {
1653- return NULL ;
1654- }
1655- if (mc -> vectorcall_args == NULL ) {
1656- if (_methodcaller_initialize_vectorcall (mc ) < 0 ) {
1657- return NULL ;
1658- }
1659- }
1660-
1661- assert (mc -> vectorcall_args != 0 );
1662-
1663- Py_ssize_t number_of_arguments = PyTuple_GET_SIZE (mc -> xargs ) +
1664- (mc -> vectorcall_kwnames ? PyTuple_GET_SIZE (mc -> vectorcall_kwnames ):0 ) + 1 ;
1665- size_t buffer_size = sizeof (PyObject * ) * (number_of_arguments + 1 );
1666-
1667- // for number_of_arguments == 1 we could optimize by setting tmp_args equal to &args
1668- PyObject * * tmp_args = (PyObject * * ) PyMem_Malloc (buffer_size );
1669- if (tmp_args == NULL ) {
1670- PyErr_NoMemory ();
1671- return NULL ;
1672- }
1673- memcpy (tmp_args , mc -> vectorcall_args , buffer_size );
1674- tmp_args [0 ] = args [0 ];
1675- return PyObject_VectorcallMethod (
1676- mc -> name , tmp_args ,
1677- (PyTuple_GET_SIZE (mc -> xargs )) | PY_VECTORCALL_ARGUMENTS_OFFSET ,
1678- mc -> vectorcall_kwnames );
1679-
1680- PyMem_Free (tmp_args );
1675+ return 1 ;
16811676}
16821677
1683-
16841678/* AC 3.5: variable number of arguments, not currently support by AC */
16851679static PyObject *
16861680methodcaller_new (PyTypeObject * type , PyObject * args , PyObject * kwds )
@@ -1713,11 +1707,27 @@ methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
17131707 _PyUnicode_InternMortal (interp , & name );
17141708 mc -> name = name ;
17151709
1716- mc -> xargs = Py_XNewRef (args ); // allows us to use borrowed references
1710+ mc -> args = PyTuple_GetSlice (args , 1 , PyTuple_GET_SIZE (args ));
1711+ if (mc -> args == NULL ) {
1712+ Py_DECREF (mc );
1713+ return NULL ;
1714+ }
17171715 mc -> kwds = Py_XNewRef (kwds );
1718- mc -> vectorcall_args = 0 ;
1716+ mc -> vectorcall_args = NULL ;
1717+
1718+ Py_ssize_t vectorcall_size = PyTuple_GET_SIZE (args )
1719+ + (kwds ? PyDict_Size (kwds ) : 0 );
1720+ printf ("methodcaller_new %d %d\n" , PyTuple_GET_SIZE (args ), vectorcall_size );
1721+ if (vectorcall_size < (_METHODCALLER_MAX_ARGS - 10 )) {
1722+ printf ("hih\n" );
1723+ if (_methodcaller_initialize_vectorcall (mc ) < 0 ) {
1724+ Py_XDECREF (mc -> args );
1725+ Py_XDECREF (mc -> kwds );
1726+ return NULL ;
1727+ }
1728+ }
17191729
1720- mc -> vectorcall = (vectorcallfunc )methodcaller_vectorcall ;
1730+ // mc->vectorcall = (vectorcallfunc)methodcaller_vectorcall;
17211731
17221732 PyObject_GC_Track (mc );
17231733 return (PyObject * )mc ;
@@ -1726,19 +1736,22 @@ methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
17261736static void
17271737methodcaller_clear (methodcallerobject * mc )
17281738{
1739+ printf ("methodcaller_clear\n" );
1740+
17291741 Py_CLEAR (mc -> name );
1730- Py_CLEAR (mc -> xargs );
1742+ Py_CLEAR (mc -> args );
17311743 Py_CLEAR (mc -> kwds );
17321744 if (mc -> vectorcall_args != NULL ) {
17331745 PyMem_Free (mc -> vectorcall_args );
1734- mc -> vectorcall_args = 0 ;
17351746 Py_CLEAR (mc -> vectorcall_kwnames );
17361747 }
17371748}
17381749
17391750static void
17401751methodcaller_dealloc (methodcallerobject * mc )
17411752{
1753+ printf ("methodcaller_dealloc\n" );
1754+
17421755 PyTypeObject * tp = Py_TYPE (mc );
17431756 PyObject_GC_UnTrack (mc );
17441757 methodcaller_clear (mc );
@@ -1749,8 +1762,9 @@ methodcaller_dealloc(methodcallerobject *mc)
17491762static int
17501763methodcaller_traverse (methodcallerobject * mc , visitproc visit , void * arg )
17511764{
1765+ printf ("methodcaller_traverse\n" );
17521766 Py_VISIT (mc -> name );
1753- Py_VISIT (mc -> xargs );
1767+ Py_VISIT (mc -> args );
17541768 Py_VISIT (mc -> kwds );
17551769 Py_VISIT (Py_TYPE (mc ));
17561770 return 0 ;
@@ -1759,6 +1773,8 @@ methodcaller_traverse(methodcallerobject *mc, visitproc visit, void *arg)
17591773static PyObject *
17601774methodcaller_call (methodcallerobject * mc , PyObject * args , PyObject * kw )
17611775{
1776+ printf ("methodcaller_call\n" );
1777+ return Py_None ;
17621778 PyObject * method , * obj , * result ;
17631779
17641780 if (!_PyArg_NoKeywords ("methodcaller" , kw ))
@@ -1770,15 +1786,7 @@ methodcaller_call(methodcallerobject *mc, PyObject *args, PyObject *kw)
17701786 if (method == NULL )
17711787 return NULL ;
17721788
1773-
1774- PyObject * cargs = PyTuple_GetSlice (mc -> xargs , 1 , PyTuple_GET_SIZE (mc -> xargs ));
1775- if (cargs == NULL ) {
1776- Py_DECREF (method );
1777- return NULL ;
1778- }
1779-
1780- result = PyObject_Call (method , cargs , mc -> kwds );
1781- Py_DECREF (cargs );
1789+ result = PyObject_Call (method , mc -> args , mc -> kwds );
17821790 Py_DECREF (method );
17831791 return result ;
17841792}
@@ -1796,7 +1804,7 @@ methodcaller_repr(methodcallerobject *mc)
17961804 }
17971805
17981806 numkwdargs = mc -> kwds != NULL ? PyDict_GET_SIZE (mc -> kwds ) : 0 ;
1799- numposargs = PyTuple_GET_SIZE (mc -> xargs ) - 1 ;
1807+ numposargs = PyTuple_GET_SIZE (mc -> args ) ;
18001808 numtotalargs = numposargs + numkwdargs ;
18011809
18021810 if (numtotalargs == 0 ) {
@@ -1812,7 +1820,7 @@ methodcaller_repr(methodcallerobject *mc)
18121820 }
18131821
18141822 for (i = 0 ; i < numposargs ; ++ i ) {
1815- PyObject * onerepr = PyObject_Repr (PyTuple_GET_ITEM (mc -> xargs , i + 1 ));
1823+ PyObject * onerepr = PyObject_Repr (PyTuple_GET_ITEM (mc -> args , i ));
18161824 if (onerepr == NULL )
18171825 goto done ;
18181826 PyTuple_SET_ITEM (argreprs , i , onerepr );
@@ -1864,14 +1872,14 @@ methodcaller_reduce(methodcallerobject *mc, PyObject *Py_UNUSED(ignored))
18641872{
18651873 if (!mc -> kwds || PyDict_GET_SIZE (mc -> kwds ) == 0 ) {
18661874 Py_ssize_t i ;
1867- Py_ssize_t newarg_size = PyTuple_GET_SIZE (mc -> xargs );
1868- PyObject * newargs = PyTuple_New (newarg_size );
1875+ Py_ssize_t callargcount = PyTuple_GET_SIZE (mc -> args );
1876+ PyObject * newargs = PyTuple_New (1 + callargcount );
18691877 if (newargs == NULL )
18701878 return NULL ;
18711879 PyTuple_SET_ITEM (newargs , 0 , Py_NewRef (mc -> name ));
1872- for (i = 1 ; i < newarg_size ; ++ i ) {
1873- PyObject * arg = PyTuple_GET_ITEM (mc -> xargs , i );
1874- PyTuple_SET_ITEM (newargs , i , Py_NewRef (arg ));
1880+ for (i = 0 ; i < callargcount ; ++ i ) {
1881+ PyObject * arg = PyTuple_GET_ITEM (mc -> args , i );
1882+ PyTuple_SET_ITEM (newargs , i + 1 , Py_NewRef (arg ));
18751883 }
18761884 return Py_BuildValue ("ON" , Py_TYPE (mc ), newargs );
18771885 }
@@ -1889,12 +1897,7 @@ methodcaller_reduce(methodcallerobject *mc, PyObject *Py_UNUSED(ignored))
18891897 constructor = PyObject_VectorcallDict (partial , newargs , 2 , mc -> kwds );
18901898
18911899 Py_DECREF (partial );
1892- PyObject * args = PyTuple_GetSlice (mc -> xargs , 1 , PyTuple_GET_SIZE (mc -> xargs ));
1893- if (!args ) {
1894- Py_DECREF (constructor );
1895- return NULL ;
1896- }
1897- return Py_BuildValue ("NO" , constructor , args );
1900+ return Py_BuildValue ("NO" , constructor , mc -> args );
18981901 }
18991902}
19001903
0 commit comments