[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