Author: Armin Rigo <ar...@tunes.org>
Branch: stmgc-c7
Changeset: r69892:0fc7602e53d3
Date: 2014-03-12 10:46 +0100
http://bitbucket.org/pypy/pypy/changeset/0fc7602e53d3/

Log:    Reimplement stm_ignored

diff --git a/rpython/memory/gctransform/stmframework.py 
b/rpython/memory/gctransform/stmframework.py
--- a/rpython/memory/gctransform/stmframework.py
+++ b/rpython/memory/gctransform/stmframework.py
@@ -5,6 +5,7 @@
      BaseFrameworkGCTransformer, BaseRootWalker, sizeofaddr)
 from rpython.memory.gctypelayout import WEAKREF, WEAKREFPTR
 from rpython.rtyper import rmodel, llannotation
+from rpython.translator.backendopt.support import var_needsgc
 
 
 class StmFrameworkGCTransformer(BaseFrameworkGCTransformer):
@@ -52,6 +53,25 @@
         for var in reversed(livevars):
             hop.genop("stm_pop_root_into", [var])
 
+    def transform_block(self, *args, **kwds):
+        self.in_stm_ignored = False
+        BaseFrameworkGCTransformer.transform_block(self, *args, **kwds)
+        assert not self.in_stm_ignored, (
+            "unbalanced stm_ignore_start/stm_ignore_stop in block")
+
+    def gct_stm_ignored_start(self, hop):
+        assert not self.in_stm_ignored
+        self.in_stm_ignored = True
+        self.default(hop)
+
+    def gct_stm_ignored_stop(self, hop):
+        assert self.in_stm_ignored
+        self.in_stm_ignored = False
+        self.default(hop)
+
+    def var_needs_set_transform(self, var):
+        return True
+
     def transform_generic_set(self, hop):
         # XXX detect if we're inside a 'stm_ignored' block and... do what?
         assert self.write_barrier_ptr == "stm"
@@ -61,8 +81,13 @@
                           'raw_store')
         if (v_struct.concretetype.TO._gckind == "gc"
                 and hop.spaceop not in self.clean_sets):
-            self.write_barrier_calls += 1
-            hop.genop("stm_write", [v_struct])
+            if self.in_stm_ignored:
+                if var_needsgc(hop.spaceop.args[-1]):
+                    raise Exception("in stm_ignored block: write of a gc "
+                                    "pointer")
+            else:
+                self.write_barrier_calls += 1
+                hop.genop("stm_write", [v_struct])
         hop.rename('bare_' + opname)
 
     def gc_header_for(self, obj, needs_hash=False):
diff --git a/rpython/rtyper/lltypesystem/lloperation.py 
b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -450,6 +450,9 @@
     'stm_abort_info_pop':     LLOp(),
     'stm_inspect_abort_info': LLOp(sideeffects=False, canmallocgc=True),
 
+    'stm_ignored_start':      LLOp(canrun=True),
+    'stm_ignored_stop':       LLOp(canrun=True),
+
 ##    'stm_allocate_nonmovable_int_adr': LLOp(sideeffects=False, 
canmallocgc=True),
 ##    'stm_become_inevitable':  LLOp(canmallocgc=True),
 ##    'stm_stop_all_other_threads': LLOp(canmallocgc=True),
@@ -467,9 +470,6 @@
 ##    'stm_get_adr_of_nursery_nextlimit': LLOp(),
 ##    'stm_get_adr_of_active': LLOp(),
 
-##    'stm_ignored_start':      LLOp(canrun=True),
-##    'stm_ignored_stop':       LLOp(canrun=True),
-
     # __________ address operations __________
 
     'boehm_malloc':         LLOp(),
diff --git a/rpython/translator/stm/funcgen.py 
b/rpython/translator/stm/funcgen.py
--- a/rpython/translator/stm/funcgen.py
+++ b/rpython/translator/stm/funcgen.py
@@ -197,6 +197,12 @@
     result = funcgen.expr(op.result)
     return '%s = NULL; //XXX stm_inspect_abort_info();' % (result,)
 
+def stm_ignored_start(funcgen, op):
+    return '/* stm_ignored_start */'
+
+def stm_ignored_stop(funcgen, op):
+    return '/* stm_ignored_stop */'
+
 
 ##def stm_initialize(funcgen, op):
 ##    return '''stm_initialize();
diff --git a/rpython/translator/stm/readbarrier.py 
b/rpython/translator/stm/readbarrier.py
--- a/rpython/translator/stm/readbarrier.py
+++ b/rpython/translator/stm/readbarrier.py
@@ -23,10 +23,20 @@
         if not block.operations:
             continue
         newops = []
+        stm_ignored = False
         for op in block.operations:
             if op.opname in READ_OPS and is_gc_ptr(op.args[0].concretetype):
-                v_none = varoftype(lltype.Void)
-                newops.append(SpaceOperation('stm_read', [op.args[0]], v_none))
-                transformer.read_barrier_counts += 1
+                if not stm_ignored:
+                    v_none = varoftype(lltype.Void)
+                    newops.append(SpaceOperation('stm_read',
+                                                 [op.args[0]], v_none))
+                    transformer.read_barrier_counts += 1
+            elif op.opname == 'stm_ignored_start':
+                assert stm_ignored == False
+                stm_ignored = True
+            elif op.opname == 'stm_ignored_stop':
+                assert stm_ignored == True
+                stm_ignored = False
             newops.append(op)
+        assert stm_ignored == False
         block.operations = newops
diff --git a/rpython/translator/stm/test/test_readbarrier.py 
b/rpython/translator/stm/test/test_readbarrier.py
--- a/rpython/translator/stm/test/test_readbarrier.py
+++ b/rpython/translator/stm/test/test_readbarrier.py
@@ -1,3 +1,4 @@
+from rpython.rlib.objectmodel import stm_ignored
 from rpython.translator.stm.test.transform_support import BaseTestTransform
 from rpython.rtyper.lltypesystem import lltype
 
@@ -24,3 +25,14 @@
         res = self.interpret(f1, [-5])
         assert res == 42
         assert self.read_barriers == [x1]
+
+    def test_stm_ignored_read(self):
+        X = lltype.GcStruct('X', ('foo', lltype.Signed))
+        x1 = lltype.malloc(X, immortal=True)
+        x1.foo = 42
+        def f1():
+            with stm_ignored:
+                return x1.foo
+        res = self.interpret(f1, [])
+        assert res == 42
+        assert self.read_barriers == []
diff --git a/rpython/translator/stm/test/test_ztranslated.py 
b/rpython/translator/stm/test/test_ztranslated.py
--- a/rpython/translator/stm/test/test_ztranslated.py
+++ b/rpython/translator/stm/test/test_ztranslated.py
@@ -395,3 +395,27 @@
         lines = dataerr.split('\n')
         assert lines[0] == ' 0.400000'
         assert lines[1] == ' 1.200000'
+
+    def test_stm_ignored(self):
+        class X:
+            foo = 84
+        prebuilt = X()
+        prebuilt2 = X()
+        def main(argv):
+            with objectmodel.stm_ignored:
+                prebuilt.foo = 42
+            with objectmodel.stm_ignored:
+                x = prebuilt2.foo
+            print 'did not crash', x
+            return 0
+
+        t, cbuilder = self.compile(main)
+        opnames = [op.opname for op in t.graphs[0].startblock.operations]
+        assert opnames[:6] == ['stm_ignored_start',
+                               'bare_setfield',    # with no stm_write
+                               'stm_ignored_stop',
+                               'stm_ignored_start',
+                               'getfield',         # with no stm_read
+                               'stm_ignored_stop']
+        data = cbuilder.cmdexec('')
+        assert 'did not crash 84\n' in data
diff --git a/rpython/translator/stm/test/transform_support.py 
b/rpython/translator/stm/test/transform_support.py
--- a/rpython/translator/stm/test/transform_support.py
+++ b/rpython/translator/stm/test/transform_support.py
@@ -87,19 +87,18 @@
         self.op_stm_read(obj)      # implicitly counts as a read barrier too
 
     def op_stm_ignored_start(self):
-        xxx
         assert self.stm_ignored == False
         self.stm_ignored = True
 
     def op_stm_ignored_stop(self):
-        xxx
         assert self.stm_ignored == True
         self.stm_ignored = False
 
     def op_getfield(self, obj, field):
         if obj._TYPE.TO._gckind == 'gc':
             if obj._TYPE.TO._immutable_field(field):
-                self.gcptrs_actually_read.append(obj)
+                if not self.stm_ignored:
+                    self.gcptrs_actually_read.append(obj)
         return LLFrame.op_getfield(self, obj, field)
 
     def op_setfield(self, obj, fieldname, fieldvalue):
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to