[pypy-svn] r79283 - in pypy/trunk/pypy: objspace/flow objspace/flow/test translator translator/backendopt translator/backendopt/test

fijal at codespeak.net fijal at codespeak.net
Fri Nov 19 19:13:08 CET 2010


Author: fijal
Date: Fri Nov 19 19:13:06 2010
New Revision: 79283

Modified:
   pypy/trunk/pypy/objspace/flow/model.py
   pypy/trunk/pypy/objspace/flow/test/test_objspace.py
   pypy/trunk/pypy/translator/backendopt/mallocprediction.py
   pypy/trunk/pypy/translator/backendopt/mallocv.py
   pypy/trunk/pypy/translator/backendopt/raisingop2direct_call.py
   pypy/trunk/pypy/translator/backendopt/removenoops.py
   pypy/trunk/pypy/translator/backendopt/storesink.py
   pypy/trunk/pypy/translator/backendopt/support.py
   pypy/trunk/pypy/translator/backendopt/test/test_ssa.py
   pypy/trunk/pypy/translator/exceptiontransform.py
   pypy/trunk/pypy/translator/simplify.py
Log:
make SpaceOperations consume less space by making them specialized on exact number of arguments.
Saves a bit of space and a bit of time when annotating.


Modified: pypy/trunk/pypy/objspace/flow/model.py
==============================================================================
--- pypy/trunk/pypy/objspace/flow/model.py	(original)
+++ pypy/trunk/pypy/objspace/flow/model.py	Fri Nov 19 19:13:06 2010
@@ -226,7 +226,7 @@
             assert isinstance(a, Variable), a
         self.inputargs = [mapping.get(a, a) for a in self.inputargs]
         for op in self.operations:
