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

cfbolz at codespeak.net cfbolz at codespeak.net
Sat Feb 4 00:54:00 CET 2006


Author: cfbolz
Date: Sat Feb  4 00:53:58 2006
New Revision: 23013

Modified:
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/memory/test/test_gctransform.py
Log:
 * add a test for the deallocator graph that involves an array
 * implemented the write barriers for setfield and setarrayitem


Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Sat Feb  4 00:53:58 2006
@@ -83,6 +83,7 @@
         livevars = [var for var in block.inputargs if var_needsgc(var)]
         for op in block.operations:
             newops.extend(self.replacement_operations(op))
+            # XXX for now we assume that everything can raise
             if 1 or op.opname in EXCEPTION_RAISING_OPS:
                 cleanup_on_exception = []
                 for var in livevars:
@@ -137,6 +138,31 @@
         else:
             return [op]
 
+    def replace_setfield(self, op):
+        if not var_needsgc(op.args[2]):
+            return [op]
+        oldval = Variable()
+        oldval.concretetype = op.args[2].concretetype
+        getoldvalop = SpaceOperation("getfield", [op.args[0], op.args[1]], oldval)
+        result = [getoldvalop]
+        result.extend(self.pop_alive(oldval))
+        result.extend(self.push_alive(op.args[2]))
+        result.append(op)
+        return result
+
+    def replace_setarrayitem(self, op):
+        if not var_needsgc(op.args[2]):
+            return [op]
+        oldval = Variable()
+        oldval.concretetype = op.args[2].concretetype
+        getoldvalop = SpaceOperation("getarrayitem",
+                                     [op.args[0], op.args[1]], oldval)
+        result = [getoldvalop]
+        result.extend(self.pop_alive(oldval))
+        result.extend(self.push_alive(op.args[2]))
+        result.append(op)
+        return result
+
     def push_alive(self, var):
         if var_ispyobj(var):
             return self.push_alive_pyobj(var)

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 Feb  4 00:53:58 2006
@@ -39,6 +39,13 @@
         if block.exitswitch is c_last_exception and link.exitcase is not None:
             assert link.last_exc_value in link.args
 
+def getops(graph):
+    ops = {}
+    for block in graph.iterblocks():
+        for op in block.operations:
+            ops.setdefault(op.opname, []).append(op)
+    return ops
+
 def rtype_and_transform(func, inputtypes, transformcls, specialize=True):
     t = TranslationContext()
     t.buildannotator().build_types(func, inputtypes)
@@ -242,7 +249,48 @@
         return 1
     t = rtype_and_transform(f, [], gctransform.GCTransformer)
 
+# ______________________________________________________________________
+# test write barrier placement
+
+def test_simple_barrier():
+    S = lltype.GcStruct("S", ('x', lltype.Signed))
+    T = lltype.GcStruct("T", ('s', lltype.Ptr(S)))
+    def f():
+        s1 = lltype.malloc(S)
+        s1.x = 1
+        s2 = lltype.malloc(S)
+        s2.x = 2
+        t = lltype.malloc(T)
+        t.s = s1
+        t.s = s2
+        return t
+    t = rtype_and_transform(f, [], gctransform.GCTransformer)
+    graph = graphof(t, f)
+    ops = getops(graph)
+    assert len(ops['getfield']) == 2
+    assert len(ops['setfield']) == 4
+
+def test_arraybarrier():
+    S = lltype.GcStruct("S", ('x', lltype.Signed))
+    A = lltype.GcArray(lltype.Ptr(S))
+    def f():
+        s1 = lltype.malloc(S)
+        s1.x = 1
+        s2 = lltype.malloc(S)
+        s2.x = 2
+        a = lltype.malloc(A, 1)
+        a[0] = s1
+        a[0] = s2
+    t = rtype_and_transform(f, [], gctransform.GCTransformer)
+    graph = graphof(t, f)
+    ops = getops(graph)
+    assert len(ops['getarrayitem']) == 2
+    assert len(ops['setarrayitem']) == 2
+    assert len(ops['setfield']) == 2
+
+
 # ----------------------------------------------------------------------
+# test deallocators
 
 def make_deallocator(TYPE, view=False):
     def f():
@@ -278,15 +326,25 @@
         ('z', TPtr),
         )
     dgraph = make_deallocator(S)
-    ops = {}
-    for block in dgraph.iterblocks():
-        for op in block.operations:
-            ops.setdefault(op.opname, []).append(op)
-
+    ops = getops(dgraph)
     assert len(ops['gc_pop_alive']) == 2
     assert len(ops['getfield']) == 2
     assert len(ops['gc_free']) == 1
 
+def test_deallocator_array():
+    TPtr = lltype.Ptr(lltype.GcStruct("T", ('a', lltype.Signed)))
+    GcA = lltype.GcArray(('x', TPtr), ('y', TPtr))
+    A = lltype.Array(('x', TPtr), ('y', TPtr))
+    APtr = lltype.Ptr(GcA)
+    S = lltype.GcStruct('S', ('t', TPtr), ('x', lltype.Signed), ('aptr', APtr),
+                             ('rest', A))
+    dgraph = make_deallocator(S)
+    ops = getops(dgraph)
+    assert len(ops['gc_pop_alive']) == 4
+    assert len(ops['getfield']) == 4
+    assert len(ops['getarraysubstruct']) == 1
+    assert len(ops['gc_free']) == 1
+
 def test_deallocator_with_destructor():
     S = lltype.GcStruct("S", ('x', lltype.Signed))
     def f(s):



More information about the Pypy-commit mailing list