diff -r 975e03b0aea6 Objects/abstract.c --- a/Objects/abstract.c Tue Feb 07 11:27:48 2017 +0300 +++ b/Objects/abstract.c Thu Feb 09 12:29:33 2017 +0100 @@ -2233,21 +2233,32 @@ PyObject_Call(PyObject *func, PyObject * assert(PyTuple_Check(args)); assert(kwargs == NULL || PyDict_Check(kwargs)); - call = func->ob_type->tp_call; - if (call == NULL) { - PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", - func->ob_type->tp_name); - return NULL; + if (PyFunction_Check(func)) { + return _PyFunction_FastCallDict(func, + &PyTuple_GET_ITEM(args, 0), + PyTuple_GET_SIZE(args), + kwargs); } - - if (Py_EnterRecursiveCall(" while calling a Python object")) - return NULL; - - result = (*call)(func, args, kwargs); - - Py_LeaveRecursiveCall(); - - return _Py_CheckFunctionResult(func, result, NULL); + else if (PyCFunction_Check(func)) { + return PyCFunction_Call(func, args, kwargs); + } + else { + call = func->ob_type->tp_call; + if (call == NULL) { + PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", + func->ob_type->tp_name); + return NULL; + } + + if (Py_EnterRecursiveCall(" while calling a Python object")) + return NULL; + + result = (*call)(func, args, kwargs); + + Py_LeaveRecursiveCall(); + + return _Py_CheckFunctionResult(func, result, NULL); + } } PyObject* @@ -2287,15 +2298,11 @@ PyObject * assert(nargs == 0 || args != NULL); assert(kwargs == NULL || PyDict_Check(kwargs)); - if (Py_EnterRecursiveCall(" while calling a Python object")) { - return NULL; - } - if (PyFunction_Check(func)) { - result = _PyFunction_FastCallDict(func, args, nargs, kwargs); + return _PyFunction_FastCallDict(func, args, nargs, kwargs); } else if (PyCFunction_Check(func)) { - result = _PyCFunction_FastCallDict(func, args, nargs, kwargs); + return _PyCFunction_FastCallDict(func, args, nargs, kwargs); } else { PyObject *tuple; @@ -2305,24 +2312,27 @@ PyObject * if (call == NULL) { PyErr_Format(PyExc_TypeError, "'%.200s' object is not callable", func->ob_type->tp_name); - goto exit; + return NULL; } tuple = _PyStack_AsTuple(args, nargs); if (tuple == NULL) { - goto exit; + return NULL; } + if (Py_EnterRecursiveCall(" while calling a Python object")) { + Py_DECREF(tuple); + return NULL; + } + result = (*call)(func, tuple, kwargs); + + Py_LeaveRecursiveCall(); Py_DECREF(tuple); result = _Py_CheckFunctionResult(func, result, NULL); + return result; } - -exit: - Py_LeaveRecursiveCall(); - - return result; } /* Positional arguments are obj followed by args. */ diff -r 975e03b0aea6 Objects/methodobject.c --- a/Objects/methodobject.c Tue Feb 07 11:27:48 2017 +0300 +++ b/Objects/methodobject.c Thu Feb 09 12:29:33 2017 +0100 @@ -83,7 +83,7 @@ PyCFunction_Call(PyObject *func, PyObjec PyCFunctionObject* f = (PyCFunctionObject*)func; PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func); - PyObject *arg, *res; + PyObject *arg, *res = NULL; Py_ssize_t size; int flags; @@ -94,19 +94,24 @@ PyCFunction_Call(PyObject *func, PyObjec flags = PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); + if (flags == METH_FASTCALL) { + PyObject **stack = &PyTuple_GET_ITEM(args, 0); + Py_ssize_t nargs = PyTuple_GET_SIZE(args); + return _PyCFunction_FastCallDict(func, stack, nargs, kwds); + } + + if (Py_EnterRecursiveCall(" while calling a Python object")) { + return NULL; + } + if (flags == (METH_VARARGS | METH_KEYWORDS)) { res = (*(PyCFunctionWithKeywords)meth)(self, args, kwds); } - else if (flags == METH_FASTCALL) { - PyObject **stack = &PyTuple_GET_ITEM(args, 0); - Py_ssize_t nargs = PyTuple_GET_SIZE(args); - res = _PyCFunction_FastCallDict(func, stack, nargs, kwds); - } else { if (kwds != NULL && PyDict_Size(kwds) != 0) { PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", f->m_ml->ml_name); - return NULL; + goto exit; } switch (flags) { @@ -120,7 +125,7 @@ PyCFunction_Call(PyObject *func, PyObjec PyErr_Format(PyExc_TypeError, "%.200s() takes no arguments (%zd given)", f->m_ml->ml_name, size); - return NULL; + goto exit; } res = (*meth)(self, NULL); @@ -132,7 +137,7 @@ PyCFunction_Call(PyObject *func, PyObjec PyErr_Format(PyExc_TypeError, "%.200s() takes exactly one argument (%zd given)", f->m_ml->ml_name, size); - return NULL; + goto exit; } arg = PyTuple_GET_ITEM(args, 0); @@ -143,11 +148,15 @@ PyCFunction_Call(PyObject *func, PyObjec PyErr_SetString(PyExc_SystemError, "Bad call flags in PyCFunction_Call. " "METH_OLDARGS is no longer supported!"); - return NULL; + goto exit; } } - return _Py_CheckFunctionResult(func, res, NULL); + res = _Py_CheckFunctionResult(func, res, NULL); + +exit: + Py_LeaveRecursiveCall(); + return res; } PyObject * @@ -157,7 +166,7 @@ PyObject * PyCFunctionObject *func = (PyCFunctionObject*)func_obj; PyCFunction meth = PyCFunction_GET_FUNCTION(func); PyObject *self = PyCFunction_GET_SELF(func); - PyObject *result; + PyObject *result = NULL; int flags; assert(PyCFunction_Check(func)); @@ -173,20 +182,24 @@ PyObject * flags = PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST); + if (Py_EnterRecursiveCall(" while calling a Python object")) { + return NULL; + } + switch (flags) { case METH_NOARGS: if (kwargs != NULL && PyDict_Size(kwargs) != 0) { PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", func->m_ml->ml_name); - return NULL; + goto exit; } if (nargs != 0) { PyErr_Format(PyExc_TypeError, "%.200s() takes no arguments (%zd given)", func->m_ml->ml_name, nargs); - return NULL; + goto exit; } result = (*meth) (self, NULL); @@ -196,14 +209,14 @@ PyObject * if (kwargs != NULL && PyDict_Size(kwargs) != 0) { PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", func->m_ml->ml_name); - return NULL; + goto exit; } if (nargs != 1) { PyErr_Format(PyExc_TypeError, "%.200s() takes exactly one argument (%zd given)", func->m_ml->ml_name, nargs); - return NULL; + goto exit; } result = (*meth) (self, args[0]); @@ -219,12 +232,12 @@ PyObject * PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", func->m_ml->ml_name); - return NULL; + goto exit; } tuple = _PyStack_AsTuple(args, nargs); if (tuple == NULL) { - return NULL; + goto exit; } if (flags & METH_KEYWORDS) { @@ -245,7 +258,7 @@ PyObject * stack = _PyStack_UnpackDict(args, nargs, kwargs, &kwnames, func_obj); if (stack == NULL) { - return NULL; + goto exit; } result = (*fastmeth) (self, stack, nargs, kwnames); @@ -260,11 +273,13 @@ PyObject * PyErr_SetString(PyExc_SystemError, "Bad call flags in PyCFunction_Call. " "METH_OLDARGS is no longer supported!"); - return NULL; + goto exit; } result = _Py_CheckFunctionResult(func_obj, result, NULL); +exit: + Py_LeaveRecursiveCall(); return result; }