Commits

Maciej Fijalkowski  committed 0af194d

Revert SpaceOperation changes, they're parked on a branch for now

  • Participants
  • Parent commits 7c5ce8b

Comments (0)

Files changed (13)

File pypy/jit/codewriter/jtransform.py

 
     def _do_renaming(self, rename, op):
         op = SpaceOperation(op.opname, op.args[:], op.result)
-        args = list(op.args)
         for i, v in enumerate(op.args):
             if isinstance(v, Variable):
                 if v in rename:
-                    args[i] = rename[v]
+                    op.args[i] = rename[v]
             elif isinstance(v, ListOfKind):
                 newlst = []
                 for x in v:
                     if x in rename:
                         x = rename[x]
                     newlst.append(x)
-                args[i] = ListOfKind(v.kind, newlst)
-        op.args = tuple(args)
+                op.args[i] = ListOfKind(v.kind, newlst)
         return op
 
     def _do_renaming_on_link(self, rename, link):
                            'float_ge': 'float_le',
                            }.get(op.opname, op.opname)
             return SpaceOperation(reversename,
-                                  (op.args[1], op.args[0],) + op.args[2:],
+                                  [op.args[1], op.args[0]] + op.args[2:],
                                   op.result)
         else:
             return op
         c_func, TP = support.builtin_func_for_spec(self.cpu.rtyper,
                                                    oopspec_name, argtypes,
                                                    resulttype, extra, extrakey)
-        return SpaceOperation('direct_call', (c_func,) + args, op.result)
+        return SpaceOperation('direct_call', [c_func] + args, op.result)
 
     def _do_builtin_call(self, op, oopspec_name=None, args=None,
                          extra=None, extrakey=None):
         if op.args[1].value['flavor'] == 'raw':
             ARRAY = op.args[0].value
             return self._do_builtin_call(op, 'raw_malloc',
-                                         (op.args[2],),
+                                         [op.args[2]],
                                          extra = (ARRAY,),
                                          extrakey = ARRAY)
         if op.args[0].value == rstr.STR:
-            return SpaceOperation('newstr', (op.args[2],), op.result)
+            return SpaceOperation('newstr', [op.args[2]], op.result)
         elif op.args[0].value == rstr.UNICODE:
-            return SpaceOperation('newunicode', (op.args[2],), op.result)
+            return SpaceOperation('newunicode', [op.args[2]], op.result)
         else:
             # XXX only strings or simple arrays for now
             ARRAY = op.args[0].value
             arraydescr = self.cpu.arraydescrof(ARRAY)
