Commits

Antonio Cuni  committed 927230d

implement the 'fast' jit mode, in which we trace only inside the 'core' graphs, and do residual calls to everything else; still in-progress, at least one case is missing, see next checkin

  • Participants
  • Parent commits da475d1
  • Branches core-only-tracing

Comments (0)

Files changed (5)

File pypy/jit/metainterp/pyjitpl.py

         result = vinfo.get_array_length(virtualizable, arrayindex)
         return ConstInt(result)
 
+    def perform_call_maybe(self, jitcode, argboxes):
+        core_only_mode = (self.metainterp.jitdriver_sd.warmstate.jitmode == 'fast')
+        if core_only_mode and self.jitcode.is_core:
+            # never inline in this mode
+            funcbox = ConstInt(jitcode.get_fnaddr_as_int())
+            # jitcode always has a calldescr, but it might not have the
+            # correct effectinfo. The result is that we might generate a
+            # call_may_force when a call might suffice; however, we don't care
+            # too much because for the PyPy interpreter most calls are to
+            # space.*, so they would be call_may_force anyway.
+            calldescr = jitcode.calldescr
+            return self.do_residual_call(funcbox, calldescr, argboxes)
+        # normal mode
+        return self.metainterp.perform_call(jitcode, argboxes)
+
     @arguments("jitcode", "boxes")
     def _opimpl_inline_call1(self, jitcode, argboxes):
-        return self.metainterp.perform_call(jitcode, argboxes)
+        return self.perform_call_maybe(jitcode, argboxes)
     @arguments("jitcode", "boxes2")
     def _opimpl_inline_call2(self, jitcode, argboxes):
-        return self.metainterp.perform_call(jitcode, argboxes)
+        return self.perform_call_maybe(jitcode, argboxes)
     @arguments("jitcode", "boxes3")
     def _opimpl_inline_call3(self, jitcode, argboxes):
-        return self.metainterp.perform_call(jitcode, argboxes)
+        return self.perform_call_maybe(jitcode, argboxes)
 
     opimpl_inline_call_r_i = _opimpl_inline_call1
     opimpl_inline_call_r_r = _opimpl_inline_call1

File pypy/jit/metainterp/test/test_ajit.py

         res = self.meta_interp(f, [32])
         assert res == f(32)
 
+    def test_residual_call_from_core_graph(self):
+        class MyPolicy(JitPolicy):
+            def is_core_graph(self, graph):
+                return graph.name == 'f'
+        myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res'])
+
+        def a(x):
+            return x
+        def b(x, y):
+            return x+y
+        def c(x, y, z):
+            return x+y+z
+        def f(x, y):
+            res = 0
+            while y > 0:
+                myjitdriver.can_enter_jit(x=x, y=y, res=res)
+                myjitdriver.jit_merge_point(x=x, y=y, res=res)
+                res = a(x) + b(x, res) + c(x, -x, -x) # at the end, it's like doing x+res :-)
+                y -= 1
+            return res
+        res = self.meta_interp(f, [6, 7], policy=MyPolicy(), jitmode='fast') # fast == trace only core graphs
+        assert res == 42
+        self.check_trace_count(1)
+        # this is suboptimal because we get a call_may_force instead of a
+        # call. Look at the comment inside pyjitpl...perform_call_maybe for
+        # details
+        self.check_resops({'jump': 1, 'int_gt': 2, 'guard_true': 2, 'int_sub': 2,
+                           'int_neg': 1, 'int_add': 4,
+                           'call_may_force': 6,
+                           'guard_no_exception': 6,
+                           'guard_not_forced': 6})
+
+
 
 class TestOOtype(BasicTests, OOJitMixin):
 

File pypy/jit/metainterp/warmspot.py

                     backendopt=False, trace_limit=sys.maxint,
                     inline=False, loop_longevity=0, retrace_limit=5,
                     function_threshold=4,
-                    enable_opts=ALL_OPTS_NAMES, max_retrace_guards=15, **kwds):
+                    enable_opts=ALL_OPTS_NAMES, max_retrace_guards=15,
+                    jitmode='full', **kwds):
     from pypy.config.config import ConfigError
     translator = interp.typer.annotator.translator
     try:
         jd.warmstate.set_param_loop_longevity(loop_longevity)
         jd.warmstate.set_param_retrace_limit(retrace_limit)
         jd.warmstate.set_param_max_retrace_guards(max_retrace_guards)
+        jd.warmstate.set_param_jitmode(jitmode)
         jd.warmstate.set_param_enable_opts(enable_opts)
     warmrunnerdesc.finish()
     if graph_and_interp_only:

File pypy/jit/metainterp/warmstate.py

     def set_param_inlining(self, value):
         self.inlining = value
 
+    def set_param_jitmode(self, value):
+        self.jitmode = value
+
     def set_param_enable_opts(self, value):
         from pypy.jit.metainterp.optimizeopt import ALL_OPTS_DICT, ALL_OPTS_NAMES
 

File pypy/rlib/jit.py

     'retrace_limit': 'how many times we can try retracing before giving up',
     'max_retrace_guards': 'number of extra guards a retrace can cause',
     'max_unroll_loops': 'number of extra unrollings a loop can cause',
+    'jitmode': '"full" (default) or "fast"',
     'enable_opts': 'optimizations to enable or all, INTERNAL USE ONLY'
     }
 
               'retrace_limit': 5,
               'max_retrace_guards': 15,
               'max_unroll_loops': 4,
+              'jitmode': 'full',
               'enable_opts': 'all',
               }
 unroll_parameters = unrolling_iterable(PARAMETERS.items())