[Python-checkins] gh-102192: Replace PyErr_Fetch/Restore etc by more efficient alternatives (in Python/) (#102193)

iritkatriel webhook-mailer at python.org
Tue Feb 28 06:51:00 EST 2023


https://github.com/python/cpython/commit/4c87537efb5fd28b4e4ee9631076ed5953720156
commit: 4c87537efb5fd28b4e4ee9631076ed5953720156
branch: main
author: Irit Katriel <1055913+iritkatriel at users.noreply.github.com>
committer: iritkatriel <1055913+iritkatriel at users.noreply.github.com>
date: 2023-02-28T11:50:52Z
summary:

gh-102192: Replace PyErr_Fetch/Restore etc by more efficient alternatives (in Python/) (#102193)

files:
M Python/bytecodes.c
M Python/ceval.c
M Python/ceval_gil.c
M Python/compile.c
M Python/frame.c
M Python/initconfig.c
M Python/modsupport.c
M Python/sysmodule.c

diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 7e9b36f69721..63dbecad3b45 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -17,7 +17,7 @@
 #include "pycore_object.h"        // _PyObject_GC_TRACK()
 #include "pycore_moduleobject.h"  // PyModuleObject
 #include "pycore_opcode.h"        // EXTRA_CASES
-#include "pycore_pyerrors.h"      // _PyErr_Fetch()
+#include "pycore_pyerrors.h"      // _PyErr_GetRaisedException()
 #include "pycore_pymem.h"         // _PyMem_IsPtrFreed()
 #include "pycore_pystate.h"       // _PyInterpreterState_GET()
 #include "pycore_range.h"         // _PyRangeIterObject
diff --git a/Python/ceval.c b/Python/ceval.c
index 5540c93d5e3d..b422d0ed34ed 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -13,7 +13,7 @@
 #include "pycore_object.h"        // _PyObject_GC_TRACK()
 #include "pycore_moduleobject.h"  // PyModuleObject
 #include "pycore_opcode.h"        // EXTRA_CASES
-#include "pycore_pyerrors.h"      // _PyErr_Fetch()
+#include "pycore_pyerrors.h"      // _PyErr_Fetch(), _PyErr_GetRaisedException()
 #include "pycore_pymem.h"         // _PyMem_IsPtrFreed()
 #include "pycore_pystate.h"       // _PyInterpreterState_GET()
 #include "pycore_range.h"         // _PyRangeIterObject
@@ -105,8 +105,7 @@ static void
 dump_stack(_PyInterpreterFrame *frame, PyObject **stack_pointer)
 {
     PyObject **stack_base = _PyFrame_Stackbase(frame);
-    PyObject *type, *value, *traceback;
-    PyErr_Fetch(&type, &value, &traceback);
+    PyObject *exc = PyErr_GetRaisedException();
     printf("    stack=[");
     for (PyObject **ptr = stack_base; ptr < stack_pointer; ptr++) {
         if (ptr != stack_base) {
@@ -120,7 +119,7 @@ dump_stack(_PyInterpreterFrame *frame, PyObject **stack_pointer)
     }
     printf("]\n");
     fflush(stdout);
-    PyErr_Restore(type, value, traceback);
+    PyErr_SetRaisedException(exc);
 }
 
 static void
@@ -157,8 +156,7 @@ lltrace_resume_frame(_PyInterpreterFrame *frame)
         return;
     }
     PyFunctionObject *f = (PyFunctionObject *)fobj;
-    PyObject *type, *value, *traceback;
-    PyErr_Fetch(&type, &value, &traceback);
+    PyObject *exc = PyErr_GetRaisedException();
     PyObject *name = f->func_qualname;
     if (name == NULL) {
         name = f->func_name;
@@ -178,7 +176,7 @@ lltrace_resume_frame(_PyInterpreterFrame *frame)
     }
     printf("\n");
     fflush(stdout);
-    PyErr_Restore(type, value, traceback);
+    PyErr_SetRaisedException(exc);
 }
 #endif
 static int call_trace(Py_tracefunc, PyObject *,
@@ -1032,7 +1030,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
                 PyObject *v = POP();
                 Py_XDECREF(v);
             }
-            PyObject *exc, *val, *tb;
             if (lasti) {
                 int frame_lasti = _PyInterpreterFrame_LASTI(frame);
                 PyObject *lasti = PyLong_FromLong(frame_lasti);
@@ -1041,19 +1038,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
                 }
                 PUSH(lasti);
             }
