mirror of https://github.com/python/cpython
bpo-45711: Remove type and traceback from exc_info (GH-30122)
* Do not PUSH/POP traceback or type to the stack as part of exc_info * Remove exc_traceback and exc_type from _PyErr_StackItem * Add to what's new, because this change breaks things like Cython
This commit is contained in:
parent
62a0a2a25d
commit
396b58345f
|
@ -474,13 +474,15 @@ the original TOS1.
|
||||||
.. opcode:: END_ASYNC_FOR
|
.. opcode:: END_ASYNC_FOR
|
||||||
|
|
||||||
Terminates an :keyword:`async for` loop. Handles an exception raised
|
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 3
|
||||||
values from the stack and restore the exception state using the second
|
values from the stack and restore the exception state using the second
|
||||||
three of them. Otherwise re-raise the exception using the three values
|
of them. Otherwise re-raise the exception using the value
|
||||||
from the stack. An exception handler block is removed from the block stack.
|
from the stack. An exception handler block is removed from the block stack.
|
||||||
|
|
||||||
.. versionadded:: 3.8
|
.. versionadded:: 3.8
|
||||||
|
|
||||||
|
.. versionchanged:: 3.11
|
||||||
|
Exception representation on the stack now consist of one, not three, items.
|
||||||
|
|
||||||
.. opcode:: BEFORE_ASYNC_WITH
|
.. opcode:: BEFORE_ASYNC_WITH
|
||||||
|
|
||||||
|
@ -561,8 +563,10 @@ iterations of the loop.
|
||||||
|
|
||||||
.. opcode:: POP_EXCEPT
|
.. opcode:: POP_EXCEPT
|
||||||
|
|
||||||
Pops three 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 one, not three, items.
|
||||||
|
|
||||||
.. opcode:: RERAISE
|
.. opcode:: RERAISE
|
||||||
|
|
||||||
|
@ -572,11 +576,13 @@ iterations of the loop.
|
||||||
|
|
||||||
.. versionadded:: 3.9
|
.. versionadded:: 3.9
|
||||||
|
|
||||||
|
.. versionchanged:: 3.11
|
||||||
|
Exception representation on the stack now consist of one, not three, items.
|
||||||
|
|
||||||
.. opcode:: PUSH_EXC_INFO
|
.. opcode:: PUSH_EXC_INFO
|
||||||
|
|
||||||
Pops the three values from the stack. Pushes the current exception to the top of the stack.
|
Pops a value from the stack. Pushes the current exception to the top of the stack.
|
||||||
Pushes the three values originally popped back to the stack.
|
Pushes the value originally popped back to the stack.
|
||||||
Used in exception handlers.
|
Used in exception handlers.
|
||||||
|
|
||||||
.. versionadded:: 3.11
|
.. versionadded:: 3.11
|
||||||
|
@ -584,8 +590,8 @@ iterations of the loop.
|
||||||
|
|
||||||
.. opcode:: WITH_EXCEPT_START
|
.. opcode:: WITH_EXCEPT_START
|
||||||
|
|
||||||
Calls the function in position 8 on the stack with the top three
|
Calls the function in position 4 on the stack with arguments (type, val, tb)
|
||||||
items on the stack as arguments.
|
representing the exception at the top of the stack.
|
||||||
Used to implement the call ``context_manager.__exit__(*exc_info())`` when an exception
|
Used to implement the call ``context_manager.__exit__(*exc_info())`` when an exception
|
||||||
has occurred in a :keyword:`with` statement.
|
has occurred in a :keyword:`with` statement.
|
||||||
|
|
||||||
|
@ -593,6 +599,9 @@ iterations of the loop.
|
||||||
.. versionchanged:: 3.11
|
.. versionchanged:: 3.11
|
||||||
The ``__exit__`` function is in position 8 of the stack rather than 7.
|
The ``__exit__`` function is in position 8 of the stack rather than 7.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.11
|
||||||
|
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
|
.. opcode:: POP_EXCEPT_AND_RERAISE
|
||||||
|
|
||||||
|
@ -890,10 +899,9 @@ All of the following opcodes use their arguments.
|
||||||
Performs exception matching for ``except*``. Applies ``split(TOS)`` on
|
Performs exception matching for ``except*``. Applies ``split(TOS)`` on
|
||||||
the exception group representing TOS1. Jumps if no match is found.
|
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
|
Pops one item from the stack (the match type). If a match was found,
|
||||||
the exception and pushes the 3 items representing the non-matching part of
|
next item (the exception) and pushes the non-matching part of the
|
||||||
the exception group, followed by the 3 items representing the matching part.
|
exception group followed by the matching part.
|
||||||
In other words, in case of a match it pops 4 items and pushes 6.
|
|
||||||
|
|
||||||
.. versionadded:: 3.11
|
.. versionadded:: 3.11
|
||||||
|
|
||||||
|
@ -903,8 +911,8 @@ All of the following opcodes use their arguments.
|
||||||
Combines the raised and reraised exceptions list from TOS, into an exception
|
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 to propagate from a try-except* block. Uses the original exception
|
||||||
group from TOS1 to reconstruct the structure of reraised exceptions. Pops
|
group from TOS1 to reconstruct the structure of reraised exceptions. Pops
|
||||||
two items from the stack and pushes a triplet representing the exception to
|
two items from the stack and pushes 0 (for lasti, which is unused) followed
|
||||||
reraise or three ``None`` if there isn't one.
|
by the exception to reraise or ``None`` if there isn't one.
|
||||||
|
|
||||||
.. versionadded:: 3.11
|
.. versionadded:: 3.11
|
||||||
|
|
||||||
|
|
|
@ -195,6 +195,11 @@ Other CPython Implementation Changes
|
||||||
reflected in the re-raised exception.
|
reflected in the re-raised exception.
|
||||||
(Contributed by Irit Katriel in :issue:`45711`.)
|
(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
|
New Modules
|
||||||
===========
|
===========
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ typedef struct _err_stackitem {
|
||||||
* This ensures that the exception state is not impacted by "yields"
|
* This ensures that the exception state is not impacted by "yields"
|
||||||
* from an except handler.
|
* from an except handler.
|
||||||
*/
|
*/
|
||||||
PyObject *exc_type, *exc_value, *exc_traceback;
|
PyObject *exc_value;
|
||||||
|
|
||||||
struct _err_stackitem *previous_item;
|
struct _err_stackitem *previous_item;
|
||||||
|
|
||||||
|
|
|
@ -24,16 +24,7 @@ static inline PyObject* _PyErr_Occurred(PyThreadState *tstate)
|
||||||
|
|
||||||
static inline void _PyErr_ClearExcState(_PyErr_StackItem *exc_state)
|
static inline void _PyErr_ClearExcState(_PyErr_StackItem *exc_state)
|
||||||
{
|
{
|
||||||
PyObject *t, *v, *tb;
|
Py_CLEAR(exc_state->exc_value);
|
||||||
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(
|
PyAPI_FUNC(PyObject*) _PyErr_StackItemToExcInfoTuple(
|
||||||
|
@ -114,6 +105,7 @@ PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalRefcountErrorFunc(
|
||||||
|
|
||||||
#define _Py_FatalRefcountError(message) _Py_FatalRefcountErrorFunc(__func__, message)
|
#define _Py_FatalRefcountError(message) _Py_FatalRefcountErrorFunc(__func__, message)
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -371,9 +371,10 @@ _code_type = type(_write_atomic.__code__)
|
||||||
# Python 3.11a3 3464 (bpo-45636: Merge numeric BINARY_*/INPLACE_* into
|
# Python 3.11a3 3464 (bpo-45636: Merge numeric BINARY_*/INPLACE_* into
|
||||||
# BINARY_OP)
|
# BINARY_OP)
|
||||||
# Python 3.11a3 3465 (Add COPY_FREE_VARS opcode)
|
# Python 3.11a3 3465 (Add COPY_FREE_VARS opcode)
|
||||||
# Python 3.11a3 3466 (bpo-45292: PEP-654 except*)
|
# Python 3.11a4 3466 (bpo-45292: PEP-654 except*)
|
||||||
# Python 3.11a4 3467 (Change CALL_xxx opcodes)
|
# Python 3.11a4 3467 (Change CALL_xxx opcodes)
|
||||||
# Python 3.11a4 3468 (Add SEND opcode)
|
# Python 3.11a4 3468 (Add SEND opcode)
|
||||||
|
# Python 3.11a4 3469 (bpo-45711: remove type, traceback from exc_info)
|
||||||
|
|
||||||
#
|
#
|
||||||
# MAGIC must change whenever the bytecode emitted by the compiler may no
|
# MAGIC must change whenever the bytecode emitted by the compiler may no
|
||||||
|
@ -383,7 +384,7 @@ _code_type = type(_write_atomic.__code__)
|
||||||
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
|
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
|
||||||
# in PC/launcher.c must also be updated.
|
# in PC/launcher.c must also be updated.
|
||||||
|
|
||||||
MAGIC_NUMBER = (3468).to_bytes(2, 'little') + b'\r\n'
|
MAGIC_NUMBER = (3469).to_bytes(2, 'little') + b'\r\n'
|
||||||
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
|
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
|
||||||
|
|
||||||
_PYCACHE = '__pycache__'
|
_PYCACHE = '__pycache__'
|
||||||
|
|
|
@ -310,33 +310,31 @@ dis_traceback = """\
|
||||||
>> 14 PUSH_EXC_INFO
|
>> 14 PUSH_EXC_INFO
|
||||||
|
|
||||||
%3d 16 LOAD_GLOBAL 0 (Exception)
|
%3d 16 LOAD_GLOBAL 0 (Exception)
|
||||||
18 JUMP_IF_NOT_EXC_MATCH 26 (to 52)
|
18 JUMP_IF_NOT_EXC_MATCH 24 (to 48)
|
||||||
20 POP_TOP
|
20 STORE_FAST 0 (e)
|
||||||
22 STORE_FAST 0 (e)
|
|
||||||
24 POP_TOP
|
|
||||||
|
|
||||||
%3d 26 LOAD_FAST 0 (e)
|
%3d 22 LOAD_FAST 0 (e)
|
||||||
28 LOAD_ATTR 1 (__traceback__)
|
24 LOAD_ATTR 1 (__traceback__)
|
||||||
30 STORE_FAST 1 (tb)
|
26 STORE_FAST 1 (tb)
|
||||||
32 POP_EXCEPT
|
28 POP_EXCEPT
|
||||||
34 LOAD_CONST 0 (None)
|
30 LOAD_CONST 0 (None)
|
||||||
36 STORE_FAST 0 (e)
|
32 STORE_FAST 0 (e)
|
||||||
38 DELETE_FAST 0 (e)
|
34 DELETE_FAST 0 (e)
|
||||||
|
|
||||||
%3d 40 LOAD_FAST 1 (tb)
|
%3d 36 LOAD_FAST 1 (tb)
|
||||||
42 RETURN_VALUE
|
38 RETURN_VALUE
|
||||||
>> 44 LOAD_CONST 0 (None)
|
>> 40 LOAD_CONST 0 (None)
|
||||||
46 STORE_FAST 0 (e)
|
42 STORE_FAST 0 (e)
|
||||||
48 DELETE_FAST 0 (e)
|
44 DELETE_FAST 0 (e)
|
||||||
50 RERAISE 1
|
46 RERAISE 1
|
||||||
|
|
||||||
%3d >> 52 RERAISE 0
|
%3d >> 48 RERAISE 0
|
||||||
>> 54 POP_EXCEPT_AND_RERAISE
|
>> 50 POP_EXCEPT_AND_RERAISE
|
||||||
ExceptionTable:
|
ExceptionTable:
|
||||||
2 to 8 -> 14 [0]
|
2 to 8 -> 14 [0]
|
||||||
14 to 24 -> 54 [3] lasti
|
14 to 20 -> 50 [1] lasti
|
||||||
26 to 30 -> 44 [3] lasti
|
22 to 26 -> 40 [1] lasti
|
||||||
44 to 52 -> 54 [3] lasti
|
40 to 48 -> 50 [1] lasti
|
||||||
""" % (TRACEBACK_CODE.co_firstlineno + 1,
|
""" % (TRACEBACK_CODE.co_firstlineno + 1,
|
||||||
TRACEBACK_CODE.co_firstlineno + 2,
|
TRACEBACK_CODE.co_firstlineno + 2,
|
||||||
TRACEBACK_CODE.co_firstlineno + 5,
|
TRACEBACK_CODE.co_firstlineno + 5,
|
||||||
|
@ -395,7 +393,7 @@ dis_tryfinally = """\
|
||||||
>> 22 POP_EXCEPT_AND_RERAISE
|
>> 22 POP_EXCEPT_AND_RERAISE
|
||||||
ExceptionTable:
|
ExceptionTable:
|
||||||
2 to 2 -> 12 [0]
|
2 to 2 -> 12 [0]
|
||||||
12 to 20 -> 22 [3] lasti
|
12 to 20 -> 22 [1] lasti
|
||||||
""" % (_tryfinally.__code__.co_firstlineno + 1,
|
""" % (_tryfinally.__code__.co_firstlineno + 1,
|
||||||
_tryfinally.__code__.co_firstlineno + 2,
|
_tryfinally.__code__.co_firstlineno + 2,
|
||||||
_tryfinally.__code__.co_firstlineno + 4,
|
_tryfinally.__code__.co_firstlineno + 4,
|
||||||
|
@ -418,7 +416,7 @@ dis_tryfinallyconst = """\
|
||||||
22 RERAISE 0
|
22 RERAISE 0
|
||||||
>> 24 POP_EXCEPT_AND_RERAISE
|
>> 24 POP_EXCEPT_AND_RERAISE
|
||||||
ExceptionTable:
|
ExceptionTable:
|
||||||
14 to 22 -> 24 [3] lasti
|
14 to 22 -> 24 [1] lasti
|
||||||
""" % (_tryfinallyconst.__code__.co_firstlineno + 1,
|
""" % (_tryfinallyconst.__code__.co_firstlineno + 1,
|
||||||
_tryfinallyconst.__code__.co_firstlineno + 2,
|
_tryfinallyconst.__code__.co_firstlineno + 2,
|
||||||
_tryfinallyconst.__code__.co_firstlineno + 4,
|
_tryfinallyconst.__code__.co_firstlineno + 4,
|
||||||
|
@ -864,7 +862,7 @@ Argument count: 0
|
||||||
Positional-only arguments: 0
|
Positional-only arguments: 0
|
||||||
Kw-only arguments: 0
|
Kw-only arguments: 0
|
||||||
Number of locals: 2
|
Number of locals: 2
|
||||||
Stack size: 10
|
Stack size: 6
|
||||||
Flags: OPTIMIZED, NEWLOCALS, COROUTINE
|
Flags: OPTIMIZED, NEWLOCALS, COROUTINE
|
||||||
Constants:
|
Constants:
|
||||||
0: None
|
0: None
|
||||||
|
@ -1107,65 +1105,61 @@ expected_opinfo_jumpy = [
|
||||||
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='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='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='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=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='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='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=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),
|
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='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=124, starts_line=23, 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_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='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=128, starts_line=23, is_jump_target=False, positions=None),
|
Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=128, starts_line=None, 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='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=130, starts_line=None, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=132, 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='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', 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='POP_EXCEPT', opcode=89, arg=None, argval=None, argrepr='', offset=136, 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='JUMP_FORWARD', opcode=110, arg=32, argval=204, argrepr='to 204', offset=138, starts_line=None, is_jump_target=False, 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='RERAISE', opcode=119, arg=0, argval=0, argrepr='', offset=140, starts_line=22, is_jump_target=True, 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='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=142, starts_line=None, is_jump_target=False, 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='LOAD_FAST', opcode=124, arg=0, argval='i', argrepr='i', offset=144, starts_line=25, is_jump_target=True, 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='BEFORE_WITH', opcode=53, arg=None, argval=None, argrepr='', offset=146, 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='STORE_FAST', opcode=125, arg=1, argval='dodgy', argrepr='dodgy', offset=148, starts_line=None, 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='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=150, starts_line=26, is_jump_target=False, positions=None),
|
Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=150, starts_line=None, 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='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=152, starts_line=None, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, 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=154, starts_line=25, 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='DUP_TOP', opcode=4, 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=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_NO_KW', opcode=169, arg=3, argval=3, 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='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=162, starts_line=None, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='CALL_NO_KW', opcode=169, arg=3, argval=3, argrepr='', 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='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=166, 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='JUMP_FORWARD', opcode=110, arg=11, argval=192, argrepr='to 192', offset=168, 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='PUSH_EXC_INFO', opcode=35, 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=88, argval=176, argrepr='to 176', 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='RERAISE', opcode=119, arg=2, argval=2, 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='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', 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_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=176, starts_line=None, is_jump_target=True, 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_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=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_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=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='LOAD_GLOBAL', opcode=116, arg=1, argval='print', argrepr='print', offset=184, starts_line=28, is_jump_target=True, 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='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='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=188, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='CALL_NO_KW', opcode=169, 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='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=0, argval=None, argrepr='None', offset=192, 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=194, 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='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=196, 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='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=198, starts_line=None, is_jump_target=False, 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=0, argval=None, argrepr='None', offset=200, 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=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='CALL_NO_KW', opcode=169, arg=1, argval=1, 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='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=204, starts_line=None, is_jump_target=False, 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=0, argval=None, argrepr='None', offset=206, 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=208, 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='CALL_NO_KW', opcode=169, arg=1, argval=1, argrepr='', offset=210, 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='POP_TOP', opcode=1, arg=None, argval=None, argrepr='', offset=212, 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=0, argval=None, argrepr='None', offset=214, 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='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=216, starts_line=None, is_jump_target=False, positions=None),
|
Instruction(opname='CALL_NO_KW', opcode=169, arg=1, argval=1, 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='POP_TOP', opcode=1, 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='RERAISE', opcode=119, arg=0, argval=0, argrepr='', 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='POP_EXCEPT_AND_RERAISE', opcode=37, arg=None, argval=None, argrepr='', offset=222, starts_line=None, is_jump_target=False, positions=None),
|
||||||
Instruction(opname='CALL_NO_KW', opcode=169, 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),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# One last piece of inspect fodder to check the default line number handling
|
# One last piece of inspect fodder to check the default line number handling
|
||||||
|
|
|
@ -1340,7 +1340,7 @@ class SizeofTest(unittest.TestCase):
|
||||||
check(bar, size('PP'))
|
check(bar, size('PP'))
|
||||||
# generator
|
# generator
|
||||||
def get_gen(): yield 1
|
def get_gen(): yield 1
|
||||||
check(get_gen(), size('P2PPP4P4c8P2iciP'))
|
check(get_gen(), size('P2P4P4c8P2iciP'))
|
||||||
# iterator
|
# iterator
|
||||||
check(iter('abc'), size('lP'))
|
check(iter('abc'), size('lP'))
|
||||||
# callable-iterator
|
# callable-iterator
|
||||||
|
|
|
@ -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``.
|
|
@ -810,9 +810,7 @@ FutureObj_traverse(FutureObj *fut, visitproc visit, void *arg)
|
||||||
Py_VISIT(fut->dict);
|
Py_VISIT(fut->dict);
|
||||||
|
|
||||||
_PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state;
|
_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_value);
|
||||||
Py_VISIT(exc_state->exc_traceback);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1376,10 +1374,6 @@ _asyncio_Future__make_cancelled_error_impl(FutureObj *self)
|
||||||
PyException_SetContext(exc, Py_NewRef(exc_state->exc_value));
|
PyException_SetContext(exc, Py_NewRef(exc_state->exc_value));
|
||||||
_PyErr_ClearExcState(exc_state);
|
_PyErr_ClearExcState(exc_state);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
assert(exc_state->exc_type == NULL);
|
|
||||||
assert(exc_state->exc_traceback == NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return exc;
|
return exc;
|
||||||
}
|
}
|
||||||
|
@ -2706,13 +2700,13 @@ task_step_impl(TaskObj *task, PyObject *exc)
|
||||||
PyErr_NormalizeException(&et, &ev, &tb);
|
PyErr_NormalizeException(&et, &ev, &tb);
|
||||||
if (tb != NULL) {
|
if (tb != NULL) {
|
||||||
PyException_SetTraceback(ev, tb);
|
PyException_SetTraceback(ev, tb);
|
||||||
|
Py_DECREF(tb);
|
||||||
}
|
}
|
||||||
|
Py_XDECREF(et);
|
||||||
|
|
||||||
FutureObj *fut = (FutureObj*)task;
|
FutureObj *fut = (FutureObj*)task;
|
||||||
_PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state;
|
_PyErr_StackItem *exc_state = &fut->fut_cancelled_exc_state;
|
||||||
exc_state->exc_type = et;
|
|
||||||
exc_state->exc_value = ev;
|
exc_state->exc_value = ev;
|
||||||
exc_state->exc_traceback = tb;
|
|
||||||
|
|
||||||
return future_cancel(fut, NULL);
|
return future_cancel(fut, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,7 @@ static const char *ASYNC_GEN_IGNORED_EXIT_MSG =
|
||||||
static inline int
|
static inline int
|
||||||
exc_state_traverse(_PyErr_StackItem *exc_state, visitproc visit, void *arg)
|
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_value);
|
||||||
Py_VISIT(exc_state->exc_traceback);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -886,9 +884,7 @@ make_gen(PyTypeObject *type, PyFunctionObject *func)
|
||||||
gen->gi_code = (PyCodeObject *)func->func_code;
|
gen->gi_code = (PyCodeObject *)func->func_code;
|
||||||
Py_INCREF(gen->gi_code);
|
Py_INCREF(gen->gi_code);
|
||||||
gen->gi_weakreflist = NULL;
|
gen->gi_weakreflist = NULL;
|
||||||
gen->gi_exc_state.exc_type = NULL;
|
|
||||||
gen->gi_exc_state.exc_value = NULL;
|
gen->gi_exc_state.exc_value = NULL;
|
||||||
gen->gi_exc_state.exc_traceback = NULL;
|
|
||||||
gen->gi_exc_state.previous_item = NULL;
|
gen->gi_exc_state.previous_item = NULL;
|
||||||
if (func->func_name != NULL)
|
if (func->func_name != NULL)
|
||||||
gen->gi_name = func->func_name;
|
gen->gi_name = func->func_name;
|
||||||
|
@ -975,9 +971,7 @@ gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f,
|
||||||
Py_INCREF(gen->gi_code);
|
Py_INCREF(gen->gi_code);
|
||||||
Py_DECREF(f);
|
Py_DECREF(f);
|
||||||
gen->gi_weakreflist = NULL;
|
gen->gi_weakreflist = NULL;
|
||||||
gen->gi_exc_state.exc_type = NULL;
|
|
||||||
gen->gi_exc_state.exc_value = NULL;
|
gen->gi_exc_state.exc_value = NULL;
|
||||||
gen->gi_exc_state.exc_traceback = NULL;
|
|
||||||
gen->gi_exc_state.previous_item = NULL;
|
gen->gi_exc_state.previous_item = NULL;
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
gen->gi_name = name;
|
gen->gi_name = name;
|
||||||
|
|
212
Python/ceval.c
212
Python/ceval.c
|
@ -1094,29 +1094,11 @@ fail:
|
||||||
static int do_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause);
|
static int do_raise(PyThreadState *tstate, PyObject *exc, PyObject *cause);
|
||||||
static PyObject *do_reraise_star(PyObject *excs, PyObject *orig);
|
static PyObject *do_reraise_star(PyObject *excs, PyObject *orig);
|
||||||
static int exception_group_match(
|
static int exception_group_match(
|
||||||
PyObject *exc_type, PyObject* exc_value, PyObject *match_type,
|
PyObject* exc_value, PyObject *match_type,
|
||||||
PyObject **match, PyObject **rest);
|
PyObject **match, PyObject **rest);
|
||||||
|
|
||||||
static int unpack_iterable(PyThreadState *, PyObject *, int, int, PyObject **);
|
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 *
|
PyObject *
|
||||||
PyEval_EvalCode(PyObject *co, PyObject *globals, PyObject *locals)
|
PyEval_EvalCode(PyObject *co, PyObject *globals, PyObject *locals)
|
||||||
{
|
{
|
||||||
|
@ -2737,25 +2719,15 @@ check_eval_breaker:
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(POP_EXCEPT) {
|
TARGET(POP_EXCEPT) {
|
||||||
PyObject *type, *value, *traceback;
|
_PyErr_StackItem *exc_info = tstate->exc_info;
|
||||||
_PyErr_StackItem *exc_info;
|
PyObject *value = exc_info->exc_value;
|
||||||
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();
|
exc_info->exc_value = POP();
|
||||||
exc_info->exc_traceback = POP();
|
|
||||||
ASSERT_EXC_TYPE_IS_REDUNDANT(exc_info->exc_type, exc_info->exc_value);
|
|
||||||
Py_XDECREF(type);
|
|
||||||
Py_XDECREF(value);
|
Py_XDECREF(value);
|
||||||
Py_XDECREF(traceback);
|
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(POP_EXCEPT_AND_RERAISE) {
|
TARGET(POP_EXCEPT_AND_RERAISE) {
|
||||||
PyObject *lasti = PEEK(4);
|
PyObject *lasti = PEEK(2);
|
||||||
if (PyLong_Check(lasti)) {
|
if (PyLong_Check(lasti)) {
|
||||||
frame->f_lasti = PyLong_AsLong(lasti);
|
frame->f_lasti = PyLong_AsLong(lasti);
|
||||||
assert(!_PyErr_Occurred(tstate));
|
assert(!_PyErr_Occurred(tstate));
|
||||||
|
@ -2764,31 +2736,24 @@ check_eval_breaker:
|
||||||
_PyErr_SetString(tstate, PyExc_SystemError, "lasti is not an int");
|
_PyErr_SetString(tstate, PyExc_SystemError, "lasti is not an int");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
PyObject *type, *value, *traceback;
|
PyObject *value = POP();
|
||||||
_PyErr_StackItem *exc_info;
|
assert(value);
|
||||||
type = POP();
|
assert(PyExceptionInstance_Check(value));
|
||||||
value = POP();
|
PyObject *type = Py_NewRef(PyExceptionInstance_Class(value));
|
||||||
traceback = POP();
|
PyObject *traceback = PyException_GetTraceback(value);
|
||||||
ASSERT_EXC_TYPE_IS_REDUNDANT(type, value);
|
|
||||||
Py_DECREF(POP()); /* lasti */
|
Py_DECREF(POP()); /* lasti */
|
||||||
_PyErr_Restore(tstate, type, value, traceback);
|
_PyErr_Restore(tstate, type, value, traceback);
|
||||||
exc_info = tstate->exc_info;
|
|
||||||
type = exc_info->exc_type;
|
_PyErr_StackItem *exc_info = tstate->exc_info;
|
||||||
value = exc_info->exc_value;
|
value = exc_info->exc_value;
|
||||||
traceback = exc_info->exc_traceback;
|
|
||||||
exc_info->exc_type = POP();
|
|
||||||
exc_info->exc_value = POP();
|
exc_info->exc_value = POP();
|
||||||
exc_info->exc_traceback = POP();
|
|
||||||
ASSERT_EXC_TYPE_IS_REDUNDANT(exc_info->exc_type, exc_info->exc_value);
|
|
||||||
Py_XDECREF(type);
|
|
||||||
Py_XDECREF(value);
|
Py_XDECREF(value);
|
||||||
Py_XDECREF(traceback);
|
|
||||||
goto exception_unwind;
|
goto exception_unwind;
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(RERAISE) {
|
TARGET(RERAISE) {
|
||||||
if (oparg) {
|
if (oparg) {
|
||||||
PyObject *lasti = PEEK(oparg+3);
|
PyObject *lasti = PEEK(oparg + 1);
|
||||||
if (PyLong_Check(lasti)) {
|
if (PyLong_Check(lasti)) {
|
||||||
frame->f_lasti = PyLong_AsLong(lasti);
|
frame->f_lasti = PyLong_AsLong(lasti);
|
||||||
assert(!_PyErr_Occurred(tstate));
|
assert(!_PyErr_Occurred(tstate));
|
||||||
|
@ -2799,11 +2764,10 @@ check_eval_breaker:
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PyObject *exc = POP();
|
|
||||||
PyObject *val = POP();
|
PyObject *val = POP();
|
||||||
PyObject *tb = POP();
|
assert(val && PyExceptionInstance_Check(val));
|
||||||
ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val);
|
PyObject *exc = Py_NewRef(PyExceptionInstance_Class(val));
|
||||||
assert(PyExceptionClass_Check(exc));
|
PyObject *tb = PyException_GetTraceback(val);
|
||||||
_PyErr_Restore(tstate, exc, val, tb);
|
_PyErr_Restore(tstate, exc, val, tb);
|
||||||
goto exception_unwind;
|
goto exception_unwind;
|
||||||
}
|
}
|
||||||
|
@ -2823,35 +2787,21 @@ check_eval_breaker:
|
||||||
|
|
||||||
PyObject *lasti_unused = Py_NewRef(_PyLong_GetZero());
|
PyObject *lasti_unused = Py_NewRef(_PyLong_GetZero());
|
||||||
PUSH(lasti_unused);
|
PUSH(lasti_unused);
|
||||||
if (!Py_IsNone(val)) {
|
PUSH(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));
|
|
||||||
}
|
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(END_ASYNC_FOR) {
|
TARGET(END_ASYNC_FOR) {
|
||||||
PyObject *exc = POP();
|
|
||||||
PyObject *val = POP();
|
PyObject *val = POP();
|
||||||
PyObject *tb = POP();
|
assert(val && PyExceptionInstance_Check(val));
|
||||||
ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val);
|
if (PyErr_GivenExceptionMatches(val, PyExc_StopAsyncIteration)) {
|
||||||
assert(PyExceptionClass_Check(exc));
|
|
||||||
if (PyErr_GivenExceptionMatches(exc, PyExc_StopAsyncIteration)) {
|
|
||||||
Py_DECREF(exc);
|
|
||||||
Py_DECREF(val);
|
Py_DECREF(val);
|
||||||
Py_DECREF(tb);
|
|
||||||
Py_DECREF(POP());
|
Py_DECREF(POP());
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
PyObject *exc = Py_NewRef(PyExceptionInstance_Class(val));
|
||||||
|
PyObject *tb = PyException_GetTraceback(val);
|
||||||
_PyErr_Restore(tstate, exc, val, tb);
|
_PyErr_Restore(tstate, exc, val, tb);
|
||||||
goto exception_unwind;
|
goto exception_unwind;
|
||||||
}
|
}
|
||||||
|
@ -3971,16 +3921,15 @@ check_eval_breaker:
|
||||||
|
|
||||||
TARGET(JUMP_IF_NOT_EG_MATCH) {
|
TARGET(JUMP_IF_NOT_EG_MATCH) {
|
||||||
PyObject *match_type = POP();
|
PyObject *match_type = POP();
|
||||||
PyObject *exc_type = TOP();
|
|
||||||
PyObject *exc_value = SECOND();
|
|
||||||
if (check_except_star_type_valid(tstate, match_type) < 0) {
|
if (check_except_star_type_valid(tstate, match_type) < 0) {
|
||||||
Py_DECREF(match_type);
|
Py_DECREF(match_type);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject *exc_value = TOP();
|
||||||
PyObject *match = NULL, *rest = NULL;
|
PyObject *match = NULL, *rest = NULL;
|
||||||
int res = exception_group_match(exc_type, exc_value,
|
int res = exception_group_match(exc_value, match_type,
|
||||||
match_type, &match, &rest);
|
&match, &rest);
|
||||||
Py_DECREF(match_type);
|
Py_DECREF(match_type);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -4001,46 +3950,21 @@ check_eval_breaker:
|
||||||
else {
|
else {
|
||||||
|
|
||||||
/* Total or partial match - update the stack from
|
/* Total or partial match - update the stack from
|
||||||
* [tb, val, exc]
|
* [val]
|
||||||
* to
|
* to
|
||||||
* [tb, rest, exc, tb, match, exc]
|
* [rest, match]
|
||||||
* (rest can be Py_None)
|
* (rest can be Py_None)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
PyObject *exc = TOP();
|
||||||
|
|
||||||
PyObject *type = TOP();
|
SET_TOP(rest);
|
||||||
PyObject *val = SECOND();
|
PUSH(match);
|
||||||
PyObject *tb = THIRD();
|
|
||||||
|
|
||||||
if (!Py_IsNone(rest)) {
|
PyErr_SetExcInfo(NULL, Py_NewRef(match), NULL);
|
||||||
/* 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));
|
Py_DECREF(exc);
|
||||||
PUSH(Py_NewRef(match));
|
|
||||||
PUSH(Py_NewRef(Py_TYPE(match)));
|
|
||||||
|
|
||||||
// set exc_info to the current match
|
|
||||||
PyErr_SetExcInfo(
|
|
||||||
Py_NewRef(Py_TYPE(match)),
|
|
||||||
Py_NewRef(match),
|
|
||||||
Py_NewRef(tb));
|
|
||||||
|
|
||||||
Py_DECREF(tb);
|
|
||||||
Py_DECREF(val);
|
|
||||||
Py_DECREF(type);
|
|
||||||
|
|
||||||
Py_DECREF(match);
|
|
||||||
Py_DECREF(rest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
@ -4048,8 +3972,7 @@ check_eval_breaker:
|
||||||
|
|
||||||
TARGET(JUMP_IF_NOT_EXC_MATCH) {
|
TARGET(JUMP_IF_NOT_EXC_MATCH) {
|
||||||
PyObject *right = POP();
|
PyObject *right = POP();
|
||||||
ASSERT_EXC_TYPE_IS_REDUNDANT(TOP(), SECOND());
|
PyObject *left = TOP();
|
||||||
PyObject *left = SECOND();
|
|
||||||
assert(PyExceptionInstance_Check(left));
|
assert(PyExceptionInstance_Check(left));
|
||||||
if (check_except_type_valid(tstate, right) < 0) {
|
if (check_except_type_valid(tstate, right) < 0) {
|
||||||
Py_DECREF(right);
|
Py_DECREF(right);
|
||||||
|
@ -4465,26 +4388,24 @@ check_eval_breaker:
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(WITH_EXCEPT_START) {
|
TARGET(WITH_EXCEPT_START) {
|
||||||
/* At the top of the stack are 8 values:
|
/* At the top of the stack are 4 values:
|
||||||
- (TOP, SECOND, THIRD) = exc_info()
|
- TOP = exc_info()
|
||||||
- (FOURTH, FIFTH, SIXTH) = previous exception
|
- SECOND = previous exception
|
||||||
- SEVENTH: lasti of exception in exc_info()
|
- THIRD: lasti of exception in exc_info()
|
||||||
- EIGHTH: the context.__exit__ bound method
|
- FOURTH: the context.__exit__ bound method
|
||||||
We call EIGHTH(TOP, SECOND, THIRD).
|
We call FOURTH(type(TOP), TOP, GetTraceback(TOP)).
|
||||||
Then we push again the TOP exception and the __exit__
|
Then we push the __exit__ return value.
|
||||||
return value.
|
|
||||||
*/
|
*/
|
||||||
PyObject *exit_func;
|
PyObject *exit_func;
|
||||||
PyObject *exc, *val, *tb, *res;
|
PyObject *exc, *val, *tb, *res;
|
||||||
|
|
||||||
exc = TOP();
|
val = TOP();
|
||||||
val = SECOND();
|
assert(val && PyExceptionInstance_Check(val));
|
||||||
tb = THIRD();
|
exc = PyExceptionInstance_Class(val);
|
||||||
ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val);
|
tb = PyException_GetTraceback(val);
|
||||||
assert(!Py_IsNone(exc));
|
Py_XDECREF(tb);
|
||||||
assert(!PyLong_Check(exc));
|
assert(PyLong_Check(PEEK(3)));
|
||||||
assert(PyLong_Check(PEEK(7)));
|
exit_func = PEEK(4);
|
||||||
exit_func = PEEK(8);
|
|
||||||
PyObject *stack[4] = {NULL, exc, val, tb};
|
PyObject *stack[4] = {NULL, exc, val, tb};
|
||||||
res = PyObject_Vectorcall(exit_func, stack + 1,
|
res = PyObject_Vectorcall(exit_func, stack + 1,
|
||||||
3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
|
3 | PY_VECTORCALL_ARGUMENTS_OFFSET, NULL);
|
||||||
|
@ -4496,40 +4417,22 @@ check_eval_breaker:
|
||||||
}
|
}
|
||||||
|
|
||||||
TARGET(PUSH_EXC_INFO) {
|
TARGET(PUSH_EXC_INFO) {
|
||||||
PyObject *type = TOP();
|
PyObject *value = TOP();
|
||||||
PyObject *value = SECOND();
|
|
||||||
PyObject *tb = THIRD();
|
|
||||||
ASSERT_EXC_TYPE_IS_REDUNDANT(type, value);
|
|
||||||
_PyErr_StackItem *exc_info = tstate->exc_info;
|
_PyErr_StackItem *exc_info = tstate->exc_info;
|
||||||
SET_THIRD(exc_info->exc_traceback);
|
|
||||||
if (exc_info->exc_value != NULL) {
|
if (exc_info->exc_value != NULL) {
|
||||||
SET_SECOND(exc_info->exc_value);
|
SET_TOP(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);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
SET_TOP(Py_None);
|
SET_TOP(Py_None);
|
||||||
}
|
}
|
||||||
Py_INCREF(tb);
|
|
||||||
PUSH(tb);
|
|
||||||
exc_info->exc_traceback = tb;
|
|
||||||
|
|
||||||
Py_INCREF(value);
|
Py_INCREF(value);
|
||||||
PUSH(value);
|
PUSH(value);
|
||||||
assert(PyExceptionInstance_Check(value));
|
assert(PyExceptionInstance_Check(value));
|
||||||
exc_info->exc_value = value;
|
exc_info->exc_value = value;
|
||||||
|
|
||||||
Py_INCREF(type);
|
|
||||||
PUSH(type);
|
|
||||||
assert(PyExceptionClass_Check(type));
|
|
||||||
exc_info->exc_type = type;
|
|
||||||
|
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5518,14 +5421,9 @@ exception_unwind:
|
||||||
PyException_SetTraceback(val, tb);
|
PyException_SetTraceback(val, tb);
|
||||||
else
|
else
|
||||||
PyException_SetTraceback(val, Py_None);
|
PyException_SetTraceback(val, Py_None);
|
||||||
if (tb == NULL) {
|
Py_XDECREF(tb);
|
||||||
tb = Py_None;
|
Py_XDECREF(exc);
|
||||||
Py_INCREF(Py_None);
|
|
||||||
}
|
|
||||||
PUSH(tb);
|
|
||||||
PUSH(val);
|
PUSH(val);
|
||||||
PUSH(exc);
|
|
||||||
ASSERT_EXC_TYPE_IS_REDUNDANT(exc, val);
|
|
||||||
JUMPTO(handler);
|
JUMPTO(handler);
|
||||||
/* Resume normal execution */
|
/* Resume normal execution */
|
||||||
frame->f_state = FRAME_EXECUTING;
|
frame->f_state = FRAME_EXECUTING;
|
||||||
|
@ -6375,19 +6273,17 @@ raise_error:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
exception_group_match(PyObject *exc_type, PyObject* exc_value,
|
exception_group_match(PyObject* exc_value, PyObject *match_type,
|
||||||
PyObject *match_type, PyObject **match, PyObject **rest)
|
PyObject **match, PyObject **rest)
|
||||||
{
|
{
|
||||||
if (Py_IsNone(exc_type)) {
|
if (Py_IsNone(exc_value)) {
|
||||||
assert(Py_IsNone(exc_value));
|
|
||||||
*match = Py_NewRef(Py_None);
|
*match = Py_NewRef(Py_None);
|
||||||
*rest = Py_NewRef(Py_None);
|
*rest = Py_NewRef(Py_None);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
assert(PyExceptionClass_Check(exc_type));
|
|
||||||
assert(PyExceptionInstance_Check(exc_value));
|
assert(PyExceptionInstance_Check(exc_value));
|
||||||
|
|
||||||
if (PyErr_GivenExceptionMatches(exc_type, match_type)) {
|
if (PyErr_GivenExceptionMatches(exc_value, match_type)) {
|
||||||
/* Full match of exc itself */
|
/* Full match of exc itself */
|
||||||
bool is_eg = _PyBaseExceptionGroup_Check(exc_value);
|
bool is_eg = _PyBaseExceptionGroup_Check(exc_value);
|
||||||
if (is_eg) {
|
if (is_eg) {
|
||||||
|
|
156
Python/compile.c
156
Python/compile.c
|
@ -1048,9 +1048,9 @@ stack_effect(int opcode, int oparg, int jump)
|
||||||
case POP_BLOCK:
|
case POP_BLOCK:
|
||||||
return 0;
|
return 0;
|
||||||
case POP_EXCEPT:
|
case POP_EXCEPT:
|
||||||
return -3;
|
return -1;
|
||||||
case POP_EXCEPT_AND_RERAISE:
|
case POP_EXCEPT_AND_RERAISE:
|
||||||
return -7;
|
return -3;
|
||||||
|
|
||||||
case STORE_NAME:
|
case STORE_NAME:
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1095,7 +1095,7 @@ stack_effect(int opcode, int oparg, int jump)
|
||||||
case JUMP_IF_NOT_EXC_MATCH:
|
case JUMP_IF_NOT_EXC_MATCH:
|
||||||
return -1;
|
return -1;
|
||||||
case JUMP_IF_NOT_EG_MATCH:
|
case JUMP_IF_NOT_EG_MATCH:
|
||||||
return jump > 0 ? -1 : 2;
|
return jump > 0 ? -1 : 0;
|
||||||
case IMPORT_NAME:
|
case IMPORT_NAME:
|
||||||
return -1;
|
return -1;
|
||||||
case IMPORT_FROM:
|
case IMPORT_FROM:
|
||||||
|
@ -1120,25 +1120,25 @@ stack_effect(int opcode, int oparg, int jump)
|
||||||
/* Exception handling pseudo-instructions */
|
/* Exception handling pseudo-instructions */
|
||||||
case SETUP_FINALLY:
|
case SETUP_FINALLY:
|
||||||
/* 0 in the normal flow.
|
/* 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. */
|
* the handler if an exception be raised. */
|
||||||
return jump ? 3 : 0;
|
return jump ? 1 : 0;
|
||||||
case SETUP_CLEANUP:
|
case SETUP_CLEANUP:
|
||||||
/* As SETUP_FINALLY, but pushes lasti as well */
|
/* As SETUP_FINALLY, but pushes lasti as well */
|
||||||
return jump ? 4 : 0;
|
return jump ? 2 : 0;
|
||||||
case SETUP_WITH:
|
case SETUP_WITH:
|
||||||
/* 0 in the normal flow.
|
/* 0 in the normal flow.
|
||||||
* Restore the stack position to the position before the result
|
* 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. */
|
* if an exception be raised. */
|
||||||
return jump ? -1 + 4 : 0;
|
return jump ? 1 : 0;
|
||||||
|
|
||||||
case PREP_RERAISE_STAR:
|
case PREP_RERAISE_STAR:
|
||||||
return 2;
|
return 0;
|
||||||
case RERAISE:
|
case RERAISE:
|
||||||
return -3;
|
return -1;
|
||||||
case PUSH_EXC_INFO:
|
case PUSH_EXC_INFO:
|
||||||
return 3;
|
return 1;
|
||||||
|
|
||||||
case WITH_EXCEPT_START:
|
case WITH_EXCEPT_START:
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1199,7 +1199,7 @@ stack_effect(int opcode, int oparg, int jump)
|
||||||
case GET_YIELD_FROM_ITER:
|
case GET_YIELD_FROM_ITER:
|
||||||
return 0;
|
return 0;
|
||||||
case END_ASYNC_FOR:
|
case END_ASYNC_FOR:
|
||||||
return -4;
|
return -2;
|
||||||
case FORMAT_VALUE:
|
case FORMAT_VALUE:
|
||||||
/* If there's a fmt_spec on the stack, we go from 2->1,
|
/* If there's a fmt_spec on the stack, we go from 2->1,
|
||||||
else 1->1. */
|
else 1->1. */
|
||||||
|
@ -1888,13 +1888,11 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
|
||||||
|
|
||||||
case FINALLY_END:
|
case FINALLY_END:
|
||||||
if (preserve_tos) {
|
if (preserve_tos) {
|
||||||
ADDOP(c, ROT_FOUR);
|
ADDOP(c, ROT_TWO);
|
||||||
}
|
}
|
||||||
ADDOP(c, POP_TOP);
|
ADDOP(c, POP_TOP); /* exc_value */
|
||||||
ADDOP(c, POP_TOP);
|
|
||||||
ADDOP(c, POP_TOP);
|
|
||||||
if (preserve_tos) {
|
if (preserve_tos) {
|
||||||
ADDOP(c, ROT_FOUR);
|
ADDOP(c, ROT_TWO);
|
||||||
}
|
}
|
||||||
ADDOP(c, POP_BLOCK);
|
ADDOP(c, POP_BLOCK);
|
||||||
ADDOP(c, POP_EXCEPT);
|
ADDOP(c, POP_EXCEPT);
|
||||||
|
@ -1927,7 +1925,7 @@ compiler_unwind_fblock(struct compiler *c, struct fblockinfo *info,
|
||||||
ADDOP(c, POP_BLOCK);
|
ADDOP(c, POP_BLOCK);
|
||||||
}
|
}
|
||||||
if (preserve_tos) {
|
if (preserve_tos) {
|
||||||
ADDOP(c, ROT_FOUR);
|
ADDOP(c, ROT_TWO);
|
||||||
}
|
}
|
||||||
ADDOP(c, POP_BLOCK);
|
ADDOP(c, POP_BLOCK);
|
||||||
ADDOP(c, POP_EXCEPT);
|
ADDOP(c, POP_EXCEPT);
|
||||||
|
@ -3310,18 +3308,16 @@ compiler_try_star_finally(struct compiler *c, stmt_ty s)
|
||||||
[] POP_BLOCK
|
[] POP_BLOCK
|
||||||
[] JUMP_FORWARD L0
|
[] JUMP_FORWARD L0
|
||||||
|
|
||||||
[tb, val, exc] L1: <evaluate E1> )
|
[exc] L1: <evaluate E1> )
|
||||||
[tb, val, exc, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1
|
[exc, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1
|
||||||
[tb, val, exc] POP
|
[exc] <assign to V1> (or POP if no V1)
|
||||||
[tb, val] <assign to V1> (or POP if no V1)
|
|
||||||
[tb] POP
|
|
||||||
[] <code for S1>
|
[] <code for S1>
|
||||||
JUMP_FORWARD L0
|
JUMP_FORWARD L0
|
||||||
|
|
||||||
[tb, val, exc] L2: <evaluate E2>
|
[exc] L2: <evaluate E2>
|
||||||
.............................etc.......................
|
.............................etc.......................
|
||||||
|
|
||||||
[tb, val, exc] Ln+1: RERAISE # re-raise exception
|
[exc] Ln+1: RERAISE # re-raise exception
|
||||||
|
|
||||||
[] L0: <next statement>
|
[] L0: <next statement>
|
||||||
|
|
||||||
|
@ -3372,7 +3368,6 @@ compiler_try_except(struct compiler *c, stmt_ty s)
|
||||||
ADDOP_JUMP(c, JUMP_IF_NOT_EXC_MATCH, except);
|
ADDOP_JUMP(c, JUMP_IF_NOT_EXC_MATCH, except);
|
||||||
NEXT_BLOCK(c);
|
NEXT_BLOCK(c);
|
||||||
}
|
}
|
||||||
ADDOP(c, POP_TOP);
|
|
||||||
if (handler->v.ExceptHandler.name) {
|
if (handler->v.ExceptHandler.name) {
|
||||||
basicblock *cleanup_end, *cleanup_body;
|
basicblock *cleanup_end, *cleanup_body;
|
||||||
|
|
||||||
|
@ -3383,7 +3378,6 @@ compiler_try_except(struct compiler *c, stmt_ty s)
|
||||||
}
|
}
|
||||||
|
|
||||||
compiler_nameop(c, handler->v.ExceptHandler.name, Store);
|
compiler_nameop(c, handler->v.ExceptHandler.name, Store);
|
||||||
ADDOP(c, POP_TOP);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
try:
|
try:
|
||||||
|
@ -3434,8 +3428,7 @@ compiler_try_except(struct compiler *c, stmt_ty s)
|
||||||
if (!cleanup_body)
|
if (!cleanup_body)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ADDOP(c, POP_TOP);
|
ADDOP(c, POP_TOP); /* exc_value */
|
||||||
ADDOP(c, POP_TOP);
|
|
||||||
compiler_use_next_block(c, cleanup_body);
|
compiler_use_next_block(c, cleanup_body);
|
||||||
if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL, NULL))
|
if (!compiler_push_fblock(c, HANDLER_CLEANUP, cleanup_body, NULL, NULL))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -3467,52 +3460,42 @@ compiler_try_except(struct compiler *c, stmt_ty s)
|
||||||
at the right; 'tb' is trace-back info, 'val' the exception instance,
|
at the right; 'tb' is trace-back info, 'val' the exception instance,
|
||||||
and 'typ' the exception's type.)
|
and 'typ' the exception's type.)
|
||||||
|
|
||||||
Value stack Label Instruction Argument
|
Value stack Label Instruction Argument
|
||||||
[] SETUP_FINALLY L1
|
[] SETUP_FINALLY L1
|
||||||
[] <code for S>
|
[] <code for S>
|
||||||
[] POP_BLOCK
|
[] POP_BLOCK
|
||||||
[] JUMP_FORWARD L0
|
[] JUMP_FORWARD L0
|
||||||
|
|
||||||
[tb, val, typ] L1: DUP_TOP_TWO ) save a copy of the
|
[exc] L1: DUP_TOP ) save copy of the original exception
|
||||||
[tb, val, typ, orig, typ] POP_TOP ) original raised exception
|
[orig, exc] BUILD_LIST ) list for raised/reraised excs ("result")
|
||||||
[tb, val, typ, orig] ROT_FOUR )
|
[orig, exc, res] ROT_TWO
|
||||||
[orig, tb, val, typ] BUILD_LIST ) list for raised/reraised
|
|
||||||
[orig, tb, val, typ, res] ROT_FOUR ) exceptions ("result")
|
|
||||||
|
|
||||||
[orig, res, tb, val, typ] <evaluate E1> )
|
[orig, res, exc] <evaluate E1>
|
||||||
[orig, res, tb, val, typ, E1] JUMP_IF_NOT_EXC_MATCH L2 ) only if E1
|
[orig, res, exc, E1] JUMP_IF_NOT_EG_MATCH L2
|
||||||
|
|
||||||
[orig, res, tb, rest, typ, tb, match, typ] POP
|
[orig, res, rest, match] <assign to V1> (or POP if no V1)
|
||||||
[orig, res, tb, rest, typ, tb, match] <assign to V1> (or POP if no V1)
|
|
||||||
[orig, res, tb, rest, typ, tb] POP
|
|
||||||
|
|
||||||
[orig, res, tb, rest, typ] SETUP_FINALLY R1
|
[orig, res, rest] SETUP_FINALLY R1
|
||||||
[orig, res, tb, rest, typ] <code for S1>
|
[orig, res, rest] <code for S1>
|
||||||
[orig, res, tb, rest, typ] JUMP_FORWARD L2
|
[orig, res, rest] JUMP_FORWARD L2
|
||||||
|
|
||||||
[orig, res, tb, rest, typ, i, tb, v, t] R1: POP ) exception raised in except* body
|
[orig, res, rest, i, v] R1: LIST_APPEND 3 ) exc raised in except* body - add to res
|
||||||
[orig, res, tb, rest, typ, i, tb, v] LIST_APPEND 6 ) add it to res
|
[orig, res, rest, i] POP
|
||||||
[orig, res, tb, rest, typ, i, tb] POP
|
|
||||||
[orig, res, tb, rest, typ, i] POP
|
|
||||||
|
|
||||||
[orig, res, tb, rest, typ] L2: <evaluate E2>
|
[orig, res, rest] L2: <evaluate E2>
|
||||||
.............................etc.......................
|
.............................etc.......................
|
||||||
|
|
||||||
[orig, res, tb, rest, typ] Ln+1: POP ) add unhandled exception
|
[orig, res, rest] Ln+1: LIST_APPEND 1 ) add unhandled exc to res (could be None)
|
||||||
[orig, res, tb, rest] LIST_APPEND 2 ) to res (could be None)
|
|
||||||
[orig, res, tb] POP
|
|
||||||
|
|
||||||
[orig, res] PREP_RERAISE_STAR
|
[orig, res] PREP_RERAISE_STAR
|
||||||
[i, tb, val, typ] POP_JUMP_IF_TRUE RER
|
[i, exc] POP_JUMP_IF_TRUE RER
|
||||||
[i, tb, val, typ] POP
|
[i, exc] POP
|
||||||
[i, tb, val] POP
|
[i] POP
|
||||||
[i, tb] POP
|
[] JUMP_FORWARD L0
|
||||||
[i] POP
|
|
||||||
[] JUMP_FORWARD L0
|
|
||||||
|
|
||||||
[i, tb, val, typ] RER: POP_EXCEPT_AND_RERAISE
|
[i, exc] RER: POP_EXCEPT_AND_RERAISE
|
||||||
|
|
||||||
[] L0: <next statement>
|
[] L0: <next statement>
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
compiler_try_star_except(struct compiler *c, stmt_ty s)
|
compiler_try_star_except(struct compiler *c, stmt_ty s)
|
||||||
|
@ -3573,30 +3556,25 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
/* Push the original EG into the stack */
|
/* Push the original EG into the stack */
|
||||||
/*
|
/*
|
||||||
[tb, val, exc] DUP_TOP_TWO
|
[exc] DUP_TOP
|
||||||
[tb, val, exc, val, exc] POP_TOP
|
[orig, exc]
|
||||||
[tb, val, exc, val] ROT_FOUR
|
|
||||||
[val, tb, val, exc]
|
|
||||||
*/
|
*/
|
||||||
ADDOP(c, DUP_TOP_TWO);
|
ADDOP(c, DUP_TOP);
|
||||||
ADDOP(c, POP_TOP);
|
|
||||||
ADDOP(c, ROT_FOUR);
|
|
||||||
|
|
||||||
/* create empty list for exceptions raised/reraise in the except* blocks */
|
/* create empty list for exceptions raised/reraise in the except* blocks */
|
||||||
/*
|
/*
|
||||||
[val, tb, val, exc] BUILD_LIST
|
[orig, exc] BUILD_LIST
|
||||||
[val, tb, val, exc, []] ROT_FOUR
|
[orig, exc, []] ROT_TWO
|
||||||
[val, [], tb, val, exc]
|
[orig, [], exc]
|
||||||
*/
|
*/
|
||||||
ADDOP_I(c, BUILD_LIST, 0);
|
ADDOP_I(c, BUILD_LIST, 0);
|
||||||
ADDOP(c, ROT_FOUR);
|
ADDOP(c, ROT_TWO);
|
||||||
}
|
}
|
||||||
if (handler->v.ExceptHandler.type) {
|
if (handler->v.ExceptHandler.type) {
|
||||||
VISIT(c, expr, handler->v.ExceptHandler.type);
|
VISIT(c, expr, handler->v.ExceptHandler.type);
|
||||||
ADDOP_JUMP(c, JUMP_IF_NOT_EG_MATCH, except);
|
ADDOP_JUMP(c, JUMP_IF_NOT_EG_MATCH, except);
|
||||||
NEXT_BLOCK(c);
|
NEXT_BLOCK(c);
|
||||||
}
|
}
|
||||||
ADDOP(c, POP_TOP); // exc_type
|
|
||||||
|
|
||||||
basicblock *cleanup_end = compiler_new_block(c);
|
basicblock *cleanup_end = compiler_new_block(c);
|
||||||
if (cleanup_end == NULL) {
|
if (cleanup_end == NULL) {
|
||||||
|
@ -3611,9 +3589,8 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
|
||||||
compiler_nameop(c, handler->v.ExceptHandler.name, Store);
|
compiler_nameop(c, handler->v.ExceptHandler.name, Store);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ADDOP(c, POP_TOP); // val
|
ADDOP(c, POP_TOP); // exc
|
||||||
}
|
}
|
||||||
ADDOP(c, POP_TOP); // tb
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
try:
|
try:
|
||||||
|
@ -3657,9 +3634,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add exception raised to the res list */
|
/* add exception raised to the res list */
|
||||||
ADDOP(c, POP_TOP); // type
|
ADDOP_I(c, LIST_APPEND, 3); // exc
|
||||||
ADDOP_I(c, LIST_APPEND, 6); // exc
|
|
||||||
ADDOP(c, POP_TOP); // tb
|
|
||||||
ADDOP(c, POP_TOP); // lasti
|
ADDOP(c, POP_TOP); // lasti
|
||||||
|
|
||||||
ADDOP_JUMP(c, JUMP_ABSOLUTE, except);
|
ADDOP_JUMP(c, JUMP_ABSOLUTE, except);
|
||||||
|
@ -3667,9 +3642,7 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
|
||||||
|
|
||||||
if (i == n - 1) {
|
if (i == n - 1) {
|
||||||
/* Add exc to the list (if not None it's the unhandled part of the EG) */
|
/* 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, 1);
|
||||||
ADDOP_I(c, LIST_APPEND, 2);
|
|
||||||
ADDOP(c, POP_TOP);
|
|
||||||
ADDOP_JUMP(c, JUMP_FORWARD, reraise_star);
|
ADDOP_JUMP(c, JUMP_FORWARD, reraise_star);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3690,8 +3663,6 @@ compiler_try_star_except(struct compiler *c, stmt_ty s)
|
||||||
/* Nothing to reraise - pop it */
|
/* Nothing to reraise - pop it */
|
||||||
ADDOP(c, POP_TOP);
|
ADDOP(c, POP_TOP);
|
||||||
ADDOP(c, POP_TOP);
|
ADDOP(c, POP_TOP);
|
||||||
ADDOP(c, POP_TOP);
|
|
||||||
ADDOP(c, POP_TOP);
|
|
||||||
ADDOP(c, POP_BLOCK);
|
ADDOP(c, POP_BLOCK);
|
||||||
ADDOP(c, POP_EXCEPT);
|
ADDOP(c, POP_EXCEPT);
|
||||||
ADDOP_JUMP(c, JUMP_FORWARD, end);
|
ADDOP_JUMP(c, JUMP_FORWARD, end);
|
||||||
|
@ -5449,13 +5420,11 @@ compiler_with_except_finish(struct compiler *c, basicblock * cleanup) {
|
||||||
return 0;
|
return 0;
|
||||||
ADDOP_JUMP(c, POP_JUMP_IF_TRUE, exit);
|
ADDOP_JUMP(c, POP_JUMP_IF_TRUE, exit);
|
||||||
NEXT_BLOCK(c);
|
NEXT_BLOCK(c);
|
||||||
ADDOP_I(c, RERAISE, 4);
|
ADDOP_I(c, RERAISE, 2);
|
||||||
compiler_use_next_block(c, cleanup);
|
compiler_use_next_block(c, cleanup);
|
||||||
ADDOP(c, POP_EXCEPT_AND_RERAISE);
|
ADDOP(c, POP_EXCEPT_AND_RERAISE);
|
||||||
compiler_use_next_block(c, exit);
|
compiler_use_next_block(c, exit);
|
||||||
ADDOP(c, POP_TOP);
|
ADDOP(c, POP_TOP); /* exc_value */
|
||||||
ADDOP(c, POP_TOP);
|
|
||||||
ADDOP(c, POP_TOP);
|
|
||||||
ADDOP(c, POP_BLOCK);
|
ADDOP(c, POP_BLOCK);
|
||||||
ADDOP(c, POP_EXCEPT);
|
ADDOP(c, POP_EXCEPT);
|
||||||
ADDOP(c, POP_TOP);
|
ADDOP(c, POP_TOP);
|
||||||
|
@ -5587,7 +5556,7 @@ compiler_async_with(struct compiler *c, stmt_ty s, int pos)
|
||||||
E: WITH_EXCEPT_START (calls EXPR.__exit__)
|
E: WITH_EXCEPT_START (calls EXPR.__exit__)
|
||||||
POP_JUMP_IF_TRUE T:
|
POP_JUMP_IF_TRUE T:
|
||||||
RERAISE
|
RERAISE
|
||||||
T: POP_TOP * 3 (remove exception from stack)
|
T: POP_TOP (remove exception from stack)
|
||||||
POP_EXCEPT
|
POP_EXCEPT
|
||||||
POP_TOP
|
POP_TOP
|
||||||
EXIT:
|
EXIT:
|
||||||
|
@ -7368,7 +7337,10 @@ assemble_emit_exception_table_entry(struct assembler *a, int start, int end, bas
|
||||||
int size = end-start;
|
int size = end-start;
|
||||||
assert(end > start);
|
assert(end > start);
|
||||||
int target = handler->b_offset;
|
int target = handler->b_offset;
|
||||||
int depth = handler->b_preserve_lasti ? handler->b_startdepth-4 : handler->b_startdepth-3;
|
int depth = handler->b_startdepth - 1;
|
||||||
|
if (handler->b_preserve_lasti) {
|
||||||
|
depth -= 1;
|
||||||
|
}
|
||||||
assert(depth >= 0);
|
assert(depth >= 0);
|
||||||
int depth_lasti = (depth<<1) | handler->b_preserve_lasti;
|
int depth_lasti = (depth<<1) | handler->b_preserve_lasti;
|
||||||
assemble_emit_exception_table_item(a, start, (1<<7));
|
assemble_emit_exception_table_item(a, start, (1<<7));
|
||||||
|
|
|
@ -84,11 +84,8 @@ _PyErr_GetTopmostException(PyThreadState *tstate)
|
||||||
while ((exc_info->exc_value == NULL || exc_info->exc_value == Py_None) &&
|
while ((exc_info->exc_value == NULL || exc_info->exc_value == Py_None) &&
|
||||||
exc_info->previous_item != NULL)
|
exc_info->previous_item != NULL)
|
||||||
{
|
{
|
||||||
assert(exc_info->exc_type == NULL || exc_info->exc_type == Py_None);
|
|
||||||
exc_info = exc_info->previous_item;
|
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;
|
return exc_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,27 +521,17 @@ PyErr_GetExcInfo(PyObject **p_type, PyObject **p_value, PyObject **p_traceback)
|
||||||
void
|
void
|
||||||
PyErr_SetExcInfo(PyObject *type, PyObject *value, PyObject *traceback)
|
PyErr_SetExcInfo(PyObject *type, PyObject *value, PyObject *traceback)
|
||||||
{
|
{
|
||||||
PyObject *oldtype, *oldvalue, *oldtraceback;
|
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
|
||||||
oldtype = tstate->exc_info->exc_type;
|
PyObject *oldvalue = tstate->exc_info->exc_value;
|
||||||
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_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 */
|
/* These args are no longer used, but we still need to steal a ref */
|
||||||
Py_XDECREF(type);
|
Py_XDECREF(type);
|
||||||
Py_XDECREF(traceback);
|
Py_XDECREF(traceback);
|
||||||
|
|
||||||
Py_XDECREF(oldtype);
|
|
||||||
Py_XDECREF(oldvalue);
|
Py_XDECREF(oldvalue);
|
||||||
Py_XDECREF(oldtraceback);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -629,9 +616,6 @@ _PyErr_ChainStackItem(_PyErr_StackItem *exc_info)
|
||||||
exc_info_given = 1;
|
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) {
|
if (exc_info->exc_value == NULL || exc_info->exc_value == Py_None) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1028,9 +1028,7 @@ PyThreadState_Clear(PyThreadState *tstate)
|
||||||
Py_CLEAR(tstate->curexc_value);
|
Py_CLEAR(tstate->curexc_value);
|
||||||
Py_CLEAR(tstate->curexc_traceback);
|
Py_CLEAR(tstate->curexc_traceback);
|
||||||
|
|
||||||
Py_CLEAR(tstate->exc_state.exc_type);
|
|
||||||
Py_CLEAR(tstate->exc_state.exc_value);
|
Py_CLEAR(tstate->exc_state.exc_value);
|
||||||
Py_CLEAR(tstate->exc_state.exc_traceback);
|
|
||||||
|
|
||||||
/* The stack of exception states should contain just this thread. */
|
/* The stack of exception states should contain just this thread. */
|
||||||
if (verbose && tstate->exc_info != &tstate->exc_state) {
|
if (verbose && tstate->exc_info != &tstate->exc_state) {
|
||||||
|
|
Loading…
Reference in New Issue