bpo-40222: "Zero cost" exception handling (GH-25729)

"Zero cost" exception handling.

* Uses a lookup table to determine how to handle exceptions.
* Removes SETUP_FINALLY and POP_TOP block instructions, eliminating (most of) the runtime overhead of try statements.
* Reduces the size of the frame object by about 60%.
This commit is contained in:
Mark Shannon 2021-05-07 15:19:19 +01:00 committed by GitHub
parent b32c8e9795
commit adcd220556
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 6614 additions and 5687 deletions

View file

@ -616,13 +616,6 @@ the original TOS1.
.. versionadded:: 3.5
.. opcode:: SETUP_ASYNC_WITH
Creates a new frame object.
.. versionadded:: 3.5
**Miscellaneous opcodes**
@ -692,28 +685,29 @@ iterations of the loop.
opcode implements ``from module import *``.
.. opcode:: POP_BLOCK
Removes one block from the block stack. Per frame, there is a stack of
blocks, denoting :keyword:`try` statements, and such.
.. opcode:: POP_EXCEPT
Removes one block from the block stack. The popped block must be an exception
handler block, as implicitly created when entering an except handler. In
addition to popping extraneous values from the frame stack, the last three
popped values are used to restore the exception state.
Pops three values from the stack, which are used to restore the exception state.
.. opcode:: RERAISE
Re-raises the exception currently on top of the stack. If oparg is non-zero,
restores ``f_lasti`` of the current frame to its value when the exception was raised.
pops an additional value from the stack which is used to set ``f_lasti``
of the current frame.
.. versionadded:: 3.9
.. 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.
Used in exception handlers.
.. versionadded:: 3.11
.. opcode:: WITH_EXCEPT_START
Calls the function in position 7 on the stack with the top three
@ -724,6 +718,17 @@ iterations of the loop.
.. versionadded:: 3.9
.. opcode:: POP_EXCEPT_AND_RERAISE
Pops the exception currently on top of the stack. Pops the integer value on top
of the stack and sets the ``f_lasti`` attribute of the frame with that value.
Then pops the next exception from the stack uses it to restore the current exception.
Finally it re-raises the originally popped exception.
Used in excpetion handler cleanup.
.. versionadded:: 3.11
.. opcode:: LOAD_ASSERTION_ERROR
Pushes :exc:`AssertionError` onto the stack. Used by the :keyword:`assert`
@ -738,18 +743,15 @@ iterations of the loop.
by :opcode:`CALL_FUNCTION` to construct a class.
.. opcode:: SETUP_WITH (delta)
.. opcode:: BEFORE_WITH (delta)
This opcode performs several operations before a with block starts. First,
it loads :meth:`~object.__exit__` from the context manager and pushes it onto
the stack for later use by :opcode:`WITH_EXCEPT_START`. Then,
:meth:`~object.__enter__` is called, and a finally block pointing to *delta*
is pushed. Finally, the result of calling the ``__enter__()`` method is pushed onto
the stack. The next opcode will either ignore it (:opcode:`POP_TOP`), or
store it in (a) variable(s) (:opcode:`STORE_FAST`, :opcode:`STORE_NAME`, or
:opcode:`UNPACK_SEQUENCE`).
:meth:`~object.__enter__` is called. Finally, the result of calling the
``__enter__()`` method is pushed onto the stack.
.. versionadded:: 3.2
.. versionadded:: 3.11
.. opcode:: COPY_DICT_WITHOUT_KEYS
@ -1039,12 +1041,6 @@ All of the following opcodes use their arguments.
Loads the global named ``co_names[namei]`` onto the stack.
.. opcode:: SETUP_FINALLY (delta)
Pushes a try block from a try-finally or try-except clause onto the block
stack. *delta* points to the finally block or the first except block.
.. opcode:: LOAD_FAST (var_num)
Pushes a reference to the local ``co_varnames[var_num]`` onto the stack.