[pypy-commit] pypy stm: - Refactor to support getfield of immutables.
arigo
noreply at buildbot.pypy.org
Thu Oct 27 19:36:46 CEST 2011
Author: Armin Rigo <arigo at tunes.org>
Branch: stm
Changeset: r48528:caa7e690cfc7
Date: 2011-10-27 17:05 +0200
http://bitbucket.org/pypy/pypy/changeset/caa7e690cfc7/
Log: - Refactor to support getfield of immutables. That's enough to
raise simple exceptions.
- Complain when an exception leaves the frame in which we did
begin_transaction().
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,4 +1,5 @@
-from pypy.rpython.llinterp import LLFrame
+from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.llinterp import LLFrame, LLException
from pypy.translator.stm import rstm
@@ -26,35 +27,36 @@
class LLSTMFrame(LLFrame):
ALWAYS_ALLOW_OPERATIONS = set([
- 'int_*',
+ 'int_*', 'same_as', 'cast_*',
'direct_call',
])
- 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([
- ])
def eval(self):
- res = LLFrame.eval(self)
- if (self.llinterpreter.stm_mode == "regular_transaction" and
- self.llinterpreter.last_transaction_started_in_frame is self):
- raise ReturnWithTransactionActive(self.graph)
+ try:
+ res = LLFrame.eval(self)
+ except LLException, e:
+ self.returning_from_frame_now()
+ raise e
+ self.returning_from_frame_now()
return res
+ def returning_from_frame_now(self):
+ if (self.llinterpreter.stm_mode == "regular_transaction" and
+ self.llinterpreter.last_transaction_started_in_frame is self):
+ raise ReturnWithTransactionActive(self.graph)
+
def getoperationhandler(self, opname):
- 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(stm_mode, opname)
- ophandler = LLFrame.getoperationhandler(self, opname)
- setattr(self, attrname, ophandler)
- return ophandler
+ try:
+ return getattr(self, 'opstm_' + opname)
+ except AttributeError:
+ 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(stm_mode, opname)
+ ophandler = LLFrame.getoperationhandler(self, opname)
+ setattr(self, attrname, ophandler)
+ return ophandler
def _op_in_set(self, opname, set):
if opname in set:
@@ -67,26 +69,42 @@
def _validate_stmoperation_handler(self, stm_mode, opname):
if self._op_in_set(opname, self.ALWAYS_ALLOW_OPERATIONS):
return
- allow = getattr(self, 'ALLOW_WHEN_' + stm_mode.upper())
- if self._op_in_set(opname, allow):
- return
raise ForbiddenInstructionInSTMMode(stm_mode, opname, self.graph)
+ # ---------- operations that are sometimes safe ----------
+
+ def opstm_getfield(self, struct, fieldname):
+ STRUCT = lltype.typeOf(struct).TO
+ if STRUCT._immutable_field(fieldname):
+ # immutable field reads are always allowed
+ return LLFrame.op_getfield(self, struct, fieldname)
+ else:
+ # mutable 'getfields' are always forbidden for now
+ self.check_stm_mode(lambda m: False)
+ xxx
+
# ---------- 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 check_stm_mode(self, checker):
+ stm_mode = self.llinterpreter.stm_mode
+ if not checker(stm_mode):
+ raise ForbiddenInstructionInSTMMode(stm_mode, self.graph)
- def op_stm_setfield(self, struct, fieldname, value):
- self.op_setfield(struct, fieldname, value)
+ def opstm_stm_getfield(self, struct, fieldname):
+ self.check_stm_mode(lambda m: m != "not_in_transaction")
+ return LLFrame.op_getfield(self, struct, fieldname)
- def op_stm_begin_transaction(self):
- assert self.llinterpreter.stm_mode == "not_in_transaction"
+ def opstm_stm_setfield(self, struct, fieldname, value):
+ self.check_stm_mode(lambda m: m != "not_in_transaction")
+ LLFrame.op_setfield(self, struct, fieldname, value)
+
+ def opstm_stm_begin_transaction(self):
+ self.check_stm_mode(lambda m: m == "not_in_transaction")
self.llinterpreter.stm_mode = "regular_transaction"
self.llinterpreter.last_transaction_started_in_frame = self
- def op_stm_commit_transaction(self):
- assert self.llinterpreter.stm_mode != "not_in_transaction"
+ def opstm_stm_commit_transaction(self):
+ self.check_stm_mode(lambda m: m != "not_in_transaction")
self.llinterpreter.stm_mode = "not_in_transaction"
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
@@ -6,6 +6,9 @@
from pypy.translator.stm.llstminterp import ReturnWithTransactionActive
from pypy.translator.stm import rstm
+ALL_STM_MODES = ["not_in_transaction",
+ "regular_transaction",
+ "inevitable_transaction"]
def test_simple():
def func(n):
@@ -42,6 +45,18 @@
res = eval_stm_graph(interp, graph, [p], stm_mode="inevitable_transaction")
assert res == 42
+def test_getfield_immutable():
+ S = lltype.GcStruct('S', ('x', lltype.Signed), hints = {'immutable': True})
+ p = lltype.malloc(S, immortal=True)
+ p.x = 42
+ def func(p):
+ return p.x
+ interp, graph = get_interpreter(func, [p])
+ # a plain 'getfield' of an immutable field works in all modes
+ for mode in ALL_STM_MODES:
+ res = eval_stm_graph(interp, graph, [p], stm_mode=mode)
+ assert res == 42
+
def test_begin_commit_transaction():
S = lltype.GcStruct('S', ('x', lltype.Signed))
p = lltype.malloc(S, immortal=True)
@@ -76,3 +91,18 @@
interp, graph = get_interpreter(func, [])
py.test.raises(ReturnWithTransactionActive,
eval_stm_graph, interp, graph, [])
+
+def test_cannot_raise_with_regular_transaction():
+ def g():
+ rstm.begin_transaction()
+ raise ValueError
+ g._dont_inline_ = True
+ def func():
+ try:
+ g()
+ except ValueError:
+ pass
+ rstm.commit_transaction()
+ interp, graph = get_interpreter(func, [])
+ py.test.raises(ReturnWithTransactionActive,
+ eval_stm_graph, interp, graph, [])
More information about the pypy-commit
mailing list