Skip to content

Commit 7934266

Browse files
bpo-35582: Inline arguments tuple unpacking in handwritten code. (pythonGH-11524)
Inline PyArg_UnpackTuple() and _PyArg_UnpackStack() in performance sensitive code in the builtins and operator modules.
1 parent cb08a71 commit 7934266

2 files changed

Lines changed: 28 additions & 24 deletions

File tree

Modules/_operator.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,15 +1011,12 @@ itemgetter_call(itemgetterobject *ig, PyObject *args, PyObject *kw)
10111011
Py_ssize_t i, nitems=ig->nitems;
10121012

10131013
assert(PyTuple_CheckExact(args));
1014-
if (kw == NULL && PyTuple_GET_SIZE(args) == 1) {
1015-
obj = PyTuple_GET_ITEM(args, 0);
1016-
}
1017-
else {
1018-
if (!_PyArg_NoKeywords("itemgetter", kw))
1019-
return NULL;
1020-
if (!PyArg_UnpackTuple(args, "itemgetter", 1, 1, &obj))
1021-
return NULL;
1022-
}
1014+
if (!_PyArg_NoKeywords("itemgetter", kw))
1015+
return NULL;
1016+
if (!_PyArg_CheckPositional("itemgetter", PyTuple_GET_SIZE(args), 1, 1))
1017+
return NULL;
1018+
1019+
obj = PyTuple_GET_ITEM(args, 0);
10231020
if (nitems == 1) {
10241021
if (ig->index >= 0
10251022
&& PyTuple_CheckExact(obj)
@@ -1317,8 +1314,9 @@ attrgetter_call(attrgetterobject *ag, PyObject *args, PyObject *kw)
13171314

13181315
if (!_PyArg_NoKeywords("attrgetter", kw))
13191316
return NULL;
1320-
if (!PyArg_UnpackTuple(args, "attrgetter", 1, 1, &obj))
1317+
if (!_PyArg_CheckPositional("attrgetter", PyTuple_GET_SIZE(args), 1, 1))
13211318
return NULL;
1319+
obj = PyTuple_GET_ITEM(args, 0);
13221320
if (ag->nattrs == 1) /* ag->attr is always a tuple */
13231321
return dotted_getattr(obj, PyTuple_GET_ITEM(ag->attr, 0));
13241322

@@ -1561,8 +1559,9 @@ methodcaller_call(methodcallerobject *mc, PyObject *args, PyObject *kw)
15611559

15621560
if (!_PyArg_NoKeywords("methodcaller", kw))
15631561
return NULL;
1564-
if (!PyArg_UnpackTuple(args, "methodcaller", 1, 1, &obj))
1562+
if (!_PyArg_CheckPositional("methodcaller", PyTuple_GET_SIZE(args), 1, 1))
15651563
return NULL;
1564+
obj = PyTuple_GET_ITEM(args, 0);
15661565
method = PyObject_GetAttr(obj, mc->name);
15671566
if (method == NULL)
15681567
return NULL;

Python/bltinmodule.c

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,19 +1067,21 @@ builtin_exec_impl(PyObject *module, PyObject *source, PyObject *globals,
10671067
static PyObject *
10681068
builtin_getattr(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
10691069
{
1070-
PyObject *v, *result, *dflt = NULL;
1071-
PyObject *name;
1070+
PyObject *v, *name, *result;
10721071

1073-
if (!_PyArg_UnpackStack(args, nargs, "getattr", 2, 3, &v, &name, &dflt))
1072+
if (!_PyArg_CheckPositional("getattr", nargs, 2, 3))
10741073
return NULL;
10751074

1075+
v = args[0];
1076+
name = args[1];
10761077
if (!PyUnicode_Check(name)) {
10771078
PyErr_SetString(PyExc_TypeError,
10781079
"getattr(): attribute name must be string");
10791080
return NULL;
10801081
}
1081-
if (dflt != NULL) {
1082+
if (nargs > 2) {
10821083
if (_PyObject_LookupAttr(v, name, &result) == 0) {
1084+
PyObject *dflt = args[2];
10831085
Py_INCREF(dflt);
10841086
return dflt;
10851087
}
@@ -1372,11 +1374,11 @@ static PyObject *
13721374
builtin_next(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
13731375
{
13741376
PyObject *it, *res;
1375-
PyObject *def = NULL;
13761377

1377-
if (!_PyArg_UnpackStack(args, nargs, "next", 1, 2, &it, &def))
1378+
if (!_PyArg_CheckPositional("next", nargs, 1, 2))
13781379
return NULL;
13791380

1381+
it = args[0];
13801382
if (!PyIter_Check(it)) {
13811383
PyErr_Format(PyExc_TypeError,
13821384
"'%.200s' object is not an iterator",
@@ -1387,7 +1389,8 @@ builtin_next(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
13871389
res = (*it->ob_type->tp_iternext)(it);
13881390
if (res != NULL) {
13891391
return res;
1390-
} else if (def != NULL) {
1392+
} else if (nargs > 1) {
1393+
PyObject *def = args[1];
13911394
if (PyErr_Occurred()) {
13921395
if(!PyErr_ExceptionMatches(PyExc_StopIteration))
13931396
return NULL;
@@ -1503,20 +1506,22 @@ builtin_hex(PyObject *module, PyObject *number)
15031506

15041507
/* AC: cannot convert yet, as needs PEP 457 group support in inspect */
15051508
static PyObject *
1506-
builtin_iter(PyObject *self, PyObject *args)
1509+
builtin_iter(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
15071510
{
1508-
PyObject *v, *w = NULL;
1511+
PyObject *v;
15091512

1510-
if (!PyArg_UnpackTuple(args, "iter", 1, 2, &v, &w))
1513+
if (!_PyArg_CheckPositional("iter", nargs, 1, 2))
15111514
return NULL;
1512-
if (w == NULL)
1515+
v = args[0];
1516+
if (nargs == 1)
15131517
return PyObject_GetIter(v);
15141518
if (!PyCallable_Check(v)) {
15151519
PyErr_SetString(PyExc_TypeError,
15161520
"iter(v, w): v must be callable");
15171521
return NULL;
15181522
}
1519-
return PyCallIter_New(v, w);
1523+
PyObject *sentinel = args[1];
1524+
return PyCallIter_New(v, sentinel);
15201525
}
15211526

15221527
PyDoc_STRVAR(iter_doc,
@@ -2718,7 +2723,7 @@ static PyMethodDef builtin_methods[] = {
27182723
BUILTIN_INPUT_METHODDEF
27192724
BUILTIN_ISINSTANCE_METHODDEF
27202725
BUILTIN_ISSUBCLASS_METHODDEF
2721-
{"iter", builtin_iter, METH_VARARGS, iter_doc},
2726+
{"iter", (PyCFunction)(void(*)(void))builtin_iter, METH_FASTCALL, iter_doc},
27222727
BUILTIN_LEN_METHODDEF
27232728
BUILTIN_LOCALS_METHODDEF
27242729
{"max", (PyCFunction)(void(*)(void))builtin_max, METH_VARARGS | METH_KEYWORDS, max_doc},

0 commit comments

Comments
 (0)