Author: Armin Rigo <ar...@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 _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit