[pypy-svn] pypy default: (fijal, arigo)

arigo commits-noreply at bitbucket.org
Sat Mar 12 22:36:42 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r42538:84f09467bad9
Date: 2011-03-12 15:03 -0500
http://bitbucket.org/pypy/pypy/changeset/84f09467bad9/

Log:	(fijal, arigo)

	Start an optimization step that helps the JIT: when writing fields
	to a fresh new structure, don't record them in the WriteAnalyzer.

diff --git a/pypy/translator/backendopt/canraise.py b/pypy/translator/backendopt/canraise.py
--- a/pypy/translator/backendopt/canraise.py
+++ b/pypy/translator/backendopt/canraise.py
@@ -10,7 +10,7 @@
 py.log.setconsumer("canraise", ansi_log) 
 
 class RaiseAnalyzer(graphanalyze.BoolGraphAnalyzer):
-    def analyze_simple_operation(self, op):
+    def analyze_simple_operation(self, op, graphinfo):
         try:
             return bool(LL_OPERATIONS[op.opname].canraise)
         except KeyError:

diff --git a/pypy/jit/codewriter/effectinfo.py b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -169,7 +169,7 @@
 # ____________________________________________________________
 
 class VirtualizableAnalyzer(BoolGraphAnalyzer):
-    def analyze_simple_operation(self, op):
+    def analyze_simple_operation(self, op, graphinfo):
         return op.opname in ('jit_force_virtualizable',
                              'jit_force_virtual')
 

diff --git a/pypy/translator/backendopt/test/test_writeanalyze.py b/pypy/translator/backendopt/test/test_writeanalyze.py
--- a/pypy/translator/backendopt/test/test_writeanalyze.py
+++ b/pypy/translator/backendopt/test/test_writeanalyze.py
@@ -51,6 +51,18 @@
         result = wa.analyze(ggraph.startblock.operations[-1])
         assert not result
 
+    def test_write_to_new_struct(self):
+        class A(object):
+            pass
+        def f(x):
+            a = A()
+            a.baz = x   # writes to a fresh new struct are ignored
+            return a
+        t, wa = self.translate(f, [int])
+        fgraph = graphof(t, f)
+        result = wa.analyze_direct_call(fgraph)
+        assert not result
+
     def test_method(self):
         class A(object):
             def f(self):
@@ -314,14 +326,14 @@
         S = lltype.GcStruct('S', ('x', lltype.Signed),
                             adtmeths = {'yep': True,
                                         'callme': ll_callme})
-        def g(x, y, z):
-            p = lltype.malloc(S)
+        def g(p, x, y, z):
             p.x = x
             if p.yep:
                 z *= p.callme(y)
             return z
         def f(x, y, z):
-            return g(x, y, z)
+            p = lltype.malloc(S)
+            return g(p, x, y, z)
 
         t, wa = self.translate(f, [int, int, int])
         fgraph = graphof(t, f)

diff --git a/pypy/translator/backendopt/writeanalyze.py b/pypy/translator/backendopt/writeanalyze.py
--- a/pypy/translator/backendopt/writeanalyze.py
+++ b/pypy/translator/backendopt/writeanalyze.py
@@ -26,7 +26,9 @@
     def is_top_result(result):
         return result is top_set
 
-    def analyze_simple_operation(self, op):
+    def analyze_simple_operation(self, op, graphinfo):
+        if graphinfo and op.args[0] in graphinfo:
+            return empty_set
         if op.opname in ("setfield", "oosetfield"):
             return frozenset([
                 ("struct", op.args[0].concretetype, op.args[1].value)])
@@ -46,14 +48,26 @@
                 return self.bottom_result()
         return graphanalyze.GraphAnalyzer.analyze_external_method(self, op, TYPE, meth)
 
+    def compute_graph_info(self, graph):
+        newstructs = set()
+        for block in graph.iterblocks():
+            for op in block.operations:
+                if (op.opname == 'malloc' or op.opname == 'malloc_varsize'
+                    or op.opname == 'new'):
+                    newstructs.add(op.result)
+                elif op.opname in ('cast_pointer', 'same_as'):
+                    if op.args[0] in newstructs:
+                        newstructs.add(op.result)
+        return newstructs
+
 
 class ReadWriteAnalyzer(WriteAnalyzer):
 
-    def analyze_simple_operation(self, op):
+    def analyze_simple_operation(self, op, graphinfo):
         if op.opname == "getfield":
             return frozenset([
                 ("readstruct", op.args[0].concretetype, op.args[1].value)])
         elif op.opname == "getarrayitem":
             return frozenset([
                 ("readarray", op.args[0].concretetype)])
-        return WriteAnalyzer.analyze_simple_operation(self, op)
+        return WriteAnalyzer.analyze_simple_operation(self, op, graphinfo)

diff --git a/pypy/translator/backendopt/graphanalyze.py b/pypy/translator/backendopt/graphanalyze.py
--- a/pypy/translator/backendopt/graphanalyze.py
+++ b/pypy/translator/backendopt/graphanalyze.py
@@ -27,7 +27,7 @@
         # only an optimization, safe to always return False
         return False
 
-    def analyze_simple_operation(self, op):
+    def analyze_simple_operation(self, op, graphinfo=None):
         raise NotImplementedError("abstract base class")
 
     # some sensible default methods, can also be overridden
@@ -64,7 +64,10 @@
             result = self.join_two_results(result, sub)
         return result
 
-    def analyze(self, op, seen=None):
+    def compute_graph_info(self, graph):
+        return None
+
+    def analyze(self, op, seen=None, graphinfo=None):
         if op.opname == "direct_call":
             graph = get_graph(op.args[0], self.translator)
             if graph is None:
@@ -82,7 +85,7 @@
             if graph is None:
                 return self.analyze_external_method(op, TYPE, meth)
             return self.analyze_oosend(TYPE, name, seen)
-        return self.analyze_simple_operation(op)
+        return self.analyze_simple_operation(op, graphinfo)
 
     def analyze_direct_call(self, graph, seen=None):
         if graph in self.analyzed_calls:
@@ -98,6 +101,7 @@
             started_here = False
             seen.add(graph)
         result = self.bottom_result()
+        graphinfo = self.compute_graph_info(graph)
         for block in graph.iterblocks():
             if block is graph.startblock:
                 result = self.join_two_results(
@@ -107,7 +111,7 @@
                         result, self.analyze_exceptblock(block, seen))
             for op in block.operations:
                 result = self.join_two_results(
-                        result, self.analyze(op, seen))
+                        result, self.analyze(op, seen, graphinfo))
             for exit in block.exits:
                 result = self.join_two_results(
                         result, self.analyze_link(exit, seen))


More information about the Pypy-commit mailing list