[pypy-commit] pypy framestate: Split RETURN_VALUE into 2 intructions and store the active return value on the flow context

rlamy noreply at buildbot.pypy.org
Sat Feb 14 19:48:15 CET 2015


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: framestate
Changeset: r75873:e4db2b64834f
Date: 2015-02-14 18:41 +0000
http://bitbucket.org/pypy/pypy/changeset/e4db2b64834f/

Log:	Split RETURN_VALUE into 2 intructions and store the active return
	value on the flow context

diff --git a/rpython/flowspace/bytecode.py b/rpython/flowspace/bytecode.py
--- a/rpython/flowspace/bytecode.py
+++ b/rpython/flowspace/bytecode.py
@@ -253,7 +253,7 @@
             if not b._exits:
                 instr = b.operations[-1]
                 assert instr.name in (
-                        'RETURN_VALUE', 'RAISE_VARARGS', 'EXEC_STMT')
+                        'RETURN', 'RAISE_VARARGS', 'EXEC_STMT')
             for x in b._exits:
                 assert x in self.blocks
 
@@ -630,13 +630,24 @@
 @bc_reader.register_opcode
 class RETURN_VALUE(NullaryOpcode):
     def bc_flow(self, reader):
-        reader.curr_block.operations.append(self)
+        block = reader.curr_block
+        block.operations.append(SET_RETURN_VALUE(offset=self.offset))
+        block.operations.append(RETURN(offset=self.offset))
         reader.end_block()
 
+class SET_RETURN_VALUE(NullaryOpcode):
+    num = name = 'SET_RETURN_VALUE'
+    arg = NO_ARG
+    def eval(self, ctx):
+        w_value = ctx.popvalue()
+        ctx.w_return_value = w_value
+
+class RETURN(NullaryOpcode):
+    num = name = 'RETURN'
+    arg = NO_ARG
     def eval(self, ctx):
         from rpython.flowspace.flowcontext import Return
-        w_returnvalue = ctx.popvalue()
-        raise Return(w_returnvalue)
+        raise Return()
 
 @bc_reader.register_opcode
 class END_FINALLY(NullaryOpcode):
diff --git a/rpython/flowspace/flowcontext.py b/rpython/flowspace/flowcontext.py
--- a/rpython/flowspace/flowcontext.py
+++ b/rpython/flowspace/flowcontext.py
@@ -291,13 +291,15 @@
 
     def getstate(self, position):
         return FrameState(self.locals_w[:], self.stack[:],
-                self.last_exception, self.blockstack[:], position)
+                self.last_exception, self.w_return_value,
+                self.blockstack[:], position)
 
     def setstate(self, state):
         """ Reset the context to the given frame state. """
         self.locals_w = state.locals_w[:]
         self.stack = state.stack[:]
         self.last_exception = state.last_exception
+        self.w_return_value = state.w_return_value
         self.blockstack = state.blocklist[:]
         self._normalize_raise_signals()
 
@@ -606,7 +608,8 @@
         w_module = self.peekvalue()
         self.pushvalue(self.import_from(w_module, w_name))
 
-    def return_value(self, w_result):
+    def do_return(self):
+        w_result = self.w_return_value
         link = Link([w_result], self.graph.returnblock)
         self.recorder.crnt_block.closeblock(link)
         raise StopFlowing
@@ -1008,22 +1011,18 @@
 
 
 class Return(FlowSignal):
-    """Signals a 'return' statement.
-    Argument is the wrapped object to return.
-    """
-    def __init__(self, w_value):
-        self.w_value = w_value
-
+    """Signals a 'return' statement.  """
     def nomoreblocks(self, ctx):
-        ctx.return_value(self.w_value)
+        ctx.do_return()
 
     @property
     def args(self):
-        return [self.w_value]
+        return []
 
     @staticmethod
-    def rebuild(w_value):
-        return Return(w_value)
+    def rebuild():
+        return Return()
+
 
 class Raise(FlowSignal):
     """Signals an application-level exception
diff --git a/rpython/flowspace/framestate.py b/rpython/flowspace/framestate.py
--- a/rpython/flowspace/framestate.py
+++ b/rpython/flowspace/framestate.py
@@ -16,10 +16,12 @@
 
 
 class FrameState(object):
-    def __init__(self, locals_w, stack, last_exception, blocklist, position):
+    def __init__(self, locals_w, stack, last_exception, w_return_value,
+                 blocklist, position):
         self.locals_w = locals_w
         self.stack = stack
         self.last_exception = last_exception
+        self.w_return_value = w_return_value
         self.blocklist = blocklist
         self.position = position
         self._mergeable = None
@@ -35,6 +37,7 @@
         else:
             data.append(self.last_exception.w_type)
             data.append(self.last_exception.w_value)
+        data.append(self.w_return_value)
         recursively_flatten(data)
         return data
 
@@ -44,7 +47,7 @@
         if exc is not None:
             exc = FSException(_copy(exc.w_type), _copy(exc.w_value))
         return FrameState(map(_copy, self.locals_w), map(_copy, self.stack),
-                exc, self.blocklist, self.position)
+                exc, _copy(self.w_return_value), self.blocklist, self.position)
 
     def getvariables(self):
         return [w for w in self.mergeable if isinstance(w, Variable)]
@@ -84,9 +87,10 @@
                 args2 = other._exc_args()
                 exc = FSException(union(args1[0], args2[0]),
                         union(args1[1], args2[1]))
+            w_rv = union(self.w_return_value, other.w_return_value)
         except UnionError:
             return None
-        return FrameState(locals, stack, exc, self.blocklist, self.position)
+        return FrameState(locals, stack, exc, w_rv, self.blocklist, self.position)
 
     def getoutputargs(self, targetstate):
         "Return the output arguments needed to link self to targetstate."
diff --git a/rpython/flowspace/pygraph.py b/rpython/flowspace/pygraph.py
--- a/rpython/flowspace/pygraph.py
+++ b/rpython/flowspace/pygraph.py
@@ -16,7 +16,7 @@
             locals[i] = Variable(code.co_varnames[i])
         bc_graph = code.graph
         start_pos = bc_graph.entry._exits[0], 0
-        state = FrameState(locals, [], None, [], start_pos)
+        state = FrameState(locals, [], None, None, [], start_pos)
         initialblock = SpamBlock(state)
         super(PyGraph, self).__init__(self._sanitize_funcname(func), initialblock)
         self.func = func
diff --git a/rpython/flowspace/test/test_flowcontext.py b/rpython/flowspace/test/test_flowcontext.py
--- a/rpython/flowspace/test/test_flowcontext.py
+++ b/rpython/flowspace/test/test_flowcontext.py
@@ -5,7 +5,7 @@
     Return, Raise, RaiseImplicit, Continue, Break)
 
 @pytest.mark.parametrize('signal', [
-    Return(Variable()),
+    Return(),
     Raise(FSException(Variable(), Variable())),
     RaiseImplicit(FSException(Variable(), Variable())),
     Break(),


More information about the pypy-commit mailing list