[pypy-svn] r69331 - in pypy/trunk/pypy/rpython/memory/gctransform: . test

fijal at codespeak.net fijal at codespeak.net
Tue Nov 17 08:59:19 CET 2009


Author: fijal
Date: Tue Nov 17 08:59:18 2009
New Revision: 69331

Modified:
   pypy/trunk/pypy/rpython/memory/gctransform/framework.py
   pypy/trunk/pypy/rpython/memory/gctransform/test/test_framework.py
Log:
Implement write barrier shortcut for the case:
x = l[i]
l[j] = x
In which case we don't need a write barrier. To work correctly
with lists (as opposed to just GcArrays), it requires storesinking
on.


Modified: pypy/trunk/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/trunk/pypy/rpython/memory/gctransform/framework.py	(original)
+++ pypy/trunk/pypy/rpython/memory/gctransform/framework.py	Tue Nov 17 08:59:18 2009
@@ -52,7 +52,7 @@
     # a bit of a hackish analysis: if a block contains a malloc and check that
     # the result is not zero, then the block following the True link will
     # usually initialize the newly allocated object
-    result = {}
+    result = set()
     def find_in_block(block, mallocvars):
         for i, op in enumerate(block.operations):
             if op.opname in ("cast_pointer", "same_as"):
@@ -63,7 +63,7 @@
                 if (op.args[0] in mallocvars and
                     isinstance(TYPE, lltype.Ptr) and
                     TYPE.TO._gckind == "gc"):
-                    result[op] = True
+                    result.add(op)
             else:
                 if collect_analyzer.analyze(op):
                     return
@@ -110,6 +110,20 @@
     #    print "found %s initializing stores in %s" % (len(result), graph.name)
     return result
 
+def find_clean_setarrayitems(collect_analyzer, graph):
+    result = set()
+    for block in graph.iterblocks():
+        cache = set()
+        for op in block.operations:
+            if op.opname == 'getarrayitem':
+                cache.add((op.args[0], op.result))
+            elif op.opname == 'setarrayitem':
+                if (op.args[0], op.args[2]) in cache:
+                    result.add(op)
+            elif collect_analyzer.analyze(op):
+                cache = set()
+    return result
+
 class FrameworkGCTransformer(GCTransformer):
     use_stackless = False
     root_stack_depth = 163840
@@ -544,11 +558,12 @@
 
     def transform_graph(self, graph):
         if self.write_barrier_ptr:
-            self.initializing_stores = find_initializing_stores(
-                self.collect_analyzer, graph)
+            self.clean_sets = (
+                find_clean_setarrayitems(self.collect_analyzer, graph).union(
+                find_initializing_stores(self.collect_analyzer, graph)))
         super(FrameworkGCTransformer, self).transform_graph(graph)
         if self.write_barrier_ptr:
-            self.initializing_stores = None
+            self.clean_sets = None
 
     def gct_direct_call(self, hop):
         if self.collect_analyzer.analyze(hop.spaceop):
@@ -879,7 +894,7 @@
         if (self.write_barrier_ptr is not None
             and not isinstance(v_newvalue, Constant)
             and v_struct.concretetype.TO._gckind == "gc"
-            and hop.spaceop not in self.initializing_stores):
+            and hop.spaceop not in self.clean_sets):
             self.write_barrier_calls += 1
             v_newvalue = hop.genop("cast_ptr_to_adr", [v_newvalue],
                                    resulttype = llmemory.Address)

Modified: pypy/trunk/pypy/rpython/memory/gctransform/test/test_framework.py
==============================================================================
--- pypy/trunk/pypy/rpython/memory/gctransform/test/test_framework.py	(original)
+++ pypy/trunk/pypy/rpython/memory/gctransform/test/test_framework.py	Tue Nov 17 08:59:18 2009
@@ -5,13 +5,14 @@
     rtype_and_transform
 from pypy.rpython.memory.gctransform.transform import GcHighLevelOp
 from pypy.rpython.memory.gctransform.framework import FrameworkGCTransformer, \
