[pypy-svn] r52900 - in pypy/branch/jit-hotpath/pypy/jit/rainbow: . test

arigo at codespeak.net arigo at codespeak.net
Tue Mar 25 13:10:19 CET 2008


Author: arigo
Date: Tue Mar 25 13:10:19 2008
New Revision: 52900

Modified:
   pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py
   pypy/branch/jit-hotpath/pypy/jit/rainbow/graphopt.py
   pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_graphopt.py
Log:
Add the detection of residual call.


Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py
==============================================================================
--- pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py	(original)
+++ pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py	Tue Mar 25 13:10:19 2008
@@ -165,6 +165,8 @@
         self.ptr_to_jitcode = {}
         self.transformer = GraphTransformer(hannotator)
         self._listcache = {}
+        if self.hannotator.policy.hotpath:
+            self.residual_call_targets = {}
 
     def create_interpreter(self, RGenOp):
         raise NotImplementedError
@@ -1118,17 +1120,21 @@
             self.register_greenvar(op.result)
 
     def handle_residual_call(self, op, withexc):
+        graphs, args_v = self.decompose_call_op(op)
         fnptr = op.args[0]
         pos = self.calldesc_position(fnptr.concretetype)
         has_result = (self.varcolor(op.result) != "gray" and
                       op.result.concretetype != lltype.Void)
         func = self.serialize_oparg("red", fnptr)
         emitted_args = []
-        for v in op.args[1:]:
-            if v.concretetype == lltype.Void:   # for indirect_call, this also
-                continue                        # skips the last argument
+        for v in args_v:
+            if v.concretetype == lltype.Void:
+                continue
             emitted_args.append(self.serialize_oparg("red", v))
         if self.hannotator.policy.hotpath:
+            if graphs is not None:
+                for graph in graphs:
+                    self.residual_call_targets[graph] = True
             self.emit("hp_residual_call")
         else:
             self.emit("red_residual_call")
@@ -1433,7 +1439,7 @@
 
     # call handling
 
-    def graphs_from(self, spaceop):
+    def decompose_call_op(self, spaceop):
         if spaceop.opname == 'direct_call':
             c_func = spaceop.args[0]
             fnobj = get_funcobj(c_func.value)
@@ -1441,11 +1447,15 @@
             args_v = spaceop.args[1:]
         elif spaceop.opname == 'indirect_call':
             graphs = spaceop.args[-1].value
-            if graphs is None:
-                return       # cannot follow at all
             args_v = spaceop.args[1:-1]
         else:
             raise AssertionError(spaceop.opname)
+        return graphs, args_v
+
+    def graphs_from(self, spaceop):
+        graphs, args_v = self.decompose_call_op(spaceop)
+        if graphs is None:   # cannot follow at all
+            return
         # if the graph - or all the called graphs - are marked as "don't
         # follow", directly return None as a special case.  (This is only
         # an optimization for the indirect_call case.)

Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/graphopt.py
==============================================================================
--- pypy/branch/jit-hotpath/pypy/jit/rainbow/graphopt.py	(original)
+++ pypy/branch/jit-hotpath/pypy/jit/rainbow/graphopt.py	Tue Mar 25 13:10:19 2008
@@ -33,7 +33,8 @@
     are safe to replace with direct getfield or setfield.
     """
 
-    def __init__(self):
+    def __init__(self, residual_call_targets):
+        self.residual_call_targets = residual_call_targets
         self.safe_variables = set()
         # set of graphs left to analyze:
         self.pending_graphs = set()
@@ -60,6 +61,8 @@
             self.pending_graphs.add(graph)
 
     def seeing_call(self, graph, safe_args):
+        if graph in self.residual_call_targets:
+            return      # don't follow that call
         prevset = self.graph2safeargs.get(graph)
         if prevset is None:
             self.graph2safeargs[graph] = set(safe_args)
@@ -147,7 +150,9 @@
 
 
 def simplify_virtualizable_accesses(codewriter):
-    tracker = VirtualizableAccessTracker()
+    assert codewriter.hannotator.policy.hotpath, (
+        "too many potential residual calls in the non-hotpath policy")
+    tracker = VirtualizableAccessTracker(codewriter.residual_call_targets)
     tracker.find_safe_points(codewriter.rtyper.annotator.translator.graphs)
     tracker.propagate()
     tracker.replace_safe_operations()

Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_graphopt.py
==============================================================================
--- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_graphopt.py	(original)
+++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_graphopt.py	Tue Mar 25 13:10:19 2008
@@ -1,4 +1,5 @@
 from pypy.rlib.jit import JitDriver, hint
+from pypy.jit.hintannotator.policy import StopAtXPolicy
 from pypy.jit.rainbow.test.test_hotpath import HotPathTest
 from pypy.jit.rainbow.graphopt import simplify_virtualizable_accesses
 from pypy.jit.rainbow.graphopt import is_vable_setter, is_vable_getter
@@ -54,3 +55,32 @@
         self.run(main, [20, 30], 2)
         assert self.setters[XY.__init__.im_func] == 0
         assert self.getters[f] == 0
+
+    def test_through_residual(self):
+        class MyJitDriver(JitDriver):
+            greens = []
+            reds = ['xy', 'i', 'res']
+
+        def debug(xy):
+            xy.x = 5
+            return xy.y
+
+        def f(xy):
+            i = 1024
+            while i > 0:
+                i >>= 1
+                res = xy.x+xy.y
+                debug(xy)
+                MyJitDriver.jit_merge_point(xy=xy, res=res, i=i)
+                MyJitDriver.can_enter_jit(xy=xy, res=res, i=i)
+            return res
+
+        def main(x, y):
+            xy = XY(x, y)
+            return f(xy)
+
+        self.run(main, [20, 30], 2, policy=StopAtXPolicy(debug))
+        assert self.setters[XY.__init__.im_func] == 0
+        assert self.getters[f] == 0
+        assert self.setters[debug] == 1
+        assert self.getters[debug] == 1



More information about the Pypy-commit mailing list