-            _PyErr_Fetch(tstate, &exc, &val, &tb);
+
             /* Make the raw exception data
                 available to the handler,
                 so a program can emulate the
                 Python main loop. */
-            _PyErr_NormalizeException(tstate, &exc, &val, &tb);
-            if (tb != NULL)
-                PyException_SetTraceback(val, tb);
-            else
-                PyException_SetTraceback(val, Py_None);
-            Py_XDECREF(tb);
-            Py_XDECREF(exc);
-            PUSH(val);
+            PUSH(_PyErr_GetRaisedException(tstate));
             JUMPTO(handler);
             /* Resume normal execution */
             DISPATCH();
@@ -2075,19 +2065,15 @@ call_trace_protected(Py_tracefunc func, PyObject *obj,
                      PyThreadState *tstate, _PyInterpreterFrame *frame,
                      int what, PyObject *arg)
 {
-    PyObject *type, *value, *traceback;
-    int err;
-    _PyErr_Fetch(tstate, &type, &value, &traceback);
-    err = call_trace(func, obj, tstate, frame, what, arg);
+    PyObject *exc = _PyErr_GetRaisedException(tstate);
+    int err = call_trace(func, obj, tstate, frame, what, arg);
     if (err == 0)
     {
-        _PyErr_Restore(tstate, type, value, traceback);
+        _PyErr_SetRaisedException(tstate, exc);
         return 0;
     }
     else {
-        Py_XDECREF(type);
-        Py_XDECREF(value);
-        Py_XDECREF(traceback);
+        Py_XDECREF(exc);
         return -1;
     }
 }
@@ -2935,18 +2921,15 @@ format_exc_check_arg(PyThreadState *tstate, PyObject *exc,
 
     if (exc == PyExc_NameError) {
         // Include the name in the NameError exceptions to offer suggestions later.
-        PyObject *type, *value, *traceback;
-        PyErr_Fetch(&type, &value, &traceback);
-        PyErr_NormalizeException(&type, &value, &traceback);
-        if (PyErr_GivenExceptionMatches(value, PyExc_NameError)) {
-            PyNameErrorObject* exc = (PyNameErrorObject*) value;
-            if (exc->name == NULL) {
+        PyObject *exc = PyErr_GetRaisedException();
+        if (PyErr_GivenExceptionMatches(exc, PyExc_NameError)) {
+            if (((PyNameErrorObject*)exc)->name == NULL) {
                 // We do not care if this fails because we are going to restore the
                 // NameError anyway.
-                (void)PyObject_SetAttr(value, &_Py_ID(name), obj);
+                (void)PyObject_SetAttr(exc, &_Py_ID(name), obj);
             }
         }
-        PyErr_Restore(type, value, traceback);
+        PyErr_SetRaisedException(exc);
     }
 }
 
diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c
index 1bf223348d28..749d8144bf7a 100644
--- a/Python/ceval_gil.c
+++ b/Python/ceval_gil.c
@@ -2,7 +2,7 @@
 #include "Python.h"
 #include "pycore_atomic.h"        // _Py_atomic_int
 #include "pycore_ceval.h"         // _PyEval_SignalReceived()
-#include "pycore_pyerrors.h"      // _PyErr_Fetch()
+#include "pycore_pyerrors.h"      // _PyErr_GetRaisedException()
 #include "pycore_pylifecycle.h"   // _PyErr_Print()
 #include "pycore_initconfig.h"    // _PyStatus_OK()
 #include "pycore_interp.h"        // _Py_RunGC()
@@ -870,10 +870,9 @@ _Py_FinishPendingCalls(PyThreadState *tstate)
     }
 
     if (make_pending_calls(tstate->interp) < 0) {
-        PyObject *exc, *val, *tb;
-        _PyErr_Fetch(tstate, &exc, &val, &tb);
+        PyObject *exc = _PyErr_GetRaisedException(tstate);
         PyErr_BadInternalCall();
-        _PyErr_ChainExceptions(exc, val, tb);
+        _PyErr_ChainExceptions1(exc);
         _PyErr_Print(tstate);
     }
 }
