Author: Armin Rigo <[email protected]>
Branch: stm
Changeset: r48527:070bf17d0fbb
Date: 2011-10-27 16:47 +0200
http://bitbucket.org/pypy/pypy/changeset/070bf17d0fbb/

Log:    We cannot return out of the frame that started a regular
        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
@@ -5,12 +5,20 @@
 class ForbiddenInstructionInSTMMode(Exception):
     pass
 
+class ReturnWithTransactionActive(Exception):
+    pass
+
 
 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)
+        llinterp.last_transaction_started_in_frame = None
+        res = llinterp.eval_graph(graph, values)
+        assert llinterp.stm_mode == stm_mode, (
+            "llinterp.stm_mode is %r after eval_graph, but should be %r" % (
+            llinterp.stm_mode, stm_mode))
+        return res
     finally:
         llinterp.frame_class = LLFrame
 
@@ -19,6 +27,7 @@
 
     ALWAYS_ALLOW_OPERATIONS = set([
         'int_*',
+        'direct_call',
         ])
     ALLOW_WHEN_NOT_IN_TRANSACTION = set([
         'stm_begin_transaction',
@@ -30,6 +39,13 @@
     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)
+        return res
+
     def getoperationhandler(self, opname):
         stm_mode = self.llinterpreter.stm_mode
         attrname = '_opstm_%s__%s' % (stm_mode, opname)
@@ -69,6 +85,7 @@
     def op_stm_begin_transaction(self):
         assert self.llinterpreter.stm_mode == "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"
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.llstminterp import ReturnWithTransactionActive
 from pypy.translator.stm import rstm
 
 
@@ -53,3 +54,25 @@
     interp, graph = get_interpreter(func, [p])
     res = eval_stm_graph(interp, graph, [p])
     assert res == 42
+
+def test_call_and_return_with_regular_transaction():
+    def g():
+        pass
+    g._dont_inline_ = True
+    def func():
+        rstm.begin_transaction()
+        g()
+        rstm.commit_transaction()
+    interp, graph = get_interpreter(func, [])
+    eval_stm_graph(interp, graph, [])
+
+def test_cannot_return_with_regular_transaction():
+    def g():
+        rstm.begin_transaction()
+    g._dont_inline_ = True
+    def func():
+        g()
+        rstm.commit_transaction()
+    interp, graph = get_interpreter(func, [])
+    py.test.raises(ReturnWithTransactionActive,
+                   eval_stm_graph, interp, graph, [])
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to