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