2
2
#include "pycore_modsupport.h" // _PyArg_NoKwnames()
3
3
#include "pycore_moduleobject.h" // _PyModule_GetState()
4
4
#include "pycore_runtime.h" // _Py_ID()
5
+
5
6
#include "structmember.h" // PyMemberDef
6
7
#include "clinic/_operator.c.h"
7
8
@@ -1548,7 +1549,7 @@ static PyType_Spec attrgetter_type_spec = {
1548
1549
typedef struct {
1549
1550
PyObject_HEAD
1550
1551
PyObject * name ;
1551
- PyObject * args ;
1552
+ PyObject * xargs ; // reference to arguments passed in constructor
1552
1553
PyObject * kwds ;
1553
1554
PyObject * * vectorcall_args ; /* Borrowed references */
1554
1555
PyObject * vectorcall_kwnames ;
@@ -1566,7 +1567,7 @@ methodcaller_vectorcall(
1566
1567
mc -> vectorcall_args [0 ] = args [0 ];
1567
1568
return PyObject_VectorcallMethod (
1568
1569
mc -> name , mc -> vectorcall_args ,
1569
- (1 + PyTuple_GET_SIZE (mc -> args )) | PY_VECTORCALL_ARGUMENTS_OFFSET ,
1570
+ (PyTuple_GET_SIZE (mc -> xargs )) | PY_VECTORCALL_ARGUMENTS_OFFSET ,
1570
1571
mc -> vectorcall_kwnames );
1571
1572
}
1572
1573
@@ -1576,7 +1577,6 @@ methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1576
1577
{
1577
1578
methodcallerobject * mc ;
1578
1579
PyObject * name , * key , * value ;
1579
- Py_ssize_t nargs , i , ppos ;
1580
1580
1581
1581
if (PyTuple_GET_SIZE (args ) < 1 ) {
1582
1582
PyErr_SetString (PyExc_TypeError , "methodcaller needs at least "
@@ -1598,37 +1598,34 @@ methodcaller_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
1598
1598
return NULL ;
1599
1599
}
1600
1600
1601
- name = PyTuple_GET_ITEM (args , 0 );
1602
1601
Py_INCREF (name );
1603
1602
PyUnicode_InternInPlace (& name );
1604
1603
mc -> name = name ;
1605
1604
1605
+ mc -> xargs = Py_XNewRef (args ); // allows us to use borrowed references
1606
1606
mc -> kwds = Py_XNewRef (kwds );
1607
1607
1608
- mc -> args = PyTuple_GetSlice (args , 1 , PyTuple_GET_SIZE (args ));
1609
- if (mc -> args == NULL ) {
1610
- Py_DECREF (mc );
1611
- return NULL ;
1612
- }
1613
-
1614
- nargs = PyTuple_GET_SIZE (args ) - 1 ;
1608
+ Py_ssize_t nargs = PyTuple_GET_SIZE (args );
1615
1609
mc -> vectorcall_args = PyMem_Calloc (
1616
- 1 + nargs + (kwds ? PyDict_Size (kwds ) : 0 ),
1610
+ nargs + (kwds ? PyDict_Size (kwds ) : 0 ),
1617
1611
sizeof (PyObject * ));
1618
1612
if (!mc -> vectorcall_args ) {
1619
1613
return PyErr_NoMemory ();
1620
1614
}
1621
- /* The first item of vectorcall_args will be filled with obj. */
1622
- memcpy (mc -> vectorcall_args + 1 , PySequence_Fast_ITEMS (mc -> args ),
1615
+ /* The first item of vectorcall_args will be filled with obj later */
1616
+ if (nargs > 1 ) {
1617
+ memcpy (mc -> vectorcall_args , PySequence_Fast_ITEMS (args ),
1623
1618
nargs * sizeof (PyObject * ));
1619
+ }
1624
1620
if (kwds ) {
1625
1621
mc -> vectorcall_kwnames = PySequence_Tuple (kwds );
1626
1622
if (!mc -> vectorcall_kwnames ) {
1627
1623
return NULL ;
1628
1624
}
1629
- i = ppos = 0 ;
1625
+ Py_ssize_t i = 0 ;
1626
+ Py_ssize_t ppos = 0 ;
1630
1627
while (PyDict_Next (kwds , & ppos , & key , & value )) {
1631
- mc -> vectorcall_args [1 + nargs + i ] = value ;
1628
+ mc -> vectorcall_args [ nargs + i ] = value ;
1632
1629
++ i ;
1633
1630
}
1634
1631
}
@@ -1645,7 +1642,7 @@ static int
1645
1642
methodcaller_clear (methodcallerobject * mc )
1646
1643
{
1647
1644
Py_CLEAR (mc -> name );
1648
- Py_CLEAR (mc -> args );
1645
+ Py_CLEAR (mc -> xargs );
1649
1646
Py_CLEAR (mc -> kwds );
1650
1647
Py_CLEAR (mc -> vectorcall_kwnames );
1651
1648
return 0 ;
@@ -1666,30 +1663,12 @@ static int
1666
1663
methodcaller_traverse (methodcallerobject * mc , visitproc visit , void * arg )
1667
1664
{
1668
1665
Py_VISIT (mc -> name );
1669
- Py_VISIT (mc -> args );
1666
+ Py_VISIT (mc -> xargs );
1670
1667
Py_VISIT (mc -> kwds );
1671
1668
Py_VISIT (Py_TYPE (mc ));
1672
1669
return 0 ;
1673
1670
}
1674
1671
1675
- static PyObject *
1676
- methodcaller_call (methodcallerobject * mc , PyObject * args , PyObject * kw )
1677
- {
1678
- PyObject * method , * obj , * result ;
1679
-
1680
- if (!_PyArg_NoKeywords ("methodcaller" , kw ))
1681
- return NULL ;
1682
- if (!_PyArg_CheckPositional ("methodcaller" , PyTuple_GET_SIZE (args ), 1 , 1 ))
1683
- return NULL ;
1684
- obj = PyTuple_GET_ITEM (args , 0 );
1685
- method = PyObject_GetAttr (obj , mc -> name );
1686
- if (method == NULL )
1687
- return NULL ;
1688
- result = PyObject_Call (method , mc -> args , mc -> kwds );
1689
- Py_DECREF (method );
1690
- return result ;
1691
- }
1692
-
1693
1672
static PyObject *
1694
1673
methodcaller_repr (methodcallerobject * mc )
1695
1674
{
@@ -1703,7 +1682,7 @@ methodcaller_repr(methodcallerobject *mc)
1703
1682
}
1704
1683
1705
1684
numkwdargs = mc -> kwds != NULL ? PyDict_GET_SIZE (mc -> kwds ) : 0 ;
1706
- numposargs = PyTuple_GET_SIZE (mc -> args ) ;
1685
+ numposargs = PyTuple_GET_SIZE (mc -> xargs ) - 1 ;
1707
1686
numtotalargs = numposargs + numkwdargs ;
1708
1687
1709
1688
if (numtotalargs == 0 ) {
@@ -1719,7 +1698,7 @@ methodcaller_repr(methodcallerobject *mc)
1719
1698
}
1720
1699
1721
1700
for (i = 0 ; i < numposargs ; ++ i ) {
1722
- PyObject * onerepr = PyObject_Repr (PyTuple_GET_ITEM (mc -> args , i ));
1701
+ PyObject * onerepr = PyObject_Repr (PyTuple_GET_ITEM (mc -> xargs , i + 1 ));
1723
1702
if (onerepr == NULL )
1724
1703
goto done ;
1725
1704
PyTuple_SET_ITEM (argreprs , i , onerepr );
@@ -1769,17 +1748,16 @@ methodcaller_repr(methodcallerobject *mc)
1769
1748
static PyObject *
1770
1749
methodcaller_reduce (methodcallerobject * mc , PyObject * Py_UNUSED (ignored ))
1771
1750
{
1772
- PyObject * newargs ;
1773
1751
if (!mc -> kwds || PyDict_GET_SIZE (mc -> kwds ) == 0 ) {
1774
1752
Py_ssize_t i ;
1775
- Py_ssize_t callargcount = PyTuple_GET_SIZE (mc -> args );
1776
- newargs = PyTuple_New (1 + callargcount );
1753
+ Py_ssize_t newarg_size = PyTuple_GET_SIZE (mc -> vectorcall_args );
1754
+ PyObject * newargs = PyTuple_New (newarg_size );
1777
1755
if (newargs == NULL )
1778
1756
return NULL ;
1779
1757
PyTuple_SET_ITEM (newargs , 0 , Py_NewRef (mc -> name ));
1780
- for (i = 0 ; i < callargcount ; ++ i ) {
1781
- PyObject * arg = PyTuple_GET_ITEM (mc -> args , i );
1782
- PyTuple_SET_ITEM (newargs , i + 1 , Py_NewRef (arg ));
1758
+ for (i = 1 ; i < newarg_size ; ++ i ) {
1759
+ PyObject * arg = PyTuple_GET_ITEM (mc -> xargs , i );
1760
+ PyTuple_SET_ITEM (newargs , i , Py_NewRef (arg ));
1783
1761
}
1784
1762
return Py_BuildValue ("ON" , Py_TYPE (mc ), newargs );
1785
1763
}
@@ -1797,7 +1775,12 @@ methodcaller_reduce(methodcallerobject *mc, PyObject *Py_UNUSED(ignored))
1797
1775
constructor = PyObject_VectorcallDict (partial , newargs , 2 , mc -> kwds );
1798
1776
1799
1777
Py_DECREF (partial );
1800
- return Py_BuildValue ("NO" , constructor , mc -> args );
1778
+ PyObject * args = PyTuple_GetSlice (mc -> xargs , 1 , PyTuple_GET_SIZE (mc -> xargs ));
1779
+ if (!args ) {
1780
+ Py_DECREF (constructor );
1781
+ return NULL ;
1782
+ }
1783
+ return Py_BuildValue ("NO" , constructor , args );
1801
1784
}
1802
1785
}
1803
1786
@@ -1822,7 +1805,6 @@ r.name('date', foo=1).");
1822
1805
static PyType_Slot methodcaller_type_slots [] = {
1823
1806
{Py_tp_doc , (void * )methodcaller_doc },
1824
1807
{Py_tp_dealloc , methodcaller_dealloc },
1825
- {Py_tp_call , methodcaller_call },
1826
1808
{Py_tp_traverse , methodcaller_traverse },
1827
1809
{Py_tp_clear , methodcaller_clear },
1828
1810
{Py_tp_methods , methodcaller_methods },
0 commit comments