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

mwh at codespeak.net mwh at codespeak.net
Sat Jan 28 15:04:53 CET 2006


Author: mwh
Date: Sat Jan 28 15:04:51 2006
New Revision: 22786

Modified:
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/memory/test/test_gctransform.py
Log:
(cfbolz, mwh)
ever more tortuous code to get the gc operations around
exceptions to be correct.


Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Sat Jan 28 15:04:51 2006
@@ -1,5 +1,5 @@
 from pypy.rpython.lltypesystem import lltype
-from pypy.objspace.flow.model import SpaceOperation, Variable
+from pypy.objspace.flow.model import SpaceOperation, Variable, c_last_exception
 from pypy.translator.unsimplify import insert_empty_block
 from pypy.rpython import rmodel
 import sets
@@ -95,13 +95,26 @@
             # everything is fine already for returnblocks and exceptblocks
             pass
         else:
-            deadinallexits = sets.Set(livevars)
-            for link in block.exits:
-                deadinallexits.difference_update(sets.Set(link.args))
+            if block.exitswitch is c_last_exception:
+                # if we're in a try block, the last operation must
+                # remain the last operation, so don't add a pop_alive
+                # to the block, even if the variable dies in all
+                # linked blocks.
+                deadinallexits = sets.Set([])
+            else:
+                deadinallexits = sets.Set(livevars)
+                for link in block.exits:
+                    deadinallexits.difference_update(sets.Set(link.args))
             for var in deadinallexits:
                 newops.extend(self.pop_alive(var))
             for link in block.exits:
                 livecounts = dict.fromkeys(sets.Set(livevars) - deadinallexits, 1)
+                if (block.exitswitch is c_last_exception and link.exitcase is not None
+                    and livevars[-1] is block.operations[-1].result):
+                    # if the last operation in the block raised an
+                    # exception, it can't have returned anything that
+                    # might need pop_aliving.
+                    del livecounts[livevars[-1]]
                 for v in link.args:
                     if v in livecounts:
                         livecounts[v] -= 1

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	Sat Jan 28 15:04:51 2006
@@ -1,4 +1,5 @@
 from pypy.rpython.memory import gctransform
+from pypy.objspace.flow.model import c_last_exception
 from pypy.rpython.memory.gctransform import var_needsgc, var_ispyobj
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.lltypesystem import lltype
@@ -26,9 +27,15 @@
         # it's a block we inserted
         return
     for link in block.exits:
+        fudge = 0
+        if (block.exitswitch is c_last_exception and link.exitcase is not None
+            and var_needsgc(block.operations[-1].result)):
+            fudge = 1
         refs_out = len([v for v in link.args
                         if isinstance(v, Variable) and var_needsgc(v)])
-        assert refs_in + push_alives + calls == pop_alives + refs_out
+        if link.last_exception is not None and link.last_exception in link.args:
+            refs_out -= 1
+        assert refs_in + push_alives + calls - fudge == pop_alives + refs_out
     
 
 def rtype_and_transform(func, inputtypes, transformcls, specialize=True):
@@ -38,10 +45,10 @@
         t.buildrtyper().specialize(t)
     transformer = transformcls()
     transformer.transform(t.graphs)
+#    t.view()
     t.checkgraphs()
     for graph in t.graphs:
         for block in graph.iterblocks():
-            print graph, block, block.isstartblock
             checkblock(block)
     return t
 
@@ -192,3 +199,35 @@
             pop_count += 1
     assert push_count == 0 and pop_count == 1
     
+def test_except_block():
+    S = lltype.GcStruct("S", ('x', lltype.Signed))
+    def f(a, n):
+        if n == 0:
+            raise ValueError
+        a.x = 1
+        return a
+    def g(n):
+        a = lltype.malloc(S)
+        try:
+            return f(a, n).x
+        except ValueError:
+            return 0
+    t = rtype_and_transform(g, [int], gctransform.GCTransformer)
+
+def test_except_block2():
+    # the difference here is that f() returns Void, not a GcStruct
+    S = lltype.GcStruct("S", ('x', lltype.Signed))
+    def f(a, n):
+        if n == 0:
+            raise ValueError
+        a.x = 1
+    def g(n):
+        a = lltype.malloc(S)
+        try:
+            f(a, n)
+            return a.x
+        except ValueError:
+            return 0
+    t = rtype_and_transform(g, [int], gctransform.GCTransformer)
+    
+    



More information about the Pypy-commit mailing list