From 10687bd025002c2faa5ac5dece48f1d423a19798 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 7 Dec 2021 17:42:36 +0000 Subject: [PATCH 01/14] bpo-45711: Do not PUSH/POP traceback to the stack as part of exc_info --- Doc/library/dis.rst | 27 ++-- Include/internal/pycore_pyerrors.h | 4 + Lib/importlib/_bootstrap_external.py | 1 + Lib/test/test_dis.py | 117 +++++++++++++----- .../2021-12-05-17-36-08.bpo-45711.3TmTSw.rst | 1 + Python/ceval.c | 67 ++++++---- Python/compile.c | 48 +++---- 7 files changed, 181 insertions(+), 84 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2021-12-05-17-36-08.bpo-45711.3TmTSw.rst diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 7ac5a9b1f54549..526a95a4d9c043 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -474,13 +474,16 @@ the original TOS1. .. opcode:: END_ASYNC_FOR Terminates an :keyword:`async for` loop. Handles an exception raised - when awaiting a next item. If TOS is :exc:`StopAsyncIteration` pop 7 + when awaiting a next item. If TOS is :exc:`StopAsyncIteration` pop 5 values from the stack and restore the exception state using the second - three of them. Otherwise re-raise the exception using the three values + two of them. Otherwise re-raise the exception using the two values from the stack. An exception handler block is removed from the block stack. .. versionadded:: 3.8 + .. versionchanged:: 3.11 + + Exception representation on the stack now consist of two, not three, items. .. opcode:: BEFORE_ASYNC_WITH @@ -561,8 +564,11 @@ iterations of the loop. .. opcode:: POP_EXCEPT - Pops three values from the stack, which are used to restore the exception state. + Pops two values from the stack, which are used to restore the exception state. + + .. versionchanged:: 3.11 + Exception representation on the stack now consist of two, not three, items. .. opcode:: RERAISE @@ -572,11 +578,14 @@ iterations of the loop. .. versionadded:: 3.9 + .. versionchanged:: 3.11 + + Exception representation on the stack now consist of two, not three, items. .. opcode:: PUSH_EXC_INFO - Pops the three values from the stack. Pushes the current exception to the top of the stack. - Pushes the three values originally popped back to the stack. + Pops two values from the stack. Pushes the current exception to the top of the stack. + Pushes the two values originally popped back to the stack. Used in exception handlers. .. versionadded:: 3.11 @@ -584,8 +593,9 @@ iterations of the loop. .. opcode:: WITH_EXCEPT_START - Calls the function in position 8 on the stack with the top three - items on the stack as arguments. + Calls the function in position 6 on the stack with the top two + items on the stack, as well as a traceback derived from the second item, + as arguments. Used to implement the call ``context_manager.__exit__(*exc_info())`` when an exception has occurred in a :keyword:`with` statement. @@ -593,6 +603,9 @@ iterations of the loop. .. versionchanged:: 3.11 The ``__exit__`` function is in position 8 of the stack rather than 7. + .. versionchanged:: 3.11 + + Exception representation on the stack now consist of two, not three, items. .. opcode:: POP_EXCEPT_AND_RERAISE diff --git a/Include/internal/pycore_pyerrors.h b/Include/internal/pycore_pyerrors.h index 5e8d2025dfaf07..4aae840eabca28 100644 --- a/Include/internal/pycore_pyerrors.h +++ b/Include/internal/pycore_pyerrors.h @@ -114,6 +114,10 @@ PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalRefcountErrorFunc( #define _Py_FatalRefcountError(message) _Py_FatalRefcountErrorFunc(__func__, message) + +/* number of items stored in the stack for each exception */ +#define PY_EXC_INFO_STACK_SIZE 2 + #ifdef __cplusplus } #endif diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index 6e7ea7b3781431..f5c3f10aac9f72 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -372,6 +372,7 @@ def _write_atomic(path, data, mode=0o666): # BINARY_OP) # Python 3.11a3 3465 (Add COPY_FREE_VARS opcode) # Python 3.11a3 3466 (bpo-45292: PEP-654 except*) +# Python 3.11a3 3467 (bpo-45711: remove type, traceback from exc_info) # # MAGIC must change whenever the bytecode emitted by the compiler may no diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index e821e001ad8800..8ff427f3e794a4 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -310,33 +310,32 @@ def bug42562(): >> 14 PUSH_EXC_INFO %3d 16 LOAD_GLOBAL 0 (Exception) - 18 JUMP_IF_NOT_EXC_MATCH 26 (to 52) + 18 JUMP_IF_NOT_EXC_MATCH 25 (to 50) 20 POP_TOP 22 STORE_FAST 0 (e) - 24 POP_TOP - -%3d 26 LOAD_FAST 0 (e) - 28 LOAD_ATTR 1 (__traceback__) - 30 STORE_FAST 1 (tb) - 32 POP_EXCEPT - 34 LOAD_CONST 0 (None) - 36 STORE_FAST 0 (e) - 38 DELETE_FAST 0 (e) - -%3d 40 LOAD_FAST 1 (tb) - 42 RETURN_VALUE - >> 44 LOAD_CONST 0 (None) - 46 STORE_FAST 0 (e) - 48 DELETE_FAST 0 (e) - 50 RERAISE 1 - -%3d >> 52 RERAISE 0 - >> 54 POP_EXCEPT_AND_RERAISE + +%3d 24 LOAD_FAST 0 (e) + 26 LOAD_ATTR 1 (__traceback__) + 28 STORE_FAST 1 (tb) + 30 POP_EXCEPT + 32 LOAD_CONST 0 (None) + 34 STORE_FAST 0 (e) + 36 DELETE_FAST 0 (e) + +%3d 38 LOAD_FAST 1 (tb) + 40 RETURN_VALUE + >> 42 LOAD_CONST 0 (None) + 44 STORE_FAST 0 (e) + 46 DELETE_FAST 0 (e) + 48 RERAISE 1 + +%3d >> 50 RERAISE 0 + >> 52 POP_EXCEPT_AND_RERAISE ExceptionTable: 2 to 8 -> 14 [0] - 14 to 24 -> 54 [3] lasti - 26 to 30 -> 44 [3] lasti - 44 to 52 -> 54 [3] lasti + 14 to 22 -> 52 [2] lasti + 24 to 28 -> 42 [2] lasti + 42 to 50 -> 52 [2] lasti """ % (TRACEBACK_CODE.co_firstlineno + 1, TRACEBACK_CODE.co_firstlineno + 2, TRACEBACK_CODE.co_firstlineno + 5, @@ -395,7 +394,7 @@ def _tryfinallyconst(b): >> 22 POP_EXCEPT_AND_RERAISE ExceptionTable: 2 to 2 -> 12 [0] - 12 to 20 -> 22 [3] lasti + 12 to 20 -> 22 [2] lasti """ % (_tryfinally.__code__.co_firstlineno + 1, _tryfinally.__code__.co_firstlineno + 2, _tryfinally.__code__.co_firstlineno + 4, @@ -418,7 +417,7 @@ def _tryfinallyconst(b): 22 RERAISE 0 >> 24 POP_EXCEPT_AND_RERAISE ExceptionTable: - 14 to 22 -> 24 [3] lasti + 14 to 22 -> 24 [2] lasti """ % (_tryfinallyconst.__code__.co_firstlineno + 1, _tryfinallyconst.__code__.co_firstlineno + 2, _tryfinallyconst.__code__.co_firstlineno + 4, @@ -864,7 +863,7 @@ async def async_def(): Positional-only arguments: 0 Kw-only arguments: 0 Number of locals: 2 -Stack size: 10 +Stack size: 8 Flags: OPTIMIZED, NEWLOCALS, COROUTINE Constants: 0: None @@ -1107,12 +1106,13 @@ def _prepare_test_cases(): Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=108, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=110, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=112, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=14, argval=144, argrepr='to 144', offset=114, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=13, argval=142, argrepr='to 142', offset=114, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=116, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=118, starts_line=22, is_jump_target=False, positions=None), - Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=70, argval=140, argrepr='to 140', offset=120, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=69, argval=138, argrepr='to 138', offset=120, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=122, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=124, starts_line=None, is_jump_target=False, positions=None), +<<<<<<< HEAD Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=126, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=128, starts_line=23, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=130, starts_line=None, is_jump_target=False, positions=None), @@ -1166,6 +1166,67 @@ def _prepare_test_cases(): Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=226, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=230, starts_line=None, is_jump_target=False, positions=None), +======= + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=126, starts_line=23, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=128, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=130, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=132, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=134, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=32, argval=202, argrepr='to 202', offset=136, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=138, starts_line=22, is_jump_target=True, positions=None), + Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=140, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=142, starts_line=25, is_jump_target=True, positions=None), + Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=144, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=146, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=148, starts_line=26, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=150, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=152, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=154, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=156, starts_line=25, is_jump_target=False, positions=None), + Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=158, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=160, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=3, argval=3, argrepr='', offset=162, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=164, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=24, argval=216, argrepr='to 216', offset=166, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=168, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=89, argval=178, argrepr='to 178', offset=172, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=3, argval=3, argrepr='', offset=174, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=176, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=178, starts_line=None, is_jump_target=True, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=184, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=190, starts_line=28, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=192, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=194, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=196, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=198, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=200, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=202, starts_line=23, is_jump_target=True, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=204, starts_line=28, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=206, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=208, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=210, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=212, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=214, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=216, starts_line=25, is_jump_target=True, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=218, starts_line=28, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=220, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=222, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=224, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=226, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=230, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=232, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=234, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=236, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=238, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=240, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=242, starts_line=None, is_jump_target=False, positions=None), +>>>>>>> 61cec252f6 (bpo-45711: Do not PUSH/POP traceback to the stack as part of exc_info) ] # One last piece of inspect fodder to check the default line number handling diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-05-17-36-08.bpo-45711.3TmTSw.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-05-17-36-08.bpo-45711.3TmTSw.rst new file mode 100644 index 00000000000000..cf90ba8bc75bf9 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-05-17-36-08.bpo-45711.3TmTSw.rst @@ -0,0 +1 @@ +:c:func:`_PyErr_ChainStackItem` no longer normalized ``exc_info`` (including setting the traceback on the exception instance) because ``exc_info`` is always normalized. \ No newline at end of file diff --git a/Python/ceval.c b/Python/ceval.c index fb19f78ba14d46..9e937497f14eae 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -19,7 +19,7 @@ #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_object.h" // _PyObject_GC_TRACK() #include "pycore_moduleobject.h" // PyModuleObject -#include "pycore_pyerrors.h" // _PyErr_Fetch() +#include "pycore_pyerrors.h" // _PyErr_Fetch(), PY_EXC_INFO_STACK_SIZE #include "pycore_pylifecycle.h" // _PyErr_Print() #include "pycore_pymem.h" // _PyMem_IsPtrFreed() #include "pycore_pystate.h" // _PyInterpreterState_GET() @@ -2737,7 +2737,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr exc_info->exc_type = POP(); exc_info->exc_value = POP(); - exc_info->exc_traceback = POP(); + + assert(exc_info->exc_value); + if (exc_info->exc_value != Py_None) { + exc_info->exc_traceback = PyException_GetTraceback(exc_info->exc_value); + } + else { + exc_info->exc_traceback = NULL; + } + ASSERT_EXC_TYPE_IS_REDUNDANT(exc_info->exc_type, exc_info->exc_value); Py_XDECREF(type); Py_XDECREF(value); @@ -2746,7 +2754,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(POP_EXCEPT_AND_RERAISE) { - PyObject *lasti = PEEK(4); + PyObject *lasti = PEEK(PY_EXC_INFO_STACK_SIZE + 1); if (PyLong_Check(lasti)) { frame->f_lasti = PyLong_AsLong(lasti); assert(!_PyErr_Occurred(tstate)); @@ -2759,7 +2767,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr _PyErr_StackItem *exc_info; type = POP(); value = POP(); - traceback = POP(); + assert(value); + assert(value != Py_None); + traceback = PyException_GetTraceback(value); ASSERT_EXC_TYPE_IS_REDUNDANT(type, value); Py_DECREF(POP()); /* lasti */ _PyErr_Restore(tstate, type, value, traceback); @@ -2769,7 +2779,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr traceback = exc_info->exc_traceback; exc_info->exc_type = POP(); exc_info->exc_value = POP(); - exc_info->exc_traceback = POP(); + + assert(exc_info->exc_value); + if (exc_info->exc_value != Py_None) { + exc_info->exc_traceback = PyException_GetTraceback(exc_info->exc_value); + } + else { + exc_info->exc_traceback = NULL; + } ASSERT_EXC_TYPE_IS_REDUNDANT(exc_info->exc_type, exc_info->exc_value); Py_XDECREF(type); Py_XDECREF(value); @@ -2779,7 +2796,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(RERAISE) { if (oparg) { - PyObject *lasti = PEEK(oparg+3); + PyObject *lasti = PEEK(oparg + PY_EXC_INFO_STACK_SIZE); if (PyLong_Check(lasti)) { frame->f_lasti = PyLong_AsLong(lasti); assert(!_PyErr_Occurred(tstate)); @@ -2792,7 +2809,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } PyObject *exc = POP(); PyObject *val = POP(); - PyObject *tb = POP(); + assert(val && PyExceptionInstance_Check(val)); + PyObject *tb = PyException_GetTraceback(val); ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); assert(PyExceptionClass_Check(exc)); _PyErr_Restore(tstate, exc, val, tb); @@ -2832,7 +2850,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(END_ASYNC_FOR) { PyObject *exc = POP(); PyObject *val = POP(); - PyObject *tb = POP(); + assert(val && PyExceptionInstance_Check(val)); + PyObject *tb = PyException_GetTraceback(val); ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); assert(PyExceptionClass_Check(exc)); if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) { @@ -4457,11 +4476,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(WITH_EXCEPT_START) { /* At the top of the stack are 8 values: - - (TOP, SECOND, THIRD) = exc_info() - - (FOURTH, FIFTH, SIXTH) = previous exception - - SEVENTH: lasti of exception in exc_info() - - EIGHTH: the context.__exit__ bound method - We call EIGHTH(TOP, SECOND, THIRD). + - (TOP, SECOND) = exc_info() + - (THIRD, FOURTH) = previous exception + - FIFTH: lasti of exception in exc_info() + - SIXTH: the context.__exit__ bound method + We call SIXTH(TOP, SECOND, GetTraceback(SECOND)). Then we push again the TOP exception and the __exit__ return value. */ @@ -4470,12 +4489,14 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr exc = TOP(); val = SECOND(); - tb = THIRD(); + assert(val && PyExceptionInstance_Check(val)); + tb = PyException_GetTraceback(val); + Py_XDECREF(tb); ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); assert(!Py_IsNone(exc)); assert(!PyLong_Check(exc)); - assert(PyLong_Check(PEEK(7))); - exit_func = PEEK(8); + assert(PyLong_Check(PEEK(1 + 2 * PY_EXC_INFO_STACK_SIZE))); + exit_func = PEEK(2 + 2 * PY_EXC_INFO_STACK_SIZE); PyObject *stack[4] = {NULL, exc, val, tb}; res = PyObject_Vectorcall(exit_func, stack + 1, 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); @@ -4489,10 +4510,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(PUSH_EXC_INFO) { PyObject *type = TOP(); PyObject *value = SECOND(); - PyObject *tb = THIRD(); + assert(value && PyExceptionInstance_Check(value)); + PyObject *tb = PyException_GetTraceback(value); ASSERT_EXC_TYPE_IS_REDUNDANT(type, value); + _PyErr_StackItem *exc_info = tstate->exc_info; - SET_THIRD(exc_info->exc_traceback); + Py_XDECREF(exc_info->exc_traceback); if (exc_info->exc_value != NULL) { SET_SECOND(exc_info->exc_value); } @@ -4507,8 +4530,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr Py_INCREF(Py_None); SET_TOP(Py_None); } - Py_INCREF(tb); - PUSH(tb); exc_info->exc_traceback = tb; Py_INCREF(value); @@ -5385,11 +5406,7 @@ MISS_WITH_OPARG_COUNTER(STORE_SUBSCR) PyException_SetTraceback(val, tb); else PyException_SetTraceback(val, Py_None); - if (tb == NULL) { - tb = Py_None; - Py_INCREF(Py_None); - } - PUSH(tb); + Py_XDECREF(tb); PUSH(val); PUSH(exc); ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); diff --git a/Python/compile.c b/Python/compile.c index 00e1e016969ad2..c16956b277e17d 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -27,6 +27,7 @@ #include "pycore_ast.h" // _PyAST_GetDocString() #include "pycore_compile.h" // _PyFuture_FromAST() #include "pycore_code.h" // _PyCode_New() +#include "pycore_pyerrors.h" // PY_EXC_INFO_STACK_SIZE #include "pycore_pymem.h" // _PyMem_IsPtrFreed() #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_symtable.h" // PySTEntryObject @@ -1050,9 +1051,9 @@ stack_effect(int opcode, int oparg, int jump) case POP_BLOCK: return 0; case POP_EXCEPT: - return -3; + return -PY_EXC_INFO_STACK_SIZE; case POP_EXCEPT_AND_RERAISE: - return -7; + return -(1 + 2 * PY_EXC_INFO_STACK_SIZE); case STORE_NAME: return -1; @@ -1123,23 +1124,23 @@ stack_effect(int opcode, int oparg, int jump) /* 0 in the normal flow. * Restore the stack position and push 3 values before jumping to * the handler if an exception be raised. */ - return jump ? 3 : 0; + return jump ? PY_EXC_INFO_STACK_SIZE : 0; case SETUP_CLEANUP: /* As SETUP_FINALLY, but pushes lasti as well */ - return jump ? 4 : 0; + return jump ? 1 + PY_EXC_INFO_STACK_SIZE : 0; case SETUP_WITH: /* 0 in the normal flow. * Restore the stack position to the position before the result * of __(a)enter__ and push 4 values before jumping to the handler * if an exception be raised. */ - return jump ? -1 + 4 : 0; + return jump ? -1 + PY_EXC_INFO_STACK_SIZE + 1 : 0; case PREP_RERAISE_STAR: return 2; case RERAISE: - return -3; + return -PY_EXC_INFO_STACK_SIZE; case PUSH_EXC_INFO: - return 3; + return PY_EXC_INFO_STACK_SIZE; case WITH_EXCEPT_START: return 1; @@ -1202,7 +1203,7 @@ stack_effect(int opcode, int oparg, int jump) case GET_YIELD_FROM_ITER: return 0; case END_ASYNC_FOR: - return -4; + return -(1 + PY_EXC_INFO_STACK_SIZE); case FORMAT_VALUE: /* If there's a fmt_spec on the stack, we go from 2->1, else 1->1. */ @@ -1870,13 +1871,12 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, case FINALLY_END: if (preserve_tos) { - ADDOP(c, ROT_FOUR); + ADDOP(c, ROT_THREE); } - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); /* exc_type */ + ADDOP(c, POP_TOP); /* exc_value */ if (preserve_tos) { - ADDOP(c, ROT_FOUR); + ADDOP(c, ROT_THREE); } ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); @@ -1909,7 +1909,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, ADDOP(c, POP_BLOCK); } if (preserve_tos) { - ADDOP(c, ROT_FOUR); + ADDOP(c, ROT_THREE); } ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); @@ -3354,7 +3354,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) ADDOP_JUMP(c, JUMP_IF_NOT_EXC_MATCH, except); NEXT_BLOCK(c); } - ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); /* exc_type */ if (handler->v.ExceptHandler.name) { basicblock *cleanup_end, *cleanup_body; @@ -3365,7 +3365,6 @@ compiler_try_except(struct compiler *c, stmt_ty s) } compiler_nameop(c, handler->v.ExceptHandler.name, Store); - ADDOP(c, POP_TOP); /* try: @@ -3416,8 +3415,7 @@ compiler_try_except(struct compiler *c, stmt_ty s) if (!cleanup_body) return 0; - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); /* exc_value */ compiler_use_next_block(c, cleanup_body); if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL, NULL)) return 0; @@ -5428,13 +5426,12 @@ compiler_with_except_finish(struct compiler *c, basicblock * cleanup) { return 0; ADDOP_JUMP(c, POP_JUMP_IF_TRUE, exit); NEXT_BLOCK(c); - ADDOP_I(c, RERAISE, 4); + ADDOP_I(c, RERAISE, 1 + PY_EXC_INFO_STACK_SIZE); compiler_use_next_block(c, cleanup); ADDOP(c, POP_EXCEPT_AND_RERAISE); compiler_use_next_block(c, exit); - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); + ADDOP(c, POP_TOP); /* exc_type */ + ADDOP(c, POP_TOP); /* exc_value */ ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); ADDOP(c, POP_TOP); @@ -5566,7 +5563,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) E: WITH_EXCEPT_START (calls EXPR.__exit__) POP_JUMP_IF_TRUE T: RERAISE - T: POP_TOP * 3 (remove exception from stack) + T: POP_TOP * PY_EXC_INFO_STACK_SIZE (remove exception from stack) POP_EXCEPT POP_TOP EXIT: @@ -7347,7 +7344,10 @@ assemble_emit_exception_table_entry(struct assembler *a, int start, int end, bas int size = end-start; assert(end > start); int target = handler->b_offset; - int depth = handler->b_preserve_lasti ? handler->b_startdepth-4 : handler->b_startdepth-3; + int depth = handler->b_startdepth - PY_EXC_INFO_STACK_SIZE; + if (handler->b_preserve_lasti) { + depth -= 1; + } assert(depth >= 0); int depth_lasti = (depth<<1) | handler->b_preserve_lasti; assemble_emit_exception_table_item(a, start, (1<<7)); From 37c7f12e5379c834168f01acefd761141741c912 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 7 Dec 2021 21:30:22 +0000 Subject: [PATCH 02/14] bpo-45711: remove exc_traceback from _PyErr_StackItem --- Include/cpython/pystate.h | 2 +- Include/internal/pycore_pyerrors.h | 5 +---- Lib/test/test_sys.py | 2 +- Modules/_asynciomodule.c | 4 +--- Objects/genobject.c | 3 --- Python/ceval.c | 26 +------------------------- Python/compile.c | 12 +++++------- Python/errors.c | 6 +----- Python/pystate.c | 1 - 9 files changed, 11 insertions(+), 50 deletions(-) diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index aa518281c80f50..7f500f61dfff0c 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -56,7 +56,7 @@ typedef struct _err_stackitem { * This ensures that the exception state is not impacted by "yields" * from an except handler. */ - PyObject *exc_type, *exc_value, *exc_traceback; + PyObject *exc_type, *exc_value; struct _err_stackitem *previous_item; diff --git a/Include/internal/pycore_pyerrors.h b/Include/internal/pycore_pyerrors.h index 4aae840eabca28..329749f2335188 100644 --- a/Include/internal/pycore_pyerrors.h +++ b/Include/internal/pycore_pyerrors.h @@ -24,16 +24,13 @@ static inline PyObject* _PyErr_Occurred(PyThreadState *tstate) static inline void _PyErr_ClearExcState(_PyErr_StackItem *exc_state) { - PyObject *t, *v, *tb; + PyObject *t, *v; t = exc_state->exc_type; v = exc_state->exc_value; - tb = exc_state->exc_traceback; exc_state->exc_type = NULL; exc_state->exc_value = NULL; - exc_state->exc_traceback = NULL; Py_XDECREF(t); Py_XDECREF(v); - Py_XDECREF(tb); } PyAPI_FUNC(PyObject*) _PyErr_StackItemToExcInfoTuple( diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 41ac03b920e64a..58310b753172c8 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1340,7 +1340,7 @@ def bar(cls): check(bar, size('PP')) # generator def get_gen(): yield 1 - check(get_gen(), size('P2PPP4P4c8P2iciP')) + check(get_gen(), size('P2PP4P4c8P2iciP')) # iterator check(iter('abc'), size('lP')) # callable-iterator diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 267faacde8a171..3d1f28ace7ebb0 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -812,7 +812,6 @@ FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg) _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state; Py_VISIT(exc_state->exc_type); Py_VISIT(exc_state->exc_value); - Py_VISIT(exc_state->exc_traceback); return 0; } @@ -1378,7 +1377,6 @@ _asyncio_Future__make_cancelled_error_impl(FutureObj *self) } else { assert(exc_state->exc_type == NULL); - assert(exc_state->exc_traceback == NULL); } return exc; @@ -2706,13 +2704,13 @@ task_step_impl(TaskObj *task, PyObject *exc) PyErr_NormalizeException(&et, &ev, &tb); if (tb != NULL) { PyException_SetTraceback(ev, tb); + Py_DECREF(tb); } FutureObj *fut = (FutureObj*)task; _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state; exc_state->exc_type = et; exc_state->exc_value = ev; - exc_state->exc_traceback = tb; return future_cancel(fut, NULL); } diff --git a/Objects/genobject.c b/Objects/genobject.c index 1b08b43ac22e90..6ec5f1b1ba51eb 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -27,7 +27,6 @@ exc_state_traverse(_PyErr_StackItem *exc_state, visitproc visit, void *arg) { Py_VISIT(exc_state->exc_type); Py_VISIT(exc_state->exc_value); - Py_VISIT(exc_state->exc_traceback); return 0; } @@ -884,7 +883,6 @@ make_gen(PyTypeObject *type, PyFunctionObject *func) gen->gi_weakreflist = NULL; gen->gi_exc_state.exc_type = NULL; gen->gi_exc_state.exc_value = NULL; - gen->gi_exc_state.exc_traceback = NULL; gen->gi_exc_state.previous_item = NULL; if (func->func_name != NULL) gen->gi_name = func->func_name; @@ -973,7 +971,6 @@ gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f, gen->gi_weakreflist = NULL; gen->gi_exc_state.exc_type = NULL; gen->gi_exc_state.exc_value = NULL; - gen->gi_exc_state.exc_traceback = NULL; gen->gi_exc_state.previous_item = NULL; if (name != NULL) gen->gi_name = name; diff --git a/Python/ceval.c b/Python/ceval.c index 9e937497f14eae..a2feba57e284f7 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2728,28 +2728,17 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(POP_EXCEPT) { - PyObject *type, *value, *traceback; + PyObject *type, *value; _PyErr_StackItem *exc_info; exc_info = tstate->exc_info; type = exc_info->exc_type; value = exc_info->exc_value; - traceback = exc_info->exc_traceback; - exc_info->exc_type = POP(); exc_info->exc_value = POP(); - assert(exc_info->exc_value); - if (exc_info->exc_value != Py_None) { - exc_info->exc_traceback = PyException_GetTraceback(exc_info->exc_value); - } - else { - exc_info->exc_traceback = NULL; - } - ASSERT_EXC_TYPE_IS_REDUNDANT(exc_info->exc_type, exc_info->exc_value); Py_XDECREF(type); Py_XDECREF(value); - Py_XDECREF(traceback); DISPATCH(); } @@ -2776,21 +2765,12 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr exc_info = tstate->exc_info; type = exc_info->exc_type; value = exc_info->exc_value; - traceback = exc_info->exc_traceback; exc_info->exc_type = POP(); exc_info->exc_value = POP(); - assert(exc_info->exc_value); - if (exc_info->exc_value != Py_None) { - exc_info->exc_traceback = PyException_GetTraceback(exc_info->exc_value); - } - else { - exc_info->exc_traceback = NULL; - } ASSERT_EXC_TYPE_IS_REDUNDANT(exc_info->exc_type, exc_info->exc_value); Py_XDECREF(type); Py_XDECREF(value); - Py_XDECREF(traceback); goto exception_unwind; } @@ -4510,12 +4490,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(PUSH_EXC_INFO) { PyObject *type = TOP(); PyObject *value = SECOND(); - assert(value && PyExceptionInstance_Check(value)); - PyObject *tb = PyException_GetTraceback(value); ASSERT_EXC_TYPE_IS_REDUNDANT(type, value); _PyErr_StackItem *exc_info = tstate->exc_info; - Py_XDECREF(exc_info->exc_traceback); if (exc_info->exc_value != NULL) { SET_SECOND(exc_info->exc_value); } @@ -4530,7 +4507,6 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr Py_INCREF(Py_None); SET_TOP(Py_None); } - exc_info->exc_traceback = tb; Py_INCREF(value); PUSH(value); diff --git a/Python/compile.c b/Python/compile.c index c16956b277e17d..fff96d4ed8177d 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3292,18 +3292,16 @@ compiler_try_star_finally(struct compiler *c, stmt_ty s) [] POP_BLOCK [] JUMP_FORWARD L0 - [tb, val, exc] L1: ) - [tb, val, exc, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1 - [tb, val, exc] POP - [tb, val] (or POP if no V1) - [tb] POP + [exc] L1: ) + [exc, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1 + [exc] (or POP if no V1) [] JUMP_FORWARD L0 - [tb, val, exc] L2: + [exc] L2: .............................etc....................... - [tb, val, exc] Ln+1: RERAISE # re-raise exception + [exc] Ln+1: RERAISE # re-raise exception [] L0: diff --git a/Python/errors.c b/Python/errors.c index 5be15e54db25b8..d535e70b9b9484 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -524,19 +524,16 @@ PyErr_GetExcInfo(PyObject **p_type, PyObject **p_value, PyObject **p_traceback) void PyErr_SetExcInfo(PyObject *type, PyObject *value, PyObject *traceback) { - PyObject *oldtype, *oldvalue, *oldtraceback; + PyObject *oldtype, *oldvalue; PyThreadState *tstate = _PyThreadState_GET(); oldtype = tstate->exc_info->exc_type; oldvalue = tstate->exc_info->exc_value; - oldtraceback = tstate->exc_info->exc_traceback; tstate->exc_info->exc_type = get_exc_type(value); Py_XINCREF(tstate->exc_info->exc_type); tstate->exc_info->exc_value = value; - tstate->exc_info->exc_traceback = get_exc_traceback(value); - Py_XINCREF(tstate->exc_info->exc_traceback); /* These args are no longer used, but we still need to steal a ref */ Py_XDECREF(type); @@ -544,7 +541,6 @@ PyErr_SetExcInfo(PyObject *type, PyObject *value, PyObject *traceback) Py_XDECREF(oldtype); Py_XDECREF(oldvalue); - Py_XDECREF(oldtraceback); } diff --git a/Python/pystate.c b/Python/pystate.c index 463b248f22336e..963b6501c8f014 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1030,7 +1030,6 @@ PyThreadState_Clear(PyThreadState *tstate) Py_CLEAR(tstate->exc_state.exc_type); Py_CLEAR(tstate->exc_state.exc_value); - Py_CLEAR(tstate->exc_state.exc_traceback); /* The stack of exception states should contain just this thread. */ if (verbose && tstate->exc_info != &tstate->exc_state) { From c5c23bdb1ea02515925270956836982db17799e7 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 9 Dec 2021 15:16:09 +0000 Subject: [PATCH 03/14] removed exc_type from stack --- Doc/library/dis.rst | 28 +++--- Include/internal/pycore_pyerrors.h | 2 +- Lib/importlib/_bootstrap_external.py | 2 +- Lib/test/test_dis.py | 129 +++++++++++++++++++-------- Python/ceval.c | 110 +++++++++-------------- Python/compile.c | 9 +- 6 files changed, 149 insertions(+), 131 deletions(-) diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 526a95a4d9c043..3a6148e486c479 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -474,16 +474,15 @@ the original TOS1. .. opcode:: END_ASYNC_FOR Terminates an :keyword:`async for` loop. Handles an exception raised - when awaiting a next item. If TOS is :exc:`StopAsyncIteration` pop 5 + when awaiting a next item. If TOS is :exc:`StopAsyncIteration` pop 3 values from the stack and restore the exception state using the second - two of them. Otherwise re-raise the exception using the two values + of them. Otherwise re-raise the exception using the value from the stack. An exception handler block is removed from the block stack. .. versionadded:: 3.8 .. versionchanged:: 3.11 - - Exception representation on the stack now consist of two, not three, items. + Exception representation on the stack now consist of one, not three, items. .. opcode:: BEFORE_ASYNC_WITH @@ -564,11 +563,10 @@ iterations of the loop. .. opcode:: POP_EXCEPT - Pops two values from the stack, which are used to restore the exception state. + Pops a value from the stack, which is used to restore the exception state. .. versionchanged:: 3.11 - - Exception representation on the stack now consist of two, not three, items. + Exception representation on the stack now consist of one, not three, items. .. opcode:: RERAISE @@ -579,13 +577,12 @@ iterations of the loop. .. versionadded:: 3.9 .. versionchanged:: 3.11 - - Exception representation on the stack now consist of two, not three, items. + Exception representation on the stack now consist of one, not three, items. .. opcode:: PUSH_EXC_INFO - Pops two values from the stack. Pushes the current exception to the top of the stack. - Pushes the two values originally popped back to the stack. + Pops a value from the stack. Pushes the current exception to the top of the stack. + Pushes the value originally popped back to the stack. Used in exception handlers. .. versionadded:: 3.11 @@ -593,9 +590,8 @@ iterations of the loop. .. opcode:: WITH_EXCEPT_START - Calls the function in position 6 on the stack with the top two - items on the stack, as well as a traceback derived from the second item, - as arguments. + Calls the function in position 4 on the stack with arguments (type, val, tb) + representing the exception at the top of the stack. Used to implement the call ``context_manager.__exit__(*exc_info())`` when an exception has occurred in a :keyword:`with` statement. @@ -604,8 +600,8 @@ iterations of the loop. The ``__exit__`` function is in position 8 of the stack rather than 7. .. versionchanged:: 3.11 - - Exception representation on the stack now consist of two, not three, items. + The ``__exit__`` function is in position 4 of the stack rather than 7. + Exception representation on the stack now consist of one, not three, items. .. opcode:: POP_EXCEPT_AND_RERAISE diff --git a/Include/internal/pycore_pyerrors.h b/Include/internal/pycore_pyerrors.h index 329749f2335188..d9f6e0ca723d6d 100644 --- a/Include/internal/pycore_pyerrors.h +++ b/Include/internal/pycore_pyerrors.h @@ -113,7 +113,7 @@ PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalRefcountErrorFunc( /* number of items stored in the stack for each exception */ -#define PY_EXC_INFO_STACK_SIZE 2 +#define PY_EXC_INFO_STACK_SIZE 1 #ifdef __cplusplus } diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py index f5c3f10aac9f72..890b1365ac14f5 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -382,7 +382,7 @@ def _write_atomic(path, data, mode=0o666): # Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array # in PC/launcher.c must also be updated. -MAGIC_NUMBER = (3466).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3467).to_bytes(2, 'little') + b'\r\n' _RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c _PYCACHE = '__pycache__' diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 8ff427f3e794a4..a692e771b9ba67 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -310,32 +310,31 @@ def bug42562(): >> 14 PUSH_EXC_INFO %3d 16 LOAD_GLOBAL 0 (Exception) - 18 JUMP_IF_NOT_EXC_MATCH 25 (to 50) - 20 POP_TOP - 22 STORE_FAST 0 (e) - -%3d 24 LOAD_FAST 0 (e) - 26 LOAD_ATTR 1 (__traceback__) - 28 STORE_FAST 1 (tb) - 30 POP_EXCEPT - 32 LOAD_CONST 0 (None) - 34 STORE_FAST 0 (e) - 36 DELETE_FAST 0 (e) - -%3d 38 LOAD_FAST 1 (tb) - 40 RETURN_VALUE - >> 42 LOAD_CONST 0 (None) - 44 STORE_FAST 0 (e) - 46 DELETE_FAST 0 (e) - 48 RERAISE 1 - -%3d >> 50 RERAISE 0 - >> 52 POP_EXCEPT_AND_RERAISE + 18 JUMP_IF_NOT_EXC_MATCH 24 (to 48) + 20 STORE_FAST 0 (e) + +%3d 22 LOAD_FAST 0 (e) + 24 LOAD_ATTR 1 (__traceback__) + 26 STORE_FAST 1 (tb) + 28 POP_EXCEPT + 30 LOAD_CONST 0 (None) + 32 STORE_FAST 0 (e) + 34 DELETE_FAST 0 (e) + +%3d 36 LOAD_FAST 1 (tb) + 38 RETURN_VALUE + >> 40 LOAD_CONST 0 (None) + 42 STORE_FAST 0 (e) + 44 DELETE_FAST 0 (e) + 46 RERAISE 1 + +%3d >> 48 RERAISE 0 + >> 50 POP_EXCEPT_AND_RERAISE ExceptionTable: 2 to 8 -> 14 [0] - 14 to 22 -> 52 [2] lasti - 24 to 28 -> 42 [2] lasti - 42 to 50 -> 52 [2] lasti + 14 to 20 -> 50 [1] lasti + 22 to 26 -> 40 [1] lasti + 40 to 48 -> 50 [1] lasti """ % (TRACEBACK_CODE.co_firstlineno + 1, TRACEBACK_CODE.co_firstlineno + 2, TRACEBACK_CODE.co_firstlineno + 5, @@ -394,7 +393,7 @@ def _tryfinallyconst(b): >> 22 POP_EXCEPT_AND_RERAISE ExceptionTable: 2 to 2 -> 12 [0] - 12 to 20 -> 22 [2] lasti + 12 to 20 -> 22 [1] lasti """ % (_tryfinally.__code__.co_firstlineno + 1, _tryfinally.__code__.co_firstlineno + 2, _tryfinally.__code__.co_firstlineno + 4, @@ -417,7 +416,7 @@ def _tryfinallyconst(b): 22 RERAISE 0 >> 24 POP_EXCEPT_AND_RERAISE ExceptionTable: - 14 to 22 -> 24 [2] lasti + 14 to 22 -> 24 [1] lasti """ % (_tryfinallyconst.__code__.co_firstlineno + 1, _tryfinallyconst.__code__.co_firstlineno + 2, _tryfinallyconst.__code__.co_firstlineno + 4, @@ -863,7 +862,7 @@ async def async_def(): Positional-only arguments: 0 Kw-only arguments: 0 Number of locals: 2 -Stack size: 8 +Stack size: 6 Flags: OPTIMIZED, NEWLOCALS, COROUTINE Constants: 0: None @@ -1106,11 +1105,12 @@ def _prepare_test_cases(): Instruction(opname='LOAD_CONST', opcode=100, arg=7, argval=0, argrepr='0', offset=108, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='BINARY_OP', opcode=122, arg=11, argval=11, argrepr='/', offset=110, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=112, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=13, argval=142, argrepr='to 142', offset=114, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=12, argval=140, argrepr='to 140', offset=114, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=116, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=118, starts_line=22, is_jump_target=False, positions=None), - Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=69, argval=138, argrepr='to 138', offset=120, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=68, argval=136, argrepr='to 136', offset=120, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=122, starts_line=None, is_jump_target=False, positions=None), +<<<<<<< HEAD Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=124, starts_line=None, is_jump_target=False, positions=None), <<<<<<< HEAD Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=126, starts_line=None, is_jump_target=False, positions=None), @@ -1183,18 +1183,38 @@ def _prepare_test_cases(): Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=152, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=154, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=156, starts_line=25, is_jump_target=False, positions=None), +======= + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=124, starts_line=23, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=126, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=128, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=130, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=132, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=31, argval=198, argrepr='to 198', offset=134, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=136, starts_line=22, is_jump_target=True, positions=None), + Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=138, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=140, starts_line=25, is_jump_target=True, positions=None), + Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=142, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=144, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=146, starts_line=26, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=148, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=150, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=152, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=154, starts_line=25, is_jump_target=False, positions=None), + Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=156, starts_line=None, is_jump_target=False, positions=None), +>>>>>>> 5acf1fb5d0 (removed exc_type from stack) Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=158, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=160, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=3, argval=3, argrepr='', offset=162, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=164, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=24, argval=216, argrepr='to 216', offset=166, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=168, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=89, argval=178, argrepr='to 178', offset=172, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=3, argval=3, argrepr='', offset=174, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=176, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=178, starts_line=None, is_jump_target=True, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=3, argval=3, argrepr='', offset=160, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=162, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=23, argval=212, argrepr='to 212', offset=164, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=168, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=88, argval=176, argrepr='to 176', offset=170, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=2, argval=2, argrepr='', offset=172, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=174, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=176, starts_line=None, is_jump_target=True, positions=None), + Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=178, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=False, positions=None), +<<<<<<< HEAD Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=184, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False, positions=None), @@ -1227,6 +1247,37 @@ def _prepare_test_cases(): Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=240, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=242, starts_line=None, is_jump_target=False, positions=None), >>>>>>> 61cec252f6 (bpo-45711: Do not PUSH/POP traceback to the stack as part of exc_info) +======= + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=184, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=186, starts_line=28, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=188, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=190, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=192, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=194, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=196, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=198, starts_line=23, is_jump_target=True, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=200, starts_line=28, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=202, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=204, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=206, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=208, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=210, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=212, starts_line=25, is_jump_target=True, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=214, starts_line=28, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=216, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=220, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=222, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=224, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=226, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=228, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=230, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=232, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=234, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=236, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=238, starts_line=None, is_jump_target=False, positions=None), +>>>>>>> 5acf1fb5d0 (removed exc_type from stack) ] # One last piece of inspect fodder to check the default line number handling diff --git a/Python/ceval.c b/Python/ceval.c index a2feba57e284f7..45c5952f78d189 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1099,24 +1099,6 @@ static int exception_group_match( static int unpack_iterable(PyThreadState *, PyObject *, int, int, PyObject **); -#ifdef Py_DEBUG -static void -_assert_exception_type_is_redundant(PyObject* type, PyObject* val) -{ - if (type == NULL || type == Py_None) { - assert(val == type); - } - else { - assert(PyExceptionInstance_Check(val)); - assert(PyExceptionInstance_Class(val) == type); - } -} - -#define ASSERT_EXC_TYPE_IS_REDUNDANT(t, v) _assert_exception_type_is_redundant(t, v) -#else -#define ASSERT_EXC_TYPE_IS_REDUNDANT(t, v) -#endif - PyObject * PyEval_EvalCode(PyObject *co, PyObject *globals, PyObject *locals) { @@ -2733,10 +2715,19 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr exc_info = tstate->exc_info; type = exc_info->exc_type; value = exc_info->exc_value; - exc_info->exc_type = POP(); + exc_info->exc_value = POP(); - ASSERT_EXC_TYPE_IS_REDUNDANT(exc_info->exc_type, exc_info->exc_value); + assert(exc_info->exc_value); + if (exc_info->exc_value != Py_None) { + assert(PyExceptionInstance_Check(exc_info->exc_value)); + exc_info->exc_type = Py_NewRef( + PyExceptionInstance_Class(exc_info->exc_value)); + } + else { + exc_info->exc_type = Py_NewRef(Py_None); + } + Py_XDECREF(type); Py_XDECREF(value); DISPATCH(); @@ -2754,21 +2745,26 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } PyObject *type, *value, *traceback; _PyErr_StackItem *exc_info; - type = POP(); value = POP(); assert(value); - assert(value != Py_None); + assert(PyExceptionInstance_Check(value)); + type = Py_NewRef(PyExceptionInstance_Class(value)); traceback = PyException_GetTraceback(value); - ASSERT_EXC_TYPE_IS_REDUNDANT(type, value); Py_DECREF(POP()); /* lasti */ _PyErr_Restore(tstate, type, value, traceback); exc_info = tstate->exc_info; type = exc_info->exc_type; value = exc_info->exc_value; - exc_info->exc_type = POP(); exc_info->exc_value = POP(); + if (exc_info->exc_value && exc_info->exc_value != Py_None) { + assert(PyExceptionInstance_Check(exc_info->exc_value)); + exc_info->exc_type = Py_NewRef( + PyExceptionInstance_Class(exc_info->exc_value)); + } + else { + exc_info->exc_type = Py_NewRef(Py_None); + } - ASSERT_EXC_TYPE_IS_REDUNDANT(exc_info->exc_type, exc_info->exc_value); Py_XDECREF(type); Py_XDECREF(value); goto exception_unwind; @@ -2787,12 +2783,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr goto error; } } - PyObject *exc = POP(); PyObject *val = POP(); assert(val && PyExceptionInstance_Check(val)); + PyObject *exc = Py_NewRef(PyExceptionInstance_Class(val)); PyObject *tb = PyException_GetTraceback(val); - ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); - assert(PyExceptionClass_Check(exc)); _PyErr_Restore(tstate, exc, val, tb); goto exception_unwind; } @@ -2828,20 +2822,16 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(END_ASYNC_FOR) { - PyObject *exc = POP(); PyObject *val = POP(); assert(val && PyExceptionInstance_Check(val)); - PyObject *tb = PyException_GetTraceback(val); - ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); - assert(PyExceptionClass_Check(exc)); - if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) { - Py_DECREF(exc); + if (PyErr_GivenExceptionMatches(val, PyExc_StopAsyncIteration)) { Py_DECREF(val); - Py_DECREF(tb); Py_DECREF(POP()); DISPATCH(); } else { + PyObject *exc = Py_NewRef(PyExceptionInstance_Class(val)); + PyObject *tb = PyException_GetTraceback(val); _PyErr_Restore(tstate, exc, val, tb); goto exception_unwind; } @@ -4038,8 +4028,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(JUMP_IF_NOT_EXC_MATCH) { PyObject *right = POP(); - ASSERT_EXC_TYPE_IS_REDUNDANT(TOP(), SECOND()); - PyObject *left = SECOND(); + PyObject *left = TOP(); assert(PyExceptionInstance_Check(left)); if (check_except_type_valid(tstate, right) < 0) { Py_DECREF(right); @@ -4455,26 +4444,22 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(WITH_EXCEPT_START) { - /* At the top of the stack are 8 values: - - (TOP, SECOND) = exc_info() - - (THIRD, FOURTH) = previous exception - - FIFTH: lasti of exception in exc_info() - - SIXTH: the context.__exit__ bound method - We call SIXTH(TOP, SECOND, GetTraceback(SECOND)). - Then we push again the TOP exception and the __exit__ - return value. + /* At the top of the stack are 4 values: + - TOP = exc_info() + - SECOND = previous exception + - THIRD: lasti of exception in exc_info() + - FOURTH: the context.__exit__ bound method + We call FOURTH(type(TOP), TOP, GetTraceback(TOP)). + Then we push the __exit__ return value. */ PyObject *exit_func; PyObject *exc, *val, *tb, *res; - exc = TOP(); - val = SECOND(); + val = TOP(); assert(val && PyExceptionInstance_Check(val)); + exc = PyExceptionInstance_Class(val); tb = PyException_GetTraceback(val); Py_XDECREF(tb); - ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); - assert(!Py_IsNone(exc)); - assert(!PyLong_Check(exc)); assert(PyLong_Check(PEEK(1 + 2 * PY_EXC_INFO_STACK_SIZE))); exit_func = PEEK(2 + 2 * PY_EXC_INFO_STACK_SIZE); PyObject *stack[4] = {NULL, exc, val, tb}; @@ -4488,35 +4473,25 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(PUSH_EXC_INFO) { - PyObject *type = TOP(); - PyObject *value = SECOND(); - ASSERT_EXC_TYPE_IS_REDUNDANT(type, value); + PyObject *value = TOP(); _PyErr_StackItem *exc_info = tstate->exc_info; if (exc_info->exc_value != NULL) { - SET_SECOND(exc_info->exc_value); - } - else { - Py_INCREF(Py_None); - SET_SECOND(Py_None); - } - if (exc_info->exc_type != NULL) { - SET_TOP(exc_info->exc_type); + SET_TOP(exc_info->exc_value); } else { Py_INCREF(Py_None); SET_TOP(Py_None); } + Py_XDECREF(exc_info->exc_type); Py_INCREF(value); PUSH(value); assert(PyExceptionInstance_Check(value)); - exc_info->exc_value = value; - Py_INCREF(type); - PUSH(type); - assert(PyExceptionClass_Check(type)); - exc_info->exc_type = type; + exc_info->exc_value = value; + exc_info->exc_type = Py_NewRef( + PyExceptionInstance_Class(exc_info->exc_value)); DISPATCH(); } @@ -5383,9 +5358,8 @@ MISS_WITH_OPARG_COUNTER(STORE_SUBSCR) else PyException_SetTraceback(val, Py_None); Py_XDECREF(tb); + Py_XDECREF(exc); PUSH(val); - PUSH(exc); - ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val); JUMPTO(handler); /* Resume normal execution */ frame->f_state = FRAME_EXECUTING; diff --git a/Python/compile.c b/Python/compile.c index fff96d4ed8177d..894bbfff977a64 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1871,12 +1871,11 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, case FINALLY_END: if (preserve_tos) { - ADDOP(c, ROT_THREE); + ADDOP(c, ROT_TWO); } - ADDOP(c, POP_TOP); /* exc_type */ ADDOP(c, POP_TOP); /* exc_value */ if (preserve_tos) { - ADDOP(c, ROT_THREE); + ADDOP(c, ROT_TWO); } ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); @@ -1909,7 +1908,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info, ADDOP(c, POP_BLOCK); } if (preserve_tos) { - ADDOP(c, ROT_THREE); + ADDOP(c, ROT_TWO); } ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); @@ -3352,7 +3351,6 @@ compiler_try_except(struct compiler *c, stmt_ty s) ADDOP_JUMP(c, JUMP_IF_NOT_EXC_MATCH, except); NEXT_BLOCK(c); } - ADDOP(c, POP_TOP); /* exc_type */ if (handler->v.ExceptHandler.name) { basicblock *cleanup_end, *cleanup_body; @@ -5428,7 +5426,6 @@ compiler_with_except_finish(struct compiler *c, basicblock * cleanup) { compiler_use_next_block(c, cleanup); ADDOP(c, POP_EXCEPT_AND_RERAISE); compiler_use_next_block(c, exit); - ADDOP(c, POP_TOP); /* exc_type */ ADDOP(c, POP_TOP); /* exc_value */ ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); From 28ce9d2fe3262a55d06c03327cd2d53f93d043db Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 9 Dec 2021 17:56:50 +0000 Subject: [PATCH 04/14] remove exc_type from exc_info --- Include/cpython/pystate.h | 2 +- Include/internal/pycore_pyerrors.h | 5 +---- Lib/test/test_sys.py | 2 +- Modules/_asynciomodule.c | 6 +----- Objects/genobject.c | 3 --- Python/ceval.c | 32 ++---------------------------- Python/errors.c | 12 +---------- Python/pystate.c | 1 - 8 files changed, 7 insertions(+), 56 deletions(-) diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index 7f500f61dfff0c..c37123c4f69224 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -56,7 +56,7 @@ typedef struct _err_stackitem { * This ensures that the exception state is not impacted by "yields" * from an except handler. */ - PyObject *exc_type, *exc_value; + PyObject *exc_value; struct _err_stackitem *previous_item; diff --git a/Include/internal/pycore_pyerrors.h b/Include/internal/pycore_pyerrors.h index d9f6e0ca723d6d..510c52bc6acad8 100644 --- a/Include/internal/pycore_pyerrors.h +++ b/Include/internal/pycore_pyerrors.h @@ -24,12 +24,9 @@ static inline PyObject* _PyErr_Occurred(PyThreadState *tstate) static inline void _PyErr_ClearExcState(_PyErr_StackItem *exc_state) { - PyObject *t, *v; - t = exc_state->exc_type; + PyObject *v; v = exc_state->exc_value; - exc_state->exc_type = NULL; exc_state->exc_value = NULL; - Py_XDECREF(t); Py_XDECREF(v); } diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index 58310b753172c8..96075cf3b3473c 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -1340,7 +1340,7 @@ def bar(cls): check(bar, size('PP')) # generator def get_gen(): yield 1 - check(get_gen(), size('P2PP4P4c8P2iciP')) + check(get_gen(), size('P2P4P4c8P2iciP')) # iterator check(iter('abc'), size('lP')) # callable-iterator diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c index 3d1f28ace7ebb0..978a1fdd0d8521 100644 --- a/Modules/_asynciomodule.c +++ b/Modules/_asynciomodule.c @@ -810,7 +810,6 @@ FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg) Py_VISIT(fut->dict); _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state; - Py_VISIT(exc_state->exc_type); Py_VISIT(exc_state->exc_value); return 0; @@ -1375,9 +1374,6 @@ _asyncio_Future__make_cancelled_error_impl(FutureObj *self) PyException_SetContext(exc, Py_NewRef(exc_state->exc_value)); _PyErr_ClearExcState(exc_state); } - else { - assert(exc_state->exc_type == NULL); - } return exc; } @@ -2706,10 +2702,10 @@ task_step_impl(TaskObj *task, PyObject *exc) PyException_SetTraceback(ev, tb); Py_DECREF(tb); } + Py_XDECREF(et); FutureObj *fut = (FutureObj*)task; _PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state; - exc_state->exc_type = et; exc_state->exc_value = ev; return future_cancel(fut, NULL); diff --git a/Objects/genobject.c b/Objects/genobject.c index 6ec5f1b1ba51eb..a7af64f89f2b21 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -25,7 +25,6 @@ static const char *ASYNC_GEN_IGNORED_EXIT_MSG = static inline int exc_state_traverse(_PyErr_StackItem *exc_state, visitproc visit, void *arg) { - Py_VISIT(exc_state->exc_type); Py_VISIT(exc_state->exc_value); return 0; } @@ -881,7 +880,6 @@ make_gen(PyTypeObject *type, PyFunctionObject *func) gen->gi_code = (PyCodeObject *)func->func_code; Py_INCREF(gen->gi_code); gen->gi_weakreflist = NULL; - gen->gi_exc_state.exc_type = NULL; gen->gi_exc_state.exc_value = NULL; gen->gi_exc_state.previous_item = NULL; if (func->func_name != NULL) @@ -969,7 +967,6 @@ gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f, Py_INCREF(gen->gi_code); Py_DECREF(f); gen->gi_weakreflist = NULL; - gen->gi_exc_state.exc_type = NULL; gen->gi_exc_state.exc_value = NULL; gen->gi_exc_state.previous_item = NULL; if (name != NULL) diff --git a/Python/ceval.c b/Python/ceval.c index 45c5952f78d189..252d7960116453 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2710,25 +2710,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(POP_EXCEPT) { - PyObject *type, *value; + PyObject *value; _PyErr_StackItem *exc_info; exc_info = tstate->exc_info; - type = exc_info->exc_type; value = exc_info->exc_value; - exc_info->exc_value = POP(); - - assert(exc_info->exc_value); - if (exc_info->exc_value != Py_None) { - assert(PyExceptionInstance_Check(exc_info->exc_value)); - exc_info->exc_type = Py_NewRef( - PyExceptionInstance_Class(exc_info->exc_value)); - } - else { - exc_info->exc_type = Py_NewRef(Py_None); - } - - Py_XDECREF(type); Py_XDECREF(value); DISPATCH(); } @@ -2752,20 +2738,10 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr traceback = PyException_GetTraceback(value); Py_DECREF(POP()); /* lasti */ _PyErr_Restore(tstate, type, value, traceback); + exc_info = tstate->exc_info; - type = exc_info->exc_type; value = exc_info->exc_value; exc_info->exc_value = POP(); - if (exc_info->exc_value && exc_info->exc_value != Py_None) { - assert(PyExceptionInstance_Check(exc_info->exc_value)); - exc_info->exc_type = Py_NewRef( - PyExceptionInstance_Class(exc_info->exc_value)); - } - else { - exc_info->exc_type = Py_NewRef(Py_None); - } - - Py_XDECREF(type); Py_XDECREF(value); goto exception_unwind; } @@ -4483,15 +4459,11 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr Py_INCREF(Py_None); SET_TOP(Py_None); } - Py_XDECREF(exc_info->exc_type); Py_INCREF(value); PUSH(value); assert(PyExceptionInstance_Check(value)); - exc_info->exc_value = value; - exc_info->exc_type = Py_NewRef( - PyExceptionInstance_Class(exc_info->exc_value)); DISPATCH(); } diff --git a/Python/errors.c b/Python/errors.c index d535e70b9b9484..deb09b997b68ed 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -84,11 +84,8 @@ _PyErr_GetTopmostException(PyThreadState *tstate) while ((exc_info->exc_value == NULL || exc_info->exc_value == Py_None) && exc_info->previous_item != NULL) { - assert(exc_info->exc_type == NULL || exc_info->exc_type == Py_None); exc_info = exc_info->previous_item; } - assert(exc_info->previous_item == NULL || - (exc_info->exc_type != NULL && exc_info->exc_type != Py_None)); return exc_info; } @@ -524,22 +521,18 @@ PyErr_GetExcInfo(PyObject **p_type, PyObject **p_value, PyObject **p_traceback) void PyErr_SetExcInfo(PyObject *type, PyObject *value, PyObject *traceback) { - PyObject *oldtype, *oldvalue; + PyObject *oldvalue; PyThreadState *tstate = _PyThreadState_GET(); - oldtype = tstate->exc_info->exc_type; oldvalue = tstate->exc_info->exc_value; - tstate->exc_info->exc_type = get_exc_type(value); - Py_XINCREF(tstate->exc_info->exc_type); tstate->exc_info->exc_value = value; /* These args are no longer used, but we still need to steal a ref */ Py_XDECREF(type); Py_XDECREF(traceback); - Py_XDECREF(oldtype); Py_XDECREF(oldvalue); } @@ -625,9 +618,6 @@ _PyErr_ChainStackItem(_PyErr_StackItem *exc_info) exc_info_given = 1; } - assert( (exc_info->exc_type == NULL || exc_info->exc_type == Py_None) == - (exc_info->exc_value == NULL || exc_info->exc_value == Py_None) ); - if (exc_info->exc_value == NULL || exc_info->exc_value == Py_None) { return; } diff --git a/Python/pystate.c b/Python/pystate.c index 963b6501c8f014..0301ce676950b0 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1028,7 +1028,6 @@ PyThreadState_Clear(PyThreadState *tstate) Py_CLEAR(tstate->curexc_value); Py_CLEAR(tstate->curexc_traceback); - Py_CLEAR(tstate->exc_state.exc_type); Py_CLEAR(tstate->exc_state.exc_value); /* The stack of exception states should contain just this thread. */ From 8ee6d849caf6cd48606589fe0e9dafd5f4467b4c Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 15 Dec 2021 00:55:15 +0000 Subject: [PATCH 05/14] update the except* opcodes --- Doc/library/dis.rst | 11 ++- Lib/test/test_dis.py | 162 ++++++------------------------------------- Python/ceval.c | 71 +++++-------------- Python/compile.c | 96 ++++++++++--------------- 4 files changed, 80 insertions(+), 260 deletions(-) diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 3a6148e486c479..883aafe0a58342 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -899,10 +899,9 @@ All of the following opcodes use their arguments. Performs exception matching for ``except*``. Applies ``split(TOS)`` on the exception group representing TOS1. Jumps if no match is found. - Pops one item from the stack. If a match was found, pops the 3 items representing - the exception and pushes the 3 items representing the non-matching part of - the exception group, followed by the 3 items representing the matching part. - In other words, in case of a match it pops 4 items and pushes 6. + Pops one item from the stack (the match type). If a match was found, + next item (the exception) and pushes the non-matching part of the + exception group followed by the matching part. .. versionadded:: 3.11 @@ -912,8 +911,8 @@ All of the following opcodes use their arguments. Combines the raised and reraised exceptions list from TOS, into an exception group to propagate from a try-except* block. Uses the original exception group from TOS1 to reconstruct the structure of reraised exceptions. Pops - two items from the stack and pushes a triplet representing the exception to - reraise or three ``None`` if there isn't one. + two items from the stack and pushes 0 (for lasti, which is unused) followed + by the exception to reraise or ``None`` if there isn't one. .. versionadded:: 3.11 diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index a692e771b9ba67..e116954bc044d4 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -1110,86 +1110,12 @@ def _prepare_test_cases(): Instruction(opname='LOAD_GLOBAL', opcode=116, arg=2, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=118, starts_line=22, is_jump_target=False, positions=None), Instruction(opname='JUMP_IF_NOT_EXC_MATCH', opcode=121, arg=68, argval=136, argrepr='to 136', offset=120, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=122, starts_line=None, is_jump_target=False, positions=None), -<<<<<<< HEAD - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=124, starts_line=None, is_jump_target=False, positions=None), -<<<<<<< HEAD - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=126, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=128, starts_line=23, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=130, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=132, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=134, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=136, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=32, argval=204, argrepr='to 204', offset=138, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=140, starts_line=22, is_jump_target=True, positions=None), - Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=142, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=144, starts_line=25, is_jump_target=True, positions=None), - Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=146, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=148, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=150, starts_line=26, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=152, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=154, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=156, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=158, starts_line=25, is_jump_target=False, positions=None), - Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=160, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=162, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=3, argval=3, argrepr='', offset=164, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=11, argval=192, argrepr='to 192', offset=168, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=170, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=172, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=90, argval=180, argrepr='to 180', offset=174, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=4, argval=4, argrepr='', offset=176, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=178, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=True, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=184, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=190, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=192, starts_line=28, is_jump_target=True, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=194, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=196, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=198, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=200, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=202, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=204, starts_line=23, is_jump_target=True, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=206, starts_line=28, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=208, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=210, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=212, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=214, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=216, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=220, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=222, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=224, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=226, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=230, starts_line=None, is_jump_target=False, positions=None), -======= - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=126, starts_line=23, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=128, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=130, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=132, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=134, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=32, argval=202, argrepr='to 202', offset=136, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=138, starts_line=22, is_jump_target=True, positions=None), - Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=140, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=142, starts_line=25, is_jump_target=True, positions=None), - Instruction(opname='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=144, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=146, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=148, starts_line=26, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=9, argval='Never reach this', argrepr="'Never reach this'", offset=150, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=152, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=154, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=156, starts_line=25, is_jump_target=False, positions=None), -======= Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=124, starts_line=23, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=8, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=126, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=128, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=130, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=132, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=31, argval=198, argrepr='to 198', offset=134, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=30, argval=196, argrepr='to 196', offset=134, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=136, starts_line=22, is_jump_target=True, positions=None), Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=138, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=140, starts_line=25, is_jump_target=True, positions=None), @@ -1201,11 +1127,10 @@ def _prepare_test_cases(): Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=152, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=154, starts_line=25, is_jump_target=False, positions=None), Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=156, starts_line=None, is_jump_target=False, positions=None), ->>>>>>> 5acf1fb5d0 (removed exc_type from stack) Instruction(opname='DUP_TOP', opcode=4, arg=None, argval=None, argrepr='', offset=158, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='CALL_FUNCTION', opcode=131, arg=3, argval=3, argrepr='', offset=160, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=162, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='JUMP_FORWARD', opcode=110, arg=23, argval=212, argrepr='to 212', offset=164, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='JUMP_FORWARD', opcode=110, arg=9, argval=184, argrepr='to 184', offset=164, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=166, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='WITH_EXCEPT_START', opcode=49, arg=None, argval=None, argrepr='', offset=168, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_JUMP_IF_TRUE', opcode=115, arg=88, argval=176, argrepr='to 176', offset=170, starts_line=None, is_jump_target=False, positions=None), @@ -1214,70 +1139,27 @@ def _prepare_test_cases(): Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=176, starts_line=None, is_jump_target=True, positions=None), Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=178, starts_line=None, is_jump_target=False, positions=None), Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=180, starts_line=None, is_jump_target=False, positions=None), -<<<<<<< HEAD - Instruction(opname='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=184, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=186, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=190, starts_line=28, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=192, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=194, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=196, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=198, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=200, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=202, starts_line=23, is_jump_target=True, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=204, starts_line=28, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=206, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=208, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=210, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=212, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=214, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=216, starts_line=25, is_jump_target=True, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=218, starts_line=28, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=220, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=222, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=224, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=226, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=230, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=232, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=234, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=236, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=238, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=240, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=242, starts_line=None, is_jump_target=False, positions=None), ->>>>>>> 61cec252f6 (bpo-45711: Do not PUSH/POP traceback to the stack as part of exc_info) -======= Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=182, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=184, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=186, starts_line=28, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=188, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=190, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=192, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=194, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=196, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=198, starts_line=23, is_jump_target=True, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=200, starts_line=28, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=202, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=204, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=206, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=208, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=210, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=212, starts_line=25, is_jump_target=True, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=214, starts_line=28, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=216, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=220, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=222, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=224, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=226, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=228, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=230, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=232, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=234, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=236, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=238, starts_line=None, is_jump_target=False, positions=None), ->>>>>>> 5acf1fb5d0 (removed exc_type from stack) + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=184, starts_line=28, is_jump_target=True, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=186, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=188, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=190, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=192, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=194, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=196, starts_line=23, is_jump_target=True, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=198, starts_line=28, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=200, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=202, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=204, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=206, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=208, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=210, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=212, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='LOAD_CONST', opcode=100, arg=10, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=214, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=216, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=220, starts_line=None, is_jump_target=False, positions=None), + Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=222, starts_line=None, is_jump_target=False, positions=None), ] # One last piece of inspect fodder to check the default line number handling diff --git a/Python/ceval.c b/Python/ceval.c index 252d7960116453..7a43b768b33d10 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1094,7 +1094,7 @@ match_class(PyThreadState *tstate, PyObject *subject, PyObject *type, static int do_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause); static PyObject *do_reraise_star(PyObject *excs, PyObject *orig); static int exception_group_match( - PyObject *exc_type, PyObject* exc_value, PyObject *match_type, + PyObject* exc_value, PyObject *match_type, PyObject **match, PyObject **rest); static int unpack_iterable(PyThreadState *, PyObject *, int, int, PyObject **); @@ -2782,18 +2782,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr PyObject *lasti_unused = Py_NewRef(_PyLong_GetZero()); PUSH(lasti_unused); - if (!Py_IsNone(val)) { - PyObject *tb = PyException_GetTraceback(val); - PUSH(tb ? tb : Py_NewRef(Py_None)); - PUSH(val); - PUSH(Py_NewRef(Py_TYPE(val))); - } - else { - // nothing to reraise - PUSH(Py_NewRef(Py_None)); - PUSH(val); - PUSH(Py_NewRef(Py_None)); - } + PUSH(val); DISPATCH(); } @@ -3927,16 +3916,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(JUMP_IF_NOT_EG_MATCH) { PyObject *match_type = POP(); - PyObject *exc_type = TOP(); - PyObject *exc_value = SECOND(); if (check_except_star_type_valid(tstate, match_type) < 0) { Py_DECREF(match_type); goto error; } + PyObject *exc_value = TOP(); PyObject *match = NULL, *rest = NULL; - int res = exception_group_match(exc_type, exc_value, - match_type, &match, &rest); + int res = exception_group_match(exc_value, match_type, + &match, &rest); Py_DECREF(match_type); if (res < 0) { goto error; @@ -3957,46 +3945,21 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr else { /* Total or partial match - update the stack from - * [tb, val, exc] + * [val] * to - * [tb, rest, exc, tb, match, exc] + * [rest, match] * (rest can be Py_None) */ + PyObject *exc = TOP(); - PyObject *type = TOP(); - PyObject *val = SECOND(); - PyObject *tb = THIRD(); + SET_TOP(rest); + PUSH(match); - if (!Py_IsNone(rest)) { - /* tb remains the same */ - SET_TOP(Py_NewRef(Py_TYPE(rest))); - SET_SECOND(Py_NewRef(rest)); - SET_THIRD(Py_NewRef(tb)); - } - else { - SET_TOP(Py_NewRef(Py_None)); - SET_SECOND(Py_NewRef(Py_None)); - SET_THIRD(Py_NewRef(Py_None)); - } - /* Push match */ - - PUSH(Py_NewRef(tb)); - PUSH(Py_NewRef(match)); - PUSH(Py_NewRef(Py_TYPE(match))); + PyErr_SetExcInfo(NULL, Py_NewRef(match), NULL); - // set exc_info to the current match - PyErr_SetExcInfo( - Py_NewRef(Py_TYPE(match)), - Py_NewRef(match), - Py_NewRef(tb)); + Py_DECREF(exc); - Py_DECREF(tb); - Py_DECREF(val); - Py_DECREF(type); - - Py_DECREF(match); - Py_DECREF(rest); } DISPATCH(); @@ -6181,19 +6144,17 @@ do_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause) */ static int -exception_group_match(PyObject *exc_type, PyObject* exc_value, - PyObject *match_type, PyObject **match, PyObject **rest) +exception_group_match(PyObject* exc_value, PyObject *match_type, + PyObject **match, PyObject **rest) { - if (Py_IsNone(exc_type)) { - assert(Py_IsNone(exc_value)); + if (Py_IsNone(exc_value)) { *match = Py_NewRef(Py_None); *rest = Py_NewRef(Py_None); return 0; } - assert(PyExceptionClass_Check(exc_type)); assert(PyExceptionInstance_Check(exc_value)); - if (PyErr_GivenExceptionMatches(exc_type, match_type)) { + if (PyErr_GivenExceptionMatches(exc_value, match_type)) { /* Full match of exc itself */ bool is_eg = _PyBaseExceptionGroup_Check(exc_value); if (is_eg) { diff --git a/Python/compile.c b/Python/compile.c index 894bbfff977a64..97b21187e8cf22 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1097,7 +1097,7 @@ stack_effect(int opcode, int oparg, int jump) case JUMP_IF_NOT_EXC_MATCH: return -1; case JUMP_IF_NOT_EG_MATCH: - return jump > 0 ? -1 : 2; + return jump > 0 ? -1 : 0; case IMPORT_NAME: return -1; case IMPORT_FROM: @@ -1136,7 +1136,7 @@ stack_effect(int opcode, int oparg, int jump) return jump ? -1 + PY_EXC_INFO_STACK_SIZE + 1 : 0; case PREP_RERAISE_STAR: - return 2; + return 0; case RERAISE: return -PY_EXC_INFO_STACK_SIZE; case PUSH_EXC_INFO: @@ -3443,52 +3443,42 @@ compiler_try_except(struct compiler *c, stmt_ty s) at the right; 'tb' is trace-back info, 'val' the exception instance, and 'typ' the exception's type.) - Value stack Label Instruction Argument - [] SETUP_FINALLY L1 - [] - [] POP_BLOCK - [] JUMP_FORWARD L0 + Value stack Label Instruction Argument + [] SETUP_FINALLY L1 + [] + [] POP_BLOCK + [] JUMP_FORWARD L0 - [tb, val, typ] L1: DUP_TOP_TWO ) save a copy of the - [tb, val, typ, orig, typ] POP_TOP ) original raised exception - [tb, val, typ, orig] ROT_FOUR ) - [orig, tb, val, typ] BUILD_LIST ) list for raised/reraised - [orig, tb, val, typ, res] ROT_FOUR ) exceptions ("result") + [exc] L1: DUP_TOP ) save copy of the original exception + [orig, exc] BUILD_LIST ) list for raised/reraised excs ("result") + [orig, exc, res] ROT_TWO - [orig, res, tb, val, typ] ) - [orig, res, tb, val, typ, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1 + [orig, res, exc] + [orig, res, exc, E1] JUMP_IF_NOT_EG_MATCH L2 - [orig, res, tb, rest, typ, tb, match, typ] POP - [orig, res, tb, rest, typ, tb, match] (or POP if no V1) - [orig, res, tb, rest, typ, tb] POP + [orig, res, rest, match] (or POP if no V1) - [orig, res, tb, rest, typ] SETUP_FINALLY R1 - [orig, res, tb, rest, typ] - [orig, res, tb, rest, typ] JUMP_FORWARD L2 + [orig, res, rest] SETUP_FINALLY R1 + [orig, res, rest] + [orig, res, rest] JUMP_FORWARD L2 - [orig, res, tb, rest, typ, i, tb, v, t] R1: POP ) exception raised in except* body - [orig, res, tb, rest, typ, i, tb, v] LIST_APPEND 6 ) add it to res - [orig, res, tb, rest, typ, i, tb] POP - [orig, res, tb, rest, typ, i] POP + [orig, res, rest, i, v] R1: LIST_APPEND 3 ) exc raised in except* body - add to res + [orig, res, rest, i] POP - [orig, res, tb, rest, typ] L2: + [orig, res, rest] L2: .............................etc....................... - [orig, res, tb, rest, typ] Ln+1: POP ) add unhandled exception - [orig, res, tb, rest] LIST_APPEND 2 ) to res (could be None) - [orig, res, tb] POP + [orig, res, rest] Ln+1: LIST_APPEND 1 ) add unhandled exc to res (could be None) - [orig, res] PREP_RERAISE_STAR - [i, tb, val, typ] POP_JUMP_IF_TRUE RER - [i, tb, val, typ] POP - [i, tb, val] POP - [i, tb] POP - [i] POP - [] JUMP_FORWARD L0 + [orig, res] PREP_RERAISE_STAR + [i, exc] POP_JUMP_IF_TRUE RER + [i, exc] POP + [i] POP + [] JUMP_FORWARD L0 - [i, tb, val, typ] RER: POP_EXCEPT_AND_RERAISE + [i, exc] RER: POP_EXCEPT_AND_RERAISE - [] L0: + [] L0: */ static int compiler_try_star_except(struct compiler *c, stmt_ty s) @@ -3549,30 +3539,25 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) if (i == 0) { /* Push the original EG into the stack */ /* - [tb, val, exc] DUP_TOP_TWO - [tb, val, exc, val, exc] POP_TOP - [tb, val, exc, val] ROT_FOUR - [val, tb, val, exc] + [val] DUP_TOP + [orig, val] */ - ADDOP(c, DUP_TOP_TWO); - ADDOP(c, POP_TOP); - ADDOP(c, ROT_FOUR); + ADDOP(c, DUP_TOP); /* create empty list for exceptions raised/reraise in the except* blocks */ /* - [val, tb, val, exc] BUILD_LIST - [val, tb, val, exc, []] ROT_FOUR - [val, [], tb, val, exc] + [orig, val] BUILD_LIST + [orig, val, []] ROT_TWO + [orig, [], val] */ ADDOP_I(c, BUILD_LIST, 0); - ADDOP(c, ROT_FOUR); + ADDOP(c, ROT_TWO); } if (handler->v.ExceptHandler.type) { VISIT(c, expr, handler->v.ExceptHandler.type); ADDOP_JUMP(c, JUMP_IF_NOT_EG_MATCH, except); NEXT_BLOCK(c); } - ADDOP(c, POP_TOP); // exc_type basicblock *cleanup_end = compiler_new_block(c); if (cleanup_end == NULL) { @@ -3587,9 +3572,8 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) compiler_nameop(c, handler->v.ExceptHandler.name, Store); } else { - ADDOP(c, POP_TOP); // val + ADDOP(c, POP_TOP); // exc } - ADDOP(c, POP_TOP); // tb /* try: @@ -3633,9 +3617,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) } /* add exception raised to the res list */ - ADDOP(c, POP_TOP); // type - ADDOP_I(c, LIST_APPEND, 6); // exc - ADDOP(c, POP_TOP); // tb + ADDOP_I(c, LIST_APPEND, 3); // exc ADDOP(c, POP_TOP); // lasti ADDOP_JUMP(c, JUMP_ABSOLUTE, except); @@ -3643,9 +3625,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) if (i == n - 1) { /* Add exc to the list (if not None it's the unhandled part of the EG) */ - ADDOP(c, POP_TOP); - ADDOP_I(c, LIST_APPEND, 2); - ADDOP(c, POP_TOP); + ADDOP_I(c, LIST_APPEND, 1); ADDOP_JUMP(c, JUMP_FORWARD, reraise_star); } } @@ -3666,8 +3646,6 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) /* Nothing to reraise - pop it */ ADDOP(c, POP_TOP); ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); - ADDOP(c, POP_TOP); ADDOP(c, POP_BLOCK); ADDOP(c, POP_EXCEPT); ADDOP_JUMP(c, JUMP_FORWARD, end); From 9b041601bbe07b423aacbc4232e69c34634eba64 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 15 Dec 2021 14:44:27 +0000 Subject: [PATCH 06/14] val --> exc in comment --- Python/compile.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 9f7a213ca1aa25..4a54619f3766e1 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3557,16 +3557,16 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) if (i == 0) { /* Push the original EG into the stack */ /* - [val] DUP_TOP - [orig, val] + [exc] DUP_TOP + [orig, exc] */ ADDOP(c, DUP_TOP); /* create empty list for exceptions raised/reraise in the except* blocks */ /* - [orig, val] BUILD_LIST - [orig, val, []] ROT_TWO - [orig, [], val] + [orig, exc] BUILD_LIST + [orig, exc, []] ROT_TWO + [orig, [], exc] */ ADDOP_I(c, BUILD_LIST, 0); ADDOP(c, ROT_TWO); From 4cd5af86a6d04d787ad57fef386a343285dd2802 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Wed, 15 Dec 2021 15:09:48 +0000 Subject: [PATCH 07/14] add to what's new, because this change breaks things like cython --- Doc/whatsnew/3.11.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 3005d1d43f25b9..5389ce8b258cf8 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -195,6 +195,11 @@ Other CPython Implementation Changes reflected in the re-raised exception. (Contributed by Irit Katriel in :issue:`45711`.) +* The interpreter state's representation of handled exceptions (a.k.a exc_info, or + _PyErr_StackItem) now has only the ``exc_value`` field, ``exc_type`` and ``exc_traceback`` + have been removed as their values can be derived from ``exc_value``. + (Contributed by Irit Katriel in :issue:`45711`.) + New Modules =========== From a72556e7f7026c4788006ce9d2a50538292bc47f Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Wed, 15 Dec 2021 15:17:06 +0000 Subject: [PATCH 08/14] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Core and Builtins/2021-12-15-15-17-04.bpo-45711.QK4QrB.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2021-12-15-15-17-04.bpo-45711.QK4QrB.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-15-15-17-04.bpo-45711.QK4QrB.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-15-15-17-04.bpo-45711.QK4QrB.rst new file mode 100644 index 00000000000000..717f89ff0e2796 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2021-12-15-15-17-04.bpo-45711.QK4QrB.rst @@ -0,0 +1 @@ +The interpreter state's representation of handled exceptions (a.k.a exc_info, or _PyErr_StackItem) now has only the ``exc_value`` field, ``exc_type`` and ``exc_traceback`` have been removed as their values can be derived from ``exc_value``. \ No newline at end of file From 787393b5e21d573ca3b57fac4ef919fed22a43bc Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Wed, 15 Dec 2021 15:26:50 +0000 Subject: [PATCH 09/14] delete duplicate news file --- .../Core and Builtins/2021-12-05-17-36-08.bpo-45711.3TmTSw.rst | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Misc/NEWS.d/next/Core and Builtins/2021-12-05-17-36-08.bpo-45711.3TmTSw.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-12-05-17-36-08.bpo-45711.3TmTSw.rst b/Misc/NEWS.d/next/Core and Builtins/2021-12-05-17-36-08.bpo-45711.3TmTSw.rst deleted file mode 100644 index cf90ba8bc75bf9..00000000000000 --- a/Misc/NEWS.d/next/Core and Builtins/2021-12-05-17-36-08.bpo-45711.3TmTSw.rst +++ /dev/null @@ -1 +0,0 @@ -:c:func:`_PyErr_ChainStackItem` no longer normalized ``exc_info`` (including setting the traceback on the exception instance) because ``exc_info`` is always normalized. \ No newline at end of file From 458ad26b1c0fe7e1e779f85a1a028aed216b1781 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 16 Dec 2021 09:49:57 +0000 Subject: [PATCH 10/14] PEP7 // formatting --- Include/internal/pycore_pyerrors.h | 3 +-- Python/ceval.c | 16 ++++++---------- Python/errors.c | 4 +--- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/Include/internal/pycore_pyerrors.h b/Include/internal/pycore_pyerrors.h index 510c52bc6acad8..ee33e753d43a6e 100644 --- a/Include/internal/pycore_pyerrors.h +++ b/Include/internal/pycore_pyerrors.h @@ -24,8 +24,7 @@ static inline PyObject* _PyErr_Occurred(PyThreadState *tstate) static inline void _PyErr_ClearExcState(_PyErr_StackItem *exc_state) { - PyObject *v; - v = exc_state->exc_value; + PyObject *v = exc_state->exc_value; exc_state->exc_value = NULL; Py_XDECREF(v); } diff --git a/Python/ceval.c b/Python/ceval.c index 791cb0d2e2de07..e37f9b043e3948 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2719,10 +2719,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(POP_EXCEPT) { - PyObject *value; - _PyErr_StackItem *exc_info; - exc_info = tstate->exc_info; - value = exc_info->exc_value; + _PyErr_StackItem *exc_info = tstate->exc_info; + PyObject *value = exc_info->exc_value; exc_info->exc_value = POP(); Py_XDECREF(value); DISPATCH(); @@ -2738,17 +2736,15 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr _PyErr_SetString(tstate, PyExc_SystemError, "lasti is not an int"); goto error; } - PyObject *type, *value, *traceback; - _PyErr_StackItem *exc_info; - value = POP(); + PyObject *value = POP(); assert(value); assert(PyExceptionInstance_Check(value)); - type = Py_NewRef(PyExceptionInstance_Class(value)); - traceback = PyException_GetTraceback(value); + PyObject *type = Py_NewRef(PyExceptionInstance_Class(value)); + PyObject *traceback = PyException_GetTraceback(value); Py_DECREF(POP()); /* lasti */ _PyErr_Restore(tstate, type, value, traceback); - exc_info = tstate->exc_info; + _PyErr_StackItem *exc_info = tstate->exc_info; value = exc_info->exc_value; exc_info->exc_value = POP(); Py_XDECREF(value); diff --git a/Python/errors.c b/Python/errors.c index deb09b997b68ed..6c5fe41142304c 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -521,11 +521,9 @@ PyErr_GetExcInfo(PyObject **p_type, PyObject **p_value, PyObject **p_traceback) void PyErr_SetExcInfo(PyObject *type, PyObject *value, PyObject *traceback) { - PyObject *oldvalue; PyThreadState *tstate = _PyThreadState_GET(); - oldvalue = tstate->exc_info->exc_value; - + PyObject *oldvalue = tstate->exc_info->exc_value; tstate->exc_info->exc_value = value; From 01f9036aea35d4cad9b286ed41b2dba17a9d46b5 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 16 Dec 2021 21:58:14 +0000 Subject: [PATCH 11/14] use Py_Clear --- Include/internal/pycore_pyerrors.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Include/internal/pycore_pyerrors.h b/Include/internal/pycore_pyerrors.h index ee33e753d43a6e..61ded04de30f90 100644 --- a/Include/internal/pycore_pyerrors.h +++ b/Include/internal/pycore_pyerrors.h @@ -24,9 +24,7 @@ static inline PyObject* _PyErr_Occurred(PyThreadState *tstate) static inline void _PyErr_ClearExcState(_PyErr_StackItem *exc_state) { - PyObject *v = exc_state->exc_value; - exc_state->exc_value = NULL; - Py_XDECREF(v); + Py_CLEAR(exc_state->exc_value); } PyAPI_FUNC(PyObject*) _PyErr_StackItemToExcInfoTuple( From ba82085f2aba13804baab581c2aa8a72fcb8d6c6 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Thu, 16 Dec 2021 23:46:11 +0000 Subject: [PATCH 12/14] 3 --> 1 in comments --- Python/compile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/compile.c b/Python/compile.c index 4a54619f3766e1..972b1eeb16aa46 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -1121,7 +1121,7 @@ stack_effect(int opcode, int oparg, int jump) /* Exception handling pseudo-instructions */ case SETUP_FINALLY: /* 0 in the normal flow. - * Restore the stack position and push 3 values before jumping to + * Restore the stack position and push 1 value before jumping to * the handler if an exception be raised. */ return jump ? PY_EXC_INFO_STACK_SIZE : 0; case SETUP_CLEANUP: @@ -1130,7 +1130,7 @@ stack_effect(int opcode, int oparg, int jump) case SETUP_WITH: /* 0 in the normal flow. * Restore the stack position to the position before the result - * of __(a)enter__ and push 4 values before jumping to the handler + * of __(a)enter__ and push 2 values before jumping to the handler * if an exception be raised. */ return jump ? -1 + PY_EXC_INFO_STACK_SIZE + 1 : 0; From 80b1e90bfef9e1c6679f9eedc7556cb1ab98a928 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Fri, 17 Dec 2021 00:10:57 +0000 Subject: [PATCH 13/14] remove PY_EXC_INFO_STACK_SIZE --- Include/internal/pycore_pyerrors.h | 3 --- Python/ceval.c | 10 +++++----- Python/compile.c | 23 +++++++++++------------ 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/Include/internal/pycore_pyerrors.h b/Include/internal/pycore_pyerrors.h index 61ded04de30f90..b9fc36cf067605 100644 --- a/Include/internal/pycore_pyerrors.h +++ b/Include/internal/pycore_pyerrors.h @@ -106,9 +106,6 @@ PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalRefcountErrorFunc( #define _Py_FatalRefcountError(message) _Py_FatalRefcountErrorFunc(__func__, message) -/* number of items stored in the stack for each exception */ -#define PY_EXC_INFO_STACK_SIZE 1 - #ifdef __cplusplus } #endif diff --git a/Python/ceval.c b/Python/ceval.c index d67b0c171897ac..bac57ccb7cc75b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -19,7 +19,7 @@ #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_object.h" // _PyObject_GC_TRACK() #include "pycore_moduleobject.h" // PyModuleObject -#include "pycore_pyerrors.h" // _PyErr_Fetch(), PY_EXC_INFO_STACK_SIZE +#include "pycore_pyerrors.h" // _PyErr_Fetch() #include "pycore_pylifecycle.h" // _PyErr_Print() #include "pycore_pymem.h" // _PyMem_IsPtrFreed() #include "pycore_pystate.h" // _PyInterpreterState_GET() @@ -2727,7 +2727,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr } TARGET(POP_EXCEPT_AND_RERAISE) { - PyObject *lasti = PEEK(PY_EXC_INFO_STACK_SIZE + 1); + PyObject *lasti = PEEK(2); if (PyLong_Check(lasti)) { frame->f_lasti = PyLong_AsLong(lasti); assert(!_PyErr_Occurred(tstate)); @@ -2753,7 +2753,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr TARGET(RERAISE) { if (oparg) { - PyObject *lasti = PEEK(oparg + PY_EXC_INFO_STACK_SIZE); + PyObject *lasti = PEEK(oparg + 1); if (PyLong_Check(lasti)) { frame->f_lasti = PyLong_AsLong(lasti); assert(!_PyErr_Occurred(tstate)); @@ -4404,8 +4404,8 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr exc = PyExceptionInstance_Class(val); tb = PyException_GetTraceback(val); Py_XDECREF(tb); - assert(PyLong_Check(PEEK(1 + 2 * PY_EXC_INFO_STACK_SIZE))); - exit_func = PEEK(2 + 2 * PY_EXC_INFO_STACK_SIZE); + assert(PyLong_Check(PEEK(3))); + exit_func = PEEK(4); PyObject *stack[4] = {NULL, exc, val, tb}; res = PyObject_Vectorcall(exit_func, stack + 1, 3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL); diff --git a/Python/compile.c b/Python/compile.c index 972b1eeb16aa46..6f2089ec837378 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -27,7 +27,6 @@ #include "pycore_ast.h" // _PyAST_GetDocString() #include "pycore_compile.h" // _PyFuture_FromAST() #include "pycore_code.h" // _PyCode_New() -#include "pycore_pyerrors.h" // PY_EXC_INFO_STACK_SIZE #include "pycore_pymem.h" // _PyMem_IsPtrFreed() #include "pycore_long.h" // _PyLong_GetZero() #include "pycore_symtable.h" // PySTEntryObject @@ -1049,9 +1048,9 @@ stack_effect(int opcode, int oparg, int jump) case POP_BLOCK: return 0; case POP_EXCEPT: - return -PY_EXC_INFO_STACK_SIZE; + return -1; case POP_EXCEPT_AND_RERAISE: - return -(1 + 2 * PY_EXC_INFO_STACK_SIZE); + return -3; case STORE_NAME: return -1; @@ -1123,23 +1122,23 @@ stack_effect(int opcode, int oparg, int jump) /* 0 in the normal flow. * Restore the stack position and push 1 value before jumping to * the handler if an exception be raised. */ - return jump ? PY_EXC_INFO_STACK_SIZE : 0; + return jump ? 1 : 0; case SETUP_CLEANUP: /* As SETUP_FINALLY, but pushes lasti as well */ - return jump ? 1 + PY_EXC_INFO_STACK_SIZE : 0; + return jump ? 2 : 0; case SETUP_WITH: /* 0 in the normal flow. * Restore the stack position to the position before the result * of __(a)enter__ and push 2 values before jumping to the handler * if an exception be raised. */ - return jump ? -1 + PY_EXC_INFO_STACK_SIZE + 1 : 0; + return jump ? 1 : 0; case PREP_RERAISE_STAR: return 0; case RERAISE: - return -PY_EXC_INFO_STACK_SIZE; + return -1; case PUSH_EXC_INFO: - return PY_EXC_INFO_STACK_SIZE; + return 1; case WITH_EXCEPT_START: return 1; @@ -1200,7 +1199,7 @@ stack_effect(int opcode, int oparg, int jump) case GET_YIELD_FROM_ITER: return 0; case END_ASYNC_FOR: - return -(1 + PY_EXC_INFO_STACK_SIZE); + return -2; case FORMAT_VALUE: /* If there's a fmt_spec on the stack, we go from 2->1, else 1->1. */ @@ -5421,7 +5420,7 @@ compiler_with_except_finish(struct compiler *c, basicblock * cleanup) { return 0; ADDOP_JUMP(c, POP_JUMP_IF_TRUE, exit); NEXT_BLOCK(c); - ADDOP_I(c, RERAISE, 1 + PY_EXC_INFO_STACK_SIZE); + ADDOP_I(c, RERAISE, 2); compiler_use_next_block(c, cleanup); ADDOP(c, POP_EXCEPT_AND_RERAISE); compiler_use_next_block(c, exit); @@ -5557,7 +5556,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos) E: WITH_EXCEPT_START (calls EXPR.__exit__) POP_JUMP_IF_TRUE T: RERAISE - T: POP_TOP * PY_EXC_INFO_STACK_SIZE (remove exception from stack) + T: POP_TOP (remove exception from stack) POP_EXCEPT POP_TOP EXIT: @@ -7338,7 +7337,7 @@ assemble_emit_exception_table_entry(struct assembler *a, int start, int end, bas int size = end-start; assert(end > start); int target = handler->b_offset; - int depth = handler->b_startdepth - PY_EXC_INFO_STACK_SIZE; + int depth = handler->b_startdepth - 1; if (handler->b_preserve_lasti) { depth -= 1; } From 550f6f95626f9e9e92a9a092b5c078b3a41d8394 Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Fri, 17 Dec 2021 11:06:02 +0000 Subject: [PATCH 14/14] Fix indent Co-authored-by: Oleg Iarygin --- Python/compile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/compile.c b/Python/compile.c index 6f2089ec837378..8e90b1ab37037d 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3308,7 +3308,7 @@ compiler_try_star_finally(struct compiler *c, stmt_ty s) [] POP_BLOCK [] JUMP_FORWARD L0 - [exc] L1: ) + [exc] L1: ) [exc, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1 [exc] (or POP if no V1) []