diff --git a/Python/compile.c b/Python/compile.c
index 2f1130e62ee1..b14c637210ff 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -1633,8 +1633,7 @@ static void
 compiler_exit_scope(struct compiler *c)
 {
     // Don't call PySequence_DelItem() with an exception raised
-    PyObject *exc_type, *exc_val, *exc_tb;
-    PyErr_Fetch(&exc_type, &exc_val, &exc_tb);
+    PyObject *exc = PyErr_GetRaisedException();
 
     c->c_nestlevel--;
     compiler_unit_free(c->u);
@@ -1655,7 +1654,7 @@ compiler_exit_scope(struct compiler *c)
         c->u = NULL;
     }
 
-    PyErr_Restore(exc_type, exc_val, exc_tb);
+    PyErr_SetRaisedException(exc);
 }
 
 /* Search if variable annotations are present statically in a block. */
diff --git a/Python/frame.c b/Python/frame.c
index b562709ce10f..c2c0be301139 100644
--- a/Python/frame.c
+++ b/Python/frame.c
@@ -29,17 +29,14 @@ PyFrameObject *
 _PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame)
 {
     assert(frame->frame_obj == NULL);
-    PyObject *error_type, *error_value, *error_traceback;
-    PyErr_Fetch(&error_type, &error_value, &error_traceback);
+    PyObject *exc = PyErr_GetRaisedException();
 
     PyFrameObject *f = _PyFrame_New_NoTrack(frame->f_code);
     if (f == NULL) {
-        Py_XDECREF(error_type);
-        Py_XDECREF(error_value);
-        Py_XDECREF(error_traceback);
+        Py_XDECREF(exc);
         return NULL;
     }
-    PyErr_Restore(error_type, error_value, error_traceback);
+    PyErr_SetRaisedException(exc);
     if (frame->frame_obj) {
         // GH-97002: How did we get into this horrible situation? Most likely,
         // allocating f triggered a GC collection, which ran some code that
diff --git a/Python/initconfig.c b/Python/initconfig.c
index deec805a6b1c..db7f11e17d66 100644
--- a/Python/initconfig.c
+++ b/Python/initconfig.c
@@ -5,7 +5,7 @@
 #include "pycore_interp.h"        // _PyInterpreterState.runtime
 #include "pycore_long.h"          // _PY_LONG_MAX_STR_DIGITS_THRESHOLD
 #include "pycore_pathconfig.h"    // _Py_path_config
-#include "pycore_pyerrors.h"      // _PyErr_Fetch()
+#include "pycore_pyerrors.h"      // _PyErr_GetRaisedException()
 #include "pycore_pylifecycle.h"   // _Py_PreInitializeFromConfig()
 #include "pycore_pymem.h"         // _PyMem_SetDefaultAllocator()
 #include "pycore_pystate.h"       // _PyThreadState_GET()
diff --git a/Python/modsupport.c b/Python/modsupport.c
index b9a10dc157e7..75698455c881 100644
--- a/Python/modsupport.c
+++ b/Python/modsupport.c
@@ -93,16 +93,12 @@ static PyObject *do_mkvalue(const char**, va_list *, int);
 static void
 do_ignore(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n, int flags)
 {
-    PyObject *v;
-    Py_ssize_t i;
     assert(PyErr_Occurred());
-    v = PyTuple_New(n);
-    for (i = 0; i < n; i++) {
-        PyObject *exception, *value, *tb, *w;
-
-        PyErr_Fetch(&exception, &value, &tb);
-        w = do_mkvalue(p_format, p_va, flags);
-        PyErr_Restore(exception, value, tb);
+    PyObject *v = PyTuple_New(n);
+    for (Py_ssize_t i = 0; i < n; i++) {
+        PyObject *exc = PyErr_GetRaisedException();
+        PyObject *w = do_mkvalue(p_format, p_va, flags);
+        PyErr_SetRaisedException(exc);
         if (w != NULL) {
             if (v != NULL) {
                 PyTuple_SET_ITEM(v, i, w);
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index b69b80356092..207abb964bca 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -23,7 +23,7 @@ Data members:
 #include "pycore_namespace.h"     // _PyNamespace_New()
 #include "pycore_object.h"        // _PyObject_IS_GC()
 #include "pycore_pathconfig.h"    // _PyPathConfig_ComputeSysPath0()
-#include "pycore_pyerrors.h"      // _PyErr_Fetch()
+#include "pycore_pyerrors.h"      // _PyErr_GetRaisedException()
 #include "pycore_pylifecycle.h"   // _PyErr_WriteUnraisableDefaultHook()
 #include "pycore_pymath.h"        // _PY_SHORT_FLOAT_REPR
 #include "pycore_pymem.h"         // _PyMem_SetDefaultAllocator()
@@ -89,12 +89,11 @@ PySys_GetObject(const char *name)
 {
     PyThreadState *tstate = _PyThreadState_GET();
 
-    PyObject *exc_type, *exc_value, *exc_tb;
-    _PyErr_Fetch(tstate, &exc_type, &exc_value, &exc_tb);
+    PyObject *exc = _PyErr_GetRaisedException(tstate);
     PyObject *value = _PySys_GetObject(tstate->interp, name);
     /* XXX Suppress a new exception if it was raised and restore
      * the old one. */
-    _PyErr_Restore(tstate, exc_type, exc_value, exc_tb);
+    _PyErr_SetRaisedException(tstate, exc);
     return value;
 }
 
@@ -203,8 +202,8 @@ sys_audit_tstate(PyThreadState *ts, const char *event,
 
     int dtrace = PyDTrace_AUDIT_ENABLED();
 
-    PyObject *exc_type, *exc_value, *exc_tb;
-    _PyErr_Fetch(ts, &exc_type, &exc_value, &exc_tb);
+
+    PyObject *exc = _PyErr_GetRaisedException(ts);
 
     /* Initialize event args now */
     if (argFormat && argFormat[0]) {
@@ -287,13 +286,11 @@ sys_audit_tstate(PyThreadState *ts, const char *event,
     Py_XDECREF(eventArgs);
 
     if (!res) {
-        _PyErr_Restore(ts, exc_type, exc_value, exc_tb);
+        _PyErr_SetRaisedException(ts, exc);
     }
     else {
         assert(_PyErr_Occurred(ts));
-        Py_XDECREF(exc_type);
-        Py_XDECREF(exc_value);
-        Py_XDECREF(exc_tb);
+        Py_XDECREF(exc);
     }
 
     return res;
@@ -3661,12 +3658,11 @@ static void
 sys_write(PyObject *key, FILE *fp, const char *format, va_list va)
 {
     PyObject *file;
-    PyObject *error_type, *error_value, *error_traceback;
     char buffer[1001];
     int written;
     PyThreadState *tstate = _PyThreadState_GET();
 
-    _PyErr_Fetch(tstate, &error_type, &error_value, &error_traceback);
+    PyObject *exc = _PyErr_GetRaisedException(tstate);
     file = _PySys_GetAttr(tstate, key);
     written = PyOS_vsnprintf(buffer, sizeof(buffer), format, va);
     if (sys_pyfile_write(buffer, file) != 0) {
@@ -3678,7 +3674,7 @@ sys_write(PyObject *key, FILE *fp, const char *format, va_list va)
         if (sys_pyfile_write(truncated, file) != 0)
             fputs(truncated, fp);
     }
-    _PyErr_Restore(tstate, error_type, error_value, error_traceback);
+    _PyErr_SetRaisedException(tstate, exc);
 }
 
 void
@@ -3708,7 +3704,7 @@ sys_format(PyObject *key, FILE *fp, const char *format, va_list va)
     const char *utf8;
     PyThreadState *tstate = _PyThreadState_GET();
 
-    PyObject *error = _PyErr_GetRaisedException(tstate);
+    PyObject *exc = _PyErr_GetRaisedException(tstate);
     file = _PySys_GetAttr(tstate, key);
     message = PyUnicode_FromFormatV(format, va);
     if (message != NULL) {
@@ -3720,7 +3716,7 @@ sys_format(PyObject *key, FILE *fp, const char *format, va_list va)
         }
         Py_DECREF(message);
     }
-    _PyErr_SetRaisedException(tstate, error);
+    _PyErr_SetRaisedException(tstate, exc);
 }
 
 void



More information about the Python-checkins mailing list