(original) (raw)
changeset: 102847:0c65a2089f00 user: Victor Stinner victor.stinner@gmail.com date: Mon Aug 22 23:59:08 2016 +0200 files: Python/errors.c description: Add _PyErr_CreateException() Issue #27809: Helper function optimized to create an exception: use fastcall whenever possible. diff -r 5587d0dfab4c -r 0c65a2089f00 Python/errors.c --- a/Python/errors.c Mon Aug 22 23:33:13 2016 +0200 +++ b/Python/errors.c Mon Aug 22 23:59:08 2016 +0200 @@ -52,6 +52,20 @@ Py_XDECREF(oldtraceback); } +static PyObject* +_PyErr_CreateException(PyObject *exception, PyObject *value) +{ + if (value == NULL || value == Py_None) { + return _PyObject_CallNoArg(exception); + } + else if (PyTuple_Check(value)) { + return PyObject_Call(exception, value, NULL); + } + else { + return _PyObject_CallArg1(exception, value); + } +} + void PyErr_SetObject(PyObject *exception, PyObject *value) { @@ -66,6 +80,7 @@ exception); return; } + Py_XINCREF(value); exc_value = tstate->exc_value; if (exc_value != NULL && exc_value != Py_None) { @@ -73,28 +88,21 @@ Py_INCREF(exc_value); if (value == NULL || !PyExceptionInstance_Check(value)) { /* We must normalize the value right now */ - PyObject *args, *fixed_value; + PyObject *fixed_value; - /* Issue #23571: PyEval_CallObject() must not be called with an + /* Issue #23571: functions must not be called with an exception set */ PyErr_Clear(); - if (value == NULL || value == Py_None) - args = PyTuple_New(0); - else if (PyTuple_Check(value)) { - Py_INCREF(value); - args = value; + fixed_value = _PyErr_CreateException(exception, value); + Py_XDECREF(value); + if (fixed_value == NULL) { + return; } - else - args = PyTuple_Pack(1, value); - fixed_value = args ? - PyEval_CallObject(exception, args) : NULL; - Py_XDECREF(args); - Py_XDECREF(value); - if (fixed_value == NULL) - return; + value = fixed_value; } + /* Avoid reference cycles through the context chain. This is O(chain length) but context chains are usually very short. Sensitive readers may try @@ -110,7 +118,8 @@ o = context; } PyException_SetContext(value, exc_value); - } else { + } + else { Py_DECREF(exc_value); } } @@ -258,25 +267,15 @@ class. */ if (!inclass || !is_subclass) { - PyObject *args, *res; + PyObject *fixed_value; - if (value == Py_None) - args = PyTuple_New(0); - else if (PyTuple_Check(value)) { - Py_INCREF(value); - args = value; + fixed_value = _PyErr_CreateException(type, value); + if (fixed_value == NULL) { + goto finally; } - else - args = PyTuple_Pack(1, value); - if (args == NULL) - goto finally; - res = PyEval_CallObject(type, args); - Py_DECREF(args); - if (res == NULL) - goto finally; Py_DECREF(value); - value = res; + value = fixed_value; } /* if the class of the instance doesn't exactly match the class of the type, believe the instance /victor.stinner@gmail.com