Author: Armin Rigo <[email protected]>
Branch: stm-thread-2
Changeset: r57078:78dfa129ccef
Date: 2012-09-02 13:21 +0200
http://bitbucket.org/pypy/pypy/changeset/78dfa129ccef/

Log:    Track more precisely the category of individual pointers, not the
        category of general objects.

diff --git a/pypy/translator/stm/test/test_transform2.py 
b/pypy/translator/stm/test/test_transform2.py
--- a/pypy/translator/stm/test/test_transform2.py
+++ b/pypy/translator/stm/test/test_transform2.py
@@ -1,18 +1,42 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.llinterp import LLFrame
 from pypy.rpython.test.test_llinterp import get_interpreter, clear_tcache
+from pypy.objspace.flow.model import Constant
 from pypy.translator.stm.transform2 import STMTransformer
 from pypy.conftest import option
 
 
+class _stmptr(lltype._ptr):
+    """Like lltype._ptr, but also keeps a current category level"""
+
+    __slots__ = ['_category']
+
+    def __init__(self, ptr, category):
+        lltype._ptr.__init__(self, ptr._TYPE, ptr._obj0, ptr._solid)
+        _stmptr._category.__set__(self, category)
+
+
 class BaseTestTransform(object):
     prebuilt = ()
 
+    def build_state(self):
+        self.writemode = set()
+        self.barriers = []
+
+    def get_category(self, p):
+        if isinstance(p, _stmptr):
+            return p._category
+        if not p:
+            return 'N'
+        if p in self.prebuilt:
+            return 'G'
+        raise AssertionError("unknown category on %r" % (p,))
+
     def interpret(self, fn, args):
+        self.build_state()
         clear_tcache()
-        self.stmstate = STMState(self.prebuilt)
         interp, self.graph = get_interpreter(fn, args, view=False)
-        interp.stmstate = self.stmstate
+        interp.tester = self
         interp.frame_class = LLSTMFrame
         #
         self.translator = interp.typer.annotator.translator
@@ -25,33 +49,6 @@
         return result
 
 
-class STMState(object):
-    def __init__(self, prebuilt=()):
-        self.categories = {None: 'N'}   # Null
-        for p in prebuilt:
-            self.categories[self._getkey(p)] = 'G'   # Global
-        self.writemode = set()
-
-    def _getkey(self, p):
-        assert lltype.typeOf(p).TO._gckind == 'gc'
-        p = lltype.normalizeptr(p)
-        if p:
-            return p._obj0
-        else:
-            return None
-
-    def get_category(self, p):
-        key = self._getkey(p)
-        return self.categories[key]
-
-    def set_category(self, p, ncat):
-        key = self._getkey(p)
-        assert key is not None and ncat != 'N'
-        self.categories[key] = ncat
-        if ncat == 'W':
-            self.writemode.add(key)
-
-
 class LLSTMFrame(LLFrame):
     _MORE_PRECISE_CATEGORIES = {
         'P': 'PGORLWN',
@@ -63,21 +60,21 @@
         'N': 'N'}
 
     def get_category(self, p):
-        return self.llinterpreter.stmstate.get_category(p)
-
-    def set_category(self, p, ncat):
-        self.llinterpreter.stmstate.set_category(p, ncat)
+        return self.llinterpreter.tester.get_category(p)
 
     def check_category(self, p, expected):
         cat = self.get_category(p)
         assert cat in self._MORE_PRECISE_CATEGORIES[expected]
 
     def op_stm_barrier(self, kind, obj):
-        frm, digittwo, to = kind
-        assert digittwo == '2'
+        frm, middledigit, to = kind
+        assert middledigit == '2'
         self.check_category(obj, frm)
-        self.set_category(obj, to)
-        return obj
+        ptr2 = _stmptr(obj, to)
+        if to == 'W':
+            self.llinterpreter.tester.writemode.add(ptr2._obj)
+        self.llinterpreter.tester.barriers.append(kind)
+        return ptr2
 
     def op_getfield(self, obj, field):
         self.check_category(obj, 'R')
@@ -106,10 +103,11 @@
 
         res = self.interpret(f1, [4])
         assert res == 81
-        assert len(self.stmstate.writemode) == 0
+        assert len(self.writemode) == 0
         res = self.interpret(f1, [-5])
         assert res == 42
-        assert len(self.stmstate.writemode) == 0
+        assert len(self.writemode) == 0
+        assert self.barriers == ['G2R']
 
     def test_simple_write(self):
         X = lltype.GcStruct('X', ('foo', lltype.Signed))
@@ -122,4 +120,27 @@
 
         self.interpret(f1, [4])
         assert x1.foo == 4
-        assert len(self.stmstate.writemode) == 1
+        assert len(self.writemode) == 1
+        assert self.barriers == ['G2W']
+
+    def test_multiple_reads(self):
+        X = lltype.GcStruct('X', ('foo', lltype.Signed),
+                                 ('bar', lltype.Signed))
+        x1 = lltype.malloc(X, immortal=True)
+        x1.foo = 6
+        x1.bar = 7
+        x2 = lltype.malloc(X, immortal=True)
+        x2.foo = 81
+        x2.bar = -1
+        self.prebuilt = [x1, x2]
+
+        def f1(n):
+            if n > 1:
+                return x2.foo * x2.bar
+            else:
+                return x1.foo * x1.bar
+
+        res = self.interpret(f1, [4])
+        assert res == -81
+        assert len(self.writemode) == 0
+        assert self.barriers == ['G2R', 'P2R']    # XXX remove the 2nd one
diff --git a/pypy/translator/stm/transform2.py 
b/pypy/translator/stm/transform2.py
--- a/pypy/translator/stm/transform2.py
+++ b/pypy/translator/stm/transform2.py
@@ -71,9 +71,13 @@
             for op in block.operations:
                 to = wants_a_barrier.get(op)
                 if to is not None:
-                    c_info = Constant('P2%s' % to, lltype.Void)
                     v = op.args[0]
                     v = renamings.get(v, v)
+                    if isinstance(v, Constant):
+                        frm = 'G'
+                    else:
+                        frm = 'P'   # XXX improve
+                    c_info = Constant('%s2%s' % (frm, to), lltype.Void)
                     w = varoftype(v.concretetype)
                     newop = SpaceOperation('stm_barrier', [c_info, v], w)
                     newoperations.append(newop)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to