Author: Armin Rigo <[email protected]>
Branch: stm-thread-2
Changeset: r58982:47e9f6ca045d
Date: 2012-11-18 13:18 +0100
http://bitbucket.org/pypy/pypy/changeset/47e9f6ca045d/

Log:    Re-import the parts of the old transform.py that insert
        'turn_inevitable' around unsupported operations.

diff --git a/pypy/translator/stm/inevitable.py 
b/pypy/translator/stm/inevitable.py
new file mode 100644
--- /dev/null
+++ b/pypy/translator/stm/inevitable.py
@@ -0,0 +1,80 @@
+from pypy.rpython.lltypesystem import lltype, lloperation
+from pypy.translator.stm.writebarrier import is_immutable
+from pypy.objspace.flow.model import SpaceOperation, Constant
+from pypy.translator.unsimplify import varoftype
+
+
+ALWAYS_ALLOW_OPERATIONS = set([
+    'direct_call', 'force_cast', 'keepalive', 'cast_ptr_to_adr',
+    'debug_print', 'debug_assert', 'cast_opaque_ptr', 'hint',
+    'indirect_call', 'stack_current', 'gc_stack_bottom',
+    'cast_current_ptr_to_int',   # this variant of 'cast_ptr_to_int' is ok
+    'jit_force_virtual', 'jit_force_virtualizable',
+    'jit_force_quasi_immutable', 'jit_marker', 'jit_is_virtual',
+    'jit_record_known_class',
+    'gc_identityhash', 'gc_id',
+    'gc_adr_of_root_stack_top',
+    ])
+ALWAYS_ALLOW_OPERATIONS |= set(lloperation.enum_tryfold_ops())
+
+for opname, opdesc in lloperation.LL_OPERATIONS.iteritems():
+    if opname.startswith('stm_'):
+        ALWAYS_ALLOW_OPERATIONS.add(opname)
+
+GETTERS = set(['getfield', 'getarrayitem', 'getinteriorfield'])
+SETTERS = set(['setfield', 'setarrayitem', 'setinteriorfield'])
+MALLOCS = set(['malloc', 'malloc_varsize',
+               'malloc_nonmovable', 'malloc_nonmovable_varsize'])
+
+# ____________________________________________________________
+
+def should_turn_inevitable_getter_setter(op):
+    # Getters and setters are allowed if their first argument is a GC pointer.
+    # If it is a RAW pointer, and it is a read from a non-immutable place,
+    # and it doesn't use the hint 'stm_dont_track_raw_accesses', then they
+    # turn inevitable.
+    S = op.args[0].concretetype.TO
+    if S._gckind == 'gc':
+        return False
+    if is_immutable(op):
+        return False
+    if S._hints.get('stm_dont_track_raw_accesses', False):
+        return False
+    return True
+
+def should_turn_inevitable(op):
+    # Always-allowed operations never cause a 'turn inevitable'
+    if op.opname in ALWAYS_ALLOW_OPERATIONS:
+        return False
+    #
+    # Getters and setters
+    if op.opname in GETTERS:
+        if op.result.concretetype is lltype.Void:
+            return False
+        return should_turn_inevitable_getter_setter(op)
+    if op.opname in SETTERS:
+        if op.args[-1].concretetype is lltype.Void:
+            return False
+        return should_turn_inevitable_getter_setter(op)
+    #
+    # Mallocs
+    if op.opname in MALLOCS:
+        flags = op.args[1].value
+        return flags['flavor'] != 'gc'
+    #
+    # Entirely unsupported operations cause a 'turn inevitable'
+    return True
+
+
+def turn_inevitable_op(info):
+    c_info = Constant(info, lltype.Void)
+    return SpaceOperation('stm_become_inevitable', [c_info],
+                          varoftype(lltype.Void))
+
+def insert_turn_inevitable(translator, graph):
+    for block in graph.iterblocks():
+        for i in range(len(block.operations)-1, -1, -1):
+            op = block.operations[i]
+            if should_turn_inevitable(op):
+                inev_op = turn_inevitable_op(op.opname)
+                block.operations.insert(i, inev_op)
diff --git a/pypy/translator/stm/test/test_inevitable.py 
b/pypy/translator/stm/test/test_inevitable.py
new file mode 100644
--- /dev/null
+++ b/pypy/translator/stm/test/test_inevitable.py
@@ -0,0 +1,116 @@
+from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.llinterp import LLFrame
+from pypy.rpython.test import test_llinterp
+from pypy.rpython.test.test_llinterp import get_interpreter, clear_tcache
+from pypy.translator.stm.inevitable import insert_turn_inevitable
+from pypy.conftest import option
+
+
+class LLSTMInevFrame(LLFrame):
+    def op_stm_become_inevitable(self, info):
+        assert info is not None
+        if self.llinterpreter.inevitable_cause is None:
+            self.llinterpreter.inevitable_cause = info
+
+
+class TestTransform:
+
+    def interpret_inevitable(self, fn, args):
+        clear_tcache()
+        interp, self.graph = get_interpreter(fn, args, view=False)
+        interp.frame_class = LLSTMInevFrame
+        self.translator = interp.typer.annotator.translator
+        insert_turn_inevitable(self.translator, self.graph)
+        if option.view:
+            self.translator.view()
+        #
+        interp.inevitable_cause = None
+        result = interp.eval_graph(self.graph, args)
+        return interp.inevitable_cause
+
+
+    def test_simple_no_inevitable(self):
+        X = lltype.GcStruct('X', ('foo', lltype.Signed))
+        x1 = lltype.malloc(X, immortal=True)
+        x1.foo = 42
+
+        def f1(n):
+            x1.foo = n
+
+        res = self.interpret_inevitable(f1, [4])
+        assert res is None
+
+    def test_unsupported_op(self):
+        X = lltype.Struct('X', ('foo', lltype.Signed))
+
+        def f1():
+            addr = llmemory.raw_malloc(llmemory.sizeof(X))
+            llmemory.raw_free(addr)
+
+        res = self.interpret_inevitable(f1, [])
+        assert res == 'raw_malloc'
+
+    def test_raw_getfield(self):
+        X = lltype.Struct('X', ('foo', lltype.Signed))
+        x1 = lltype.malloc(X, immortal=True)
+        x1.foo = 42
+
+        def f1():
+            return x1.foo
+
+        res = self.interpret_inevitable(f1, [])
+        assert res == 'getfield'
+
+    def test_raw_getfield_immutable(self):
+        X = lltype.Struct('X', ('foo', lltype.Signed),
+                          hints={'immutable': True})
+        x1 = lltype.malloc(X, immortal=True)
+        x1.foo = 42
+
+        def f1():
+            return x1.foo
+
+        res = self.interpret_inevitable(f1, [])
+        assert res is None
+
+    def test_raw_getfield_with_hint(self):
+        X = lltype.Struct('X', ('foo', lltype.Signed),
+                          hints={'stm_dont_track_raw_accesses': True})
+        x1 = lltype.malloc(X, immortal=True)
+        x1.foo = 42
+
+        def f1():
+            return x1.foo
+
+        res = self.interpret_inevitable(f1, [])
+        assert res is None
+
+    def test_raw_setfield(self):
+        X = lltype.Struct('X', ('foo', lltype.Signed))
+        x1 = lltype.malloc(X, immortal=True)
+        x1.foo = 42
+
+        def f1(n):
+            x1.foo = n
+
+        res = self.interpret_inevitable(f1, [43])
+        assert res == 'setfield'
+
+    def test_malloc_no_inevitable(self):
+        X = lltype.GcStruct('X', ('foo', lltype.Signed))
+
+        def f1():
+            return lltype.malloc(X)
+
+        res = self.interpret_inevitable(f1, [])
+        assert res is None
+
+    def test_raw_malloc(self):
+        X = lltype.Struct('X', ('foo', lltype.Signed))
+
+        def f1():
+            p = lltype.malloc(X, flavor='raw')
+            lltype.free(p, flavor='raw')
+
+        res = self.interpret_inevitable(f1, [])
+        assert res == 'malloc'
diff --git a/pypy/translator/stm/test/test_transform2.py 
b/pypy/translator/stm/test/test_writebarrier.py
rename from pypy/translator/stm/test/test_transform2.py
rename to pypy/translator/stm/test/test_writebarrier.py
--- a/pypy/translator/stm/test/test_transform2.py
+++ b/pypy/translator/stm/test/test_writebarrier.py
@@ -1,124 +1,10 @@
-from pypy.rpython.lltypesystem import lltype, rffi, opimpl
-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.translator.stm.transform2 import MORE_PRECISE_CATEGORIES
-from pypy.conftest import option
-
-
-class _stmptr(lltype._ptr):
-    """Like lltype._ptr, but also keeps a current category level"""
-
-    __slots__ = ['_category', '_original_ptr']
-
-    def __init__(self, ptr, category):
-        lltype._ptr.__init__(self, ptr._TYPE, ptr._obj0, ptr._solid)
-        _stmptr._category.__set__(self, category)
-        _stmptr._original_ptr.__set__(self, ptr)
-
-    def __eq__(self, other):
-        return self._original_ptr == other
-
-
-class BaseTestTransform(object):
-
-    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._solid:
-            return 'G'     # allocated with immortal=True
-        raise AssertionError("unknown category on %r" % (p,))
-
-    def interpret(self, fn, args):
-        self.build_state()
-        clear_tcache()
-        interp, self.graph = get_interpreter(fn, args, view=False)
-        interp.tester = self
-        interp.frame_class = LLSTMFrame
-        #
-        self.translator = interp.typer.annotator.translator
-        self.stmtransformer = STMTransformer(self.translator)
-        self.stmtransformer.transform()
-        if option.view:
-            self.translator.view()
-        #
-        result = interp.eval_graph(self.graph, args)
-        return result
-
-
-class LLSTMFrame(LLFrame):
-
-    def all_stm_ptrs(self):
-        for frame in self.llinterpreter.frame_stack:
-            for value in frame.bindings.values():
-                if isinstance(value, _stmptr):
-                    yield value
-
-    def get_category(self, p):
-        return self.llinterpreter.tester.get_category(p)
-
-    def check_category(self, p, expected):
-        cat = self.get_category(p)
-        assert cat in MORE_PRECISE_CATEGORIES[expected]
-        return cat
-
-    def op_stm_barrier(self, kind, obj):
-        frm, middledigit, to = kind
-        assert middledigit == '2'
-        cat = self.check_category(obj, frm)
-        if cat in MORE_PRECISE_CATEGORIES[to]:
-            # a barrier, but with no effect
-            self.llinterpreter.tester.barriers.append(kind.lower())
-            return obj
-        else:
-            # a barrier, calling a helper
-            ptr2 = _stmptr(obj, to)
-            if to == 'W':
-                self.llinterpreter.tester.writemode.add(ptr2._obj)
-            self.llinterpreter.tester.barriers.append(kind)
-            return ptr2
-
-    def op_stm_ptr_eq(self, obj1, obj2):
-        self.check_category(obj1, 'P')
-        self.check_category(obj2, 'P')
-        self.llinterpreter.tester.barriers.append('=')
-        return obj1 == obj2
-
-    def op_getfield(self, obj, field):
-        if not obj._TYPE.TO._immutable_field(field):
-            self.check_category(obj, 'R')
-        return LLFrame.op_getfield(self, obj, field)
-
-    def op_setfield(self, obj, fieldname, fieldvalue):
-        if not obj._TYPE.TO._immutable_field(fieldname):
-            self.check_category(obj, 'W')
-            # convert R -> O all other pointers to the same object we can find
-            for p in self.all_stm_ptrs():
-                if p._category == 'R' and p._T == obj._T and p == obj:
-                    _stmptr._category.__set__(p, 'O')
-        return LLFrame.op_setfield(self, obj, fieldname, fieldvalue)
-
-    def op_cast_pointer(self, RESTYPE, obj):
-        cat = self.check_category(obj, 'P')
-        p = opimpl.op_cast_pointer(RESTYPE, obj)
-        return _stmptr(p, cat)
-    op_cast_pointer.need_result_type = True
-
-    def op_malloc(self, obj, flags):
-        p = LLFrame.op_malloc(self, obj, flags)
-        ptr2 = _stmptr(p, 'W')
-        self.llinterpreter.tester.writemode.add(ptr2._obj)
-        return ptr2
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.translator.stm.test.transform2_support import BaseTestTransform
 
 
 class TestTransform(BaseTestTransform):
+    do_write_barrier = True
+    do_turn_inevitable = False
 
     def test_simple_read(self):
         X = lltype.GcStruct('X', ('foo', lltype.Signed))
diff --git a/pypy/translator/stm/test/test_transform2.py 
b/pypy/translator/stm/test/transform2_support.py
copy from pypy/translator/stm/test/test_transform2.py
copy to pypy/translator/stm/test/transform2_support.py
--- a/pypy/translator/stm/test/test_transform2.py
+++ b/pypy/translator/stm/test/transform2_support.py
@@ -1,9 +1,8 @@
-from pypy.rpython.lltypesystem import lltype, rffi, opimpl
+from pypy.rpython.lltypesystem import lltype, opimpl
 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.translator.stm.transform2 import MORE_PRECISE_CATEGORIES
+from pypy.translator.stm.writebarrier import MORE_PRECISE_CATEGORIES
 from pypy.conftest import option
 
 
@@ -45,7 +44,10 @@
         #
         self.translator = interp.typer.annotator.translator
         self.stmtransformer = STMTransformer(self.translator)
-        self.stmtransformer.transform()
+        if self.do_write_barrier:
+            self.stmtransformer.transform_write_barrier()
+        if self.do_turn_inevitable:
+            self.stmtransformer.transform_turn_inevitable()
         if option.view:
             self.translator.view()
         #
@@ -116,247 +118,3 @@
         ptr2 = _stmptr(p, 'W')
         self.llinterpreter.tester.writemode.add(ptr2._obj)
         return ptr2
-
-
-class TestTransform(BaseTestTransform):
-
-    def test_simple_read(self):
-        X = lltype.GcStruct('X', ('foo', lltype.Signed))
-        x1 = lltype.malloc(X, immortal=True)
-        x1.foo = 42
-        x2 = lltype.malloc(X, immortal=True)
-        x2.foo = 81
-
-        def f1(n):
-            if n > 1:
-                return x2.foo
-            else:
-                return x1.foo
-
-        res = self.interpret(f1, [4])
-        assert res == 81
-        assert len(self.writemode) == 0
-        res = self.interpret(f1, [-5])
-        assert res == 42
-        assert len(self.writemode) == 0
-        assert self.barriers == ['G2R']
-
-    def test_simple_write(self):
-        X = lltype.GcStruct('X', ('foo', lltype.Signed))
-        x1 = lltype.malloc(X, immortal=True)
-        x1.foo = 42
-
-        def f1(n):
-            x1.foo = n
-
-        self.interpret(f1, [4])
-        assert x1.foo == 4
-        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
-
-        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']
-
-    def test_malloc(self):
-        X = lltype.GcStruct('X', ('foo', lltype.Signed))
-        def f1(n):
-            p = lltype.malloc(X)
-            p.foo = n
-
-        self.interpret(f1, [4])
-        assert len(self.writemode) == 1
-        assert self.barriers == []
-
-    def test_write_may_alias(self):
-        X = lltype.GcStruct('X', ('foo', lltype.Signed))
-        def f1(p, q):
-            x1 = p.foo
-            q.foo = 7
-            x2 = p.foo
-            return x1 * x2
-
-        x = lltype.malloc(X, immortal=True); x.foo = 6
-        y = lltype.malloc(X, immortal=True)
-        res = self.interpret(f1, [x, y])
-        assert res == 36
-        assert self.barriers == ['P2R', 'P2W', 'o2r']
-        res = self.interpret(f1, [x, x])
-        assert res == 42
-        assert self.barriers == ['P2R', 'P2W', 'O2R']
-
-    def test_write_cannot_alias(self):
-        X = lltype.GcStruct('X', ('foo', lltype.Signed))
-        Y = lltype.GcStruct('Y', ('foo', lltype.Signed))
-        def f1(p, q):
-            x1 = p.foo
-            q.foo = 7
-            x2 = p.foo
-            return x1 * x2
-
-        x = lltype.malloc(X, immortal=True); x.foo = 6
-        y = lltype.malloc(Y, immortal=True)
-        res = self.interpret(f1, [x, y])
-        assert res == 36
-        assert self.barriers == ['P2R', 'P2W']
-
-    def test_call_external_random_effects(self):
-        X = lltype.GcStruct('X', ('foo', lltype.Signed))
-        def f1(p):
-            x1 = p.foo
-            external_stuff()
-            x2 = p.foo
-            return x1 * x2
-
-        x = lltype.malloc(X, immortal=True); x.foo = 6
-        res = self.interpret(f1, [x])
-        assert res == 36
-        assert self.barriers == ['P2R', 'p2r']
-
-    def test_call_external_no_random_effects(self):
-        X = lltype.GcStruct('X', ('foo', lltype.Signed))
-        external_stuff = rffi.llexternal('external_stuff2', [], lltype.Void,
-                                         _callable=lambda: None,
-                                         random_effects_on_gcobjs=False,
-                                         threadsafe=False)
-        def f1(p):
-            x1 = p.foo
-            external_stuff()
-            x2 = p.foo
-            return x1 * x2
-
-        x = lltype.malloc(X, immortal=True); x.foo = 6
-        res = self.interpret(f1, [x])
-        assert res == 36
-        assert self.barriers == ['P2R']
-
-    def test_pointer_compare_0(self):
-        X = lltype.GcStruct('X', ('foo', lltype.Signed))
-        def f1(x):
-            return x != lltype.nullptr(X)
-        x = lltype.malloc(X, immortal=True)
-        res = self.interpret(f1, [x])
-        assert res == 1
-        assert self.barriers == []
-
-    def test_pointer_compare_1(self):
-        X = lltype.GcStruct('X', ('foo', lltype.Signed))
-        def f1(x, y):
-            return x != y
-        x = lltype.malloc(X, immortal=True)
-        y = lltype.malloc(X, immortal=True)
-        res = self.interpret(f1, [x, y])
-        assert res == 1
-        assert self.barriers == ['=']
-        res = self.interpret(f1, [x, x])
-        assert res == 0
-        assert self.barriers == ['=']
-
-    def test_pointer_compare_2(self):
-        X = lltype.GcStruct('X', ('foo', lltype.Signed))
-        def f1(x, y):
-            x.foo = 41
-            return x == y
-        x = lltype.malloc(X, immortal=True)
-        y = lltype.malloc(X, immortal=True)
-        res = self.interpret(f1, [x, y])
-        assert res == 0
-        assert self.barriers == ['P2W', '=']
-        res = self.interpret(f1, [x, x])
-        assert res == 1
-        assert self.barriers == ['P2W', '=']
-
-    def test_pointer_compare_3(self):
-        X = lltype.GcStruct('X', ('foo', lltype.Signed))
-        def f1(x, y):
-            y.foo = 41
-            return x != y
-        x = lltype.malloc(X, immortal=True)
-        y = lltype.malloc(X, immortal=True)
-        res = self.interpret(f1, [x, y])
-        assert res == 1
-        assert self.barriers == ['P2W', '=']
-        res = self.interpret(f1, [x, x])
-        assert res == 0
-        assert self.barriers == ['P2W', '=']
-
-    def test_pointer_compare_4(self):
-        X = lltype.GcStruct('X', ('foo', lltype.Signed))
-        def f1(x, y):
-            x.foo = 40
-            y.foo = 41
-            return x != y
-        x = lltype.malloc(X, immortal=True)
-        y = lltype.malloc(X, immortal=True)
-        res = self.interpret(f1, [x, y])
-        assert res == 1
-        assert self.barriers == ['P2W', 'P2W']
-        res = self.interpret(f1, [x, x])
-        assert res == 0
-        assert self.barriers == ['P2W', 'P2W']
-
-    def test_simple_loop(self):
-        X = lltype.GcStruct('X', ('foo', lltype.Signed))
-        def f1(x, i):
-            while i > 0:
-                x.foo = i
-                i -= 1
-            return i
-        x = lltype.malloc(X, immortal=True)
-        res = self.interpret(f1, [x, 5])
-        assert res == 0
-        # for now we get this.  Later, we could probably optimize it
-        assert self.barriers == ['P2W', 'p2w', 'p2w', 'p2w', 'p2w']
-
-    def test_subclassing(self):
-        class X:
-            __slots__ = ['foo']
-        class Y(X):
-            pass
-        class Z(X):
-            pass
-        def f1(i):
-            if i > 5:
-                x = Y()
-                x.foo = 42
-                x.ybar = i
-            else:
-                x = Z()
-                x.foo = 815
-                x.zbar = 'A'
-            external_stuff()
-            result = x.foo
-            if isinstance(x, Y):
-                result += x.ybar
-            return result
-
-        res = self.interpret(f1, [10])
-        assert res == 42 + 10
-        assert self.barriers == ['p2r', 'p2r']  # from two blocks (could be
-                                                # optimized later)
-        res = self.interpret(f1, [-10])
-        assert res == 815
-        assert self.barriers == ['p2r']
-
-
-external_stuff = rffi.llexternal('external_stuff', [], lltype.Void,
-                                 _callable=lambda: None,
-                                 random_effects_on_gcobjs=True,
-                                 threadsafe=False)
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
@@ -1,10 +1,3 @@
-from pypy.objspace.flow.model import SpaceOperation, Constant, Variable
-from pypy.objspace.flow.model import checkgraph, c_last_exception, Block, Link
-from pypy.translator.unsimplify import varoftype, insert_empty_block
-from pypy.rpython.lltypesystem import lltype
-from pypy.translator.backendopt.writeanalyze import WriteAnalyzer, top_set
-
-
 
 class STMTransformer(object):
 
@@ -14,12 +7,25 @@
     def transform(self):
         assert not hasattr(self.translator, 'stm_transformation_applied')
         self.start_log()
+        self.transform_write_barrier()
+        self.transform_turn_inevitable()
+        self.print_logs()
+        self.translator.stm_transformation_applied = True
+
+    def transform_write_barrier(self):
+        from pypy.translator.backendopt.writeanalyze import WriteAnalyzer
+        from pypy.translator.stm.writebarrier import insert_stm_barrier
+        #
         self.write_analyzer = WriteAnalyzer(self.translator)
         for graph in self.translator.graphs:
-            pre_insert_stm_barrier(self, graph)
+            insert_stm_barrier(self, graph)
         del self.write_analyzer
-        self.translator.stm_transformation_applied = True
-        self.print_logs()
+
+    def transform_turn_inevitable(self):
+        from pypy.translator.stm.inevitable import insert_turn_inevitable
+        #
+        for graph in self.translator.graphs:
+            insert_turn_inevitable(self.translator, graph)
 
     def start_log(self):
         from pypy.translator.c.support import log
@@ -28,158 +34,3 @@
     def print_logs(self):
         from pypy.translator.c.support import log
         log.info("Software Transactional Memory transformation applied")
-
-
-MALLOCS = set([
-    'malloc', 'malloc_varsize',
-    'malloc_nonmovable', 'malloc_nonmovable_varsize',
-    ])
-
-MORE_PRECISE_CATEGORIES = {
-    'P': 'PGORLWN',
-    'G': 'GN',
-    'O': 'ORLWN',
-    'R': 'RLWN',
-    'L': 'LWN',
-    'W': 'WN',
-    'N': 'N'}
-
-def unwraplist(list_v):
-    for v in list_v: 
-        if isinstance(v, Constant):
-            yield v.value
-        elif isinstance(v, Variable):
-            yield None    # unknown
-        else:
-            raise AssertionError(v)
-
-def is_immutable(op):
-    if op.opname in ('getfield', 'setfield'):
-        STRUCT = op.args[0].concretetype.TO
-        return STRUCT._immutable_field(op.args[1].value)
-    if op.opname in ('getarrayitem', 'setarrayitem'):
-        ARRAY = op.args[0].concretetype.TO
-        return ARRAY._immutable_field()
-    if op.opname == 'getinteriorfield':
-        OUTER = op.args[0].concretetype.TO
-        return OUTER._immutable_interiorfield(unwraplist(op.args[1:]))
-    if op.opname == 'setinteriorfield':
-        OUTER = op.args[0].concretetype.TO
-        return OUTER._immutable_interiorfield(unwraplist(op.args[1:-1]))
-    raise AssertionError(op)
-
-
-def pre_insert_stm_barrier(stmtransformer, graph):
-    graphinfo = stmtransformer.write_analyzer.compute_graph_info(graph)
-
-    def get_category(v):
-        if isinstance(v, Constant):
-            if v.value:
-                return 'G'
-            else:
-                return 'N'     # NULL
-        return category.get(v, 'P')
-
-    def renamings_get(v):
-        if v not in renamings:
-            return v
-        v2 = renamings[v][0]
-        if v2.concretetype == v.concretetype:
-            return v2
-        v3 = varoftype(v.concretetype)
-        newoperations.append(SpaceOperation('cast_pointer', [v2], v3))
-        return v3
-
-    for block in graph.iterblocks():
-        if block.operations == ():
-            continue
-        #
-        wants_a_barrier = {}
-        expand_comparison = set()
-        for op in block.operations:
-            if (op.opname in ('getfield', 'getarrayitem',
-                              'getinteriorfield') and
-                  op.result.concretetype is not lltype.Void and
-                  op.args[0].concretetype.TO._gckind == 'gc' and
-                  not is_immutable(op)):
-                wants_a_barrier.setdefault(op, 'R')
-            elif (op.opname in ('setfield', 'setarrayitem',
-                                'setinteriorfield') and
-                  op.args[-1].concretetype is not lltype.Void and
-                  op.args[0].concretetype.TO._gckind == 'gc' and
-                  not is_immutable(op)):
-                wants_a_barrier[op] = 'W'
-            elif (op.opname in ('ptr_eq', 'ptr_ne') and
-                  op.args[0].concretetype.TO._gckind == 'gc'):
-                expand_comparison.add(op)
-        #
-        if wants_a_barrier or expand_comparison:
-            # note: 'renamings' maps old vars to new vars, but cast_pointers
-            # are done lazily.  It means that the two vars may not have
-            # exactly the same type.
-            renamings = {}   # {original-var: [var-in-newoperations] (len 1)}
-            category = {}    # {var-in-newoperations: LETTER}
-            newoperations = []
-            for op in block.operations:
-                #
-                if op.opname == 'cast_pointer':
-                    v = op.args[0]
-                    renamings[op.result] = renamings.setdefault(v, [v])
-                    continue
-                #
-                to = wants_a_barrier.get(op)
-                if to is not None:
-                    v = op.args[0]
-                    v_holder = renamings.setdefault(v, [v])
-                    v = v_holder[0]
-                    frm = get_category(v)
-                    if frm not in MORE_PRECISE_CATEGORIES[to]:
-                        c_info = Constant('%s2%s' % (frm, to), lltype.Void)
-                        w = varoftype(v.concretetype)
-                        newop = SpaceOperation('stm_barrier', [c_info, v], w)
-                        newoperations.append(newop)
-                        v_holder[0] = w
-                        category[w] = to
-                #
-                newop = SpaceOperation(op.opname,
-                                       [renamings_get(v) for v in op.args],
-                                       op.result)
-                newoperations.append(newop)
-                #
-                if op in expand_comparison:
-                    cats = ''.join([get_category(v) for v in newop.args])
-                    if ('N' not in cats and
-                            cats not in ('LL', 'LW', 'WL', 'WW')):
-                        if newop.opname == 'ptr_ne':
-                            v = varoftype(lltype.Bool)
-                            negop = SpaceOperation('bool_not', [v],
-                                                   newop.result)
-                            newoperations.append(negop)
-                            newop.result = v
-                        newop.opname = 'stm_ptr_eq'
-                #
-                effectinfo = stmtransformer.write_analyzer.analyze(
-                    op, graphinfo=graphinfo)
-                if effectinfo:
-                    if effectinfo is top_set:
-                        category.clear()
-                    else:
-                        types = set([entry[1] for entry in effectinfo])
-                        for v in category.keys():
-                            if v.concretetype in types and category[v] == 'R':
-                                category[v] = 'O'
-                #
-                if op.opname in MALLOCS:
-                    category[op.result] = 'W'
-
-            block.operations = newoperations
-            #
-            for link in block.exits:
-                newoperations = []
-                for i, v in enumerate(link.args):
-                    link.args[i] = renamings_get(v)
-                if newoperations:
-                    # must put them in a fresh block along the link
-                    annotator = stmtransformer.translator.annotator
-                    newblock = insert_empty_block(annotator, link,
-                                                  newoperations)
diff --git a/pypy/translator/stm/transform2.py 
b/pypy/translator/stm/writebarrier.py
copy from pypy/translator/stm/transform2.py
copy to pypy/translator/stm/writebarrier.py
--- a/pypy/translator/stm/transform2.py
+++ b/pypy/translator/stm/writebarrier.py
@@ -1,33 +1,7 @@
 from pypy.objspace.flow.model import SpaceOperation, Constant, Variable
-from pypy.objspace.flow.model import checkgraph, c_last_exception, Block, Link
 from pypy.translator.unsimplify import varoftype, insert_empty_block
 from pypy.rpython.lltypesystem import lltype
-from pypy.translator.backendopt.writeanalyze import WriteAnalyzer, top_set
-
-
-
-class STMTransformer(object):
-
-    def __init__(self, translator):
-        self.translator = translator
-
-    def transform(self):
-        assert not hasattr(self.translator, 'stm_transformation_applied')
-        self.start_log()
-        self.write_analyzer = WriteAnalyzer(self.translator)
-        for graph in self.translator.graphs:
-            pre_insert_stm_barrier(self, graph)
-        del self.write_analyzer
-        self.translator.stm_transformation_applied = True
-        self.print_logs()
-
-    def start_log(self):
-        from pypy.translator.c.support import log
-        log.info("Software Transactional Memory transformation")
-
-    def print_logs(self):
-        from pypy.translator.c.support import log
-        log.info("Software Transactional Memory transformation applied")
+from pypy.translator.backendopt.writeanalyze import top_set
 
 
 MALLOCS = set([
@@ -69,7 +43,7 @@
     raise AssertionError(op)
 
 
-def pre_insert_stm_barrier(stmtransformer, graph):
+def insert_stm_barrier(stmtransformer, graph):
     graphinfo = stmtransformer.write_analyzer.compute_graph_info(graph)
 
     def get_category(v):
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to