Raymond's patch for #1819: speedup function calls with named parameters

(35% faster according to pybench)
This commit is contained in:
Antoine Pitrou 2008-07-25 22:13:52 +00:00
parent 0c37ae0464
commit c2cc80c64e

View file

@ -2779,6 +2779,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
} }
} }
for (i = 0; i < kwcount; i++) { for (i = 0; i < kwcount; i++) {
PyObject **co_varnames;
PyObject *keyword = kws[2*i]; PyObject *keyword = kws[2*i];
PyObject *value = kws[2*i + 1]; PyObject *value = kws[2*i + 1];
int j; int j;
@ -2788,14 +2789,21 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
PyString_AsString(co->co_name)); PyString_AsString(co->co_name));
goto fail; goto fail;
} }
/* XXX slow -- speed up using dictionary? */ /* Speed hack: do raw pointer compares. As names are
normally interned this should almost always hit. */
co_varnames = PySequence_Fast_ITEMS(co->co_varnames);
for (j = 0; j < co->co_argcount; j++) { for (j = 0; j < co->co_argcount; j++) {
PyObject *nm = PyTuple_GET_ITEM( PyObject *nm = co_varnames[j];
co->co_varnames, j); if (nm == keyword)
goto kw_found;
}
/* Slow fallback, just in case */
for (j = 0; j < co->co_argcount; j++) {
PyObject *nm = co_varnames[j];
int cmp = PyObject_RichCompareBool( int cmp = PyObject_RichCompareBool(
keyword, nm, Py_EQ); keyword, nm, Py_EQ);
if (cmp > 0) if (cmp > 0)
break; goto kw_found;
else if (cmp < 0) else if (cmp < 0)
goto fail; goto fail;
} }
@ -2812,8 +2820,9 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
goto fail; goto fail;
} }
PyDict_SetItem(kwdict, keyword, value); PyDict_SetItem(kwdict, keyword, value);
continue;
} }
else { kw_found:
if (GETLOCAL(j) != NULL) { if (GETLOCAL(j) != NULL) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"%.200s() got multiple " "%.200s() got multiple "
@ -2826,7 +2835,6 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
Py_INCREF(value); Py_INCREF(value);
SETLOCAL(j, value); SETLOCAL(j, value);
} }
}
if (argcount < co->co_argcount) { if (argcount < co->co_argcount) {
int m = co->co_argcount - defcount; int m = co->co_argcount - defcount;
for (i = argcount; i < m; i++) { for (i = argcount; i < m; i++) {