diff -r f4dcb5ff3ecd Include/methodobject.h --- a/Include/methodobject.h Thu Aug 25 00:39:34 2016 +0200 +++ b/Include/methodobject.h Thu Aug 25 00:41:37 2016 +0200 @@ -42,6 +42,11 @@ PyAPI_FUNC(PyObject *) _PyCFunction_Fast PyObject **args, Py_ssize_t nargs, PyObject *kwargs); + +PyAPI_FUNC(PyObject *) _PyCFunction_FastCallKeywords(PyObject *func, + PyObject **stack, + Py_ssize_t nargs, + Py_ssize_t nkwargs); #endif struct PyMethodDef { diff -r f4dcb5ff3ecd Objects/methodobject.c --- a/Objects/methodobject.c Thu Aug 25 00:39:34 2016 +0200 +++ b/Objects/methodobject.c Thu Aug 25 00:41:37 2016 +0200 @@ -243,6 +243,19 @@ PyObject * return result; } +PyObject * +_PyCFunction_FastCallKeywords(PyObject *func, PyObject **stack, + Py_ssize_t nargs, Py_ssize_t nkwargs) +{ + assert((nargs == 0 && nkwargs == 0) || stack != NULL); + + if (nkwargs == 0) { + return _PyCFunction_FastCallDict(func, stack, nargs, NULL); + } + + return _PyObject_FastCallKeywords(func, stack, nargs, nkwargs); +} + /* Methods (the standard built-in methods, that is) */ static void diff -r f4dcb5ff3ecd Python/ceval.c --- a/Python/ceval.c Thu Aug 25 00:39:34 2016 +0200 +++ b/Python/ceval.c Thu Aug 25 00:41:37 2016 +0200 @@ -113,7 +113,7 @@ static PyObject * call_function(PyObject #else static PyObject * call_function(PyObject ***, int); #endif -static PyObject * do_call(PyObject *, PyObject ***, Py_ssize_t, Py_ssize_t); +static PyObject * do_call(PyObject *, PyObject **, Py_ssize_t, Py_ssize_t); static PyObject * ext_do_call(PyObject *, PyObject ***, int, Py_ssize_t, Py_ssize_t); static PyObject * update_keyword_args(PyObject *, Py_ssize_t, PyObject ***, PyObject *); @@ -4769,7 +4769,7 @@ call_function(PyObject ***pp_stack, int x = _PyFunction_FastCallKeywords(func, (*pp_stack) - n, nargs, nkwargs); } else { - x = do_call(func, pp_stack, nargs, nkwargs); + x = do_call(func, *(pp_stack) - n, nargs, nkwargs); } READ_TIMESTAMP(*pintr1); Py_DECREF(func); @@ -5078,20 +5078,10 @@ load_args(PyObject ***pp_stack, Py_ssize } static PyObject * -do_call(PyObject *func, PyObject ***pp_stack, Py_ssize_t nargs, Py_ssize_t nkwargs) +do_call(PyObject *func, PyObject **stack, Py_ssize_t nargs, Py_ssize_t nkwargs) { - PyObject *callargs = NULL; - PyObject *kwdict = NULL; - PyObject *result = NULL; - - if (nkwargs > 0) { - kwdict = update_keyword_args(NULL, nkwargs, pp_stack, func); - if (kwdict == NULL) - goto call_fail; - } - callargs = load_args(pp_stack, nargs); - if (callargs == NULL) - goto call_fail; + PyObject *result; + #ifdef CALL_PROFILE /* At this point, we have to look at the type of func to update the call stats properly. Do it here so as to avoid @@ -5108,15 +5098,14 @@ do_call(PyObject *func, PyObject ***pp_s else PCALL(PCALL_OTHER); #endif + if (PyCFunction_Check(func)) { PyThreadState *tstate = PyThreadState_GET(); - C_TRACE(result, PyCFunction_Call(func, callargs, kwdict)); + C_TRACE(result, _PyCFunction_FastCallKeywords(func, stack, nargs, nkwargs)); } - else - result = PyObject_Call(func, callargs, kwdict); -call_fail: - Py_XDECREF(callargs); - Py_XDECREF(kwdict); + else { + result = _PyObject_FastCallKeywords(func, stack, nargs, nkwargs); + } return result; }