Author: Ronan Lamy <ronan.l...@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 _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit