Skip to content

Commit 4c87537

Browse files
authored
gh-102192: Replace PyErr_Fetch/Restore etc by more efficient alternatives (in Python/) (#102193)
1 parent 85b1fc1 commit 4c87537

File tree

8 files changed

+42
-72
lines changed

8 files changed

+42
-72
lines changed

Python/bytecodes.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include "pycore_object.h" // _PyObject_GC_TRACK()
1818
#include "pycore_moduleobject.h" // PyModuleObject
1919
#include "pycore_opcode.h" // EXTRA_CASES
20-
#include "pycore_pyerrors.h" // _PyErr_Fetch()
20+
#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
2121
#include "pycore_pymem.h" // _PyMem_IsPtrFreed()
2222
#include "pycore_pystate.h" // _PyInterpreterState_GET()
2323
#include "pycore_range.h" // _PyRangeIterObject

Python/ceval.c

+16-33
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#include "pycore_object.h" // _PyObject_GC_TRACK()
1414
#include "pycore_moduleobject.h" // PyModuleObject
1515
#include "pycore_opcode.h" // EXTRA_CASES
16-
#include "pycore_pyerrors.h" // _PyErr_Fetch()
16+
#include "pycore_pyerrors.h" // _PyErr_Fetch(), _PyErr_GetRaisedException()
1717
#include "pycore_pymem.h" // _PyMem_IsPtrFreed()
1818
#include "pycore_pystate.h" // _PyInterpreterState_GET()
1919
#include "pycore_range.h" // _PyRangeIterObject
@@ -105,8 +105,7 @@ static void
105105
dump_stack(_PyInterpreterFrame *frame, PyObject **stack_pointer)
106106
{
107107
PyObject **stack_base = _PyFrame_Stackbase(frame);
108-
PyObject *type, *value, *traceback;
109-
PyErr_Fetch(&type, &value, &traceback);
108+
PyObject *exc = PyErr_GetRaisedException();
110109
printf(" stack=[");
111110
for (PyObject **ptr = stack_base; ptr < stack_pointer; ptr++) {
112111
if (ptr != stack_base) {
@@ -120,7 +119,7 @@ dump_stack(_PyInterpreterFrame *frame, PyObject **stack_pointer)
120119
}
121120
printf("]\n");
122121
fflush(stdout);
123-
PyErr_Restore(type, value, traceback);
122+
PyErr_SetRaisedException(exc);
124123
}
125124

126125
static void
@@ -157,8 +156,7 @@ lltrace_resume_frame(_PyInterpreterFrame *frame)
157156
return;
158157
}
159158
PyFunctionObject *f = (PyFunctionObject *)fobj;
160-
PyObject *type, *value, *traceback;
161-
PyErr_Fetch(&type, &value, &traceback);
159+
PyObject *exc = PyErr_GetRaisedException();
162160
PyObject *name = f->func_qualname;
163161
if (name == NULL) {
164162
name = f->func_name;
@@ -178,7 +176,7 @@ lltrace_resume_frame(_PyInterpreterFrame *frame)
178176
}
179177
printf("\n");
180178
fflush(stdout);
181-
PyErr_Restore(type, value, traceback);
179+
PyErr_SetRaisedException(exc);
182180
}
183181
#endif
184182
static int call_trace(Py_tracefunc, PyObject *,
@@ -1032,7 +1030,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
10321030
PyObject *v = POP();
10331031
Py_XDECREF(v);
10341032
}
1035-
PyObject *exc, *val, *tb;
10361033
if (lasti) {
10371034
int frame_lasti = _PyInterpreterFrame_LASTI(frame);
10381035
PyObject *lasti = PyLong_FromLong(frame_lasti);
@@ -1041,19 +1038,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
10411038
}
10421039
PUSH(lasti);
10431040
}
1044-
_PyErr_Fetch(tstate, &exc, &val, &tb);
1041+
10451042
/* Make the raw exception data
10461043
available to the handler,
10471044
so a program can emulate the
10481045
Python main loop. */
1049-
_PyErr_NormalizeException(tstate, &exc, &val, &tb);
1050-
if (tb != NULL)
1051-
PyException_SetTraceback(val, tb);
1052-
else
1053-
PyException_SetTraceback(val, Py_None);
1054-
Py_XDECREF(tb);
1055-
Py_XDECREF(exc);
1056-
PUSH(val);
1046+
PUSH(_PyErr_GetRaisedException(tstate));
10571047
JUMPTO(handler);
10581048
/* Resume normal execution */
10591049
DISPATCH();
@@ -2075,19 +2065,15 @@ call_trace_protected(Py_tracefunc func, PyObject *obj,
20752065
PyThreadState *tstate, _PyInterpreterFrame *frame,
20762066
int what, PyObject *arg)
20772067
{
2078-
PyObject *type, *value, *traceback;
2079-
int err;
2080-
_PyErr_Fetch(tstate, &type, &value, &traceback);
2081-
err = call_trace(func, obj, tstate, frame, what, arg);
2068+
PyObject *exc = _PyErr_GetRaisedException(tstate);
2069+
int err = call_trace(func, obj, tstate, frame, what, arg);
20822070
if (err == 0)
20832071
{
2084-
_PyErr_Restore(tstate, type, value, traceback);
2072+
_PyErr_SetRaisedException(tstate, exc);
20852073
return 0;
20862074
}
20872075
else {
2088-
Py_XDECREF(type);
2089-
Py_XDECREF(value);
2090-
Py_XDECREF(traceback);
2076+
Py_XDECREF(exc);
20912077
return -1;
20922078
}
20932079
}
@@ -2935,18 +2921,15 @@ format_exc_check_arg(PyThreadState *tstate, PyObject *exc,
29352921

29362922
if (exc == PyExc_NameError) {
29372923
// Include the name in the NameError exceptions to offer suggestions later.
2938-
PyObject *type, *value, *traceback;
2939-
PyErr_Fetch(&type, &value, &traceback);
2940-
PyErr_NormalizeException(&type, &value, &traceback);
2941-
if (PyErr_GivenExceptionMatches(value, PyExc_NameError)) {
2942-
PyNameErrorObject* exc = (PyNameErrorObject*) value;
2943-
if (exc->name == NULL) {
2924+
PyObject *exc = PyErr_GetRaisedException();
2925+
if (PyErr_GivenExceptionMatches(exc, PyExc_NameError)) {
2926+
if (((PyNameErrorObject*)exc)->name == NULL) {
29442927
// We do not care if this fails because we are going to restore the
29452928
// NameError anyway.
2946-
(void)PyObject_SetAttr(value, &_Py_ID(name), obj);
2929+
(void)PyObject_SetAttr(exc, &_Py_ID(name), obj);
29472930
}
29482931
}
2949-
PyErr_Restore(type, value, traceback);
2932+
PyErr_SetRaisedException(exc);
29502933
}
29512934
}
29522935

Python/ceval_gil.c

+3-4
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#include "Python.h"
33
#include "pycore_atomic.h" // _Py_atomic_int
44
#include "pycore_ceval.h" // _PyEval_SignalReceived()
5-
#include "pycore_pyerrors.h" // _PyErr_Fetch()
5+
#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
66
#include "pycore_pylifecycle.h" // _PyErr_Print()
77
#include "pycore_initconfig.h" // _PyStatus_OK()
88
#include "pycore_interp.h" // _Py_RunGC()
@@ -870,10 +870,9 @@ _Py_FinishPendingCalls(PyThreadState *tstate)
870870
}
871871

872872
if (make_pending_calls(tstate->interp) < 0) {
873-
PyObject *exc, *val, *tb;
874-
_PyErr_Fetch(tstate, &exc, &val, &tb);
873+
PyObject *exc = _PyErr_GetRaisedException(tstate);
875874
PyErr_BadInternalCall();
876-
_PyErr_ChainExceptions(exc, val, tb);
875+
_PyErr_ChainExceptions1(exc);
877876
_PyErr_Print(tstate);
878877
}
879878
}

Python/compile.c

+2-3
Original file line numberDiff line numberDiff line change
@@ -1633,8 +1633,7 @@ static void
16331633
compiler_exit_scope(struct compiler *c)
16341634
{
16351635
// Don't call PySequence_DelItem() with an exception raised
1636-
PyObject *exc_type, *exc_val, *exc_tb;
1637-
PyErr_Fetch(&exc_type, &exc_val, &exc_tb);
1636+
PyObject *exc = PyErr_GetRaisedException();
16381637

16391638
c->c_nestlevel--;
16401639
compiler_unit_free(c->u);
@@ -1655,7 +1654,7 @@ compiler_exit_scope(struct compiler *c)
16551654
c->u = NULL;
16561655
}
16571656

1658-
PyErr_Restore(exc_type, exc_val, exc_tb);
1657+
PyErr_SetRaisedException(exc);
16591658
}
16601659

16611660
/* Search if variable annotations are present statically in a block. */

Python/frame.c

+3-6
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,14 @@ PyFrameObject *
2929
_PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame)
3030
{
3131
assert(frame->frame_obj == NULL);
32-
PyObject *error_type, *error_value, *error_traceback;
33-
PyErr_Fetch(&error_type, &error_value, &error_traceback);
32+
PyObject *exc = PyErr_GetRaisedException();
3433

3534
PyFrameObject *f = _PyFrame_New_NoTrack(frame->f_code);
3635
if (f == NULL) {
37-
Py_XDECREF(error_type);
38-
Py_XDECREF(error_value);
39-
Py_XDECREF(error_traceback);
36+
Py_XDECREF(exc);
4037
return NULL;
4138
}
42-
PyErr_Restore(error_type, error_value, error_traceback);
39+
PyErr_SetRaisedException(exc);
4340
if (frame->frame_obj) {
4441
// GH-97002: How did we get into this horrible situation? Most likely,
4542
// allocating f triggered a GC collection, which ran some code that

Python/initconfig.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include "pycore_interp.h" // _PyInterpreterState.runtime
66
#include "pycore_long.h" // _PY_LONG_MAX_STR_DIGITS_THRESHOLD
77
#include "pycore_pathconfig.h" // _Py_path_config
8-
#include "pycore_pyerrors.h" // _PyErr_Fetch()
8+
#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
99
#include "pycore_pylifecycle.h" // _Py_PreInitializeFromConfig()
1010
#include "pycore_pymem.h" // _PyMem_SetDefaultAllocator()
1111
#include "pycore_pystate.h" // _PyThreadState_GET()

Python/modsupport.c

+5-9
Original file line numberDiff line numberDiff line change
@@ -93,16 +93,12 @@ static PyObject *do_mkvalue(const char**, va_list *, int);
9393
static void
9494
do_ignore(const char **p_format, va_list *p_va, char endchar, Py_ssize_t n, int flags)
9595
{
96-
PyObject *v;
97-
Py_ssize_t i;
9896
assert(PyErr_Occurred());
99-
v = PyTuple_New(n);
100-
for (i = 0; i < n; i++) {
101-
PyObject *exception, *value, *tb, *w;
102-
103-
PyErr_Fetch(&exception, &value, &tb);
104-
w = do_mkvalue(p_format, p_va, flags);
105-
PyErr_Restore(exception, value, tb);
97+
PyObject *v = PyTuple_New(n);
98+
for (Py_ssize_t i = 0; i < n; i++) {
99+
PyObject *exc = PyErr_GetRaisedException();
100+
PyObject *w = do_mkvalue(p_format, p_va, flags);
101+
PyErr_SetRaisedException(exc);
106102
if (w != NULL) {
107103
if (v != NULL) {
108104
PyTuple_SET_ITEM(v, i, w);

Python/sysmodule.c

+11-15
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Data members:
2323
#include "pycore_namespace.h" // _PyNamespace_New()
2424
#include "pycore_object.h" // _PyObject_IS_GC()
2525
#include "pycore_pathconfig.h" // _PyPathConfig_ComputeSysPath0()
26-
#include "pycore_pyerrors.h" // _PyErr_Fetch()
26+
#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
2727
#include "pycore_pylifecycle.h" // _PyErr_WriteUnraisableDefaultHook()
2828
#include "pycore_pymath.h" // _PY_SHORT_FLOAT_REPR
2929
#include "pycore_pymem.h" // _PyMem_SetDefaultAllocator()
@@ -89,12 +89,11 @@ PySys_GetObject(const char *name)
8989
{
9090
PyThreadState *tstate = _PyThreadState_GET();
9191

92-
PyObject *exc_type, *exc_value, *exc_tb;
93-
_PyErr_Fetch(tstate, &exc_type, &exc_value, &exc_tb);
92+
PyObject *exc = _PyErr_GetRaisedException(tstate);
9493
PyObject *value = _PySys_GetObject(tstate->interp, name);
9594
/* XXX Suppress a new exception if it was raised and restore
9695
* the old one. */
97-
_PyErr_Restore(tstate, exc_type, exc_value, exc_tb);
96+
_PyErr_SetRaisedException(tstate, exc);
9897
return value;
9998
}
10099

@@ -203,8 +202,8 @@ sys_audit_tstate(PyThreadState *ts, const char *event,
203202

204203
int dtrace = PyDTrace_AUDIT_ENABLED();
205204

206-
PyObject *exc_type, *exc_value, *exc_tb;
207-
_PyErr_Fetch(ts, &exc_type, &exc_value, &exc_tb);
205+
206+
PyObject *exc = _PyErr_GetRaisedException(ts);
208207

209208
/* Initialize event args now */
210209
if (argFormat && argFormat[0]) {
@@ -287,13 +286,11 @@ sys_audit_tstate(PyThreadState *ts, const char *event,
287286
Py_XDECREF(eventArgs);
288287

289288
if (!res) {
290-
_PyErr_Restore(ts, exc_type, exc_value, exc_tb);
289+
_PyErr_SetRaisedException(ts, exc);
291290
}
292291
else {
293292
assert(_PyErr_Occurred(ts));
294-
Py_XDECREF(exc_type);
295-
Py_XDECREF(exc_value);
296-
Py_XDECREF(exc_tb);
293+
Py_XDECREF(exc);
297294
}
298295

299296
return res;
@@ -3661,12 +3658,11 @@ static void
36613658
sys_write(PyObject *key, FILE *fp, const char *format, va_list va)
36623659
{
36633660
PyObject *file;
3664-
PyObject *error_type, *error_value, *error_traceback;
36653661
char buffer[1001];
36663662
int written;
36673663
PyThreadState *tstate = _PyThreadState_GET();
36683664

3669-
_PyErr_Fetch(tstate, &error_type, &error_value, &error_traceback);
3665+
PyObject *exc = _PyErr_GetRaisedException(tstate);
36703666
file = _PySys_GetAttr(tstate, key);
36713667
written = PyOS_vsnprintf(buffer, sizeof(buffer), format, va);
36723668
if (sys_pyfile_write(buffer, file) != 0) {
@@ -3678,7 +3674,7 @@ sys_write(PyObject *key, FILE *fp, const char *format, va_list va)
36783674
if (sys_pyfile_write(truncated, file) != 0)
36793675
fputs(truncated, fp);
36803676
}
3681-
_PyErr_Restore(tstate, error_type, error_value, error_traceback);
3677+
_PyErr_SetRaisedException(tstate, exc);
36823678
}
36833679

36843680
void
@@ -3708,7 +3704,7 @@ sys_format(PyObject *key, FILE *fp, const char *format, va_list va)
37083704
const char *utf8;
37093705
PyThreadState *tstate = _PyThreadState_GET();
37103706

3711-
PyObject *error = _PyErr_GetRaisedException(tstate);
3707+
PyObject *exc = _PyErr_GetRaisedException(tstate);
37123708
file = _PySys_GetAttr(tstate, key);
37133709
message = PyUnicode_FromFormatV(format, va);
37143710
if (message != NULL) {
@@ -3720,7 +3716,7 @@ sys_format(PyObject *key, FILE *fp, const char *format, va_list va)
37203716
}
37213717
Py_DECREF(message);
37223718
}
3723-
_PyErr_SetRaisedException(tstate, error);
3719+
_PyErr_SetRaisedException(tstate, exc);
37243720
}
37253721

37263722
void

0 commit comments

Comments
 (0)