-            return SpaceOperation('new_array', (arraydescr, op.args[2]),
+            return SpaceOperation('new_array', [arraydescr, op.args[2]],
                                   op.result)
 
     def rewrite_op_free(self, op):
         flags = op.args[1].value
         assert flags['flavor'] == 'raw'
         ARRAY = op.args[0].concretetype.TO
-        return self._do_builtin_call(op, 'raw_free', (op.args[0],),
+        return self._do_builtin_call(op, 'raw_free', [op.args[0]],
                                      extra = (ARRAY,), extrakey = ARRAY)
 
     def rewrite_op_getarrayitem(self, op):
                 if hasattr(rtti._obj, 'destructor_funcptr'):
                     RESULT = lltype.Ptr(STRUCT)
                     assert RESULT == op.result.concretetype
-                    return self._do_builtin_call(op, 'alloc_with_del', (),
+                    return self._do_builtin_call(op, 'alloc_with_del', [],
                                                  extra = (RESULT, vtable),
                                                  extrakey = STRUCT)
             heaptracker.register_known_gctype(self.cpu, vtable, STRUCT)

File pypy/jit/codewriter/test/test_jtransform.py

                 if isinstance(name2, str):
                     name2 = name2, name2
                 if isinstance(v1, Constant) and isinstance(v2, Variable):
-                    assert op1.args == (v2, v1)
+                    assert op1.args == [v2, v1]
                     assert op1.result == v3
                     assert op1.opname == name2[1]
                 else:
-                    assert op1.args == (v1, v2)
+                    assert op1.args == [v1, v2]
                     assert op1.result == v3
                     assert op1.opname == name2[0]
 
             op0, op1 = oplist
             assert op0.opname == 'int_add_ovf'
             if isinstance(v1, Constant) and isinstance(v2, Variable):
-                assert op0.args == (v2, v1)
+                assert op0.args == [v2, v1]
                 assert op0.result == v3
             else:
-                assert op0.args == (v1, v2)
+                assert op0.args == [v1, v2]
                 assert op0.result == v3
             assert op1.opname == '-live-'
-            assert op1.args == ()
+            assert op1.args == []
             assert op1.result is None
 
 def test_calls():
         kind = getkind(v.concretetype)
         assert kind == 'void' or kind[0] in expectedkind
     assert op1.opname == '-live-'
-    assert op1.args == ()
+    assert op1.args == []
 
 def direct_call_test(argtypes, restype, expectedkind):
     op = get_direct_call_op(argtypes, restype)
         kind = getkind(v.concretetype)
         assert kind == 'void' or kind[0] in expectedkind
     assert op1.opname == '-live-'
-    assert op1.args == ()
+    assert op1.args == []
 
 def indirect_residual_call_test(argtypes, restype, expectedkind):
     # an indirect call that is residual in all cases is very similar to
     # a residual direct call
     op = get_direct_call_op(argtypes, restype)
-    op = SpaceOperation('indirect_call', (varoftype(op.args[0].concretetype),)
-                        + op.args[1:] + (Constant(['somegraph1', 'somegraph2'],
-                                                  lltype.Void),),
-                        op.result)
+    op.opname = 'indirect_call'
+    op.args[0] = varoftype(op.args[0].concretetype)
+    op.args.append(Constant(['somegraph1', 'somegraph2'], lltype.Void))
     tr = Transformer(FakeCPU(), FakeResidualIndirectCallControl())
     tr.graph = 'someinitialgraph'
     oplist = tr.rewrite_operation(op)
         kind = getkind(v.concretetype)
         assert kind == 'void' or kind[0] in expectedkind
     assert op1.opname == '-live-'
-    assert op1.args == ()
+    assert op1.args == []
 
 def indirect_regular_call_test(argtypes, restype, expectedkind):
     # a regular indirect call is preceded by a guard_value on the
     # function address, so that pyjitpl can know which jitcode to follow
     from pypy.jit.codewriter.flatten import IndirectCallTargets
     op = get_direct_call_op(argtypes, restype)
-    op = SpaceOperation('indirect_call', (varoftype(op.args[0].concretetype),)
-                        + op.args[1:] + (Constant(['somegraph1', 'somegraph2'],
-                                                  lltype.Void),),
-                        op.result)
+    op.opname = 'indirect_call'
+    op.args[0] = varoftype(op.args[0].concretetype)
+    op.args.append(Constant(['somegraph1', 'somegraph2'], lltype.Void))
     tr = Transformer(FakeCPU(), FakeRegularIndirectCallControl())
     tr.graph = 'someinitialgraph'
     oplist = tr.rewrite_operation(op)
     op0gv, op1gv, op0, op1 = oplist
     assert op0gv.opname == '-live-'
-    assert op0gv.args == ()
+    assert op0gv.args == []
     assert op1gv.opname == 'int_guard_value'
-    assert op1gv.args == (op.args[0],)
+    assert op1gv.args == [op.args[0]]
     assert op1gv.result is None
     #
     reskind = getkind(restype)[0]
     # False, because this 'residual_call' will likely call further jitcodes
     # which can do e.g. guard_class or other stuff requiring anyway a -live-.
     assert op1.opname == '-live-'
-    assert op1.args == ()
+    assert op1.args == []
 
 def test_getfield():
     # XXX a more compact encoding would be possible, something along
         op1 = Transformer(FakeCPU()).rewrite_operation(op)
         assert op1.opname == 'getfield_gc_' + suffix
         fielddescr = ('fielddescr', S, name)
-        assert op1.args == (v_parent, fielddescr)
+        assert op1.args == [v_parent, fielddescr]
         assert op1.result == v_result
 
 def test_getfield_typeptr():
     oplist = Transformer(FakeCPU()).rewrite_operation(op)
     op0, op1 = oplist
     assert op0.opname == '-live-'
-    assert op0.args == ()
+    assert op0.args == []
     assert op1.opname == 'guard_class'
-    assert op1.args == (v_parent,)
+    assert op1.args == [v_parent]
     assert op1.result == v_result
 
 def test_setfield():
         op1 = Transformer(FakeCPU()).rewrite_operation(op)
         assert op1.opname == 'setfield_gc_' + suffix
         fielddescr = ('fielddescr', S, name)
-        assert op1.args == (v_parent, fielddescr, v_newvalue)
+        assert op1.args == [v_parent, fielddescr, v_newvalue]
         assert op1.result is None
 
 def test_malloc_new():
                                    Constant({'flavor': 'gc'}, lltype.Void)], v)
     op1 = Transformer(FakeCPU()).rewrite_operation(op)
     assert op1.opname == 'new'
-    assert op1.args == (('sizedescr', S),)
+    assert op1.args == [('sizedescr', S)]
 
 def test_malloc_new_with_vtable():
     vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)
     cpu = FakeCPU()
     op1 = Transformer(cpu).rewrite_operation(op)
     assert op1.opname == 'new_with_vtable'
