Index: Python/ceval.c =================================================================== --- Python/ceval.c (revision 45831) +++ Python/ceval.c (working copy) @@ -92,7 +92,7 @@ static PyObject *ext_do_call(PyObject *, PyObject ***, int, int, int); static PyObject *update_keyword_args(PyObject *, int, PyObject ***,PyObject *); static PyObject *update_star_args(int, int, PyObject *, PyObject ***); -static PyObject *load_args(PyObject ***, int); +static PyObject *load_args(PyObject ***, int, int*); #define CALL_FLAG_VAR 1 #define CALL_FLAG_KW 2 @@ -3509,11 +3509,11 @@ if (PyCFunction_Check(func) && nk == 0) { int flags = PyCFunction_GET_FLAGS(func); PyThreadState *tstate = PyThreadState_GET(); + PyCFunction meth = PyCFunction_GET_FUNCTION(func); + PyObject *self = PyCFunction_GET_SELF(func); PCALL(PCALL_CFUNCTION); if (flags & (METH_NOARGS | METH_O)) { - PyCFunction meth = PyCFunction_GET_FUNCTION(func); - PyObject *self = PyCFunction_GET_SELF(func); if (flags & METH_NOARGS && na == 0) { C_TRACE(x, (*meth)(self,NULL)); } @@ -3528,11 +3528,26 @@ } } else { + int needs_free; PyObject *callargs; - callargs = load_args(pp_stack, na); + callargs = load_args(pp_stack, na, &needs_free); READ_TIMESTAMP(*pintr0); - C_TRACE(x, PyCFunction_Call(func,callargs,NULL)); + if ((flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST)) + == METH_VARARGS) { + C_TRACE(x, (*meth)(self,callargs)); + } + else { + C_TRACE(x, PyCFunction_Call(func,callargs,NULL)); + } READ_TIMESTAMP(*pintr1); + if (needs_free) { + int i; + for (i = 0; i < na; i++) { + w = PyTuple_GET_ITEM(callargs, i); + Py_DECREF(w); + } + ((PyVarObject*)callargs)->ob_size = 0; + } Py_XDECREF(callargs); } } else { @@ -3698,14 +3713,36 @@ return callargs; } +#define _MAX_ARG_COUNT 8 +#define _NUM_ARG_HOLDERS 64 +static PyObject* _args_holder[_NUM_ARG_HOLDERS]; +static int _last_index = 0; + +int +_PyEval_Init(void) +{ + int i; + for (i = 0; i < _NUM_ARG_HOLDERS; i++) + _args_holder[i] = PyTuple_New(_MAX_ARG_COUNT); + return !PyErr_Occurred(); +} + static PyObject * -load_args(PyObject ***pp_stack, int na) +load_args(PyObject ***pp_stack, int na, int *needs_free) { - PyObject *args = PyTuple_New(na); + PyObject *args = _args_holder[_last_index++ & (_NUM_ARG_HOLDERS - 1)]; PyObject *w; - if (args == NULL) - return NULL; + *needs_free = na <= _MAX_ARG_COUNT && args->ob_refcnt == 1; + if (*needs_free) { + ((PyVarObject*)args)->ob_size = na; + Py_INCREF(args); + } + else { + args = PyTuple_New(na); + if (args == NULL) + return NULL; + } while (--na >= 0) { w = EXT_POP(*pp_stack); PyTuple_SET_ITEM(args, na, w); @@ -3719,13 +3756,14 @@ PyObject *callargs = NULL; PyObject *kwdict = NULL; PyObject *result = NULL; + int needs_free; if (nk > 0) { kwdict = update_keyword_args(NULL, nk, pp_stack, func); if (kwdict == NULL) goto call_fail; } - callargs = load_args(pp_stack, na); + callargs = load_args(pp_stack, na, &needs_free); if (callargs == NULL) goto call_fail; #ifdef CALL_PROFILE @@ -3743,6 +3781,14 @@ PCALL(PCALL_OTHER); #endif result = PyObject_Call(func, callargs, kwdict); + if (needs_free) { + int i; + for (i = 0; i < na; i++) { + PyObject *tmp = PyTuple_GET_ITEM(callargs, i); + Py_DECREF(tmp); + } + ((PyVarObject*)callargs)->ob_size = 0; + } call_fail: Py_XDECREF(callargs); Py_XDECREF(kwdict); Index: Python/pythonrun.c =================================================================== --- Python/pythonrun.c (revision 45831) +++ Python/pythonrun.c (working copy) @@ -156,6 +156,7 @@ char *saved_locale; PyObject *sys_stream, *sys_isatty; #endif + extern int _PyEval_Init(void); extern void _Py_ReadyTypes(void); if (initialized) @@ -183,6 +184,9 @@ if (!_PyFrame_Init()) Py_FatalError("Py_Initialize: can't init frames"); + if (!_PyEval_Init()) + Py_FatalError("Py_Initialize: can't init eval"); + if (!_PyInt_Init()) Py_FatalError("Py_Initialize: can't init ints");