From bc08ab4598ef05705fd1172f8be8f47307af96c1 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 15 Dec 2016 12:40:53 +0100 Subject: [PATCH] Add _PY_FASTCALL_SMALL_STACK constant Issue #28870: Add a new _PY_FASTCALL_SMALL_STACK constant, size of "small stacks" allocated on the C stack to pass positional arguments to _PyObject_FastCall(). _PyObject_Call_Prepend() now uses a small stack of 5 arguments (40 bytes) instead of 8 (64 bytes), since it is modified to use _PY_FASTCALL_SMALL_STACK. --- Include/abstract.h | 11 +++++++++++ Objects/abstract.c | 6 +++--- Python/bltinmodule.c | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Include/abstract.h b/Include/abstract.h index 8c1e45bb267..f6dfc675853 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -303,6 +303,17 @@ PyAPI_FUNC(PyObject **) _PyStack_UnpackDict( PyObject **kwnames, PyObject *func); +/* Suggested size (number of positional arguments) for arrays of PyObject* + allocated on a C stack to avoid allocating memory on the heap memory. Such + array is used to pass positional arguments to call functions of the + _PyObject_FastCall() family. + + The size is chosen to not abuse the C stack and so limit the risk of stack + overflow. The size is also chosen to allow using the small stack for most + function calls of the Python standard library. On 64-bit CPU, it allocates + 40 bytes on the stack. */ +#define _PY_FASTCALL_SMALL_STACK 5 + /* Call the callable object 'callable' with the "fast call" calling convention: args is a C array for positional arguments (nargs is the number of positional arguments), kwargs is a dictionary for keyword arguments. diff --git a/Objects/abstract.c b/Objects/abstract.c index 7da97ac8a8d..351c6eb56b2 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2337,7 +2337,7 @@ PyObject * _PyObject_Call_Prepend(PyObject *callable, PyObject *obj, PyObject *args, PyObject *kwargs) { - PyObject *small_stack[8]; + PyObject *small_stack[_PY_FASTCALL_SMALL_STACK]; PyObject **stack; Py_ssize_t argcount; PyObject *result; @@ -2523,7 +2523,7 @@ static PyObject * _PyObject_CallFunctionVa(PyObject *callable, const char *format, va_list va, int is_size_t) { - PyObject* small_stack[5]; + PyObject* small_stack[_PY_FASTCALL_SMALL_STACK]; const Py_ssize_t small_stack_len = Py_ARRAY_LENGTH(small_stack); PyObject **stack; Py_ssize_t nargs, i; @@ -2704,7 +2704,7 @@ _PyObject_CallMethodId_SizeT(PyObject *obj, _Py_Identifier *name, PyObject * _PyObject_VaCallFunctionObjArgs(PyObject *callable, va_list vargs) { - PyObject *small_stack[5]; + PyObject *small_stack[_PY_FASTCALL_SMALL_STACK]; PyObject **stack; Py_ssize_t nargs; PyObject *result; diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 5e1f5624b96..292a7bc2a06 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1186,7 +1186,7 @@ map_traverse(mapobject *lz, visitproc visit, void *arg) static PyObject * map_next(mapobject *lz) { - PyObject *small_stack[5]; + PyObject *small_stack[_PY_FASTCALL_SMALL_STACK]; PyObject **stack; Py_ssize_t niters, nargs, i; PyObject *result = NULL;