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) [] pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy