summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2016-12-06 23:37:38 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2016-12-06 23:37:38 (GMT)
commitf2d568ff954741c482c64611b164f1506ee9cbe9 (patch)
tree99dd2cb0e93ddb0fcf6b2838427ecf5e0ffa906c /Objects
parenteae4357871850da992a30deeece6bf4c78efc3f8 (diff)
downloadcpython-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.c60
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*