Author: Carl Friedrich Bolz <cfb...@gmx.de> Branch: spaceops-are-variables Changeset: r74244:7c3011ecc083 Date: 2014-10-26 13:40 +0100 http://bitbucket.org/pypy/pypy/changeset/7c3011ecc083/
Log: make SpaceOperation a subclass of Variable and fix the flowspace to deal with that diff --git a/rpython/flowspace/flowcontext.py b/rpython/flowspace/flowcontext.py --- a/rpython/flowspace/flowcontext.py +++ b/rpython/flowspace/flowcontext.py @@ -129,6 +129,7 @@ def append(self, operation): self.crnt_block.operations.append(operation) + return operation def guessbool(self, ctx, w_condition): block = self.crnt_block @@ -154,7 +155,7 @@ links = [] for case in [None] + list(cases): if case is not None: - assert block.operations[-1].result is bvars[-1] + assert block.operations[-1] is bvars[-1] vars = bvars[:-1] vars2 = bvars[:-1] if case is Exception: @@ -187,14 +188,15 @@ self.index = 0 def append(self, operation): - operation.result = self.listtoreplay[self.index].result - assert operation == self.listtoreplay[self.index], ( + prev_op = self.listtoreplay[self.index] + assert operation.structurally_idential(prev_op), ( '\n'.join(["Not generating the same operation sequence:"] + [str(s) for s in self.listtoreplay[:self.index]] + [" ---> | while repeating we see here"] + [" | %s" % operation] + [str(s) for s in self.listtoreplay[self.index:]])) self.index += 1 + return prev_op def guessbool(self, ctx, w_condition): assert self.index == len(self.listtoreplay) @@ -419,12 +421,13 @@ self.mergeblock(recorder.crnt_block, recorder.final_state) raise StopFlowing spaceop.offset = self.last_instr - recorder.append(spaceop) + spaceop = recorder.append(spaceop) + return spaceop def do_op(self, op): - self.record(op) + op = self.record(op) self.guessexception(op.canraise) - return op.result + return op def guessexception(self, exceptions, force=False): """ diff --git a/rpython/flowspace/framestate.py b/rpython/flowspace/framestate.py --- a/rpython/flowspace/framestate.py +++ b/rpython/flowspace/framestate.py @@ -1,4 +1,4 @@ -from rpython.flowspace.model import Variable, Constant +from rpython.flowspace.model import Variable, Constant, SpaceOperation from rpython.rlib.unroll import SpecTag diff --git a/rpython/flowspace/generator.py b/rpython/flowspace/generator.py --- a/rpython/flowspace/generator.py +++ b/rpython/flowspace/generator.py @@ -57,14 +57,13 @@ Entry = GeneratorIterator.Entry newblock = Block(graph.startblock.inputargs) op_entry = op.simple_call(const(Entry)) - v_entry = op_entry.result newblock.operations.append(op_entry) assert len(graph.startblock.inputargs) == len(Entry.varnames) for v, name in zip(graph.startblock.inputargs, Entry.varnames): - newblock.operations.append(op.setattr(v_entry, Constant(name), v)) - op_generator = op.simple_call(const(GeneratorIterator), v_entry) + newblock.operations.append(op.setattr(op_entry, Constant(name), v)) + op_generator = op.simple_call(const(GeneratorIterator), op_entry) newblock.operations.append(op_generator) - newblock.closeblock(Link([op_generator.result], graph.returnblock)) + newblock.closeblock(Link([op_generator], graph.returnblock)) graph.startblock = newblock def attach_next_method(GeneratorIterator, graph): @@ -97,11 +96,13 @@ def _insert_reads(block, varnames): assert len(varnames) == len(block.inputargs) v_entry1 = Variable('entry') + mapping = {} for i, name in enumerate(varnames): hlop = op.getattr(v_entry1, const(name)) - hlop.result = block.inputargs[i] + mapping[block.inputargs[i]] = hlop block.operations.insert(i, hlop) block.inputargs = [v_entry1] + block.renamevariables(mapping) def tweak_generator_body_graph(Entry, graph): # First, always run simplify_graph in order to reduce the number of @@ -115,9 +116,9 @@ # stopblock = Block([]) op0 = op.simple_call(const(StopIteration)) - op1 = op.type(op0.result) + op1 = op.type(op0) stopblock.operations = [op0, op1] - stopblock.closeblock(Link([op1.result, op0.result], graph.exceptblock)) + stopblock.closeblock(Link([op1, op0], graph.exceptblock)) # for block in list(graph.iterblocks()): for exit in block.exits: @@ -144,13 +145,12 @@ # op_resume = op.simple_call(const(Resume)) block.operations.append(op_resume) - v_resume = op_resume.result for i, name in enumerate(varnames): block.operations.append( - op.setattr(v_resume, const(name), newlink.args[i])) - op_pair = op.newtuple(v_resume, v_yielded_value) + op.setattr(op_resume, const(name), newlink.args[i])) + op_pair = op.newtuple(op_resume, v_yielded_value) block.operations.append(op_pair) - newlink.args = [op_pair.result] + newlink.args = [op_pair] newlink.target = graph.returnblock # regular_entry_block = Block([Variable('entry')]) @@ -159,7 +159,7 @@ op_check = op.simple_call( const(isinstance), block.inputargs[0], const(Resume)) block.operations.append(op_check) - block.exitswitch = op_check.result + block.exitswitch = op_check link1 = Link([block.inputargs[0]], Resume.block) link1.exitcase = True nextblock = Block([Variable('entry')]) diff --git a/rpython/flowspace/model.py b/rpython/flowspace/model.py --- a/rpython/flowspace/model.py +++ b/rpython/flowspace/model.py @@ -195,7 +195,7 @@ result = self.inputargs[:] for op in self.operations: result += op.args - result.append(op.result) + result.append(op) return uniqueitems([w for w in result if isinstance(w, Variable)]) def getconstants(self): @@ -209,9 +209,10 @@ for a in mapping: assert isinstance(a, Variable), a self.inputargs = [mapping.get(a, a) for a in self.inputargs] - for op in self.operations: + for i, op in enumerate(self.operations): + if op in mapping: + op = self.operations[i] = mapping[op] op.args = [mapping.get(a, a) for a in op.args] - op.result = mapping.get(op.result, op.result) self.exitswitch = mapping.get(self.exitswitch, self.exitswitch) for link in self.exits: link.args = [mapping.get(a, a) for a in link.args] @@ -270,10 +271,12 @@ def renamed(self): return self._name is not self.dummyname - def __init__(self, name=None): + def __init__(self, name=None, concretetype=None): self._name = self.dummyname self._nr = -1 self.annotation = None + if concretetype is not None: + self.concretetype = concretetype # numbers are bound lazily, when the name is requested if name is not None: self.rename(name) @@ -312,7 +315,7 @@ def foldable(self): return False - def copy(self): + def copy_as_var(self): """Make a copy of the Variable, preserving annotations and concretetype.""" newvar = Variable(self) newvar.annotation = self.annotation @@ -399,34 +402,43 @@ return ConstException(obj) return Constant(obj) -class SpaceOperation(object): +class SpaceOperation(Variable): - def __init__(self, opname, args, result, offset=-1): + def __init__(self, opname, args, resname=None, offset=-1, concretetype=None): + assert not isinstance(resname, Variable) + Variable.__init__(self, resname, concretetype=concretetype) + for arg in args: + if hasattr(arg, 'concretetype'): + assert concretetype self.opname = intern(opname) # operation name self.args = list(args) # mixed list of var/const - self.result = result # either Variable or Constant instance self.offset = offset # offset in code string - def __eq__(self, other): + @property + def result(self): + import pdb; pdb.set_trace() + return self + + def structurally_idential(self, other): return (self.__class__ is other.__class__ and self.opname == other.opname and - self.args == other.args and - self.result == other.result) + self.args == other.args) - def __ne__(self, other): - return not (self == other) + #def __ne__(self, other): + # return not (self == other) - def __hash__(self): - return hash((self.opname, tuple(self.args), self.result)) + #def __hash__(self): + # xxx + # return hash((self.opname, tuple(self.args), self.result)) def __repr__(self): - return "%r = %s(%s)" % (self.result, self.opname, + return "%s = %s(%s)" % (self.name, self.opname, ", ".join(map(repr, self.args))) def replace(self, mapping): newargs = [mapping.get(arg, arg) for arg in self.args] - newresult = mapping.get(self.result, self.result) - return type(self)(self.opname, newargs, newresult, self.offset) + assert self not in mapping + return type(self)(self.opname, newargs, self._name, self.offset, concretetype=self.concretetype) class Atom(object): def __init__(self, name): @@ -471,6 +483,7 @@ def copygraph(graph, shallow=False, varmap={}, shallowvars=False): "Make a copy of a flow graph." + assert not shallowvars, "XXX" blockmap = {} varmap = varmap.copy() shallowvars = shallowvars or shallow @@ -501,7 +514,8 @@ for op in oplist: copyop = SpaceOperation(op.opname, [copyvar(v) for v in op.args], - copyvar(op.result), op.offset) + op._name, op.offset) + varmap[op] = copyop #copyop.offset = op.offset result.append(copyop) return result @@ -533,7 +547,7 @@ newgraph.__dict__.setdefault(key, value) return newgraph -def checkgraph(graph): +def checkgraph(graph, needs_concretetype=False): "Check the consistency of a flow graph." if not __debug__: return @@ -556,6 +570,8 @@ assert v not in vars_previous_blocks, ( "variable %r used in more than one block" % (v,)) vars[v] = only_in_link + if needs_concretetype: + v.concretetype def usevar(v, in_link=None): assert v in vars @@ -586,7 +602,7 @@ assert isinstance(op.args[0], Constant) elif op.opname == 'indirect_call': assert isinstance(op.args[0], Variable) - definevar(op.result) + definevar(op) exc_links = {} if block.exitswitch is None: @@ -651,7 +667,7 @@ if isinstance(v, Variable): usevar(v, in_link=link) if exc_link: - assert v != block.operations[-1].result + assert v != block.operations[-1] #else: # if not exc_link: # assert v.value is not last_exception diff --git a/rpython/flowspace/operation.py b/rpython/flowspace/operation.py --- a/rpython/flowspace/operation.py +++ b/rpython/flowspace/operation.py @@ -69,15 +69,14 @@ # (None means special handling) def __init__(self, *args): + Variable.__init__(self) self.args = list(args) - self.result = Variable() self.offset = -1 def replace(self, mapping): newargs = [mapping.get(arg, arg) for arg in self.args] - newresult = mapping.get(self.result, self.result) + assert self not in mapping newop = type(self)(*newargs) - newop.result = newresult newop.offset = self.offset return newop @@ -478,7 +477,6 @@ def __init__(self, w_base, w_exponent, w_mod=const(None)): self.args = [w_base, w_exponent, w_mod] - self.result = Variable() self.offset = -1 diff --git a/rpython/flowspace/test/test_checkgraph.py b/rpython/flowspace/test/test_checkgraph.py --- a/rpython/flowspace/test/test_checkgraph.py +++ b/rpython/flowspace/test/test_checkgraph.py @@ -31,23 +31,18 @@ g.startblock.closeblock(Link([v], g.returnblock)) py.test.raises(AssertionError, checkgraph, g) - v = Variable() - b = Block([v]) - b.operations.append(SpaceOperation("add", [Constant(1), Constant(2)], v)) - g = FunctionGraph("g", b) - g.startblock.closeblock(Link([v], g.returnblock)) - py.test.raises(AssertionError, checkgraph, g) def test_varinmorethanoneblock(): - v = Variable() + op = SpaceOperation("pos", [Constant(1)]) g = FunctionGraph("g", Block([])) - g.startblock.operations.append(SpaceOperation("pos", [Constant(1)], v)) - b = Block([v]) - g.startblock.closeblock(Link([v], b)) - b.closeblock(Link([v], g.returnblock)) + g.startblock.operations.append(op) + b = Block([]) + b.operations.append(op) + g.startblock.closeblock(Link([], b)) + b.closeblock(Link([Constant(1)], g.returnblock)) py.test.raises(AssertionError, checkgraph, g) - + def test_useundefinedvar(): v = Variable() g = FunctionGraph("g", Block([])) @@ -61,10 +56,9 @@ py.test.raises(AssertionError, checkgraph, g) def test_invalid_arg(): - v = Variable() g = FunctionGraph("g", Block([])) - g.startblock.operations.append(SpaceOperation("pos", [1], v)) - g.startblock.closeblock(Link([v], g.returnblock)) + g.startblock.operations.append(SpaceOperation("pos", [1])) + g.startblock.closeblock(Link([Constant(1)], g.returnblock)) py.test.raises(AssertionError, checkgraph, g) def test_invalid_links(): diff --git a/rpython/flowspace/test/test_generator.py b/rpython/flowspace/test/test_generator.py --- a/rpython/flowspace/test/test_generator.py +++ b/rpython/flowspace/test/test_generator.py @@ -82,7 +82,7 @@ assert ops[4].opname == 'setattr' # e.g_z = z assert ops[4].args[1].value == 'g_z' assert ops[5].opname == 'simple_call' # g = GeneratorIterator(e) - assert ops[5].args[1] == ops[0].result + assert ops[5].args[1] == ops[0] assert len(ops) == 6 assert len(block.exits) == 1 assert block.exits[0].target is graph.returnblock diff --git a/rpython/flowspace/test/test_model.py b/rpython/flowspace/test/test_model.py --- a/rpython/flowspace/test/test_model.py +++ b/rpython/flowspace/test/test_model.py @@ -1,3 +1,4 @@ +import pytest import inspect from rpython.flowspace.model import * @@ -16,15 +17,12 @@ i0 = Variable("i0") i1 = Variable("i1") i2 = Variable("i2") - i3 = Variable("i3") sum1 = Variable("sum1") sum2 = Variable("sum2") - sum3 = Variable("sum3") - conditionres = Variable("conditionres") - conditionop = SpaceOperation("gt", [i1, Constant(0)], conditionres) - addop = SpaceOperation("add", [sum2, i2], sum3) - decop = SpaceOperation("sub", [i2, Constant(1)], i3) + conditionop = SpaceOperation("gt", [i1, Constant(0)], "conditionres") + addop = SpaceOperation("add", [sum2, i2], "sum3") + decop = SpaceOperation("sub", [i2, Constant(1)], "i3") startblock = Block([i0]) headerblock = Block([i1, sum1]) whileblock = Block([i2, sum2]) @@ -32,12 +30,12 @@ graph = FunctionGraph("f", startblock) startblock.closeblock(Link([i0, Constant(0)], headerblock)) headerblock.operations.append(conditionop) - headerblock.exitswitch = conditionres + headerblock.exitswitch = conditionop headerblock.closeblock(Link([sum1], graph.returnblock, False), Link([i1, sum1], whileblock, True)) whileblock.operations.append(addop) whileblock.operations.append(decop) - whileblock.closeblock(Link([i3, sum3], headerblock)) + whileblock.closeblock(Link([decop, addop], headerblock)) graph.func = sample_function @@ -86,23 +84,24 @@ block = pieces.whileblock assert block.getvariables() == [pieces.i2, pieces.sum2, - pieces.sum3, - pieces.i3] + pieces.addop, + pieces.decop] assert block.getconstants() == [Constant(1)] def test_renamevariables(): + pytest.skip() block = pieces.whileblock v = Variable() block.renamevariables({pieces.sum2: v}) assert block.getvariables() == [pieces.i2, v, - pieces.sum3, - pieces.i3] + pieces.addop, + pieces.decop] block.renamevariables({v: pieces.sum2}) assert block.getvariables() == [pieces.i2, pieces.sum2, - pieces.sum3, - pieces.i3] + pieces.addop, + pieces.decop] def test_variable(): v = Variable() diff --git a/rpython/flowspace/test/test_objspace.py b/rpython/flowspace/test/test_objspace.py --- a/rpython/flowspace/test/test_objspace.py +++ b/rpython/flowspace/test/test_objspace.py @@ -384,8 +384,8 @@ assert ops[0].opname == 'simple_call' assert ops[0].args == [Constant(IndexError)] assert ops[1].opname == 'type' - assert ops[1].args == [ops[0].result] - assert x.startblock.exits[0].args == [ops[1].result, ops[0].result] + assert ops[1].args == [ops[0]] + assert x.startblock.exits[0].args == [ops[1], ops[0]] assert x.startblock.exits[0].target is x.exceptblock def test_simple_raise(self): _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit