diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2016-12-06 23:37:38 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2016-12-06 23:37:38 (GMT) |
commit | f2d568ff954741c482c64611b164f1506ee9cbe9 (patch) | |
tree | 99dd2cb0e93ddb0fcf6b2838427ecf5e0ffa906c /Objects | |
parent | eae4357871850da992a30deeece6bf4c78efc3f8 (diff) | |
download | cpython-f2d568ff954741c482c64611b164f1506ee9cbe9.zip cpython-f2d568ff954741c482c64611b164f1506ee9cbe9.tar.gz cpython-f2d568ff954741c482c64611b164f1506ee9cbe9.tar.bz2 |
_PyObject_FastCallKeywords() now calls directly tp_call
_PyObject_FastCallKeywords() doesn't call _PyObject_FastCallDict() anymore:
call directly tp_call.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/abstract.c | 60 |
1 files 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* |