-    assert op1.args == (('sizedescr', S),)
+    assert op1.args == [('sizedescr', S)]
     #assert heaptracker.descr2vtable(cpu, op1.args[0]) == vtable [type check]
     vtable_int = heaptracker.adr2int(llmemory.cast_ptr_to_adr(vtable))
     assert heaptracker.vtable2descr(cpu, vtable_int) == op1.args[0]
     assert op0.args[0].value == 'alloc_with_del'    # pseudo-function as a str
     assert list(op0.args[2]) == []
     assert op1.opname == '-live-'
-    assert op1.args == ()
+    assert op1.args == []
 
 def test_rename_on_links():
     v1 = Variable()
         op = SpaceOperation(opname, [v1, v2], v3)
         op1 = Transformer().rewrite_operation(op)
         assert op1.opname == opname
-        assert op1.args == (v1, v2)
+        assert op1.args == [v1, v2]
         #
         op = SpaceOperation(opname, [v1, c0], v3)
         op1 = Transformer().rewrite_operation(op)
         assert op1.opname == reducedname
-        assert op1.args == (v1,)
+        assert op1.args == [v1]
         #
         op = SpaceOperation(opname, [c0, v2], v3)
         op1 = Transformer().rewrite_operation(op)
         assert op1.opname == reducedname
-        assert op1.args == (v2,)
+        assert op1.args == [v2]
 
 def test_ptr_eq():
     v1 = varoftype(rclass.OBJECTPTR)
         op = SpaceOperation(opname, [v1, v2], v3)
         op1 = Transformer().rewrite_operation(op)
         assert op1.opname == opname
-        assert op1.args == (v1, v2)
+        assert op1.args == [v1, v2]
         #
         op = SpaceOperation(opname, [v1, c0], v3)
         op1 = Transformer().rewrite_operation(op)
         assert op1.opname == reducedname
-        assert op1.args == (v1,)
+        assert op1.args == [v1]
         #
         op = SpaceOperation(opname, [c0, v2], v3)
         op1 = Transformer().rewrite_operation(op)
         assert op1.opname == reducedname
-        assert op1.args == (v2,)
+        assert op1.args == [v2]
 
 def test_nongc_ptr_eq():
     v1 = varoftype(rclass.NONGCOBJECTPTR)
         op = SpaceOperation(opname, [v1, v2], v3)
         op1 = Transformer().rewrite_operation(op)
         assert op1.opname == opname.replace('ptr_', 'int_')
-        assert op1.args == (v1, v2)
+        assert op1.args == [v1, v2]
         #
         op = SpaceOperation(opname, [v1, c0], v3)
         op1 = Transformer().rewrite_operation(op)
         assert op1.opname == reducedname
-        assert op1.args == (v1,)
+        assert op1.args == [v1]
         #
         op = SpaceOperation(opname, [c0, v2], v3)
         op1 = Transformer().rewrite_operation(op)
         assert op1.opname == reducedname
-        assert op1.args == (v2,)
+        assert op1.args == [v2]
     #
     op = SpaceOperation('ptr_iszero', [v1], v3)
     op1 = Transformer().rewrite_operation(op)
     assert op1.opname == 'int_is_zero'
-    assert op1.args == (v1,)
+    assert op1.args == [v1]
     #
     op = SpaceOperation('ptr_nonzero', [v1], v3)
     op1 = Transformer().rewrite_operation(op)
     assert op1.opname == 'int_is_true'
-    assert op1.args == (v1,)
+    assert op1.args == [v1]
 
 def test_str_getinteriorarraysize():
     v = varoftype(lltype.Ptr(rstr.STR))
                         v_result)
     op1 = Transformer().rewrite_operation(op)
     assert op1.opname == 'strlen'
-    assert op1.args == (v,)
+    assert op1.args == [v]
     assert op1.result == v_result
 
 def test_unicode_getinteriorarraysize():
                         v_result)
     op1 = Transformer().rewrite_operation(op)
     assert op1.opname == 'unicodelen'
-    assert op1.args == (v,)
+    assert op1.args == [v]
     assert op1.result == v_result
 
 def test_str_getinteriorfield():
                         v_result)
     op1 = Transformer().rewrite_operation(op)
     assert op1.opname == 'strgetitem'
-    assert op1.args == (v, v_index,)
+    assert op1.args == [v, v_index]
     assert op1.result == v_result
 
 def test_unicode_getinteriorfield():
                         v_result)
     op1 = Transformer().rewrite_operation(op)
     assert op1.opname == 'unicodegetitem'
-    assert op1.args == (v, v_index,)
+    assert op1.args == [v, v_index]
     assert op1.result == v_result
 
 def test_str_setinteriorfield():
                         v_void)
     op1 = Transformer().rewrite_operation(op)
     assert op1.opname == 'strsetitem'
-    assert op1.args == (v, v_index, v_newchr,)
+    assert op1.args == [v, v_index, v_newchr]
     assert op1.result == v_void
 
 def test_unicode_setinteriorfield():
                         v_void)
     op1 = Transformer().rewrite_operation(op)
     assert op1.opname == 'unicodesetitem'
-    assert op1.args == (v, v_index, v_newchr,)
+    assert op1.args == [v, v_index, v_newchr]
     assert op1.result == v_void
 
 def test_promote_1():
     oplist = Transformer().rewrite_operation(op)
     op0, op1, op2 = oplist
     assert op0.opname == '-live-'
-    assert op0.args == ()
+    assert op0.args == []
     assert op1.opname == 'int_guard_value'
-    assert op1.args == (v1,)
+    assert op1.args == [v1]
     assert op1.result is None
     assert op2 is None
 
     Transformer().optimize_block(block)
     assert len(block.operations) == 2
     assert block.operations[0].opname == '-live-'
-    assert block.operations[0].args == ()
+    assert block.operations[0].args == []
     assert block.operations[1].opname == 'int_guard_value'
-    assert block.operations[1].args == (v1,)
+    assert block.operations[1].args == [v1]
     assert block.operations[1].result is None
     assert block.exits[0].args == [v1]
 
     assert len(oplist) == 6
     assert oplist[0].opname == '-live-'
     assert oplist[1].opname == 'int_guard_value'
-    assert oplist[1].args   == (v1,)
+    assert oplist[1].args   == [v1]
     assert oplist[2].opname == '-live-'
     assert oplist[3].opname == 'int_guard_value'
-    assert oplist[3].args   == (v2,)
+    assert oplist[3].args   == [v2]
     assert oplist[4].opname == 'jit_merge_point'
     assert oplist[4].args[0].value == 42
     assert list(oplist[4].args[1]) == [v1, v2]
     op = SpaceOperation('getfield', [v1, Constant('x', lltype.Void)], v2)
     op1 = Transformer(FakeCPU()).rewrite_operation(op)
     assert op1.opname == 'getfield_gc_i'
-    assert op1.args == (v1, ('fielddescr', S, 'x'),)
+    assert op1.args == [v1, ('fielddescr', S, 'x')]
     assert op1.result == v2
 
 def test_getfield_gc_pure():
     op = SpaceOperation('getfield', [v1, Constant('x', lltype.Void)], v2)
     op1 = Transformer(FakeCPU()).rewrite_operation(op)
     assert op1.opname == 'getfield_gc_i_pure'
-    assert op1.args == (v1, ('fielddescr', S, 'x'),)
+    assert op1.args == [v1, ('fielddescr', S, 'x')]
     assert op1.result == v2
 
 def test_getfield_gc_greenfield():
     op = SpaceOperation('getfield', [v1, Constant('x', lltype.Void)], v2)
     op1 = Transformer(FakeCPU(), FakeCC()).rewrite_operation(op)
     assert op1.opname == 'getfield_gc_i_greenfield'
-    assert op1.args == (v1, ('fielddescr', S, 'x'),)
+    assert op1.args == [v1, ('fielddescr', S, 'x')]
     assert op1.result == v2
 
 def test_int_abs():
     op = SpaceOperation('malloc_varsize', [c_STR, c_flavor, v1], v2)
     op1 = Transformer().rewrite_operation(op)
     assert op1.opname == 'newstr'
-    assert op1.args == (v1,)
+    assert op1.args == [v1]
     assert op1.result == v2
 
 def test_str_concat():

File pypy/objspace/flow/model.py

             assert isinstance(a, Variable), a
         self.inputargs = [mapping.get(a, a) for a in self.inputargs]
         for op in self.operations:
-            op.args = tuple([mapping.get(a, a) for a in op.args])
+            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:
     """Attempted wrapping of a type that cannot sanely appear in flow graph or
     during its construction"""
 
+
 class SpaceOperation(object):
     __slots__ = "opname args result offset".split()
-    def __new__(cls, opname, args, result, offset=-1):
-        if opname == 'direct_call':
-            assert isinstance(args[0], Constant)
-        cls = globals().get('SpaceOperation' + str(len(args)), SpaceOperationN)
-        return object.__new__(cls, opname, args, result, offset)
 
     def __init__(self, opname, args, result, offset=-1):
         self.opname = intern(opname)      # operation name
-        self.args   = tuple(args) # mixed list of var/const
+        self.args   = list(args)  # mixed list of var/const
         self.result = result      # either Variable or Constant instance
         self.offset = offset      # offset in code string
 
         return "%r = %s(%s)" % (self.result, self.opname,
                                 ", ".join(map(repr, self.args)))
 
-    def getargs(self):
-        raise NotImplementedError
-    def setargs(self, args):
-        raise NotImplementedError
-    args = property(getargs, setargs)
-
-class SpaceOperation0(SpaceOperation):
-    __slots__ = "opname result offset".split()
-
-    def getargs(self):
-        return ()
-    def setargs(self, args):
-        assert not args
-    args = property(getargs, setargs)
-
-class SpaceOperation1(SpaceOperation):
-    __slots__ = "opname result offset arg0".split()
-
-    def getargs(self):
-        return (self.arg0,)
-    def setargs(self, args):
-        self.arg0, = args
-    args = property(getargs, setargs)
-
-class SpaceOperation2(SpaceOperation):
-    __slots__ = "opname result offset arg0 arg1".split()
-
-    def getargs(self):
-        return (self.arg0, self.arg1)
-    def setargs(self, args):
-        self.arg0, self.arg1 = args
-    args = property(getargs, setargs)
-
-class SpaceOperation3(SpaceOperation):
-    __slots__ = "opname result offset arg0 arg1 arg2".split()
-
-    def getargs(self):
-        return (self.arg0, self.arg1, self.arg2)
-    def setargs(self, args):
-        self.arg0, self.arg1, self.arg2 = args
-    args = property(getargs, setargs)
-
-class SpaceOperationN(SpaceOperation):
-    __slots__ = "opname result offset _args".split()
-
-    def getargs(self):
-        return self._args
-    def setargs(self, args):
-        assert isinstance(args, tuple)
-        self._args = args
-    args = property(getargs, setargs)
-
 class Atom(object):
     def __init__(self, name):
         self.__name__ = name # make save_global happy

File pypy/objspace/flow/test/test_objspace.py

         ops = x.startblock.operations
         assert len(ops) == 2
         assert ops[0].opname == 'simple_call'
-        assert ops[0].args == (Constant(IndexError),)
+        assert ops[0].args == [Constant(IndexError)]
         assert ops[1].opname == 'type'
-        assert ops[1].args == (ops[0].result,)
+        assert ops[1].args == [ops[0].result]
         assert x.startblock.exits[0].args == [ops[1].result, ops[0].result]
         assert x.startblock.exits[0].target is x.exceptblock
 

File pypy/translator/backendopt/mallocprediction.py

                 graphvars = [None] * len(op.args)
             else:
                 graphvars = called_graph.getargs() + [called_graph.getreturnvar()]
-            for var, graphvar in zip(op.args[1:] + (op.result,), graphvars):
+            for var, graphvar in zip(op.args[1:] + [op.result], graphvars):
                 varstate = adi.getstate(var)
                 if varstate is None:
                     #print "no varstate"

File pypy/translator/backendopt/mallocv.py

     def handle_op_indirect_call(self, op):
         v_func = self.rename_nonvirtual(op.args[0], op)
         if isinstance(v_func, Constant):
-            op = SpaceOperation('direct_call', (v_func,) + op.args[1:-1],
+            op = SpaceOperation('direct_call', [v_func] + op.args[1:-1],
                                 op.result)
             return self.handle_op_direct_call(op)
         else:

File pypy/translator/backendopt/raisingop2direct_call.py

 from pypy.translator.backendopt.support import log, all_operations, annotate
 import pypy.rpython.raisingops.raisingops
-from pypy.objspace.flow.model import SpaceOperation
 log = log.raisingop2directcall
 
 def is_raisingop(op):
 
     log('starting')
     seen = {}
-    for block, i, op in all_operations(graphs):
+    for op in all_operations(graphs):
         if not is_raisingop(op):
             continue
         func = getattr(pypy.rpython.raisingops.raisingops, op.opname, None)
         if op.opname not in seen:
             seen[op.opname] = 0
         seen[op.opname] += 1
-        arg = annotate(translator, func, op.result, op.args)
-        block.operations[i] = SpaceOperation('direct_call',
-                                             (arg,) + op.args,
-                                             op.result, i)
+        op.args.insert(0, annotate(translator, func, op.result, op.args))
+        op.opname = 'direct_call'
 
     #statistics...
     for k, v in seen.iteritems():
     #       op.opname += '_' 
 
     #selfdiagnostics... assert that there are no more raisingops
-    for block, i, op in all_operations(graphs):
+    for op in all_operations(graphs):
         if is_raisingop(op):
             log.warning("%s not transformed" % op.opname)
 

File pypy/translator/backendopt/removenoops.py

             if op is not None:
                 for i in range(len(op.args)):
                     if op.args[i] == op_result:
-                        op.args = op.args[:i] + (op_arg,) + op.args[i + 1:]
+                        op.args[i] = op_arg
                 if (op.opname == "indirect_call"
                     and isinstance(op.args[0], Constant)):
                     op.opname = "direct_call"

File pypy/translator/backendopt/storesink.py

 
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.translator.backendopt import removenoops
-from pypy.objspace.flow.model import SpaceOperation
 
 def has_side_effects(op):
     if op.opname == 'debug_assert':
     for block in graph.iterblocks():
         newops = []
         cache = {}
-        for i, op in enumerate(block.operations):
+        for op in block.operations:
             if op.opname == 'getfield':
                 tup = (op.args[0], op.args[1].value)
                 res = cache.get(tup, None)
                 if res is not None:
-                    op = SpaceOperation('same_as', [res], op.result, i)
+                    op.opname = 'same_as'
+                    op.args = [res]
                     added_some_same_as = True
                 else:
                     cache[tup] = op.result

File pypy/translator/backendopt/support.py

 def all_operations(graphs):
     for graph in graphs:
         for block in graph.iterblocks():
-            for i, op in enumerate(block.operations):
-                yield block, i, op
+            for op in block.operations: 
+                yield op
 
 def annotate(translator, func, result, args):
     args   = [arg.concretetype for arg in args]

File pypy/translator/backendopt/test/test_ssa.py

     assert len(b2.inputargs) == 2
     assert len(b3.inputargs) == 2
 
-    assert b2.inputargs == list(b2.operations[0].args)
+    assert b2.inputargs == b2.operations[0].args
     assert len(b1.exits[0].args) == 2
     assert b1.exits[0].args[1] is c
     assert len(b2.exits[0].args) == 2

File pypy/translator/exceptiontransform.py

 
     def replace_stack_unwind(self, block):
         for i in range(len(block.operations)):
-            op = block.operations[i]
-            if op.opname == 'stack_unwind':
+            if block.operations[i].opname == 'stack_unwind':
                 # if there are stack_unwind ops left,
                 # the graph was not stackless-transformed
                 # so we need to raise a StackOverflow in any
                 # case
-                args = [self.rpyexc_raise_stack_overflow_ptr]
-                block.operations[i] = SpaceOperation('direct_call',
-                                                     args, op.result, i)
+                block.operations[i].opname = "direct_call"
+                block.operations[i].args = [self.rpyexc_raise_stack_overflow_ptr]
 
     def replace_fetch_restore_operations(self, block):
         # the gctransformer will create these operations.  It looks as if the
         # order of transformations is important - but the gctransformer will
         # put them in a new graph, so all transformations will run again.
         for i in range(len(block.operations)):
-            op = block.operations[i]
-            opname = op.opname
+            opname = block.operations[i].opname
             if opname == 'gc_fetch_exception':
-                args = [self.rpyexc_fetch_exception_ptr]
-                block.operations[i] = SpaceOperation('direct_call', args,
-                                                     op.result, i)
+                block.operations[i].opname = "direct_call"
+                block.operations[i].args = [self.rpyexc_fetch_exception_ptr]
+
             elif opname == 'gc_restore_exception':
-                args = (self.rpyexc_restore_exception_ptr,) + op.args
-                block.operations[i] = SpaceOperation('direct_call', args,
-                                                     op.result, i)
+                block.operations[i].opname = "direct_call"
+                block.operations[i].args.insert(0, self.rpyexc_restore_exception_ptr)
             elif opname == 'get_exception_addr':    # only for lltype
-                args = (self.rpyexc_get_exception_addr_ptr,) + op.args
-                block.operations[i] = SpaceOperation('direct_call', args,
-                                                     op.result, i)
+                block.operations[i].opname = "direct_call"
+                block.operations[i].args.insert(0, self.rpyexc_get_exception_addr_ptr)
             elif opname == 'get_exc_value_addr':    # only for lltype
-                args = (self.rpyexc_get_exc_value_addr_ptr,) + op.args
-                block.operations[i] = SpaceOperation('direct_call', args,
-                                                     op.result, i)
+                block.operations[i].opname = "direct_call"
+                block.operations[i].args.insert(0, self.rpyexc_get_exc_value_addr_ptr)
 
     def transform_block(self, graph, block):
         need_exc_matching = False

File pypy/translator/simplify.py

                 del block.operations[i]
                 block.renamevariables({op.result: op1.result})
             elif op.args[0] == covfls:
-                block.operations[i] = SpaceOperation('lshift_ovf',
-                                                     op.args[1:], op.result,
-                                                     i)
+                op.opname = 'lshift_ovf'
+                del op.args[0]
 
 def simplify_exceptions(graph):
     """The exception handling caused by non-implicit exceptions
             def rename(v):
                 return renaming.get(v, v)
             def rename_op(op):
-                opname = op.opname
                 args = [rename(a) for a in op.args]
-                if (opname == 'indirect_call' and
-                    isinstance(args[0], Constant)):
-                    opname = 'direct_call'
-                    del args[-1]
-                op = SpaceOperation(opname, args, rename(op.result), op.offset)
+                op = SpaceOperation(op.opname, args, rename(op.result), op.offset)
+                # special case...
+                if op.opname == 'indirect_call':
+                    if isinstance(op.args[0], Constant):
+                        assert isinstance(op.args[-1], Constant)
+                        del op.args[-1]
+                        op.opname = 'direct_call'
                 return op
             for op in link.target.operations:
                 link.prevblock.operations.append(rename_op(op))