Commits

Ronan Lamy committed a86581f Draft

Simplify FrameState constructor

Use frame.getstate() to save the state of the frame instead of the ctor.

Comments (0)

Files changed (3)

pypy/objspace/flow/flowcontext.py

 from pypy.interpreter.pycode import PyCode, cpython_code_signature
 from pypy.objspace.flow import operation
 from pypy.objspace.flow.model import *
-from pypy.objspace.flow.framestate import FrameState, recursively_unflatten
+from pypy.objspace.flow.framestate import (FrameState, recursively_unflatten,
+        recursively_flatten)
 from pypy.rlib import jit
 from pypy.tool.stdlib_opcode import host_bytecode_spec
 
             # the same block.  We will continue, to figure out where the next
             # such operation *would* appear, and we make a join point just
             # before.
-            self.last_join_point = FrameState(frame)
+            self.last_join_point = frame.getstate()
 
     def guessbool(self, ec, w_condition, cases=[False,True],
                   replace_last_variable_except_in_first_case = None):
             arg_list[position] = Constant(value)
         frame.setfastscope(arg_list)
         self.joinpoints = {}
-        initialblock = SpamBlock(FrameState(frame).copy())
+        initialblock = SpamBlock(frame.getstate().copy())
         self.pendingblocks = collections.deque([initialblock])
 
         # CallableFactory.pycall may add class_ to functions that are methods
 
 class FlowSpaceFrame(pyframe.CPythonFrame):
 
+    def getstate(self):
+        # getfastscope() can return real None, for undefined locals
+        data = self.save_locals_stack()
+        if self.last_exception is None:
+            data.append(Constant(None))
+            data.append(Constant(None))
+        else:
+            data.append(self.last_exception.w_type)
+            data.append(self.last_exception.get_w_value(self.space))
+        recursively_flatten(self.space, data)
+        nonmergeable = (self.get_blocklist(),
+            self.last_instr,   # == next_instr when between bytecodes
+            self.w_locals,)
+        return FrameState(data, nonmergeable)
+
     def setstate(self, state):
         """ Reset the frame to the given state. """
         data = state.mergeable[:]

pypy/objspace/flow/framestate.py

-from pypy.interpreter.pyframe import PyFrame
 from pypy.interpreter.pyopcode import SuspendedUnroller
-from pypy.interpreter.error import OperationError
 from pypy.rlib.unroll import SpecTag
 from pypy.objspace.flow.model import *
 
 class FrameState:
