Author: Armin Rigo <[email protected]>
Branch:
Changeset: r82905:c4c54cb69aba
Date: 2016-03-09 14:04 +0100
http://bitbucket.org/pypy/pypy/changeset/c4c54cb69aba/
Log: Test and workaround for issue #2200: tries to remove the rpython-
level recursion that can rarely occur after failing a guard in the
jit
diff --git a/rpython/jit/metainterp/blackhole.py
b/rpython/jit/metainterp/blackhole.py
--- a/rpython/jit/metainterp/blackhole.py
+++ b/rpython/jit/metainterp/blackhole.py
@@ -1148,35 +1148,45 @@
@arguments("cpu", "i", "R", "d", returns="i")
def bhimpl_residual_call_r_i(cpu, func, args_r, calldescr):
+ workaround2200.active = True
return cpu.bh_call_i(func, None, args_r, None, calldescr)
@arguments("cpu", "i", "R", "d", returns="r")
def bhimpl_residual_call_r_r(cpu, func, args_r, calldescr):
+ workaround2200.active = True
return cpu.bh_call_r(func, None, args_r, None, calldescr)
@arguments("cpu", "i", "R", "d")
def bhimpl_residual_call_r_v(cpu, func, args_r, calldescr):
+ workaround2200.active = True
return cpu.bh_call_v(func, None, args_r, None, calldescr)
@arguments("cpu", "i", "I", "R", "d", returns="i")
def bhimpl_residual_call_ir_i(cpu, func, args_i, args_r, calldescr):
+ workaround2200.active = True
return cpu.bh_call_i(func, args_i, args_r, None, calldescr)
@arguments("cpu", "i", "I", "R", "d", returns="r")
def bhimpl_residual_call_ir_r(cpu, func, args_i, args_r, calldescr):
+ workaround2200.active = True
return cpu.bh_call_r(func, args_i, args_r, None, calldescr)
@arguments("cpu", "i", "I", "R", "d")
def bhimpl_residual_call_ir_v(cpu, func, args_i, args_r, calldescr):
+ workaround2200.active = True
return cpu.bh_call_v(func, args_i, args_r, None, calldescr)
@arguments("cpu", "i", "I", "R", "F", "d", returns="i")
def bhimpl_residual_call_irf_i(cpu, func, args_i,args_r,args_f,calldescr):
+ workaround2200.active = True
return cpu.bh_call_i(func, args_i, args_r, args_f, calldescr)
@arguments("cpu", "i", "I", "R", "F", "d", returns="r")
def bhimpl_residual_call_irf_r(cpu, func, args_i,args_r,args_f,calldescr):
+ workaround2200.active = True
return cpu.bh_call_r(func, args_i, args_r, args_f, calldescr)
@arguments("cpu", "i", "I", "R", "F", "d", returns="f")
def bhimpl_residual_call_irf_f(cpu, func, args_i,args_r,args_f,calldescr):
+ workaround2200.active = True
return cpu.bh_call_f(func, args_i, args_r, args_f, calldescr)
@arguments("cpu", "i", "I", "R", "F", "d")
def bhimpl_residual_call_irf_v(cpu, func, args_i,args_r,args_f,calldescr):
+ workaround2200.active = True
return cpu.bh_call_v(func, args_i, args_r, args_f, calldescr)
# conditional calls - note that they cannot return stuff
@@ -1204,44 +1214,54 @@
@arguments("cpu", "j", "R", returns="i")
def bhimpl_inline_call_r_i(cpu, jitcode, args_r):
+ workaround2200.active = True
return cpu.bh_call_i(jitcode.get_fnaddr_as_int(),
None, args_r, None, jitcode.calldescr)
@arguments("cpu", "j", "R", returns="r")
def bhimpl_inline_call_r_r(cpu, jitcode, args_r):
+ workaround2200.active = True
return cpu.bh_call_r(jitcode.get_fnaddr_as_int(),
None, args_r, None, jitcode.calldescr)
@arguments("cpu", "j", "R")
def bhimpl_inline_call_r_v(cpu, jitcode, args_r):
+ workaround2200.active = True
return cpu.bh_call_v(jitcode.get_fnaddr_as_int(),
None, args_r, None, jitcode.calldescr)
@arguments("cpu", "j", "I", "R", returns="i")
def bhimpl_inline_call_ir_i(cpu, jitcode, args_i, args_r):
+ workaround2200.active = True
return cpu.bh_call_i(jitcode.get_fnaddr_as_int(),
args_i, args_r, None, jitcode.calldescr)
@arguments("cpu", "j", "I", "R", returns="r")
def bhimpl_inline_call_ir_r(cpu, jitcode, args_i, args_r):
+ workaround2200.active = True
return cpu.bh_call_r(jitcode.get_fnaddr_as_int(),
args_i, args_r, None, jitcode.calldescr)
@arguments("cpu", "j", "I", "R")
def bhimpl_inline_call_ir_v(cpu, jitcode, args_i, args_r):
+ workaround2200.active = True
return cpu.bh_call_v(jitcode.get_fnaddr_as_int(),
args_i, args_r, None, jitcode.calldescr)
@arguments("cpu", "j", "I", "R", "F", returns="i")
def bhimpl_inline_call_irf_i(cpu, jitcode, args_i, args_r, args_f):
+ workaround2200.active = True
return cpu.bh_call_i(jitcode.get_fnaddr_as_int(),
args_i, args_r, args_f, jitcode.calldescr)
@arguments("cpu", "j", "I", "R", "F", returns="r")
def bhimpl_inline_call_irf_r(cpu, jitcode, args_i, args_r, args_f):
+ workaround2200.active = True
return cpu.bh_call_r(jitcode.get_fnaddr_as_int(),
args_i, args_r, args_f, jitcode.calldescr)
@arguments("cpu", "j", "I", "R", "F", returns="f")
def bhimpl_inline_call_irf_f(cpu, jitcode, args_i, args_r, args_f):
+ workaround2200.active = True
return cpu.bh_call_f(jitcode.get_fnaddr_as_int(),
args_i, args_r, args_f, jitcode.calldescr)
@arguments("cpu", "j", "I", "R", "F")
def bhimpl_inline_call_irf_v(cpu, jitcode, args_i, args_r, args_f):
+ workaround2200.active = True
return cpu.bh_call_v(jitcode.get_fnaddr_as_int(),
args_i, args_r, args_f, jitcode.calldescr)
@@ -1528,6 +1548,8 @@
if not self.nextblackholeinterp:
self._exit_frame_with_exception(current_exc)
return current_exc
+ finally:
+ workaround2200.active = False
#
# pass the frame's return value to the caller
caller = self.nextblackholeinterp
@@ -1701,3 +1723,10 @@
#
_run_forever(firstbh, current_exc)
convert_and_run_from_pyjitpl._dont_inline_ = True
+
+# ____________________________________________________________
+
+class WorkaroundIssue2200(object):
+ pass
+workaround2200 = WorkaroundIssue2200()
+workaround2200.active = False
diff --git a/rpython/jit/metainterp/test/test_ajit.py
b/rpython/jit/metainterp/test/test_ajit.py
--- a/rpython/jit/metainterp/test/test_ajit.py
+++ b/rpython/jit/metainterp/test/test_ajit.py
@@ -4377,3 +4377,30 @@
assert res == -1
else:
assert res == 4294967295
+
+ def test_issue2200_recursion(self):
+ # Reproduces issue #2200. This test contains no recursion,
+ # but due to an unlikely combination of factors it ends up
+ # creating an RPython-level recursion, one per loop iteration.
+ # The recursion is: blackhole interp from the failing guard ->
+ # does the call to enter() as a normal call -> enter() runs
+ # can_enter_jit() as if we're interpreted -> we enter the JIT
+ # again from the start of the loop -> the guard fails again
+ # during the next iteration -> blackhole interp. All arrows
+ # in the previous sentence are one or more levels of RPython
+ # function calls.
+ driver = JitDriver(greens=[], reds=["i"])
+ def enter(i):
+ driver.can_enter_jit(i=i)
+ def f():
+ set_param(None, 'trace_eagerness', 999999)
+ i = 0
+ while True:
+ driver.jit_merge_point(i=i)
+ i += 1
+ if i >= 300:
+ return i
+ promote(i + 1) # a failing guard
+ enter(i)
+
+ self.meta_interp(f, [])
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
@@ -433,6 +433,14 @@
bound_reached(hash, None, *args)
return
+ # Workaround for issue #2200, maybe temporary. This is not
+ # a proper fix, but only a hack that should work well enough
+ # for PyPy's main jitdriver... See test_issue2200_recursion
+ from rpython.jit.metainterp.blackhole import workaround2200
+ if workaround2200.active:
+ workaround2200.active = False
+ return
+
# Here, we have found 'cell'.
#
if cell.flags & (JC_TRACING | JC_TEMPORARY):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit