[pypy-commit] pypy stmgc-c8: some cleanup and some more tests

Raemi noreply at buildbot.pypy.org
Wed Nov 25 10:58:34 EST 2015


Author: Remi Meier <remi.meier at gmail.com>
Branch: stmgc-c8
Changeset: r80948:cb4f5b7f309c
Date: 2015-11-25 12:46 +0100
http://bitbucket.org/pypy/pypy/changeset/cb4f5b7f309c/

Log:	some cleanup and some more tests

diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -106,8 +106,10 @@
                 writeable = {}
             #
             if op.opname == "stm_ignored_start":
+                assert not self.in_stm_ignored
                 self.in_stm_ignored = True
             elif op.opname == "stm_ignored_stop":
+                assert self.in_stm_ignored
                 self.in_stm_ignored = False
             elif op.opname == "gc_writebarrier":
                 assert not self.in_stm_ignored
@@ -115,50 +117,49 @@
             elif op.opname == "malloc":
                 rtti = get_rtti(op.args[0].value)
                 if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'):
-                    # XXX: not sure why that matters, copied from
-                    # find_initializing_stores
-                    continue
-                writeable[op.result] = True
+                    # objs with finalizers are allocated directly as "old", so
+                    # they need write barriers
+                    assert op not in self.clean_ops
+                else:
+                    # freshly allocated object
+                    writeable[op.result] = True
                 #
             elif op.opname in ("cast_pointer", "same_as"):
                 if writeable.get(op.args[0], False):
                     writeable[op.result] = True
                 #
             elif op.opname in ('setfield', 'setarrayitem', 'setinteriorfield', 'raw_store'):
+                # generic_set case
                 if op.args[-1].concretetype == lltype.Void:
+                    # always ignore setfields of Void type
                     self.clean_ops.add(op)
-                    continue # ignore setfields of Void type
                 elif not var_needsgc(op.args[0]):
+                    # raw setfields don't need a barrier
                     if (var_needsgc(op.args[-1]) and
                         'is_excdata' not in op.args[0].concretetype.TO._hints):
                         raise Exception("%s: GC pointer written into a non-GC location"
                                         % (op,))
                     self.clean_ops.add(op)
-                    continue
                 elif self.in_stm_ignored:
-                    # detect if we're inside a 'stm_ignored' block and in
-                    # that case don't call stm_write().  This only works for
-                    # writing non-GC pointers.
+                    # within stm_ignored, don't emit stm_write(). This only works
+                    # for writing non-GC pointers.
                     if var_needsgc(op.args[-1]):
                         raise Exception("in stm_ignored block: write of a gc pointer")
                     self.clean_ops.add(op)
-                    continue
-                elif self._set_into_gc_array_part(op) is None:
-                    # full write barrier required
-                    if writeable.get(op.args[0], False):
-                        # already writeable, this op is also clean
-                        self.clean_ops.add(op)
-                    elif op in self.clean_ops:
-                        # we changed our opinion in this iteration
-                        self.clean_ops.remove(op)
-                    # always writeable after this op
-                    writeable[op.args[0]] = True
-                else:
+                elif self._set_into_gc_array_part(op) is not None:
                     # things that need partial write barriers (card marking)
                     if writeable.get(op.args[0], False):
                         self.clean_ops.add(op)
                     elif op in self.clean_ops:
                         self.clean_ops.remove(op)
+                else:
+                    # full write barrier possibly required
+                    if writeable.get(op.args[0], False):
+                        self.clean_ops.add(op)
+                    elif op in self.clean_ops:
+                        self.clean_ops.remove(op)
+                    # always writeable after this op
+                    writeable[op.args[0]] = True
         #
         # update in_states of all successors
         updated = set()
diff --git a/rpython/memory/gctransform/test/test_framework.py b/rpython/memory/gctransform/test/test_framework.py
--- a/rpython/memory/gctransform/test/test_framework.py
+++ b/rpython/memory/gctransform/test/test_framework.py
@@ -396,6 +396,141 @@
     assert summary(ff)['stm_write'] == 3
 
 
+def test_remove_write_barrier_stm4():
+    from rpython.translator.c.genc import CStandaloneBuilder
+    from rpython.flowspace.model import summary
+
+    rS = lltype.Struct('rS')
+    S = lltype.GcStruct('S')
+    rA = lltype.Array(lltype.Ptr(rS))
+    A = lltype.GcArray(lltype.Ptr(S))
+    Ar = lltype.GcArray(lltype.Ptr(rS))
+    def f(ra, a, ar, i):
+        s = lltype.malloc(S)
+        rs = lltype.malloc(rS, flavor='raw')
+        ra[0] = rs
+        ra[1] = rs
+        a[0] = s
+        a[1] = s
+        ar[0] = rs
+        ar[1] = rs
+    def g(argv):
+        n = int(argv[1])
+        ra = lltype.malloc(rA, n, flavor='raw')
+        a = lltype.malloc(A, n)
+        ar = lltype.malloc(Ar, n)
+        f(ra, a, ar, n)
+        return 0
+    t = rtype(g, [s_list_of_strings])
+    t.config.translation.stm = True
+    gcpolicy = StmFrameworkGcPolicy
+    t.config.translation.gc = "stmgc"
+    cbuild = CStandaloneBuilder(t, g, t.config,
+                                gcpolicy=gcpolicy)
+    db = cbuild.generate_graphs_for_llinterp()
+
+    ff = graphof(t, f)
+    #ff.show()
+    assert summary(ff)['stm_write'] == 4
+
+def test_remove_write_barrier_stm5():
+    from rpython.translator.c.genc import CStandaloneBuilder
+    from rpython.flowspace.model import summary
+
+    class B(object):
+        def __del__(self):
+            pass
+    class A(object): pass
+    def f():
+        b = B()
+        b.x = 1 # needs WB bc. of finalizer
+        a = A()
+        a.x = 1
+    def g(argv):
+        f()
+        return 0
+    t = rtype(g, [s_list_of_strings])
+    t.config.translation.stm = True
+    gcpolicy = StmFrameworkGcPolicy
+    t.config.translation.gc = "stmgc"
+    cbuild = CStandaloneBuilder(t, g, t.config,
+                                gcpolicy=gcpolicy)
+    db = cbuild.generate_graphs_for_llinterp()
+
+    ff = graphof(t, f)
+    #ff.show()
+    assert summary(ff)['stm_write'] == 1
+
+def test_remove_write_barrier_stm6():
+    from rpython.translator.c.genc import CStandaloneBuilder
+    from rpython.flowspace.model import summary
+    #
+    rSi = lltype.Struct('rSi', ('i', lltype.Signed))
+    rSr = lltype.Struct('rSr', ('s', lltype.Ptr(rSi)))
+    Si = lltype.GcStruct('Si', ('i', lltype.Signed))
+    Ss = lltype.GcStruct('Ss', ('s', lltype.Ptr(Si)))
+    Sr = lltype.GcStruct('Sr', ('r', lltype.Ptr(rSi)))
+    def f(rsi, rsr, si, ss, sr):
+        rsi.i = 0
+        rsr.s = rsi
+        si.i = 0
+        ss.s = si
+        sr.r = rsi
+    def g(argv):
+        rsi = lltype.malloc(rSi, flavor='raw')
+        rsr = lltype.malloc(rSr, flavor='raw')
+        si = lltype.malloc(Si, flavor='gc')
+        ss = lltype.malloc(Ss, flavor='gc')
+        sr = lltype.malloc(Sr, flavor='gc')
+        f(rsi, rsr, si, ss, sr)
+        return 0
+    t = rtype(g, [s_list_of_strings])
+    t.config.translation.stm = True
+    gcpolicy = StmFrameworkGcPolicy
+    t.config.translation.gc = "stmgc"
+    cbuild = CStandaloneBuilder(t, g, t.config,
+                                gcpolicy=gcpolicy)
+    db = cbuild.generate_graphs_for_llinterp()
+
+    ff = graphof(t, f)
+    #ff.show()
+    assert summary(ff)['stm_write'] == 3
+
+def test_remove_write_barrier_stm7():
+    from rpython.translator.c.genc import CStandaloneBuilder
+    from rpython.flowspace.model import summary
+    #
+    rSi = lltype.Struct('rSi', ('i', lltype.Signed))
+    rSr = lltype.Struct('rSr', ('s', rSi))
+    Si = lltype.GcStruct('Si', ('i', lltype.Signed))
+    Ss = lltype.GcStruct('Ss', ('s', Si))
+    Sr = lltype.GcStruct('Sr', ('r', rSi))
+    def f(rsi, rsr, si, ss, sr):
+        rsi.i = 0
+        rsr.s.i = 0
+        si.i = 0
+        ss.s.i = 0
+        sr.r.i = 0
+    def g(argv):
+        rsi = lltype.malloc(rSi, flavor='raw')
+        rsr = lltype.malloc(rSr, flavor='raw')
+        si = lltype.malloc(Si, flavor='gc')
+        ss = lltype.malloc(Ss, flavor='gc')
+        sr = lltype.malloc(Sr, flavor='gc')
+        f(rsi, rsr, si, ss, sr)
+        return 0
+    t = rtype(g, [s_list_of_strings])
+    t.config.translation.stm = True
+    gcpolicy = StmFrameworkGcPolicy
+    t.config.translation.gc = "stmgc"
+    cbuild = CStandaloneBuilder(t, g, t.config,
+                                gcpolicy=gcpolicy)
+    db = cbuild.generate_graphs_for_llinterp()
+
+    ff = graphof(t, f)
+    #ff.show()
+    assert summary(ff)['stm_write'] == 3
+
 def test_write_barrier_collector():
     class A(object):
         pass


More information about the pypy-commit mailing list