-    # XXX this class depends on the internal state of PyFrame objects
-
-    def __init__(self, state):
-        if isinstance(state, PyFrame):
-            # getfastscope() can return real None, for undefined locals
-            data = state.save_locals_stack()
-            if state.last_exception is None:
-                data.append(Constant(None))
-                data.append(Constant(None))
-            else:
-                data.append(state.last_exception.w_type)
-                data.append(state.last_exception.get_w_value(state.space))
-            recursively_flatten(state.space, data)
-            self.mergeable = data
-            self.nonmergeable = (
-                state.get_blocklist(),
-                state.last_instr,   # == next_instr when between bytecodes
-                state.w_locals,
-            )
-        elif isinstance(state, tuple):
-            self.mergeable, self.nonmergeable = state
-        else:
-            raise TypeError("can't get framestate for %r" %
-                            state.__class__.__name__)
+    def __init__(self, mergeable, nonmergeable):
+        self.mergeable = mergeable
+        self.nonmergeable = nonmergeable
         self.next_instr = self.nonmergeable[1]
         for w1 in self.mergeable:
             assert isinstance(w1, (Variable, Constant)) or w1 is None, (
             if isinstance(w, Variable):
                 w = Variable()
             newstate.append(w)
-        return FrameState((newstate, self.nonmergeable))
+        return FrameState(newstate, self.nonmergeable)
 
     def getvariables(self):
         return [w for w in self.mergeable if isinstance(w, Variable)]
                 newstate.append(union(w1, w2))
         except UnionError:
             return None
-        return FrameState((newstate, self.nonmergeable))
+        return FrameState(newstate, self.nonmergeable)
 
     def getoutputargs(self, targetstate):
         "Return the output arguments needed to link self to targetstate."

pypy/objspace/flow/test/test_framestate.py

-
-
 from py.test import raises
 from pypy.objspace.flow.model import *
-from pypy.objspace.flow.framestate import *
 from pypy.interpreter.pycode import PyCode
+from pypy.rlib.unroll import SpecTag
 from pypy.objspace.flow.objspace import FlowObjSpace
 
 class TestFrameState:
 
     def test_eq_framestate(self):
         frame = self.getframe(self.func_simple)
-        fs1 = FrameState(frame)
-        fs2 = FrameState(frame)
+        fs1 = frame.getstate()
+        fs2 = frame.getstate()
         assert fs1 == fs2
 
     def test_neq_hacked_framestate(self):
         frame = self.getframe(self.func_simple)
-        fs1 = FrameState(frame)
+        fs1 = frame.getstate()
         frame.locals_stack_w[frame.pycode.co_nlocals-1] = Variable()
-        fs2 = FrameState(frame)
+        fs2 = frame.getstate()
         assert fs1 != fs2
 
     def test_union_on_equal_framestates(self):
         frame = self.getframe(self.func_simple)
-        fs1 = FrameState(frame)
-        fs2 = FrameState(frame)
+        fs1 = frame.getstate()
+        fs2 = frame.getstate()
         assert fs1.union(fs2) == fs1
 
     def test_union_on_hacked_framestates(self):
         frame = self.getframe(self.func_simple)
-        fs1 = FrameState(frame)
+        fs1 = frame.getstate()
         frame.locals_stack_w[frame.pycode.co_nlocals-1] = Variable()
-        fs2 = FrameState(frame)
+        fs2 = frame.getstate()
         assert fs1.union(fs2) == fs2  # fs2 is more general
         assert fs2.union(fs1) == fs2  # fs2 is more general
 
     def test_restore_frame(self):
         frame = self.getframe(self.func_simple)
-        fs1 = FrameState(frame)
+        fs1 = frame.getstate()
         frame.locals_stack_w[frame.pycode.co_nlocals-1] = Variable()
         frame.setstate(fs1)
-        assert fs1 == FrameState(frame)
+        assert fs1 == frame.getstate()
 
     def test_copy(self):
         frame = self.getframe(self.func_simple)
-        fs1 = FrameState(frame)
+        fs1 = frame.getstate()
         fs2 = fs1.copy()
         assert fs1 == fs2
 
     def test_getvariables(self):
         frame = self.getframe(self.func_simple)
-        fs1 = FrameState(frame)
+        fs1 = frame.getstate()
         vars = fs1.getvariables()
         assert len(vars) == 1
 
     def test_getoutputargs(self):
         frame = self.getframe(self.func_simple)
-        fs1 = FrameState(frame)
+        fs1 = frame.getstate()
         frame.locals_stack_w[frame.pycode.co_nlocals-1] = Variable()
-        fs2 = FrameState(frame)
+        fs2 = frame.getstate()
         outputargs = fs1.getoutputargs(fs2)
         # 'x' -> 'x' is a Variable
         # locals_w[n-1] -> locals_w[n-1] is Constant(None)
 
     def test_union_different_constants(self):
         frame = self.getframe(self.func_simple)
-        fs1 = FrameState(frame)
+        fs1 = frame.getstate()
         frame.locals_stack_w[frame.pycode.co_nlocals-1] = Constant(42)
-        fs2 = FrameState(frame)
+        fs2 = frame.getstate()
         fs3 = fs1.union(fs2)
         frame.setstate(fs3)
         assert isinstance(frame.locals_stack_w[frame.pycode.co_nlocals-1],
 
     def test_union_spectag(self):
         frame = self.getframe(self.func_simple)
-        fs1 = FrameState(frame)
+        fs1 = frame.getstate()
         frame.locals_stack_w[frame.pycode.co_nlocals-1] = Constant(SpecTag())
-        fs2 = FrameState(frame)
+        fs2 = frame.getstate()
         assert fs1.union(fs2) is None   # UnionError