diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst index 9665e8dbf6cfc6..a0368622240342 100644 --- a/Doc/library/dis.rst +++ b/Doc/library/dis.rst @@ -474,13 +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 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 +563,10 @@ 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 +576,13 @@ 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,15 +590,16 @@ 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. .. versionadded:: 3.9 .. versionchanged:: 3.11 - The ``__exit__`` function is in position 8 of the stack rather than 7. - + The ``__exit__`` function is in position 6 of the stack rather than 7. + 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 14ea182f4f47aa..149434940b1933 100644 --- a/Include/internal/pycore_pyerrors.h +++ b/Include/internal/pycore_pyerrors.h @@ -98,6 +98,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 6970e9f0a94d49..fd248ee8a59131 100644 --- a/Lib/importlib/_bootstrap_external.py +++ b/Lib/importlib/_bootstrap_external.py @@ -371,6 +371,7 @@ def _write_atomic(path, data, mode=0o666): # Python 3.11a3 3464 (bpo-45636: Merge numeric BINARY_*/INPLACE_* into # BINARY_OP) # Python 3.11a3 3465 (Add COPY_FREE_VARS opcode) +# Python 3.11a3 3466 (bpo-45711: exc_info on the stack does not include traceback) # # MAGIC must change whenever the bytecode emitted by the compiler may no @@ -380,7 +381,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 = (3465).to_bytes(2, 'little') + b'\r\n' +MAGIC_NUMBER = (3466).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 dd328f072e45dc..b6044eaa38503f 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,73 +1106,71 @@ 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), - 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=33, argval=206, argrepr='to 206', 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='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='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=25, argval=220, argrepr='to 220', 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='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_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='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=192, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=194, 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=196, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=198, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=200, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=202, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=204, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=206, starts_line=23, is_jump_target=True, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=208, 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=210, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=212, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=214, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=216, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=218, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='NOP', opcode=9, arg=None, argval=None, argrepr='', offset=220, starts_line=25, is_jump_target=True, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=222, 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=224, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=226, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=228, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_CONST', opcode=100, arg=0, argval=None, argrepr='None', offset=230, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=232, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='PUSH_EXC_INFO', opcode=35, arg=None, argval=None, argrepr='', offset=234, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=236, 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=238, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='CALL_FUNCTION', opcode=131, arg=1, argval=1, argrepr='', offset=240, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=242, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=244, starts_line=None, is_jump_target=False, positions=None), - Instruction(opname='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=246, 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), ] # One last piece of inspect fodder to check the default line number handling diff --git a/Python/ceval.c b/Python/ceval.c index 4f5ccf51e9cfe7..64df9117767155 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() @@ -2729,7 +2729,15 @@ _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); @@ -2738,7 +2746,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)); @@ -2751,7 +2759,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); @@ -2761,7 +2771,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); @@ -2771,7 +2788,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)); @@ -2784,7 +2801,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); @@ -2794,7 +2812,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)) { @@ -4347,11 +4366,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. */ @@ -4360,12 +4379,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); @@ -4379,10 +4400,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); } @@ -4397,8 +4420,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); @@ -5275,11 +5296,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 6138031833ac93..e2d9dc156c3b31 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 @@ -1049,9 +1050,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; @@ -1120,21 +1121,21 @@ 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 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; @@ -1197,7 +1198,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. */ @@ -1852,13 +1853,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); @@ -1891,7 +1891,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); @@ -3259,7 +3259,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; @@ -3270,7 +3270,6 @@ compiler_try_except(struct compiler *c, stmt_ty s) } compiler_nameop(c, handler->v.ExceptHandler.name, Store); - ADDOP(c, POP_TOP); /* try: @@ -3321,8 +3320,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; @@ -5074,13 +5072,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); @@ -5212,7 +5209,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: @@ -6993,7 +6990,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));