Skip to content

Commit 2476ce4

Browse files
committed
wip
1 parent cf6b79b commit 2476ce4

File tree

1 file changed

+75
-72
lines changed

1 file changed

+75
-72
lines changed

Modules/_operator.c

Lines changed: 75 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,21 +1595,51 @@ static PyType_Spec attrgetter_type_spec = {
15951595
typedef 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+
16061637
static 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 */
16851679
static PyObject *
16861680
methodcaller_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)
17261736
static void
17271737
methodcaller_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

17391750
static void
17401751
methodcaller_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)
17491762
static int
17501763
methodcaller_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)
17591773
static PyObject *
17601774
methodcaller_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

Comments
 (0)