[pypy-svn] r48269 - in pypy/dist/pypy/translator/backendopt: . test

cfbolz at codespeak.net cfbolz at codespeak.net
Sat Nov 3 16:19:46 CET 2007


Author: cfbolz
Date: Sat Nov  3 16:19:46 2007
New Revision: 48269

Modified:
   pypy/dist/pypy/translator/backendopt/coalloc.py
   pypy/dist/pypy/translator/backendopt/test/test_coalloc.py
Log:
replace mallocs by coallocs


Modified: pypy/dist/pypy/translator/backendopt/coalloc.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/coalloc.py	(original)
+++ pypy/dist/pypy/translator/backendopt/coalloc.py	Sat Nov  3 16:19:46 2007
@@ -7,6 +7,7 @@
 from pypy.tool.uid import uid
 
 class CreationPoint(object):
+    constant = None
     def __init__(self, creation_method, TYPE):
         self.creation_method = creation_method
         self.TYPE = TYPE
@@ -64,6 +65,7 @@
         else:
             if var_or_const not in self.constant_cps:
                 crep = CreationPoint("constant", var_or_const.concretetype)
+                crep.constant = var_or_const
                 self.constant_cps[var_or_const] = crep
             else:
                 crep = self.constant_cps[var_or_const]
@@ -154,8 +156,7 @@
                 return
             
         if isonheap(op.result) or filter(None, args):
-            raise NotImplementedError("can't handle %s" % (op.opname, ))
-            #print "assuming that '%s' is irrelevant" % op
+            print "assuming that '%s' is irrelevant" % op
         
     def complete(self):
         while self.scheduled:
@@ -304,4 +305,59 @@
         if graph.startblock not in adi.flown_blocks:
             adi.schedule_function(graph)
             adi.complete()
-    return adi
+    look_at = t.graphs[:]
+    total = 0
+    while look_at:
+        graph = look_at.pop()
+        for block, op in graph.iterblockops():
+            if not op.opname.startswith("set"):
+                continue
+            if not isonheap(op.args[-1]):
+                continue
+            tovarstate = adi.getstate(op.args[-1])
+            fromvarstate = adi.getstate(op.args[0])
+            if (len(tovarstate.creation_points) != 1 or
+                len(fromvarstate.creation_points) != 1):
+                continue
+            fromcrep = fromvarstate.creation_points.keys()[0]
+            tocrep = tovarstate.creation_points.keys()[0]
+            if not tocrep.creation_method.startswith("malloc"):
+                continue
+            if fromcrep.creation_method.startswith("malloc"):
+                continue # also recently malloced
+
+            num = do_coalloc(adi, graph, fromcrep, tocrep)
+
+            if num:
+                look_at.append(graph)
+                print "changed %s mallocs to coallocs in %s" % (num, graph.name)
+                total += num
+    return total
+
+
+def do_coalloc(adi, graph, fromcrep, tocrep):
+    result = 0
+    for block, op in graph.iterblockops():
+        if not op.opname.startswith("malloc"):
+            continue
+        # find coallocation var
+        if fromcrep.creation_method == "constant":
+            coallocvar = fromcrep.constant
+        else:
+            for var in block.inputargs:
+                varstate = adi.getstate(var)
+                assert len(varstate.creation_points) == 1
+                crep = varstate.creation_points.keys()[0]
+                if crep is fromcrep:
+                    coallocvar = var
+                    break
+            else:
+                continue
+        op.opname = "coalloc" + op.opname[len("malloc"):]
+        op.args.insert(1, coallocvar)
+        mallocvarstate = adi.getstate(op.result)
+        assert len(mallocvarstate.creation_points) == 1
+        malloccrep = mallocvarstate.creation_points.keys()[0]
+        malloccrep.creation_method = "coalloc"
+        result += 1
+    return result

Modified: pypy/dist/pypy/translator/backendopt/test/test_coalloc.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_coalloc.py	(original)
+++ pypy/dist/pypy/translator/backendopt/test/test_coalloc.py	Sat Nov  3 16:19:46 2007
@@ -1,5 +1,5 @@
 from pypy.translator.translator import TranslationContext, graphof
-from pypy.translator.backendopt.coalloc import AbstractDataFlowInterpreter
+from pypy.translator.backendopt.coalloc import AbstractDataFlowInterpreter, malloc_to_coalloc
 from pypy.rpython.llinterp import LLInterpreter
 from pypy.rlib.objectmodel import instantiate
 from pypy import conftest
@@ -18,6 +18,27 @@
     adi.complete()
     return t, adi, graph
 
+def check_malloc_to_coalloc(function, types, args, expected_result, must_remove=-1):
+    t = TranslationContext()
+    t.buildannotator().build_types(function, types)
+    t.buildrtyper().specialize()
+    interp = LLInterpreter(t.rtyper)
+    graph = graphof(t, function)
+    res = interp.eval_graph(graph, args)
+    assert res == expected_result
+    num = malloc_to_coalloc(t)
+    if must_remove == -1:
+        for block in graph.iterblocks():
+            for op in block.operations:
+                assert op.opname != "malloc"
+    else:
+        assert num == must_remove
+    t.view()
+    res = interp.eval_graph(graph, args)
+    assert res == expected_result
+    return t
+
+
 def test_simple():
     class A(object):
         pass
@@ -112,3 +133,41 @@
     for crep in state.creation_points.keys():
         assert crep.creation_method == "malloc"
 
+def test_coalloc_constants():
+    class A(object):
+        pass
+    a = A()
+    def f():
+        n = A()
+        a.next = n
+        return 1
+    check_malloc_to_coalloc(f, [], [], 1)
+
+def test_nocoalloc_aliasing():
+    class A:
+        pass
+    def fn6(n):
+        a1 = A()
+        a1.x = 5
+        a2 = A()
+        a2.x = 6
+        if n > 0:
+            a = a1
+        else:
+            a = a2
+        a.x = 12
+        return a1.x
+    t = check_malloc_to_coalloc(fn6, [int], [2], 12, must_remove=0)
+
+def test_coalloc_with_arg():
+    class A(object):
+        pass
+    def g(b):
+        b.x = A()
+    def f():
+        a = A()
+        g(a)
+        a.i = 2
+        return 4
+    t = check_malloc_to_coalloc(f, [], [], 4, must_remove=1)
+


More information about the pypy-svn mailing list