-            op.args = [mapping.get(a, a) for a in op.args]
+            op.args = tuple([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:
@@ -329,13 +329,17 @@
     """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   = list(args)  # mixed list of var/const
+        self.args   = tuple(args) # mixed list of var/const
         self.result = result      # either Variable or Constant instance
         self.offset = offset      # offset in code string
 
@@ -355,6 +359,58 @@
         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

Modified: pypy/trunk/pypy/objspace/flow/test/test_objspace.py
==============================================================================
--- pypy/trunk/pypy/objspace/flow/test/test_objspace.py	(original)
+++ pypy/trunk/pypy/objspace/flow/test/test_objspace.py	Fri Nov 19 19:13:06 2010
@@ -373,9 +373,9 @@
         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
 

Modified: pypy/trunk/pypy/translator/backendopt/mallocprediction.py
==============================================================================
--- pypy/trunk/pypy/translator/backendopt/mallocprediction.py	(original)
+++ pypy/trunk/pypy/translator/backendopt/mallocprediction.py	Fri Nov 19 19:13:06 2010
@@ -80,7 +80,7 @@
                 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"

Modified: pypy/trunk/pypy/translator/backendopt/mallocv.py
==============================================================================
--- pypy/trunk/pypy/translator/backendopt/mallocv.py	(original)
+++ pypy/trunk/pypy/translator/backendopt/mallocv.py	Fri Nov 19 19:13:06 2010
@@ -980,7 +980,7 @@
     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:

Modified: pypy/trunk/pypy/translator/backendopt/raisingop2direct_call.py
==============================================================================
--- pypy/trunk/pypy/translator/backendopt/raisingop2direct_call.py	(original)
+++ pypy/trunk/pypy/translator/backendopt/raisingop2direct_call.py	Fri Nov 19 19:13:06 2010
@@ -1,5 +1,6 @@
 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):
@@ -26,7 +27,7 @@
 
     log('starting')
     seen = {}
-    for op in all_operations(graphs):
+    for block, i, op in all_operations(graphs):
         if not is_raisingop(op):
             continue
         func = getattr(pypy.rpython.raisingops.raisingops, op.opname, None)
@@ -36,8 +37,10 @@
         if op.opname not in seen:
             seen[op.opname] = 0
         seen[op.opname] += 1
-        op.args.insert(0, annotate(translator, func, op.result, op.args))
-        op.opname = 'direct_call'
+        arg = annotate(translator, func, op.result, op.args)
+        block.operations[i] = SpaceOperation('direct_call',
+                                             (arg,) + op.args,
+                                             op.result, i)
 
     #statistics...
     for k, v in seen.iteritems():
@@ -55,7 +58,7 @@
     #       op.opname += '_' 
 
     #selfdiagnostics... assert that there are no more raisingops
-    for op in all_operations(graphs):
+    for block, i, op in all_operations(graphs):
         if is_raisingop(op):
             log.warning("%s not transformed" % op.opname)
 

Modified: pypy/trunk/pypy/translator/backendopt/removenoops.py
==============================================================================
--- pypy/trunk/pypy/translator/backendopt/removenoops.py	(original)
+++ pypy/trunk/pypy/translator/backendopt/removenoops.py	Fri Nov 19 19:13:06 2010
@@ -23,7 +23,7 @@
             if op is not None:
                 for i in range(len(op.args)):
                     if op.args[i] == op_result:
-                        op.args[i] = op_arg
+                        op.args = op.args[:i] + (op_arg,) + op.args[i + 1:]
                 if (op.opname == "indirect_call"
                     and isinstance(op.args[0], Constant)):
                     op.opname = "direct_call"

Modified: pypy/trunk/pypy/translator/backendopt/storesink.py
==============================================================================
--- pypy/trunk/pypy/translator/backendopt/storesink.py	(original)
+++ pypy/trunk/pypy/translator/backendopt/storesink.py	Fri Nov 19 19:13:06 2010
@@ -1,6 +1,7 @@
 
 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':
@@ -22,13 +23,12 @@
     for block in graph.iterblocks():
         newops = []
         cache = {}
-        for op in block.operations:
+        for i, op in enumerate(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.opname = 'same_as'
-                    op.args = [res]
+                    op = SpaceOperation('same_as', [res], op.result, i)
                     added_some_same_as = True
                 else:
                     cache[tup] = op.result

Modified: pypy/trunk/pypy/translator/backendopt/support.py
==============================================================================
--- pypy/trunk/pypy/translator/backendopt/support.py	(original)
+++ pypy/trunk/pypy/translator/backendopt/support.py	Fri Nov 19 19:13:06 2010
@@ -21,8 +21,8 @@
 def all_operations(graphs):
     for graph in graphs:
         for block in graph.iterblocks():
-            for op in block.operations: 
-                yield op
+            for i, op in enumerate(block.operations):
+                yield block, i, op
 
 def annotate(translator, func, result, args):
     args   = [arg.concretetype for arg in args]

Modified: pypy/trunk/pypy/translator/backendopt/test/test_ssa.py
==============================================================================
--- pypy/trunk/pypy/translator/backendopt/test/test_ssa.py	(original)
+++ pypy/trunk/pypy/translator/backendopt/test/test_ssa.py	Fri Nov 19 19:13:06 2010
@@ -75,7 +75,7 @@
     assert len(b2.inputargs) == 2
     assert len(b3.inputargs) == 2
 
-    assert b2.inputargs == b2.operations[0].args
+    assert b2.inputargs == list(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

Modified: pypy/trunk/pypy/translator/exceptiontransform.py
==============================================================================
--- pypy/trunk/pypy/translator/exceptiontransform.py	(original)
+++ pypy/trunk/pypy/translator/exceptiontransform.py	Fri Nov 19 19:13:06 2010
@@ -234,33 +234,39 @@
 
     def replace_stack_unwind(self, block):
         for i in range(len(block.operations)):
-            if block.operations[i].opname == 'stack_unwind':
+            op = block.operations[i]
+            if op.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
-                block.operations[i].opname = "direct_call"
-                block.operations[i].args = [self.rpyexc_raise_stack_overflow_ptr]
+                args = [self.rpyexc_raise_stack_overflow_ptr]
+                block.operations[i] = SpaceOperation('direct_call',
+                                                     args, op.result, i)
 
     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)):
-            opname = block.operations[i].opname
+            op = block.operations[i]
+            opname = op.opname
             if opname == 'gc_fetch_exception':
-                block.operations[i].opname = "direct_call"
-                block.operations[i].args = [self.rpyexc_fetch_exception_ptr]
-
+                args = [self.rpyexc_fetch_exception_ptr]
+                block.operations[i] = SpaceOperation('direct_call', args,
+                                                     op.result, i)
             elif opname == 'gc_restore_exception':
-                block.operations[i].opname = "direct_call"
-                block.operations[i].args.insert(0, self.rpyexc_restore_exception_ptr)
+                args = (self.rpyexc_restore_exception_ptr,) + op.args
+                block.operations[i] = SpaceOperation('direct_call', args,
+                                                     op.result, i)
             elif opname == 'get_exception_addr':    # only for lltype
-                block.operations[i].opname = "direct_call"
-                block.operations[i].args.insert(0, self.rpyexc_get_exception_addr_ptr)
+                args = (self.rpyexc_get_exception_addr_ptr,) + op.args
+                block.operations[i] = SpaceOperation('direct_call', args,
+                                                     op.result, i)
             elif opname == 'get_exc_value_addr':    # only for lltype
-                block.operations[i].opname = "direct_call"
-                block.operations[i].args.insert(0, self.rpyexc_get_exc_value_addr_ptr)
+                args = (self.rpyexc_get_exc_value_addr_ptr,) + op.args
+                block.operations[i] = SpaceOperation('direct_call', args,
+                                                     op.result, i)
 
     def transform_block(self, graph, block):
         need_exc_matching = False

Modified: pypy/trunk/pypy/translator/simplify.py
==============================================================================
--- pypy/trunk/pypy/translator/simplify.py	(original)
+++ pypy/trunk/pypy/translator/simplify.py	Fri Nov 19 19:13:06 2010
@@ -146,8 +146,9 @@
                 del block.operations[i]
                 block.renamevariables({op.result: op1.result})
             elif op.args[0] == covfls:
-                op.opname = 'lshift_ovf'
-                del op.args[0]
+                block.operations[i] = SpaceOperation('lshift_ovf',
+                                                     op.args[1:], op.result,
+                                                     i)
 
 def simplify_exceptions(graph):
     """The exception handling caused by non-implicit exceptions
@@ -293,14 +294,13 @@
             def rename(v):
                 return renaming.get(v, v)
             def rename_op(op):
+                opname = op.opname
                 args = [rename(a) for a in op.args]
-                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'
+                if (opname == 'indirect_call' and
+                    isinstance(args[0], Constant)):
+                    opname = 'direct_call'
+                    del args[-1]
+                op = SpaceOperation(opname, args, rename(op.result), op.offset)
                 return op
             for op in link.target.operations:
                 link.prevblock.operations.append(rename_op(op))



More information about the Pypy-commit mailing list