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 <rep...@bugs.python.org> <http://bugs.python.org/issue17611> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com