[pypy-commit] pypy stm: Keep track of the stm mode in which the LLSTMFrame is.

arigo noreply at buildbot.pypy.org
Thu Oct 27 19:36:42 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: stm
Changeset: r48525:acb04280b949
Date: 2011-10-27 16:10 +0200
http://bitbucket.org/pypy/pypy/changeset/acb04280b949/

Log:	Keep track of the stm mode in which the LLSTMFrame is. Only allow
	operations that make sense in the current mode.

diff --git a/pypy/translator/stm/_rffi_stm.py b/pypy/translator/stm/_rffi_stm.py
--- a/pypy/translator/stm/_rffi_stm.py
+++ b/pypy/translator/stm/_rffi_stm.py
@@ -24,7 +24,7 @@
 descriptor_init = llexternal('stm_descriptor_init', [], lltype.Void)
 descriptor_done = llexternal('stm_descriptor_done', [], lltype.Void)
 
-begin_transaction = llexternal('STM_begin_transaction',[], lltype.Void)
+begin_transaction = llexternal('STM_begin_transaction', [], lltype.Void)
 commit_transaction = llexternal('stm_commit_transaction', [], lltype.Signed)
 
 stm_read_word = llexternal('stm_read_word', [SignedP], lltype.Signed)
diff --git a/pypy/translator/stm/llstminterp.py b/pypy/translator/stm/llstminterp.py
--- a/pypy/translator/stm/llstminterp.py
+++ b/pypy/translator/stm/llstminterp.py
@@ -1,13 +1,15 @@
 from pypy.rpython.llinterp import LLFrame
+from pypy.translator.stm import rstm
 
 
 class ForbiddenInstructionInSTMMode(Exception):
     pass
 
 
-def eval_stm_graph(llinterp, graph, values):
+def eval_stm_graph(llinterp, graph, values, stm_mode="not_in_transaction"):
     llinterp.frame_class = LLSTMFrame
     try:
+        llinterp.stm_mode = stm_mode
         return llinterp.eval_graph(graph, values)
     finally:
         llinterp.frame_class = LLFrame
@@ -15,23 +17,60 @@
 
 class LLSTMFrame(LLFrame):
 
-    ALLOW_OPERATIONS = set([
+    ALWAYS_ALLOW_OPERATIONS = set([
         'int_*',
         ])
+    ALLOW_WHEN_NOT_IN_TRANSACTION = set([
+        'stm_begin_transaction',
+        ])
+    ALLOW_WHEN_REGULAR_TRANSACTION = set([
+        'stm_getfield', 'stm_setfield',
+        'stm_commit_transaction',
+        ])
+    ALLOW_WHEN_INEVITABLE_TRANSACTION = ALLOW_WHEN_REGULAR_TRANSACTION.union(
+        set([
+        ]))
 
     def getoperationhandler(self, opname):
-        ophandler = getattr(self, 'opstm_' + opname, None)
+        stm_mode = self.llinterpreter.stm_mode
+        attrname = '_opstm_%s__%s' % (stm_mode, opname)
+        ophandler = getattr(self, attrname, None)
         if ophandler is None:
-            self._validate_stmoperation_handler(opname)
+            self._validate_stmoperation_handler(stm_mode, opname)
             ophandler = LLFrame.getoperationhandler(self, opname)
-            setattr(self, 'opstm_' + opname, ophandler)
+            setattr(self, attrname, ophandler)
         return ophandler
 
-    def _validate_stmoperation_handler(self, opname):
-        OK = self.ALLOW_OPERATIONS
-        if opname in OK:
+    def _op_in_set(self, opname, set):
+        if opname in set:
+            return True
+        for i in range(len(opname)-1, -1, -1):
+            if (opname[:i] + '*') in set:
+                return True
+        return False
+
+    def _validate_stmoperation_handler(self, stm_mode, opname):
+        if self._op_in_set(opname, self.ALWAYS_ALLOW_OPERATIONS):
             return
-        for i in range(len(opname)-1, -1, -1):
-            if (opname[:i] + '*') in OK:
-                return
-        raise ForbiddenInstructionInSTMMode(opname, self.graph)
+        allow = getattr(self, 'ALLOW_WHEN_' + stm_mode.upper())
+        if self._op_in_set(opname, allow):
+            return
+        raise ForbiddenInstructionInSTMMode(stm_mode, opname, self.graph)
+
+    # ---------- stm-only operations ----------
+    # Note that for these tests we assume no real multithreading,
+    # so that we just emulate the operations the easy way
+
+    def op_stm_getfield(self, struct, fieldname):
+        return self.op_getfield(struct, fieldname)
+
+    def op_stm_setfield(self, struct, fieldname, value):
+        self.op_setfield(struct, fieldname, value)
+
+    def op_stm_begin_transaction(self):
+        assert self.llinterpreter.stm_mode == "not_in_transaction"
+        self.llinterpreter.stm_mode = "regular_transaction"
+
+    def op_stm_commit_transaction(self):
+        assert self.llinterpreter.stm_mode != "not_in_transaction"
+        self.llinterpreter.stm_mode = "not_in_transaction"
diff --git a/pypy/translator/stm/rstm.py b/pypy/translator/stm/rstm.py
--- a/pypy/translator/stm/rstm.py
+++ b/pypy/translator/stm/rstm.py
@@ -79,6 +79,14 @@
         #print 'getting %x, mask=%x, replacing with %x' % (word, mask, val)
         _rffi_stm.stm_write_word(p, val)
 
+def begin_transaction():
+    "NOT_RPYTHON"
+    raise NotImplementedError("hard to really emulate")
+
+def commit_transaction():
+    "NOT_RPYTHON"
+    raise NotImplementedError("hard to really emulate")
+
 # ____________________________________________________________
 
 
@@ -93,6 +101,7 @@
         v_structptr = hop.inputarg(r_structptr, arg=0)
         fieldname = hop.args_v[1].value
         c_fieldname = hop.inputconst(lltype.Void, fieldname)
+        hop.exception_cannot_occur()
         return hop.genop('stm_getfield', [v_structptr, c_fieldname],
                          resulttype = hop.r_result)
 
@@ -109,4 +118,16 @@
         fieldname = hop.args_v[1].value
         v_newvalue = hop.inputarg(hop.args_r[2], arg=2)
         c_fieldname = hop.inputconst(lltype.Void, fieldname)
+        hop.exception_cannot_occur()
         hop.genop('stm_setfield', [v_structptr, c_fieldname, v_newvalue])
+
+
+class ExtEntry(ExtRegistryEntry):
+    _about_ = (begin_transaction, commit_transaction)
+
+    def compute_result_annotation(self):
+        return None
+
+    def specialize_call(self, hop):
+        hop.exception_cannot_occur()
+        hop.genop("stm_" + self.instance.__name__, [])
diff --git a/pypy/translator/stm/test/test_llstminterp.py b/pypy/translator/stm/test/test_llstminterp.py
--- a/pypy/translator/stm/test/test_llstminterp.py
+++ b/pypy/translator/stm/test/test_llstminterp.py
@@ -3,6 +3,7 @@
 from pypy.rpython.test.test_llinterp import get_interpreter
 from pypy.translator.stm.llstminterp import eval_stm_graph
 from pypy.translator.stm.llstminterp import ForbiddenInstructionInSTMMode
+from pypy.translator.stm import rstm
 
 
 def test_simple():
@@ -20,4 +21,35 @@
         return p.x
     interp, graph = get_interpreter(func, [p])
     py.test.raises(ForbiddenInstructionInSTMMode,
+                   eval_stm_graph, interp, graph, [p],
+                   stm_mode="regular_transaction")
+
+def test_stm_getfield():
+    S = lltype.GcStruct('S', ('x', lltype.Signed))
+    p = lltype.malloc(S, immortal=True)
+    p.x = 42
+    def func(p):
+        return rstm.stm_getfield(p, 'x')
+    interp, graph = get_interpreter(func, [p])
+    # forbidden in "not_in_transaction" mode
+    py.test.raises(ForbiddenInstructionInSTMMode,
                    eval_stm_graph, interp, graph, [p])
+    # works in "regular_transaction" mode
+    res = eval_stm_graph(interp, graph, [p], stm_mode="regular_transaction")
+    assert res == 42
+    # works in "inevitable_transaction" mode
+    res = eval_stm_graph(interp, graph, [p], stm_mode="inevitable_transaction")
+    assert res == 42
+
+def test_begin_commit_transaction():
+    S = lltype.GcStruct('S', ('x', lltype.Signed))
+    p = lltype.malloc(S, immortal=True)
+    p.x = 42
+    def func(p):
+        rstm.begin_transaction()
+        res = rstm.stm_getfield(p, 'x')
+        rstm.commit_transaction()
+        return res
+    interp, graph = get_interpreter(func, [p])
+    res = eval_stm_graph(interp, graph, [p])
+    assert res == 42


More information about the pypy-commit mailing list