diff options
author | Jeffrey Yasskin <jyasskin@gmail.com> | 2009-02-25 02:25:04 (GMT) |
---|---|---|
committer | Jeffrey Yasskin <jyasskin@gmail.com> | 2009-02-25 02:25:04 (GMT) |
commit | 9de7ec7868554e92700e4bda6c5f9d8fcad634dc (patch) | |
tree | ce9c4c821286769b6057d94ea20e337ea726f60f /Lib/test | |
parent | 0a68b01d649168f096fddd3cd8d433f2b8b6bb9e (diff) | |
download | cpython-9de7ec7868554e92700e4bda6c5f9d8fcad634dc.zip cpython-9de7ec7868554e92700e4bda6c5f9d8fcad634dc.tar.gz cpython-9de7ec7868554e92700e4bda6c5f9d8fcad634dc.tar.bz2 |
http://bugs.python.org/issue4715
This patch by Antoine Pitrou optimizes the bytecode for conditional branches by
merging the following "POP_TOP" instruction into the conditional jump. For
example, the list comprehension "[x for x in l if not x]" produced the
following bytecode:
1 0 BUILD_LIST 0
3 LOAD_FAST 0 (.0)
>> 6 FOR_ITER 23 (to 32)
9 STORE_FAST 1 (x)
12 LOAD_FAST 1 (x)
15 JUMP_IF_TRUE 10 (to 28)
18 POP_TOP
19 LOAD_FAST 1 (x)
22 LIST_APPEND 2
25 JUMP_ABSOLUTE 6
>> 28 POP_TOP
29 JUMP_ABSOLUTE 6
>> 32 RETURN_VALUE
but after the patch it produces the following bytecode:
1 0 BUILD_LIST 0
3 LOAD_FAST 0 (.0)
>> 6 FOR_ITER 18 (to 27)
9 STORE_FAST 1 (x)
12 LOAD_FAST 1 (x)
15 POP_JUMP_IF_TRUE 6
18 LOAD_FAST 1 (x)
21 LIST_APPEND 2
24 JUMP_ABSOLUTE 6
>> 27 RETURN_VALUE
Notice that not only the code is shorter, but the conditional jump
(POP_JUMP_IF_TRUE) jumps right to the start of the loop instead of going through
the JUMP_ABSOLUTE at the end. "continue" statements are helped
similarly.
Furthermore, the old jump opcodes (JUMP_IF_FALSE, JUMP_IF_TRUE) have been
replaced by two new opcodes:
- JUMP_IF_TRUE_OR_POP, which jumps if true and pops otherwise
- JUMP_IF_FALSE_OR_POP, which jumps if false and pops otherwise
Diffstat (limited to 'Lib/test')
-rw-r--r-- | Lib/test/test_peepholer.py | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index f3e240e..1543f3b 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -19,14 +19,14 @@ def dis_single(line): class TestTranforms(unittest.TestCase): def test_unot(self): - # UNARY_NOT JUMP_IF_FALSE POP_TOP --> JUMP_IF_TRUE POP_TOP' + # UNARY_NOT POP_JUMP_IF_FALSE --> POP_JUMP_IF_TRUE' def unot(x): if not x == 2: del x asm = disassemble(unot) - for elem in ('UNARY_NOT', 'JUMP_IF_FALSE'): + for elem in ('UNARY_NOT', 'POP_JUMP_IF_FALSE'): self.assert_(elem not in asm) - for elem in ('JUMP_IF_TRUE', 'POP_TOP'): + for elem in ('POP_JUMP_IF_TRUE',): self.assert_(elem in asm) def test_elim_inversion_of_is_or_in(self): @@ -64,13 +64,13 @@ class TestTranforms(unittest.TestCase): self.assert_('LOAD_GLOBAL' not in disassemble(f)) def test_while_one(self): - # Skip over: LOAD_CONST trueconst JUMP_IF_FALSE xx POP_TOP + # Skip over: LOAD_CONST trueconst POP_JUMP_IF_FALSE xx def f(): while 1: pass return list asm = disassemble(f) - for elem in ('LOAD_CONST', 'JUMP_IF_FALSE'): + for elem in ('LOAD_CONST', 'POP_JUMP_IF_FALSE'): self.assert_(elem not in asm) for elem in ('JUMP_ABSOLUTE',): self.assert_(elem in asm) |