[pypy-commit] pypy guard-compatible: need to try the descrs in order old-to-new

cfbolz pypy.commits at gmail.com
Tue Mar 22 12:47:39 EDT 2016


Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: guard-compatible
Changeset: r83258:8a97958ad065
Date: 2016-03-22 15:26 +0100
http://bitbucket.org/pypy/pypy/changeset/8a97958ad065/

Log:	need to try the descrs in order old-to-new

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
@@ -1089,23 +1089,26 @@
         # XXX think about what is being kept alive here
         self._compatibility_conditions = None
         self.failarg_index = -1
-        self._prev_guard_compatible_descr = None
+        # list of descrs about the same variable, potentially shared with
+        # subsequent guards in bridges
+        self.guard_descrs_list = [self]
 
     def handle_fail(self, deadframe, metainterp_sd, jitdriver_sd):
         index = intmask(self.status >> self.ST_SHIFT)
         typetag = intmask(self.status & self.ST_TYPE_MASK)
         assert typetag == self.TY_REF # for now
         refval = metainterp_sd.cpu.get_value_direct(deadframe, 'r', index)
-        curr = self
-        while curr:
+        if not we_are_translated():
+            assert self in self.guard_descrs_list
+        # need to do the checking oldest to newest, to check the most specific
+        # condition first
+        for curr in self.guard_descrs_list:
             if curr.is_compatible(metainterp_sd.cpu, refval):
                 from rpython.jit.metainterp.blackhole import resume_in_blackhole
                 metainterp_sd.cpu.grow_guard_compatible_switch(
                     curr.rd_loop_token, curr, refval)
                 resume_in_blackhole(metainterp_sd, jitdriver_sd, self, deadframe)
                 return
-            # try previous guards, maybe one of them would have matched
-            curr = curr._prev_guard_compatible_descr
         # a real failure
         return ResumeGuardDescr.handle_fail(self, deadframe, metainterp_sd, jitdriver_sd)
 
@@ -1130,7 +1133,8 @@
             # a guard_compatible about the same box
             newdescr = firstop.getdescr()
             assert isinstance(newdescr, GuardCompatibleDescr)
-            newdescr._prev_guard_compatible_descr = self
+            newdescr.guard_descrs_list = self.guard_descrs_list
+            self.guard_descrs_list.append(newdescr)
         ResumeGuardDescr.compile_and_attach(
             self, metainterp, new_loop, orig_inputargs)
 
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
@@ -222,3 +222,57 @@
         # trace, two bridges, a finish bridge
         self.check_trace_count(4)
 
+
+    def test_order_of_chained_guards(self):
+        class Obj(object):
+            def __init__(self):
+                self.m = Map()
+        class Map(object):
+            pass
+
+        p1 = Obj()
+        p1.m.x = 5
+        p1.m.y = 5
+
+        p2 = Obj()
+        p2.m.x = 5
+        p2.m.y = 5
+
+        p3 = Obj()
+        p3.m.x = 5
+        p3.m.y = 6
+        driver = jit.JitDriver(greens = [], reds = ['n', 'x'])
+
+        class A(object):
+            pass
+
+        c = A()
+        c.count = 0
+        @jit.elidable_compatible()
+        def check1(m, ignored):
+            c.count += 1
+            return m.x
+
+        @jit.elidable_compatible()
+        def check2(m, ignored):
+            c.count += 1
+            return m.y
+
+        def f(n, x):
+            while n > 0:
+                driver.can_enter_jit(n=n, x=x)
+                driver.jit_merge_point(n=n, x=x)
+                n -= check1(x.m, 7) + check2(x.m, 7)
+
+        def main():
+            check1(p1.m, 9) # make annotator not make argument constant
+            f(100, p1)
+            f(100, p3) # not compatible, so make a bridge
+            f(100, p2) # compatible with loop again, too bad
+            return c.count
+
+        x = self.meta_interp(main, [])
+
+        # trace, two bridges, a finish bridge
+        self.check_trace_count(4)
+        assert x < 50


More information about the pypy-commit mailing list