[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