Message185950
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. |
|
Date |
User |
Action |
Args |
2013-04-03 20:25:54 | Mark.Shannon | set | recipients:
+ Mark.Shannon, rhettinger, pitrou, skrah |
2013-04-03 20:25:54 | Mark.Shannon | set | messageid: <1365020754.91.0.312023351881.issue17611@psf.upfronthosting.co.za> |
2013-04-03 20:25:54 | Mark.Shannon | link | issue17611 messages |
2013-04-03 20:25:54 | Mark.Shannon | create | |
|