[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