bpo-32949: Better bytecodes for "with" statement. by markshannon · Pull Request #5112 · python/cpython

This PR cleans up the interpreter by generating two different code paths for exiting a with statement. One for normal exits and another for the exceptional case.

For this function:

The bytecode generated changes from:

 2           0 LOAD_GLOBAL              0 (a)
             2 SETUP_WITH              10 (to 14)
             4 POP_TOP

 3           6 LOAD_GLOBAL              1 (b)
             8 POP_TOP
             10 POP_BLOCK
             12 BEGIN_FINALLY
        >>   14 WITH_CLEANUP_START
             16 WITH_CLEANUP_FINISH
             18 END_FINALLY
             20 LOAD_CONST               0 (None)
             22 RETURN_VALUE

to

 2           0 LOAD_GLOBAL              0 (a)
             2 SETUP_WITH    20 (to 24)
             4 POP_TOP
 3           6 LOAD_GLOBAL              1 (b)
              8 POP_TOP
             10 POP_BLOCK
             12 LOAD_CONST               0 (None)
             14 DUP_TOP
             16 DUP_TOP
             18 CALL_FUNCTION            3
             20 POP_TOP
             22 JUMP_FORWARD            16 (to 40)
        >>   24 WITH_EXCEPT_START
             26 POP_JUMP_IF_TRUE        30
             28 RERAISE
        >>   30 POP_TOP
             32 POP_TOP
             34 POP_TOP
             36 POP_EXCEPT
             38 POP_TOP
        >>   40 LOAD_CONST               0 (None)
             42 RETURN_VALUE

Although this superficially appears worse, consider the non-exceptional path, after the POP_BLOCK bytecode.
before:

             12 BEGIN_FINALLY
        >>   14 WITH_CLEANUP_START
             16 WITH_CLEANUP_FINISH
             18 END_FINALLY

after:

             12 LOAD_CONST               0 (None)
             14 DUP_TOP
             16 DUP_TOP
             18 CALL_FUNCTION            3
             20 POP_TOP
             22 JUMP_FORWARD            16 (to 40)

we have replaced several complex and inefficient bytecodes with a few more simpler and faster bytecodes.

https://bugs.python.org/issue32949