diff -r f9dd607dc04c Python/ceval.c --- a/Python/ceval.c Tue Jan 03 02:01:42 2017 +0100 +++ b/Python/ceval.c Tue Jan 03 02:08:01 2017 +0100 @@ -5009,12 +5009,14 @@ PyObject * _PyFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { + /* small stack allocated on the C stack to pass keyword arguments + (key+value pairs) */ + PyObject *small_stack[_PY_FASTCALL_SMALL_STACK * 2]; 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; @@ -5044,12 +5046,17 @@ PyObject * if (nk != 0) { Py_ssize_t pos, i; - 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; + } + } + pos = i = 0; while (PyDict_Next(kwargs, &pos, &k[i], &k[i+1])) { /* We must hold strong references because keyword arguments can be @@ -5062,7 +5069,6 @@ PyObject * nk = i / 2; } else { - kwtuple = NULL; k = NULL; } @@ -5085,7 +5091,21 @@ 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; }