[pypy-svn] r9675 - in pypy/dist/pypy/objspace/flow: . test

arigo at codespeak.net arigo at codespeak.net
Sun Mar 6 19:31:35 CET 2005


Author: arigo
Date: Sun Mar  6 19:31:35 2005
New Revision: 9675

Modified:
   pypy/dist/pypy/objspace/flow/flowcontext.py
   pypy/dist/pypy/objspace/flow/test/test_model.py
   pypy/dist/pypy/objspace/flow/test/test_objspace.py
Log:
Removed a case where the flow objspace would repeat some operations: near the
beginning of the function.

Cleaned up the tests, which were too precise about the shape and generally not
precise enough about what's really in the graph.



Modified: pypy/dist/pypy/objspace/flow/flowcontext.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/flowcontext.py	(original)
+++ pypy/dist/pypy/objspace/flow/flowcontext.py	Sun Mar  6 19:31:35 2005
@@ -71,32 +71,33 @@
         self.crnt_block = block
         # saved state at the join point most recently seen
         self.last_join_point = None
-        self.progress = False
+        self.enterspamblock = isinstance(block, SpamBlock)
 
     def append(self, operation):
         if self.last_join_point is not None:
-            # don't add more operations if we already crossed a join point
+            # only add operations corresponding to the first bytecode
             raise MergeBlock(self.crnt_block, self.last_join_point)
         self.crnt_block.operations.append(operation)
 
     def bytecode_trace(self, ec, frame):
         assert frame is ec.crnt_frame, "seeing an unexpected frame!"
-        next_instr = frame.next_instr
-        if self.crnt_block.operations or isinstance(self.crnt_block, EggBlock):
-            # if we have already produced at least one operation or a branch,
-            # make a join point as early as possible (but not before we
-            # actually try to generate more operations)
-            self.last_join_point = FrameState(frame)
-        else:
-            ec.crnt_offset = next_instr # save offset for opcode
+        ec.crnt_offset = frame.next_instr      # save offset for opcode
+        if self.enterspamblock:
+            # If we have a SpamBlock, the first call to bytecode_trace()
+            # occurs as soon as frame.resume() starts, before interpretation
+            # really begins.
             varnames = frame.code.getvarnames()
             for name, w_value in zip(varnames, frame.getfastscope()):
                 if isinstance(w_value, Variable):
                     w_value.rename(name)
-            # record passage over already-existing join points
-            if self.progress and next_instr in ec.joinpoints:
-                self.last_join_point = FrameState(frame)
-        self.progress = True
+            self.enterspamblock = False
+        else:
+            # At this point, we progress to the next bytecode.  When this
+            # occurs, we no longer allow any more operations to be recorded in
+            # the same block.  We will continue, to figure out where the next
+            # such operation *would* appear, and we make a join point just
+            # before.
+            self.last_join_point = FrameState(frame)
 
     def guessbool(self, ec, w_condition, cases=[False,True],
                   replace_last_variable_except_in_first_case = None):
@@ -259,14 +260,27 @@
         # EggBlocks reuse the variables of their previous block,
         # which is deemed not acceptable for simplicity of the operations
         # that will be performed later on the flow graph.
-        def fixegg(node):
-            if isinstance(node, EggBlock):
-                mapping = {}
-                for a in node.inputargs:
-                    mapping[a] = Variable(a)
-                node.renamevariables(mapping)
-            elif isinstance(node, SpamBlock):
-                del node.framestate     # memory saver
+        def fixegg(link):
+            if isinstance(link, Link):
+                block = link.target
+                if isinstance(block, EggBlock):
+                    if (not block.operations and len(block.exits) == 1 and
+                        link.args == block.inputargs):   # not renamed
+                        # if the variables are not renamed across this link
+                        # (common case for EggBlocks) then it's easy enough to
+                        # get rid of the empty EggBlock.
+                        link2 = block.exits[0]
+                        link.args = list(link2.args)
+                        link.target = link2.target
+                        assert link2.exitcase is None
+                        fixegg(link)
+                    else:
+                        mapping = {}
+                        for a in block.inputargs:
+                            mapping[a] = Variable(a)
+                        block.renamevariables(mapping)
+            elif isinstance(link, SpamBlock):
+                del link.framestate     # memory saver
         traverse(fixegg, self.graph)
 
     def mergeblock(self, currentblock, currentstate):

