diff -r f9dd607dc04c Objects/abstract.c --- a/Objects/abstract.c Tue Jan 03 02:01:42 2017 +0100 +++ b/Objects/abstract.c Tue Jan 03 02:37:43 2017 +0100 @@ -2700,58 +2700,72 @@ PyObject * return retval; } -PyObject * -_PyObject_VaCallFunctionObjArgs(PyObject *callable, va_list vargs) +static PyObject * +object_vacall(PyObject *callable, va_list vargs) { - PyObject *small_stack[_PY_FASTCALL_SMALL_STACK]; + Py_ssize_t allocated, nargs; PyObject **stack; - Py_ssize_t nargs; PyObject *result; - Py_ssize_t i; - va_list countva; if (callable == NULL) { return null_error(); } - /* Count the number of arguments */ - va_copy(countva, vargs); nargs = 0; + allocated = 0; + stack = NULL; while (1) { - PyObject *arg = va_arg(countva, PyObject *); + PyObject *arg = va_arg(vargs, PyObject *); if (arg == NULL) { break; } nargs++; - } - va_end(countva); - - /* Copy arguments */ - if (nargs <= (Py_ssize_t)Py_ARRAY_LENGTH(small_stack)) { - stack = small_stack; - } - else { - stack = PyMem_Malloc(nargs * sizeof(stack[0])); - if (stack == NULL) { - PyErr_NoMemory(); - return NULL; + + if (nargs > allocated) { + if (stack == NULL) { + /* Size chosen to be small enough to not waste heap memory + and to reduce the need of realloc() */ + allocated = 8; + + stack = PyMem_Malloc(allocated * sizeof(PyObject*)); + if (stack == NULL) { + PyErr_NoMemory(); + return NULL; + } + } + else { + PyObject **stack2; + + /* overallocate to reduce the number of realloc() */ + allocated = nargs * 2; + + stack2 = PyMem_Realloc(stack, allocated * sizeof(PyObject*)); + if (stack2 == NULL) { + PyMem_Free(stack); + PyErr_NoMemory(); + return NULL; + } + stack = stack2; + } } - } - - for (i = 0; i < nargs; ++i) { - stack[i] = va_arg(vargs, PyObject *); + stack[nargs - 1] = arg; } - /* Call the function */ result = _PyObject_FastCall(callable, stack, nargs); - if (stack != small_stack) { - PyMem_Free(stack); - } + /* Note: stack is NULL if nargs is equal to 0, which is fine */ + PyMem_Free(stack); + return result; } PyObject * +_PyObject_VaCallFunctionObjArgs(PyObject *callable, va_list vargs) +{ + return object_vacall(callable, vargs); +} + +PyObject * PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...) { va_list vargs; @@ -2767,7 +2781,7 @@ PyObject_CallMethodObjArgs(PyObject *cal } va_start(vargs, name); - result = _PyObject_VaCallFunctionObjArgs(callable, vargs); + result = object_vacall(callable, vargs); va_end(vargs); Py_DECREF(callable); @@ -2791,7 +2805,7 @@ PyObject * } va_start(vargs, name); - result = _PyObject_VaCallFunctionObjArgs(callable, vargs); + result = object_vacall(callable, vargs); va_end(vargs); Py_DECREF(callable); @@ -2805,7 +2819,7 @@ PyObject_CallFunctionObjArgs(PyObject *c PyObject *result; va_start(vargs, callable); - result = _PyObject_VaCallFunctionObjArgs(callable, vargs); + result = object_vacall(callable, vargs); va_end(vargs); return result;