-    CollectAnalyzer, find_initializing_stores
+    CollectAnalyzer, find_initializing_stores, find_clean_setarrayitems
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.rtyper import LowLevelOpList
 from pypy.translator.c.gc import FrameworkGcPolicy
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.translator.unsimplify import varoftype
 from pypy.translator.exceptiontransform import ExceptionTransformer
+from pypy.translator.backendopt.all import backend_optimizations
 from pypy import conftest
 
 import py
@@ -87,7 +88,7 @@
     assert can_collect
 
 class WriteBarrierTransformer(FrameworkGCTransformer):
-    initializing_stores = {}
+    clean_sets = {}
     GC_PARAMS = {}
     class GCClass(MarkSweepGC):
         needs_write_barrier = True
@@ -188,3 +189,88 @@
     collect_analyzer = CollectAnalyzer(t)
     init_stores = find_initializing_stores(collect_analyzer, t.graphs[0])
     assert len(init_stores) == 5
+
+def test_find_clean_setarrayitems():
+    S = lltype.GcStruct('S')
+    A = lltype.GcArray(lltype.Ptr(S))
+    
+    def f():
+        l = lltype.malloc(A, 3)
+        l[0] = lltype.malloc(S)
+        l[1] = lltype.malloc(S)
+        l[2] = lltype.malloc(S)
+        x = l[1]
+        l[0] = x
+        return len(l)
+
+    t = rtype(f, [])
+    etrafo = ExceptionTransformer(t)
+    graph = etrafo.transform_completely()
+    collect_analyzer = CollectAnalyzer(t)
+    clean_setarrayitems = find_clean_setarrayitems(collect_analyzer,
+                                                   t.graphs[0])
+    assert len(clean_setarrayitems) == 1
+
+def test_find_clean_setarrayitems_2():
+    S = lltype.GcStruct('S')
+    A = lltype.GcArray(lltype.Ptr(S))
+    
+    def f():
+        l = lltype.malloc(A, 3)
+        l[0] = lltype.malloc(S)
+        l[1] = lltype.malloc(S)
+        l[2] = lltype.malloc(S)
+        x = l[1]
+        l[2] = lltype.malloc(S) # <- this can possibly collect
+        l[0] = x
+        return len(l)
+
+    t = rtype(f, [])
+    etrafo = ExceptionTransformer(t)
+    graph = etrafo.transform_completely()
+    collect_analyzer = CollectAnalyzer(t)
+    clean_setarrayitems = find_clean_setarrayitems(collect_analyzer,
+                                                   t.graphs[0])
+    assert len(clean_setarrayitems) == 0
+
+def test_find_clean_setarrayitems_3():
+    S = lltype.GcStruct('S')
+    A = lltype.GcArray(lltype.Ptr(S))
+    
+    def f():
+        l = lltype.malloc(A, 3)
+        l[0] = lltype.malloc(S)
+        l[1] = lltype.malloc(S)
+        l[2] = lltype.malloc(S)
+        l2 = lltype.malloc(A, 4)
+        x = l[1]
+        l2[0] = x # <- different list
+        return len(l)
+
+    t = rtype(f, [])
+    etrafo = ExceptionTransformer(t)
+    graph = etrafo.transform_completely()
+    collect_analyzer = CollectAnalyzer(t)
+    clean_setarrayitems = find_clean_setarrayitems(collect_analyzer,
+                                                   t.graphs[0])
+    assert len(clean_setarrayitems) == 0
+
+def test_list_operations():
+
+    class A(object):
+        pass
+
+    def f():
+        l = [A(), A()]
+        l.append(A())
+        l[1] = l[0]
+        return len(l)
+
+    t = rtype(f, [])
+    backend_optimizations(t, clever_malloc_removal=False, storesink=True)
+    etrafo = ExceptionTransformer(t)
+    graph = etrafo.transform_completely()
+    collect_analyzer = CollectAnalyzer(t)
+    clean_setarrayitems = find_clean_setarrayitems(collect_analyzer,
+                                                   t.graphs[0])
+    assert len(clean_setarrayitems) == 1



More information about the Pypy-commit mailing list