Modified: pypy/dist/pypy/objspace/flow/test/test_model.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/test/test_model.py	(original)
+++ pypy/dist/pypy/objspace/flow/test/test_model.py	Sun Mar  6 19:31:35 2005
@@ -24,9 +24,7 @@
 
     def test_simplefunc(self):
         graph = self.getflow(self.simplefunc)
-        l = flatten(graph)
-        #print l
-        assert len(l) == 4
+        assert all_operations(graph) == {'add': 1}
 
     def test_class(self):
         graph = self.getflow(self.simplefunc)
@@ -45,32 +43,32 @@
 
         v = MyVisitor()
         traverse(v, graph)
-        assert len(v.blocks) == 2
-        assert len(v.links) == 1
+        #assert len(v.blocks) == 2
+        #assert len(v.links) == 1
         assert v.graph == graph
         assert v.links[0] == graph.startblock.exits[0]
 
-    def test_partial_class(self):
-        graph = self.getflow(self.simplefunc)
+##    def test_partial_class(self):
+##        graph = self.getflow(self.simplefunc)
 
-        class MyVisitor:
-            def __init__(self):
-                self.blocks = []
-                self.links = []
-
-            def visit_FunctionGraph(self, graph):
-                self.graph = graph
-            def visit_Block(self, block):
-                self.blocks.append(block)
-            def visit(self, link):
-                self.links.append(link)
-
-        v = MyVisitor()
-        traverse(v, graph)
-        assert len(v.blocks) == 2
-        assert len(v.links) == 1
-        assert v.graph == graph
-        assert v.links[0] == graph.startblock.exits[0]
+##        class MyVisitor:
+##            def __init__(self):
+##                self.blocks = []
+##                self.links = []
+
+##            def visit_FunctionGraph(self, graph):
+##                self.graph = graph
+##            def visit_Block(self, block):
+##                self.blocks.append(block)
+##            def visit(self, link):
+##                self.links.append(link)
+
+##        v = MyVisitor()
+##        traverse(v, graph)
+##        assert len(v.blocks) == 2
+##        assert len(v.links) == 1
+##        assert v.graph == graph
+##        assert v.links[0] == graph.startblock.exits[0]
 
     def loop(x):
         x = abs(x)
@@ -78,6 +76,18 @@
             x = x - 1
 
     def test_loop(self):
-        graph = self.getflow(self.simplefunc)
-        l = flatten(graph)
-        assert len(l) == 4
+        graph = self.getflow(self.loop)
+        assert all_operations(graph) == {'simple_call': 1,
+                                         'is_true': 1,
+                                         'sub': 1}
+
+
+def all_operations(graph):
+    result = {}
+    def visit(node):
+        if isinstance(node, Block):
+            for op in node.operations:
+                result.setdefault(op.opname, 0)
+                result[op.opname] += 1
+    traverse(visit, graph)
+    return result

Modified: pypy/dist/pypy/objspace/flow/test/test_objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/test/test_objspace.py	(original)
+++ pypy/dist/pypy/objspace/flow/test/test_objspace.py	Sun Mar  6 19:31:35 2005
@@ -1,6 +1,7 @@
 import autopath
 from pypy.objspace.flow.model import Constant, Block, traverse
 from pypy.interpreter.argument import Arguments
+from pypy.translator.simplify import simplify_graph
 
 
 objspacename = 'flow'
@@ -256,6 +257,7 @@
     def test_raise3(self):
         x = self.codetest(self.raise3)
         self.show(x)
+        simplify_graph(x)
         assert len(x.startblock.operations) == 1
         assert x.startblock.operations[0].opname == 'simple_call'
         assert list(x.startblock.operations[0].args) == [



More information about the Pypy-commit mailing list