summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>2023-03-08 17:03:18 (GMT)
committerGitHub <noreply@github.com>2023-03-08 17:03:18 (GMT)
commit11a2c6ce516b24b2435cb627742a6c4df92d411c (patch)
tree56d6359741570d46994530d5098318c0046e089d
parentb097925858c6975c73e989226cf278cc382c0416 (diff)
downloadcpython-11a2c6ce516b24b2435cb627742a6c4df92d411c.zip
cpython-11a2c6ce516b24b2435cb627742a6c4df92d411c.tar.gz
cpython-11a2c6ce516b24b2435cb627742a6c4df92d411c.tar.bz2
gh-102192: Replace PyErr_Fetch/Restore etc by more efficient alternatives (in Objects/) (#102218)
-rw-r--r--Objects/dictobject.c2
-rw-r--r--Objects/exceptions.c39
-rw-r--r--Objects/frameobject.c5
-rw-r--r--Objects/genobject.c64
-rw-r--r--Objects/object.c25
-rw-r--r--Objects/odictobject.c5
-rw-r--r--Objects/typeobject.c10
-rw-r--r--Objects/weakrefobject.c7
8 files changed, 51 insertions, 106 deletions
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index e3795e7..75c9217 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -119,7 +119,7 @@ As a consequence of this, split keys have a maximum size of 16.
#include "pycore_dict.h" // PyDictKeysObject
#include "pycore_gc.h" // _PyObject_GC_IS_TRACKED()
#include "pycore_object.h" // _PyObject_GC_TRACK()
-#include "pycore_pyerrors.h" // _PyErr_Fetch()
+#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "stringlib/eq.h" // unicode_eq()
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index a473cbd..c6fb6a3 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -3781,16 +3781,13 @@ PyObject *
_PyErr_TrySetFromCause(const char *format, ...)
{
PyObject* msg_prefix;
- PyObject *exc, *val, *tb;
- PyTypeObject *caught_type;
PyObject *instance_args;
Py_ssize_t num_args, caught_type_size, base_exc_size;
- PyObject *new_exc, *new_val, *new_tb;
va_list vargs;
int same_basic_size;
- PyErr_Fetch(&exc, &val, &tb);
- caught_type = (PyTypeObject *)exc;
+ PyObject *exc = PyErr_GetRaisedException();
+ PyTypeObject *caught_type = Py_TYPE(exc);
/* Ensure type info indicates no extra state is stored at the C level
* and that the type can be reinstantiated using PyErr_Format
*/
@@ -3810,31 +3807,30 @@ _PyErr_TrySetFromCause(const char *format, ...)
* more state than just the exception type. Accordingly, we just
* leave it alone.
*/
- PyErr_Restore(exc, val, tb);
+ PyErr_SetRaisedException(exc);
return NULL;
}
/* Check the args are empty or contain a single string */
- PyErr_NormalizeException(&exc, &val, &tb);
- instance_args = ((PyBaseExceptionObject *)val)->args;
+ instance_args = ((PyBaseExceptionObject *)exc)->args;
num_args = PyTuple_GET_SIZE(instance_args);
if (num_args > 1 ||
(num_args == 1 &&
!PyUnicode_CheckExact(PyTuple_GET_ITEM(instance_args, 0)))) {
/* More than 1 arg, or the one arg we do have isn't a string
*/
- PyErr_Restore(exc, val, tb);
+ PyErr_SetRaisedException(exc);
return NULL;
}
/* Ensure the instance dict is also empty */
- if (!_PyObject_IsInstanceDictEmpty(val)) {
+ if (!_PyObject_IsInstanceDictEmpty(exc)) {
/* While we could potentially copy a non-empty instance dictionary
* to the replacement exception, for now we take the more
* conservative path of leaving exceptions with attributes set
* alone.
*/
- PyErr_Restore(exc, val, tb);
+ PyErr_SetRaisedException(exc);
return NULL;
}
@@ -3847,28 +3843,19 @@ _PyErr_TrySetFromCause(const char *format, ...)
* types as well, but that's quite a bit trickier due to the extra
* state potentially stored on OSError instances.
*/
- /* Ensure the traceback is set correctly on the existing exception */
- if (tb != NULL) {
- PyException_SetTraceback(val, tb);
- Py_DECREF(tb);
- }
-
va_start(vargs, format);
msg_prefix = PyUnicode_FromFormatV(format, vargs);
va_end(vargs);
if (msg_prefix == NULL) {
Py_DECREF(exc);
- Py_DECREF(val);
return NULL;
}
- PyErr_Format(exc, "%U (%s: %S)",
- msg_prefix, Py_TYPE(val)->tp_name, val);
- Py_DECREF(exc);
+ PyErr_Format((PyObject*)Py_TYPE(exc), "%U (%s: %S)",
+ msg_prefix, Py_TYPE(exc)->tp_name, exc);
Py_DECREF(msg_prefix);
- PyErr_Fetch(&new_exc, &new_val, &new_tb);
- PyErr_NormalizeException(&new_exc, &new_val, &new_tb);
- PyException_SetCause(new_val, val);
- PyErr_Restore(new_exc, new_val, new_tb);
- return new_val;
+ PyObject *new_exc = PyErr_GetRaisedException();
+ PyException_SetCause(new_exc, exc);
+ PyErr_SetRaisedException(new_exc);
+ return new_exc;
}
diff --git a/Objects/frameobject.c b/Objects/frameobject.c
index 34143c9..133c991 100644
--- a/Objects/frameobject.c
+++ b/Objects/frameobject.c
@@ -1308,7 +1308,6 @@ _PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear)
/* Merge locals into fast locals */
PyObject *locals;
PyObject **fast;
- PyObject *error_type, *error_value, *error_traceback;
PyCodeObject *co;
locals = frame->f_locals;
if (locals == NULL) {
@@ -1317,7 +1316,7 @@ _PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear)
fast = _PyFrame_GetLocalsArray(frame);
co = frame->f_code;
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
+ PyObject *exc = PyErr_GetRaisedException();
for (int i = 0; i < co->co_nlocalsplus; i++) {
_PyLocals_Kind kind = _PyLocals_GetKind(co->co_localspluskinds, i);
@@ -1374,7 +1373,7 @@ _PyFrame_LocalsToFast(_PyInterpreterFrame *frame, int clear)
}
Py_XDECREF(value);
}
- PyErr_Restore(error_type, error_value, error_traceback);
+ PyErr_SetRaisedException(exc);
}
void
diff --git a/Objects/genobject.c b/Objects/genobject.c
index be08a59..6146377 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -69,8 +69,6 @@ void
_PyGen_Finalize(PyObject *self)
{
PyGenObject *gen = (PyGenObject *)self;
- PyObject *res = NULL;
- PyObject *error_type, *error_value, *error_traceback;
if (gen->gi_frame_state >= FRAME_COMPLETED) {
/* Generator isn't paused, so no need to close */
@@ -82,23 +80,22 @@ _PyGen_Finalize(PyObject *self)
PyObject *finalizer = agen->ag_origin_or_finalizer;
if (finalizer && !agen->ag_closed) {
/* Save the current exception, if any. */
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
-
- res = PyObject_CallOneArg(finalizer, self);
+ PyObject *exc = PyErr_GetRaisedException();
+ PyObject *res = PyObject_CallOneArg(finalizer, self);
if (res == NULL) {
PyErr_WriteUnraisable(self);
} else {
Py_DECREF(res);
}
/* Restore the saved exception. */
- PyErr_Restore(error_type, error_value, error_traceback);
+ PyErr_SetRaisedException(exc);
return;
}
}
/* Save the current exception, if any. */
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
+ PyObject *exc = PyErr_GetRaisedException();
/* If `gen` is a coroutine, and if it was never awaited on,
issue a RuntimeWarning. */
@@ -109,20 +106,19 @@ _PyGen_Finalize(PyObject *self)
_PyErr_WarnUnawaitedCoroutine((PyObject *)gen);
}
else {
- res = gen_close(gen, NULL);
- }
-
- if (res == NULL) {
- if (PyErr_Occurred()) {
- PyErr_WriteUnraisable(self);
+ PyObject *res = gen_close(gen, NULL);
+ if (res == NULL) {
+ if (PyErr_Occurred()) {
+ PyErr_WriteUnraisable(self);
+ }
+ }
+ else {
+ Py_DECREF(res);
}
- }
- else {
- Py_DECREF(res);
}
/* Restore the saved exception. */
- PyErr_Restore(error_type, error_value, error_traceback);
+ PyErr_SetRaisedException(exc);
}
static void
@@ -648,39 +644,11 @@ _PyGen_SetStopIterationValue(PyObject *value)
int
_PyGen_FetchStopIterationValue(PyObject **pvalue)
{
- PyObject *et, *ev, *tb;
PyObject *value = NULL;
-
if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
- PyErr_Fetch(&et, &ev, &tb);
- if (ev) {
- /* exception will usually be normalised already */
- if (PyObject_TypeCheck(ev, (PyTypeObject *) et)) {
- value = Py_NewRef(((PyStopIterationObject *)ev)->value);
- Py_DECREF(ev);
- } else if (et == PyExc_StopIteration && !PyTuple_Check(ev)) {
- /* Avoid normalisation and take ev as value.
- *
- * Normalization is required if the value is a tuple, in
- * that case the value of StopIteration would be set to
- * the first element of the tuple.
- *
- * (See _PyErr_CreateException code for details.)
- */
- value = ev;
- } else {
- /* normalisation required */
- PyErr_NormalizeException(&et, &ev, &tb);
- if (!PyObject_TypeCheck(ev, (PyTypeObject *)PyExc_StopIteration)) {
- PyErr_Restore(et, ev, tb);
- return -1;
- }
- value = Py_NewRef(((PyStopIterationObject *)ev)->value);
- Py_DECREF(ev);
- }
- }
- Py_XDECREF(et);
- Py_XDECREF(tb);
+ PyObject *exc = PyErr_GetRaisedException();
+ value = Py_NewRef(((PyStopIterationObject *)exc)->value);
+ Py_DECREF(exc);
} else if (PyErr_Occurred()) {
return -1;
}
diff --git a/Objects/object.c b/Objects/object.c
index 446c7b1..5db2b6a 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -370,13 +370,12 @@ _PyObject_Dump(PyObject* op)
fflush(stderr);
PyGILState_STATE gil = PyGILState_Ensure();
- PyObject *error_type, *error_value, *error_traceback;
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
+ PyObject *exc = PyErr_GetRaisedException();
(void)PyObject_Print(op, stderr, 0);
fflush(stderr);
- PyErr_Restore(error_type, error_value, error_traceback);
+ PyErr_SetRaisedException(exc);
PyGILState_Release(gil);
fprintf(stderr, "\n");
@@ -860,25 +859,22 @@ set_attribute_error_context(PyObject* v, PyObject* name)
return 0;
}
// Intercept AttributeError exceptions and augment them to offer suggestions later.
- PyObject *type, *value, *traceback;
- PyErr_Fetch(&type, &value, &traceback);
- PyErr_NormalizeException(&type, &value, &traceback);
- // Check if the normalized exception is indeed an AttributeError
- if (!PyErr_GivenExceptionMatches(value, PyExc_AttributeError)) {
+ PyObject *exc = PyErr_GetRaisedException();
+ if (!PyErr_GivenExceptionMatches(exc, PyExc_AttributeError)) {
goto restore;
}
- PyAttributeErrorObject* the_exc = (PyAttributeErrorObject*) value;
+ PyAttributeErrorObject* the_exc = (PyAttributeErrorObject*) exc;
// Check if this exception was already augmented
if (the_exc->name || the_exc->obj) {
goto restore;
}
// Augment the exception with the name and object
- if (PyObject_SetAttr(value, &_Py_ID(name), name) ||
- PyObject_SetAttr(value, &_Py_ID(obj), v)) {
+ if (PyObject_SetAttr(exc, &_Py_ID(name), name) ||
+ PyObject_SetAttr(exc, &_Py_ID(obj), v)) {
return 1;
}
restore:
- PyErr_Restore(type, value, traceback);
+ PyErr_SetRaisedException(exc);
return 0;
}
@@ -2190,9 +2186,8 @@ Py_ReprLeave(PyObject *obj)
PyObject *dict;
PyObject *list;
Py_ssize_t i;
- PyObject *error_type, *error_value, *error_traceback;
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
+ PyObject *exc = PyErr_GetRaisedException();
dict = PyThreadState_GetDict();
if (dict == NULL)
@@ -2213,7 +2208,7 @@ Py_ReprLeave(PyObject *obj)
finally:
/* ignore exceptions because there is no way to report them. */
- PyErr_Restore(error_type, error_value, error_traceback);
+ PyErr_SetRaisedException(exc);
}
/* Trashcan support. */
diff --git a/Objects/odictobject.c b/Objects/odictobject.c
index 215a8af..39b0f68 100644
--- a/Objects/odictobject.c
+++ b/Objects/odictobject.c
@@ -1556,10 +1556,9 @@ _PyODict_SetItem_KnownHash(PyObject *od, PyObject *key, PyObject *value,
res = _odict_add_new_node((PyODictObject *)od, key, hash);
if (res < 0) {
/* Revert setting the value on the dict */
- PyObject *exc, *val, *tb;
- PyErr_Fetch(&exc, &val, &tb);
+ PyObject *exc = PyErr_GetRaisedException();
(void) _PyDict_DelItem_KnownHash(od, key, hash);
- _PyErr_ChainExceptions(exc, val, tb);
+ _PyErr_ChainExceptions1(exc);
}
}
return res;
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 981930f..f486b83 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -4397,10 +4397,9 @@ static void
type_dealloc_common(PyTypeObject *type)
{
if (type->tp_bases != NULL) {
- PyObject *tp, *val, *tb;
- PyErr_Fetch(&tp, &val, &tb);
+ PyObject *exc = PyErr_GetRaisedException();
remove_all_subclasses(type, type->tp_bases);
- PyErr_Restore(tp, val, tb);
+ PyErr_SetRaisedException(exc);
}
}
@@ -8445,10 +8444,9 @@ slot_tp_finalize(PyObject *self)
{
int unbound;
PyObject *del, *res;
- PyObject *error_type, *error_value, *error_traceback;
/* Save the current exception, if any. */
- PyErr_Fetch(&error_type, &error_value, &error_traceback);
+ PyObject *exc = PyErr_GetRaisedException();
/* Execute __del__ method, if any. */
del = lookup_maybe_method(self, &_Py_ID(__del__), &unbound);
@@ -8462,7 +8460,7 @@ slot_tp_finalize(PyObject *self)
}
/* Restore the saved exception. */
- PyErr_Restore(error_type, error_value, error_traceback);
+ PyErr_SetRaisedException(exc);
}
static PyObject *
diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c
index bd7720e..5a3e49a 100644
--- a/Objects/weakrefobject.c
+++ b/Objects/weakrefobject.c
@@ -959,9 +959,8 @@ PyObject_ClearWeakRefs(PyObject *object)
if (*list != NULL) {
PyWeakReference *current = *list;
Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
- PyObject *err_type, *err_value, *err_tb;
+ PyObject *exc = PyErr_GetRaisedException();
- PyErr_Fetch(&err_type, &err_value, &err_tb);
if (count == 1) {
PyObject *callback = current->wr_callback;
@@ -980,7 +979,7 @@ PyObject_ClearWeakRefs(PyObject *object)
tuple = PyTuple_New(count * 2);
if (tuple == NULL) {
- _PyErr_ChainExceptions(err_type, err_value, err_tb);
+ _PyErr_ChainExceptions1(exc);
return;
}
@@ -1010,7 +1009,7 @@ PyObject_ClearWeakRefs(PyObject *object)
Py_DECREF(tuple);
}
assert(!PyErr_Occurred());
- PyErr_Restore(err_type, err_value, err_tb);
+ PyErr_SetRaisedException(exc);
}
}