diff -r 20bb8babc505 Objects/funcobject.c --- a/Objects/funcobject.c Wed Nov 30 12:10:54 2016 +0100 +++ b/Objects/funcobject.c Thu Dec 01 11:04:58 2016 +0100 @@ -563,55 +563,14 @@ func_traverse(PyFunctionObject *f, visit } static PyObject * -function_call(PyObject *func, PyObject *arg, PyObject *kw) +function_call(PyObject *func, PyObject *args, PyObject *kwargs) { - PyObject *result; - PyObject *argdefs; - PyObject *kwtuple = NULL; - PyObject **d, **k; - Py_ssize_t nk, nd; - - argdefs = PyFunction_GET_DEFAULTS(func); - if (argdefs != NULL && PyTuple_Check(argdefs)) { - d = &PyTuple_GET_ITEM((PyTupleObject *)argdefs, 0); - nd = PyTuple_GET_SIZE(argdefs); - } - else { - d = NULL; - nd = 0; - } + PyObject **stack; + Py_ssize_t nargs; - if (kw != NULL && PyDict_Check(kw)) { - Py_ssize_t pos, i; - nk = PyDict_Size(kw); - kwtuple = PyTuple_New(2*nk); - if (kwtuple == NULL) - return NULL; - k = &PyTuple_GET_ITEM(kwtuple, 0); - pos = i = 0; - while (PyDict_Next(kw, &pos, &k[i], &k[i+1])) { - Py_INCREF(k[i]); - Py_INCREF(k[i+1]); - i += 2; - } - nk = i/2; - } - else { - k = NULL; - nk = 0; - } - - result = PyEval_EvalCodeEx( - PyFunction_GET_CODE(func), - PyFunction_GET_GLOBALS(func), (PyObject *)NULL, - &PyTuple_GET_ITEM(arg, 0), PyTuple_GET_SIZE(arg), - k, nk, d, nd, - PyFunction_GET_KW_DEFAULTS(func), - PyFunction_GET_CLOSURE(func)); - - Py_XDECREF(kwtuple); - - return result; + stack = &PyTuple_GET_ITEM(args, 0); + nargs = PyTuple_GET_SIZE(args); + return _PyFunction_FastCallDict(func, stack, nargs, kwargs); } /* Bind a function to an object */ diff -r 20bb8babc505 Python/ceval.c --- a/Python/ceval.c Wed Nov 30 12:10:54 2016 +0100 +++ b/Python/ceval.c Thu Dec 01 11:04:58 2016 +0100 @@ -4890,12 +4890,14 @@ PyObject * _PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { + /* small stack allocated on the C stack to pass 5 keyword arguments + (5 key+value pairs) */ + PyObject *small_stack[2 * 5]; PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func); PyObject *globals = PyFunction_GET_GLOBALS(func); PyObject *argdefs = PyFunction_GET_DEFAULTS(func); PyObject *kwdefs, *closure, *name, *qualname; - PyObject *kwtuple, **k; - PyObject **d; + PyObject **k, **d; Py_ssize_t nd, nk; PyObject *result; @@ -4925,12 +4927,20 @@ PyObject * Py_ssize_t pos, i; nk = PyDict_Size(kwargs); - kwtuple = PyTuple_New(2 * nk); - if (kwtuple == NULL) { - return NULL; - } - - k = &PyTuple_GET_ITEM(kwtuple, 0); + if (nk <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack) / 2) { + k = small_stack; + } + else { + k = PyMem_Malloc((2 * nk) * sizeof(PyObject *)); + if (k == NULL) { + PyErr_NoMemory(); + return NULL; + } + } + + /* We must hold strong references because kwargs can be indirectly + modified while the function is called: see issue #2016 + and test_extcall */ pos = i = 0; while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { Py_INCREF(k[i]); @@ -4940,7 +4950,6 @@ PyObject * nk = i / 2; } else { - kwtuple = NULL; k = NULL; nk = 0; } @@ -4964,7 +4973,19 @@ PyObject * k, k + 1, nk, 2, d, nd, kwdefs, closure, name, qualname); - Py_XDECREF(kwtuple); + if (k != NULL) { + Py_ssize_t i; + + for (i=0; i < nk * 2; ) { + Py_DECREF(k[i]); + Py_DECREF(k[i+1]); + i += 2; + } + + if (k != small_stack) { + PyMem_Free(k); + } + } return result; }