diff options
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/compiler/pyassem.py | 3 | ||||
-rw-r--r-- | Lib/compiler/pycodegen.py | 47 | ||||
-rw-r--r-- | Lib/opcode.py | 8 | ||||
-rw-r--r-- | Lib/test/test_dis.py | 36 | ||||
-rw-r--r-- | Lib/test/test_peepholer.py | 11 |
5 files changed, 42 insertions, 63 deletions
diff --git a/Lib/compiler/pyassem.py b/Lib/compiler/pyassem.py index 5098f2c..be0255d 100644 --- a/Lib/compiler/pyassem.py +++ b/Lib/compiler/pyassem.py @@ -122,6 +122,9 @@ def order_blocks(start_block, exit_block): for b in remaining: if __debug__ and b.next: assert b is b.next[0].prev[0], (b, b.next) + # Make sure every block appears in dominators, even if no + # other block must precede it. + dominators.setdefault(b, set()) # preceeding blocks dominate following blocks for c in b.get_followers(): while 1: diff --git a/Lib/compiler/pycodegen.py b/Lib/compiler/pycodegen.py index 6d5a41c..81234d1 100644 --- a/Lib/compiler/pycodegen.py +++ b/Lib/compiler/pycodegen.py @@ -421,13 +421,11 @@ class CodeGenerator: self.set_lineno(test) self.visit(test) nextTest = self.newBlock() - self.emit('JUMP_IF_FALSE', nextTest) + self.emit('POP_JUMP_IF_FALSE', nextTest) self.nextBlock() - self.emit('POP_TOP') self.visit(suite) self.emit('JUMP_FORWARD', end) self.startBlock(nextTest) - self.emit('POP_TOP') if node.else_: self.visit(node.else_) self.nextBlock(end) @@ -446,15 +444,13 @@ class CodeGenerator: self.set_lineno(node, force=True) self.visit(node.test) - self.emit('JUMP_IF_FALSE', else_ or after) + self.emit('POP_JUMP_IF_FALSE', else_ or after) self.nextBlock() - self.emit('POP_TOP') self.visit(node.body) self.emit('JUMP_ABSOLUTE', loop) self.startBlock(else_) # or just the POPs if not else clause - self.emit('POP_TOP') self.emit('POP_BLOCK') self.setups.pop() if node.else_: @@ -525,26 +521,23 @@ class CodeGenerator: self.visit(child) self.emit(jump, end) self.nextBlock() - self.emit('POP_TOP') self.visit(node.nodes[-1]) self.nextBlock(end) def visitAnd(self, node): - self.visitTest(node, 'JUMP_IF_FALSE') + self.visitTest(node, 'JUMP_IF_FALSE_OR_POP') def visitOr(self, node): - self.visitTest(node, 'JUMP_IF_TRUE') + self.visitTest(node, 'JUMP_IF_TRUE_OR_POP') def visitIfExp(self, node): endblock = self.newBlock() elseblock = self.newBlock() self.visit(node.test) - self.emit('JUMP_IF_FALSE', elseblock) - self.emit('POP_TOP') + self.emit('POP_JUMP_IF_FALSE', elseblock) self.visit(node.then) self.emit('JUMP_FORWARD', endblock) self.nextBlock(elseblock) - self.emit('POP_TOP') self.visit(node.else_) self.nextBlock(endblock) @@ -556,9 +549,8 @@ class CodeGenerator: self.emit('DUP_TOP') self.emit('ROT_THREE') self.emit('COMPARE_OP', op) - self.emit('JUMP_IF_FALSE', cleanup) + self.emit('JUMP_IF_FALSE_OR_POP', cleanup) self.nextBlock() - self.emit('POP_TOP') # now do the last comparison if node.ops: op, code = node.ops[-1] @@ -593,11 +585,7 @@ class CodeGenerator: for start, cont, anchor in stack: if cont: - skip_one = self.newBlock() - self.emit('JUMP_FORWARD', skip_one) - self.startBlock(cont) - self.emit('POP_TOP') - self.nextBlock(skip_one) + self.nextBlock(cont) self.emit('JUMP_ABSOLUTE', start) self.startBlock(anchor) @@ -617,9 +605,8 @@ class CodeGenerator: def visitListCompIf(self, node, branch): self.set_lineno(node, force=True) self.visit(node.test) - self.emit('JUMP_IF_FALSE', branch) + self.emit('POP_JUMP_IF_FALSE', branch) self.newBlock() - self.emit('POP_TOP') def _makeClosure(self, gen, args): frees = gen.scope.get_free_vars() @@ -665,11 +652,7 @@ class CodeGenerator: for start, cont, anchor, end in stack: if cont: - skip_one = self.newBlock() - self.emit('JUMP_FORWARD', skip_one) - self.startBlock(cont) - self.emit('POP_TOP') - self.nextBlock(skip_one) + self.nextBlock(cont) self.emit('JUMP_ABSOLUTE', start) self.startBlock(anchor) self.emit('POP_BLOCK') @@ -702,9 +685,8 @@ class CodeGenerator: def visitGenExprIf(self, node, branch): self.set_lineno(node, force=True) self.visit(node.test) - self.emit('JUMP_IF_FALSE', branch) + self.emit('POP_JUMP_IF_FALSE', branch) self.newBlock() - self.emit('POP_TOP') # exception related @@ -719,9 +701,8 @@ class CodeGenerator: # is a sort of renaming op. self.nextBlock() self.visit(node.test) - self.emit('JUMP_IF_TRUE', end) + self.emit('POP_JUMP_IF_TRUE', end) self.nextBlock() - self.emit('POP_TOP') self.emit('LOAD_GLOBAL', 'AssertionError') if node.fail: self.visit(node.fail) @@ -729,7 +710,6 @@ class CodeGenerator: else: self.emit('RAISE_VARARGS', 1) self.nextBlock(end) - self.emit('POP_TOP') def visitRaise(self, node): self.set_lineno(node) @@ -772,9 +752,8 @@ class CodeGenerator: self.visit(expr) self.emit('COMPARE_OP', 'exception match') next = self.newBlock() - self.emit('JUMP_IF_FALSE', next) + self.emit('POP_JUMP_IF_FALSE', next) self.nextBlock() - self.emit('POP_TOP') self.emit('POP_TOP') if target: self.visit(target) @@ -787,8 +766,6 @@ class CodeGenerator: self.nextBlock(next) else: self.nextBlock() - if expr: # XXX - self.emit('POP_TOP') self.emit('END_FINALLY') if node.else_: self.nextBlock(lElse) diff --git a/Lib/opcode.py b/Lib/opcode.py index d41383b..24d5dcc 100644 --- a/Lib/opcode.py +++ b/Lib/opcode.py @@ -146,9 +146,11 @@ name_op('IMPORT_NAME', 107) # Index in name list name_op('IMPORT_FROM', 108) # Index in name list jrel_op('JUMP_FORWARD', 110) # Number of bytes to skip -jrel_op('JUMP_IF_FALSE', 111) # "" -jrel_op('JUMP_IF_TRUE', 112) # "" -jabs_op('JUMP_ABSOLUTE', 113) # Target byte offset from beginning of code +jabs_op('JUMP_IF_FALSE_OR_POP', 111) # Target byte offset from beginning of code +jabs_op('JUMP_IF_TRUE_OR_POP', 112) # "" +jabs_op('JUMP_ABSOLUTE', 113) # "" +jabs_op('POP_JUMP_IF_FALSE', 114) # "" +jabs_op('POP_JUMP_IF_TRUE', 115) # "" name_op('LOAD_GLOBAL', 116) # Index in name list diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py index 6fa437b..613d30a 100644 --- a/Lib/test/test_dis.py +++ b/Lib/test/test_dis.py @@ -54,25 +54,23 @@ def bug1333982(x=[]): dis_bug1333982 = """\ %-4d 0 LOAD_CONST 1 (0) - 3 JUMP_IF_TRUE 33 (to 39) - 6 POP_TOP - 7 LOAD_GLOBAL 0 (AssertionError) - 10 BUILD_LIST 0 - 13 LOAD_FAST 0 (x) - 16 GET_ITER - >> 17 FOR_ITER 12 (to 32) - 20 STORE_FAST 1 (s) - 23 LOAD_FAST 1 (s) - 26 LIST_APPEND 2 - 29 JUMP_ABSOLUTE 17 - - %-4d >> 32 LOAD_CONST 2 (1) - 35 BINARY_ADD - 36 RAISE_VARARGS 2 - >> 39 POP_TOP - - %-4d 40 LOAD_CONST 0 (None) - 43 RETURN_VALUE + 3 POP_JUMP_IF_TRUE 38 + 6 LOAD_GLOBAL 0 (AssertionError) + 9 BUILD_LIST 0 + 12 LOAD_FAST 0 (x) + 15 GET_ITER + >> 16 FOR_ITER 12 (to 31) + 19 STORE_FAST 1 (s) + 22 LOAD_FAST 1 (s) + 25 LIST_APPEND 2 + 28 JUMP_ABSOLUTE 16 + + %-4d >> 31 LOAD_CONST 2 (1) + 34 BINARY_ADD + 35 RAISE_VARARGS 2 + + %-4d >> 38 LOAD_CONST 0 (None) + 41 RETURN_VALUE """%(bug1333982.func_code.co_firstlineno + 1, bug1333982.func_code.co_firstlineno + 2, bug1333982.func_code.co_firstlineno + 3) diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index c547984..6638a5a 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -19,15 +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'): - self.assert_(elem in asm) + self.assert_('POP_JUMP_IF_TRUE' in asm) def test_elim_inversion_of_is_or_in(self): for line, elem in ( @@ -56,13 +55,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) |