Add _PyErr_CreateException()

Issue #27809: Helper function optimized to create an exception: use fastcall
whenever possible.
This commit is contained in:
Victor Stinner 2016-08-22 23:59:08 +02:00
parent 463b86a881
commit 3a84097291

View file

@ -52,6 +52,20 @@ PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback)
Py_XDECREF(oldtraceback); 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 void
PyErr_SetObject(PyObject *exception, PyObject *value) PyErr_SetObject(PyObject *exception, PyObject *value)
{ {
@ -66,6 +80,7 @@ PyErr_SetObject(PyObject *exception, PyObject *value)
exception); exception);
return; return;
} }
Py_XINCREF(value); Py_XINCREF(value);
exc_value = tstate->exc_value; exc_value = tstate->exc_value;
if (exc_value != NULL && exc_value != Py_None) { if (exc_value != NULL && exc_value != Py_None) {
@ -73,28 +88,21 @@ PyErr_SetObject(PyObject *exception, PyObject *value)
Py_INCREF(exc_value); Py_INCREF(exc_value);
if (value == NULL || !PyExceptionInstance_Check(value)) { if (value == NULL || !PyExceptionInstance_Check(value)) {
/* We must normalize the value right now */ /* 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 */ exception set */
PyErr_Clear(); PyErr_Clear();
if (value == NULL || value == Py_None) fixed_value = _PyErr_CreateException(exception, value);
args = PyTuple_New(0);
else if (PyTuple_Check(value)) {
Py_INCREF(value);
args = value;
}
else
args = PyTuple_Pack(1, value);
fixed_value = args ?
PyEval_CallObject(exception, args) : NULL;
Py_XDECREF(args);
Py_XDECREF(value); Py_XDECREF(value);
if (fixed_value == NULL) if (fixed_value == NULL) {
return; return;
}
value = fixed_value; value = fixed_value;
} }
/* Avoid reference cycles through the context chain. /* Avoid reference cycles through the context chain.
This is O(chain length) but context chains are This is O(chain length) but context chains are
usually very short. Sensitive readers may try usually very short. Sensitive readers may try
@ -110,7 +118,8 @@ PyErr_SetObject(PyObject *exception, PyObject *value)
o = context; o = context;
} }
PyException_SetContext(value, exc_value); PyException_SetContext(value, exc_value);
} else { }
else {
Py_DECREF(exc_value); Py_DECREF(exc_value);
} }
} }
@ -258,25 +267,15 @@ PyErr_NormalizeException(PyObject **exc, PyObject **val, PyObject **tb)
class. class.
*/ */
if (!inclass || !is_subclass) { if (!inclass || !is_subclass) {
PyObject *args, *res; PyObject *fixed_value;
if (value == Py_None) fixed_value = _PyErr_CreateException(type, value);
args = PyTuple_New(0); if (fixed_value == NULL) {
else if (PyTuple_Check(value)) { goto finally;
Py_INCREF(value);
args = value;
} }
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); Py_DECREF(value);
value = res; value = fixed_value;
} }
/* if the class of the instance doesn't exactly match the /* if the class of the instance doesn't exactly match the
class of the type, believe the instance class of the type, believe the instance