[pypy-svn] r22746 - in pypy/dist/pypy/rpython/memory: . test

mwh at codespeak.net mwh at codespeak.net
Fri Jan 27 17:38:52 CET 2006


Author: mwh
Date: Fri Jan 27 17:38:50 2006
New Revision: 22746

Modified:
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/memory/test/test_gctransform.py
Log:
(cfbolz,mwh)
Fix logic for what to do with variables passed across links in the case that
more than one variable is passed.
Add a general consistency check that would have caught this and apply it to
every block of every graph that gets transformed.


Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Fri Jan 27 17:38:50 2006
@@ -37,11 +37,18 @@
         self.links_to_split = {} # link -> vars to pop_alive across the link
         for block in graph.iterblocks():
             self.transform_block(block)
-        for link, vars in self.links_to_split.iteritems():
+        for link, livecounts in self.links_to_split.iteritems():
             newops = []
-            for var in vars:
-                newops.extend(self.pop_alive(var))
-            insert_empty_block(None, link, newops)
+            for var, livecount in livecounts.iteritems():
+                for i in range(livecount):
+                    newops.extend(self.pop_alive(var))
+                for i in range(-livecount):
+                    newops.extend(self.push_alive(var))
+            if newops:
+                if len(link.prevblock.exits) == 1:
+                    link.prevblock.operations.extend(newops)
+                else:
+                    insert_empty_block(None, link, newops)
 
     def transform_block(self, block):
         newops = []
@@ -60,10 +67,6 @@
         if len(block.exits) == 0:
             # everything is fine already for returnblocks and exceptblocks
             pass
-        elif len(block.exits) == 1:
-            for var in livevars:
-                if var not in block.exits[0].args:
-                    newops.extend(self.pop_alive(var))
         else:
             deadinallexits = sets.Set(livevars)
             for link in block.exits:
@@ -71,9 +74,11 @@
             for var in deadinallexits:
                 newops.extend(self.pop_alive(var))
             for link in block.exits:
-                deadvarsforlink = sets.Set(livevars) - deadinallexits - sets.Set(link.args)
-                if deadvarsforlink:
-                    self.links_to_split[link] = deadvarsforlink
+                livecounts = dict.fromkeys(sets.Set(livevars) - deadinallexits, 1)
+                for v in link.args:
+                    if v in livecounts:
+                        livecounts[v] -= 1
+                self.links_to_split[link] = livecounts
         if newops:
             block.operations = newops
 

Modified: pypy/dist/pypy/rpython/memory/test/test_gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_gctransform.py	Fri Jan 27 17:38:50 2006
@@ -1,6 +1,25 @@
 from pypy.rpython.memory import gctransform
+from pypy.rpython.memory.gctransform import var_needsgc
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.lltypesystem import lltype
+from pypy.objspace.flow.model import Variable
+
+def checkblock(block):
+    vars_in = len([v for v in block.inputargs if var_needsgc(v)])
+    push_alives = len([op for op in block.operations
+                       if op.opname.startswith('gc_push_alive')])
+    pop_alives = len([op for op in block.operations
+                      if op.opname.startswith('gc_pop_alive')])
+    calls = len([op for op in block.operations
+                 if 'direct_call' in op.opname and var_needsgc(op.result)])
+    if pop_alives == len(block.operations):
+        # it's a block we inserted
+        return
+    for link in block.exits:
+        vars_out = len([v for v in link.args
+                        if isinstance(v, Variable) and var_needsgc(v)])
+        assert vars_in + push_alives + calls == pop_alives + vars_out
+    
 
 def rtype_and_transform(func, inputtypes, transformcls):
     t = TranslationContext()
@@ -9,6 +28,9 @@
     transformer = transformcls(t.graphs)
     transformer.transform()
     t.checkgraphs()
+    for graph in t.graphs:
+        for block in graph.iterblocks():
+            checkblock(block)
     return t
 
 def test_simple():
@@ -105,6 +127,21 @@
     assert direct_calls[1].args[1].value[0].args[0] == direct_calls[0].result
     assert [op.args[0] for op in direct_calls[2].args[1].value] == [direct_calls[0].result, direct_calls[1].result]
 
+def test_multiply_passed_var():
+    S = lltype.GcStruct("S", ('x', lltype.Signed))
+    def f(x):
+        if x:
+            a = lltype.malloc(S)
+            a.x = 1
+            b = a
+        else:
+            a = lltype.malloc(S)
+            a.x = 1
+            b = lltype.malloc(S)
+            b.x = 2
+        return a.x + b.x
+    t = rtype_and_transform(f, [int], gctransform.GCTransformer)
+
 def test_pyobj():
     def f(x):
         if x:



More information about the Pypy-commit mailing list