[pypy-commit] pypy framestate: Refactor FrameState
rlamy
noreply at buildbot.pypy.org
Fri Nov 21 00:57:17 CET 2014
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: framestate
Changeset: r74622:06b064a032d8
Date: 2014-11-20 23:48 +0000
http://bitbucket.org/pypy/pypy/changeset/06b064a032d8/
Log: Refactor FrameState
diff --git a/rpython/flowspace/flowcontext.py b/rpython/flowspace/flowcontext.py
--- a/rpython/flowspace/flowcontext.py
+++ b/rpython/flowspace/flowcontext.py
@@ -12,8 +12,7 @@
from rpython.flowspace.argument import CallSpec
from rpython.flowspace.model import (Constant, Variable, Block, Link,
c_last_exception, const, FSException)
-from rpython.flowspace.framestate import (FrameState, recursively_unflatten,
- recursively_flatten)
+from rpython.flowspace.framestate import FrameState
from rpython.flowspace.specialcase import (rpython_print_item,
rpython_print_newline)
from rpython.flowspace.operation import op
@@ -342,28 +341,14 @@
del self.stack[finaldepth:]
def getstate(self, next_offset):
- data = self.locals_w[:]
- data.extend(self.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.w_value)
- recursively_flatten(data)
- return FrameState(data, self.blockstack[:], next_offset)
+ return FrameState(self.locals_w[:], self.stack[:],
+ self.last_exception, self.blockstack[:], next_offset)
def setstate(self, state):
""" Reset the context to the given frame state. """
- data = state.mergeable[:]
- recursively_unflatten(data)
- self.locals_w = data[:self.nlocals]
- self.stack = data[self.nlocals:-2]
- if data[-2] == Constant(None):
- assert data[-1] == Constant(None)
- self.last_exception = None
- else:
- self.last_exception = FSException(data[-2], data[-1])
+ self.locals_w = state.locals_w[:]
+ self.stack = state.stack[:]
+ self.last_exception = state.last_exception
self.blockstack = state.blocklist[:]
self._normalize_raise_signals()
diff --git a/rpython/flowspace/framestate.py b/rpython/flowspace/framestate.py
--- a/rpython/flowspace/framestate.py
+++ b/rpython/flowspace/framestate.py
@@ -1,21 +1,47 @@
-from rpython.flowspace.model import Variable, Constant
+from rpython.flowspace.model import Variable, Constant, FSException
from rpython.rlib.unroll import SpecTag
+def _copy(v):
+ from rpython.flowspace.flowcontext import FlowSignal
+ if isinstance(v, Variable):
+ return Variable(v)
+ elif isinstance(v, FlowSignal):
+ vars = [_copy(var) for var in v.args]
+ return v.rebuild(*vars)
+ else:
+ return v
+
+def _union(seq1, seq2):
+ return [union(v1, v2) for v1, v2 in zip(seq1, seq2)]
+
class FrameState(object):
- def __init__(self, mergeable, blocklist, next_offset):
- self.mergeable = mergeable
+ def __init__(self, locals_w, stack, last_exception, blocklist, next_offset):
+ self.locals_w = locals_w
+ self.stack = stack
+ self.last_exception = last_exception
self.blocklist = blocklist
self.next_offset = next_offset
+ @property
+ def mergeable(self):
+ data = self.locals_w + self.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.w_value)
+ recursively_flatten(data)
+ return data
+
def copy(self):
"Make a copy of this state in which all Variables are fresh."
- newstate = []
- for w in self.mergeable:
- if isinstance(w, Variable):
- w = Variable(w)
- newstate.append(w)
- return FrameState(newstate, self.blocklist, self.next_offset)
+ exc = self.last_exception
+ 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.next_offset)
def getvariables(self):
return [w for w in self.mergeable if isinstance(w, Variable)]
@@ -38,13 +64,21 @@
A state 'a' is more general than a state 'b' if all Variables in 'b'
are also Variables in 'a', but 'a' may have more Variables.
"""
- newstate = []
try:
- for w1, w2 in zip(self.mergeable, other.mergeable):
- newstate.append(union(w1, w2))
+ locals = _union(self.locals_w, other.locals_w)
+ stack = _union(self.stack, other.stack)
+ if self.last_exception is None:
+ exc = other.last_exception
+ elif other.last_exception is None:
+ exc = self.last_exception
+ else:
+ e1 = self.last_exception
+ e2 = other.last_exception
+ exc = FSException(union(e1.w_type, e2.w_type),
+ union(e1.w_value, e2.w_value))
except UnionError:
return None
- return FrameState(newstate, self.blocklist, self.next_offset)
+ return FrameState(locals, stack, exc, self.blocklist, self.next_offset)
def getoutputargs(self, targetstate):
"Return the output arguments needed to link self to targetstate."
@@ -61,6 +95,7 @@
def union(w1, w2):
"Union of two variables or constants."
+ from rpython.flowspace.flowcontext import FlowSignal
if w1 == w2:
return w1
if w1 is None or w2 is None:
@@ -69,17 +104,17 @@
if isinstance(w1, Variable) or isinstance(w2, Variable):
return Variable() # new fresh Variable
if isinstance(w1, Constant) and isinstance(w2, Constant):
- # FlowSignal represent stack unrollers in the stack.
- # They should not be merged because they will be unwrapped.
- # This is needed for try:except: and try:finally:, though
- # it makes the control flow a bit larger by duplicating the
- # handlers.
- dont_merge_w1 = w1 in UNPICKLE_TAGS or isinstance(w1.value, SpecTag)
- dont_merge_w2 = w2 in UNPICKLE_TAGS or isinstance(w2.value, SpecTag)
- if dont_merge_w1 or dont_merge_w2:
+ if isinstance(w1.value, SpecTag) or isinstance(w2.value, SpecTag):
raise UnionError
else:
return Variable() # generalize different constants
+ if isinstance(w1, FlowSignal) and isinstance(w2, FlowSignal):
+ if type(w1) is not type(w2):
+ raise UnionError
+ vars = [union(v1, v2) for v1, v2 in zip(w1.args, w2.args)]
+ return w1.rebuild(*vars)
+ if isinstance(w1, FlowSignal) or isinstance(w2, FlowSignal):
+ raise UnionError
raise TypeError('union of %r and %r' % (w1.__class__.__name__,
w2.__class__.__name__))
diff --git a/rpython/flowspace/pygraph.py b/rpython/flowspace/pygraph.py
--- a/rpython/flowspace/pygraph.py
+++ b/rpython/flowspace/pygraph.py
@@ -11,10 +11,10 @@
def __init__(self, func, code):
from rpython.flowspace.flowcontext import SpamBlock
- data = [None] * code.co_nlocals
+ locals = [None] * code.co_nlocals
for i in range(code.formalargcount):
- data[i] = Variable(code.co_varnames[i])
- state = FrameState(data + [Constant(None), Constant(None)], [], 0)
+ locals[i] = Variable(code.co_varnames[i])
+ state = FrameState(locals, [], None, [], 0)
initialblock = SpamBlock(state)
super(PyGraph, self).__init__(self._sanitize_funcname(func), initialblock)
self.func = func
More information about the pypy-commit
mailing list