From f2d568ff954741c482c64611b164f1506ee9cbe9 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 7 Dec 2016 00:37:38 +0100 Subject: _PyObject_FastCallKeywords() now calls directly tp_call _PyObject_FastCallKeywords() doesn't call _PyObject_FastCallDict() anymore: call directly tp_call. --- Objects/abstract.c | 60 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/Objects/abstract.c b/Objects/abstract.c index 034209c..9b4c124 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2456,12 +2456,9 @@ PyObject * _PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t nargs, PyObject *kwnames) { - PyObject *kwdict, *result; - Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames); - assert(nargs >= 0); assert(kwnames == NULL || PyTuple_CheckExact(kwnames)); - assert((nargs == 0 && nkwargs == 0) || stack != NULL); + /* kwnames must only contains str strings, no subclass, and all keys must be unique: these checks are implemented in Python/ceval.c and _PyArg_ParseStack(). */ @@ -2469,24 +2466,57 @@ _PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t narg if (PyFunction_Check(callable)) { return _PyFunction_FastCallKeywords(callable, stack, nargs, kwnames); } - if (PyCFunction_Check(callable)) { return _PyCFunction_FastCallKeywords(callable, stack, nargs, kwnames); } + else { + /* Slow-path: build a temporary tuple for positional arguments and a + temporary dictionary for keyword arguments (if any) */ - if (nkwargs > 0) { - kwdict = _PyStack_AsDict(stack + nargs, kwnames); - if (kwdict == NULL) { + ternaryfunc call; + PyObject *argtuple; + PyObject *kwdict, *result; + Py_ssize_t nkwargs; + + result = NULL; + nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames); + assert((nargs == 0 && nkwargs == 0) || stack != NULL); + + if (Py_EnterRecursiveCall(" while calling a Python object")) { return NULL; } - } - else { - kwdict = NULL; - } - result = _PyObject_FastCallDict(callable, stack, nargs, kwdict); - Py_XDECREF(kwdict); - return result; + call = callable->ob_type->tp_call; + if (call == NULL) { + PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", + callable->ob_type->tp_name); + goto exit; + } + + argtuple = _PyStack_AsTuple(stack, nargs); + if (argtuple == NULL) { + goto exit; + } + + if (nkwargs > 0) { + kwdict = _PyStack_AsDict(stack + nargs, kwnames); + if (kwdict == NULL) { + Py_DECREF(argtuple); + goto exit; + } + } + else { + kwdict = NULL; + } + + result = (*call)(callable, argtuple, kwdict); + Py_DECREF(argtuple); + Py_XDECREF(kwdict); + + exit: + Py_LeaveRecursiveCall(); + return result; + } } static PyObject* -- cgit v0.12