Author: Laurence Tratt <[email protected]>
Branch: recursion_and_inlining
Changeset: r74498:2fa67aa20eea
Date: 2014-11-13 10:53 +0000
http://bitbucket.org/pypy/pypy/changeset/2fa67aa20eea/

Log:    Unroll a (customisable) fixed number of iterations of recursive
        functions.

        In essence, we count how instances of the function we're about to
        call are already on the meta-interpreter stack and only stop tracing
        when that count has been exceeded. Initial experiments suggest that
        7 is a reasonable number, though this shouldn't be considered fixed
        in stone, as it's heavily dependent on what benchmarks one uses.

diff --git a/rpython/jit/metainterp/pyjitpl.py 
b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -959,6 +959,7 @@
                 portal_code = targetjitdriver_sd.mainjitcode
                 inline = True
                 if self.metainterp.is_main_jitcode(portal_code):
+                    count = 0
                     for gk, _ in self.metainterp.portal_trace_positions:
                         if gk is None:
                             continue
@@ -968,12 +969,16 @@
                             if not gk[i].same_constant(greenboxes[i]):
                                 break
                         else:
-                            # The greenkey of a trace position on the stack
-                            # matches what we have, which means we're 
definitely
-                            # about to recurse.
-                            warmrunnerstate.dont_trace_here(greenboxes)
-                            inline = False
-                            break
+                            count += 1
+                    memmgr = 
self.metainterp.staticdata.warmrunnerdesc.memory_manager
+                    if count >= memmgr.max_unroll_recursion:
+                        # This function is recursive and has exceeded the
+                        # maximum number of unrollings we allow. We want to 
stop
+                        # inlining it further and to make sure that, if it
+                        # hasn't happened already, the function is traced
+                        # separately as soon as possible.
+                        warmrunnerstate.dont_trace_here(greenboxes)
+                        inline = False
                 if inline:
                     return self.metainterp.perform_call(portal_code, allboxes,
                                 greenkey=greenboxes)
diff --git a/rpython/jit/metainterp/warmspot.py 
b/rpython/jit/metainterp/warmspot.py
--- a/rpython/jit/metainterp/warmspot.py
+++ b/rpython/jit/metainterp/warmspot.py
@@ -69,7 +69,8 @@
                     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, 
+                    max_unroll_recursion=7, **kwds):
     from rpython.config.config import ConfigError
     translator = interp.typer.annotator.translator
     try:
@@ -91,6 +92,7 @@
         jd.warmstate.set_param_retrace_limit(retrace_limit)
         jd.warmstate.set_param_max_retrace_guards(max_retrace_guards)
         jd.warmstate.set_param_enable_opts(enable_opts)
+        jd.warmstate.set_param_max_unroll_recursion(max_unroll_recursion)
     warmrunnerdesc.finish()
     if graph_and_interp_only:
         return interp, graph
diff --git a/rpython/jit/metainterp/warmstate.py 
b/rpython/jit/metainterp/warmstate.py
--- a/rpython/jit/metainterp/warmstate.py
+++ b/rpython/jit/metainterp/warmstate.py
@@ -291,6 +291,11 @@
             if self.warmrunnerdesc.memory_manager:
                 self.warmrunnerdesc.memory_manager.max_unroll_loops = value
 
+    def set_param_max_unroll_recursion(self, value):
+        if self.warmrunnerdesc:
+            if self.warmrunnerdesc.memory_manager:
+                self.warmrunnerdesc.memory_manager.max_unroll_recursion = value
+
     def disable_noninlinable_function(self, greenkey):
         cell = self.JitCell.ensure_jit_cell_at_key(greenkey)
         cell.flags |= JC_DONT_TRACE_HERE
diff --git a/rpython/rlib/jit.py b/rpython/rlib/jit.py
--- a/rpython/rlib/jit.py
+++ b/rpython/rlib/jit.py
@@ -463,6 +463,7 @@
     'max_unroll_loops': 'number of extra unrollings a loop can cause',
     'enable_opts': 'INTERNAL USE ONLY (MAY NOT WORK OR LEAD TO CRASHES): '
                    'optimizations to enable, or all = %s' % ENABLE_ALL_OPTS,
+    'max_unroll_recursion': 'how many levels deep to unroll a recursive 
function'
     }
 
 PARAMETERS = {'threshold': 1039, # just above 1024, prime
@@ -476,6 +477,7 @@
               'max_retrace_guards': 15,
               'max_unroll_loops': 0,
               'enable_opts': 'all',
+              'max_unroll_recursion': 7,
               }
 unroll_parameters = unrolling_iterable(PARAMETERS.items())
 
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to