diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2017-02-08 11:06:00 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2017-02-08 11:06:00 (GMT) |
commit | 7399a05965162f46ca00b5453a59f71fdb5851f1 (patch) | |
tree | 08c61a1b6830a77d5ebf86da2ce6b59d4597b2f4 /Objects/abstract.c | |
parent | ee0ee9ae8e9111a5ce8a09e7b705cfd380394ce7 (diff) | |
download | cpython-7399a05965162f46ca00b5453a59f71fdb5851f1.zip cpython-7399a05965162f46ca00b5453a59f71fdb5851f1.tar.gz cpython-7399a05965162f46ca00b5453a59f71fdb5851f1.tar.bz2 |
Issue #29306: Fix usage of Py_EnterRecursiveCall()
* *PyCFunction_*Call*() functions now call Py_EnterRecursiveCall().
* PyObject_Call() now calls directly _PyFunction_FastCallDict() and
PyCFunction_Call() to avoid calling Py_EnterRecursiveCall() twice per
function call
Diffstat (limited to 'Objects/abstract.c')
-rw-r--r-- | Objects/abstract.c | 102 |
1 files changed, 54 insertions, 48 deletions
diff --git a/Objects/abstract.c b/Objects/abstract.c index 1e394f8..8d18313 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -2239,21 +2239,32 @@ PyObject_Call(PyObject *callable, PyObject *args, PyObject *kwargs) assert(PyTuple_Check(args)); assert(kwargs == NULL || PyDict_Check(kwargs)); - call = callable->ob_type->tp_call; - if (call == NULL) { - PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", - callable->ob_type->tp_name); - return NULL; + if (PyFunction_Check(callable)) { + return _PyFunction_FastCallDict(callable, + &PyTuple_GET_ITEM(args, 0), + PyTuple_GET_SIZE(args), + kwargs); + } + else if (PyCFunction_Check(callable)) { + return PyCFunction_Call(callable, args, kwargs); } + else { + call = callable->ob_type->tp_call; + if (call == NULL) { + PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", + callable->ob_type->tp_name); + return NULL; + } - if (Py_EnterRecursiveCall(" while calling a Python object")) - return NULL; + if (Py_EnterRecursiveCall(" while calling a Python object")) + return NULL; - result = (*call)(callable, args, kwargs); + result = (*call)(callable, args, kwargs); - Py_LeaveRecursiveCall(); + Py_LeaveRecursiveCall(); - return _Py_CheckFunctionResult(callable, result, NULL); + return _Py_CheckFunctionResult(callable, result, NULL); + } } /* Issue #29234: Inlining _PyStack_AsTuple() into callers increases their @@ -2305,9 +2316,6 @@ PyObject * _PyObject_FastCallDict(PyObject *callable, PyObject **args, Py_ssize_t nargs, PyObject *kwargs) { - ternaryfunc call; - PyObject *result = NULL; - /* _PyObject_FastCallDict() must not be called with an exception set, because it can clear it (directly or indirectly) and so the caller loses its exception */ @@ -2318,42 +2326,41 @@ _PyObject_FastCallDict(PyObject *callable, PyObject **args, Py_ssize_t nargs, assert(nargs == 0 || args != NULL); assert(kwargs == NULL || PyDict_Check(kwargs)); - if (Py_EnterRecursiveCall(" while calling a Python object")) { - return NULL; - } - if (PyFunction_Check(callable)) { - result = _PyFunction_FastCallDict(callable, args, nargs, kwargs); + return _PyFunction_FastCallDict(callable, args, nargs, kwargs); } else if (PyCFunction_Check(callable)) { - result = _PyCFunction_FastCallDict(callable, args, nargs, kwargs); + return _PyCFunction_FastCallDict(callable, args, nargs, kwargs); } else { - PyObject *tuple; + PyObject *argstuple, *result; + ternaryfunc call; /* Slow-path: build a temporary tuple */ 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; + return NULL; } - tuple = _PyStack_AsTuple(args, nargs); - if (tuple == NULL) { - goto exit; + argstuple = _PyStack_AsTuple(args, nargs); + if (argstuple == NULL) { + return NULL; } - result = (*call)(callable, tuple, kwargs); - Py_DECREF(tuple); + if (Py_EnterRecursiveCall(" while calling a Python object")) { + return NULL; + } - result = _Py_CheckFunctionResult(callable, result, NULL); - } + result = (*call)(callable, argstuple, kwargs); -exit: - Py_LeaveRecursiveCall(); + Py_LeaveRecursiveCall(); - return result; + Py_DECREF(argstuple); + result = _Py_CheckFunctionResult(callable, result, NULL); + return result; + } } /* Positional arguments are obj followed by args: @@ -2506,49 +2513,48 @@ _PyObject_FastCallKeywords(PyObject *callable, PyObject **stack, Py_ssize_t narg temporary dictionary for keyword arguments (if any) */ ternaryfunc call; - PyObject *argtuple; + PyObject *argstuple; 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; - } - 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; + return NULL; } - argtuple = _PyStack_AsTuple(stack, nargs); - if (argtuple == NULL) { - goto exit; + argstuple = _PyStack_AsTuple(stack, nargs); + if (argstuple == NULL) { + return NULL; } if (nkwargs > 0) { kwdict = _PyStack_AsDict(stack + nargs, kwnames); if (kwdict == NULL) { - Py_DECREF(argtuple); - goto exit; + Py_DECREF(argstuple); + return NULL; } } else { kwdict = NULL; } - result = (*call)(callable, argtuple, kwdict); - Py_DECREF(argtuple); - Py_XDECREF(kwdict); + if (Py_EnterRecursiveCall(" while calling a Python object")) { + return NULL; + } - result = _Py_CheckFunctionResult(callable, result, NULL); + result = (*call)(callable, argstuple, kwdict); - exit: Py_LeaveRecursiveCall(); + + Py_DECREF(argstuple); + Py_XDECREF(kwdict); + + result = _Py_CheckFunctionResult(callable, result, NULL); return result; } } |