[pypy-commit] pypy guard-compatible: corner case: sometimes the guarded value is really missing from the failargs,
cfbolz
pypy.commits at gmail.com
Tue Jun 28 08:47:25 EDT 2016
Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: guard-compatible
Changeset: r85430:f8abbe802a80
Date: 2016-06-24 23:39 +0200
http://bitbucket.org/pypy/pypy/changeset/f8abbe802a80/
Log: corner case: sometimes the guarded value is really missing from the
failargs, in which case we are annoyed, but should still not crash.
diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -1114,19 +1114,19 @@
# if new_loop starts with another guard_compatible on the same argument
# (which is most of the time) we have to connect the new guard's descr
# to this descr
- assert self.failarg_index != -1
- arg = new_loop.inputargs[self.failarg_index]
- firstop = new_loop.operations[0]
compat_cond = None
- if (firstop.getopnum() == rop.GUARD_COMPATIBLE and
- firstop.getarg(0) is arg):
- # a guard_compatible about the same box
- # remove it, it doesn't have to be checked in the bridge
- del new_loop.operations[0]
- newdescr = firstop.getdescr()
- assert isinstance(newdescr, GuardCompatibleDescr)
- compat_cond = newdescr._compatibility_conditions
- self.other_compat_conditions.append(compat_cond)
+ if self.failarg_index != -1:
+ arg = new_loop.inputargs[self.failarg_index]
+ firstop = new_loop.operations[0]
+ if (firstop.getopnum() == rop.GUARD_COMPATIBLE and
+ firstop.getarg(0) is arg):
+ # a guard_compatible about the same box
+ # remove it, it doesn't have to be checked in the bridge
+ del new_loop.operations[0]
+ newdescr = firstop.getdescr()
+ assert isinstance(newdescr, GuardCompatibleDescr)
+ compat_cond = newdescr._compatibility_conditions
+ self.other_compat_conditions.append(compat_cond)
asminfo = ResumeGuardDescr.compile_and_attach(
self, metainterp, new_loop, orig_inputargs)
if compat_cond:
@@ -1134,8 +1134,12 @@
return asminfo
def make_a_counter_per_value(self, guard_value_op, index):
- self.failarg_index = guard_value_op.getfailargs().index(
- guard_value_op.getarg(0))
+ try:
+ self.failarg_index = guard_value_op.getfailargs().index(
+ guard_value_op.getarg(0))
+ except ValueError:
+ pass # we don't set the failarg_index, too bad
+
# this is not actually enabling the counter_per_value logic,
# which right now gives bad results with a GUARD_COMPATIBLE
#ResumeGuardDescr.make_a_counter_per_value(self, guard_value_op, index)
diff --git a/rpython/jit/metainterp/test/test_compatible.py b/rpython/jit/metainterp/test/test_compatible.py
--- a/rpython/jit/metainterp/test/test_compatible.py
+++ b/rpython/jit/metainterp/test/test_compatible.py
@@ -362,6 +362,53 @@
# trace, two bridges, a finish bridge
self.check_trace_count(4)
+ def test_merge_obj_not_in_failargs(self):
+ S = lltype.GcStruct('S', ('x', lltype.Signed))
+ p1 = lltype.malloc(S)
+ p1.x = 1
+
+ p2 = lltype.malloc(S)
+ p2.x = 1
+
+ driver = jit.JitDriver(greens = [], reds = ['n'])
+
+ class A(object):
+ pass
+
+ c = A()
+ c.count = 0
+ @jit.elidable_compatible()
+ def g(s, ignored):
+ c.count += 1
+ return s.x
+
+ class B(object):
+ pass
+
+ glob_b = B()
+
+ def f(n):
+ while n > 0:
+ driver.can_enter_jit(n=n)
+ driver.jit_merge_point(n=n)
+ x = glob_b.x
+ n -= g(x, "abc")
+ if n & 2:
+ n -= 2
+
+ def main():
+ g(p1, "def") # make annotator not make argument constant
+ glob_b.x = p1
+ f(1000)
+ glob_b.x = p2
+ f(1000)
+ return c.count
+
+ x = self.meta_interp(main, [])
+
+ # trace, two bridges, a finish bridge
+ self.check_trace_count(4)
+
def test_merge_switch_object(self):
S = lltype.GcStruct('S', ('x', lltype.Signed))
p1 = lltype.malloc(S)
More information about the pypy-commit
mailing list