[issue17611] Move unwinding of stack for "pseudo exceptions" from interpreter to compiler.

Mark Shannon report at bugs.python.org
Wed Apr 3 22:25:54 CEST 2013


Mark Shannon added the comment:

Antoine,
Two bytecode examples.


For the following function:
>>> def f(x):
...     try:
...         return x
...     except:
...         pass

Without the patch:
  2           0 SETUP_EXCEPT             8 (to 11) 

  3           3 LOAD_FAST                0 (x) 
              6 RETURN_VALUE         
              7 POP_BLOCK            
              8 JUMP_FORWARD             8 (to 19) 

  4     >>   11 POP_TOP              
             12 POP_TOP              
             13 POP_TOP              

  5          14 POP_EXCEPT           
             15 JUMP_FORWARD             1 (to 19) 
             18 END_FINALLY          
        >>   19 LOAD_CONST               0 (None) 
             22 RETURN_VALUE         

With the patch:
  2           0 SETUP_EXCEPT             9 (to 12) 

  3           3 LOAD_FAST                0 (x) 
              6 POP_BLOCK            
              7 RETURN_VALUE         
              8 POP_BLOCK            
              9 JUMP_FORWARD             8 (to 20) 

  4     >>   12 POP_TOP              
             13 POP_TOP              
             14 POP_TOP              

  5          15 POP_EXCEPT           
             16 JUMP_FORWARD             1 (to 20) 
             19 RERAISE              
        >>   20 LOAD_CONST               0 (None) 
             23 RETURN_VALUE         

The difference is the 'POP_BLOCK' inserted at offset 7 *before* the 'RETURN_VALUE', so that the RETURN_VALUE bytecode does not have to do any unwinding of the block stack.

For loops the SETUP_LOOP and the matching POP_BLOCK are eliminated:

>>> def f(x):
...    for y in x:
...        g(x)

Without the patch:
  2           0 SETUP_LOOP              24 (to 27) 
              3 LOAD_FAST                0 (x) 
              6 GET_ITER             
        >>    7 FOR_ITER                16 (to 26) 
             10 STORE_FAST               1 (y) 

  3          13 LOAD_GLOBAL              0 (g) 
             16 LOAD_FAST                1 (y) 
             19 CALL_FUNCTION            1 (1 positional, 0 keyword pair) 
             22 POP_TOP              
             23 JUMP_ABSOLUTE            7 
        >>   26 POP_BLOCK            
        >>   27 LOAD_CONST               0 (None) 
             30 RETURN_VALUE         

With the patch:
  2           0 LOAD_FAST                0 (x) 
              3 GET_ITER             
        >>    4 FOR_ITER                16 (to 23) 
              7 STORE_FAST               1 (y) 

  3          10 LOAD_GLOBAL              0 (g) 
             13 LOAD_FAST                0 (x) 
             16 CALL_FUNCTION            1 (1 positional, 0 keyword pair) 
             19 POP_TOP              
             20 END_ITER                 4 
        >>   23 LOAD_CONST               0 (None) 
             26 RETURN_VALUE        

END_ITER is a synonym for JUMP_ABSOLUTE. It is needed so that frame.set_lineno() can identify loop blocks.

----------

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue17611>
_______________________________________


More information about the Python-bugs-list mailing list