Author: Carl Friedrich Bolz <[email protected]>
Branch: guard-compatible
Changeset: r85375:7add21f0e70a
Date: 2016-06-24 16:51 +0200
http://bitbucket.org/pypy/pypy/changeset/7add21f0e70a/

Log:    a test with virtualstate merging and quasi-immutables

diff --git a/rpython/jit/metainterp/compatible.py 
b/rpython/jit/metainterp/compatible.py
--- a/rpython/jit/metainterp/compatible.py
+++ b/rpython/jit/metainterp/compatible.py
@@ -395,6 +395,7 @@
 
     def emit_condition(self, op, short, optimizer, const=None):
         from rpython.jit.metainterp.resoperation import rop, ResOperation
+        from rpython.jit.metainterp.quasiimmut import QuasiImmutDescr
         # more mess
         fielddescr = self.fielddescr
         if fielddescr.is_pointer_field():
@@ -406,9 +407,15 @@
         else:
             getfield_op = ResOperation(
                 rop.GETFIELD_GC_I, [op], fielddescr)
+        if const is not None:
+            ref = const.getref_base()
+            qmutdescr = QuasiImmutDescr(
+                    optimizer.cpu, ref, self.fielddescr, self.mutatefielddescr)
+        else:
+            qmutdescr = self.qmutdescr
         short.extend([
             ResOperation(
-                rop.QUASIIMMUT_FIELD, [op], self.qmutdescr),
+                rop.QUASIIMMUT_FIELD, [op], qmutdescr),
             ResOperation(
                 rop.GUARD_NOT_INVALIDATED, []),
             getfield_op])
@@ -416,15 +423,19 @@
         PureCallCondition.emit_condition(self, op, short, optimizer, const)
         call_op = short[index]
         # puh, not pretty
-        args = call_op.getarglist()
+        args = call_op.getarglist()[:]
         if const is not None:
+            args[1] = const
             del optimizer.call_pure_results[args]
         assert call_op.opnum in (
                 rop.CALL_PURE_I, rop.CALL_PURE_R,
                 rop.CALL_PURE_F, rop.CALL_PURE_N)
         call_op.setarg(2, getfield_op)
         if const is not None:
-            optimizer.call_pure_results[call_op.getarglist()] = self.res
+            ref = const.getref_base()
+            args[2] = QuasiImmutDescr._get_fieldvalue(
+                self.fielddescr, ref, optimizer.cpu)
+            optimizer.call_pure_results[args] = self.res
 
     def repr(self, argrepr="?"):
         addr = self.args[0].getaddr()
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py 
b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -629,7 +629,8 @@
                                              self._last_guard_op)
         else:
             op = self.store_final_boxes_in_guard(guard_op, pendingfields)
-            self._last_guard_op = op
+            if opnum == rop.GUARD_COMPATIBLE:
+                self._last_guard_op = op # XXX don't share the next one either
             # for unrolling
             for farg in op.getfailargs():
                 if farg:
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py 
b/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_virtualstate.py
@@ -482,7 +482,7 @@
         """
         self.compare(guards, expected, [box])
 
-    def make_ccond(self):
+    def make_ccond_info(self):
         from rpython.jit.metainterp.compatible import CompatibilityCondition
         optimizer = FakeOptimizer(self.cpu)
         ccond = CompatibilityCondition(ConstPtr(self.quasiptr))
@@ -507,13 +507,12 @@
         copied_op, cond = ccond.prepare_const_arg_call(
                 op, optimizer)
         ccond.record_condition(cond, ConstInt(5), optimizer)
-
-        return ccond
+        value = info.PtrInfo()
+        value._compatibility_conditions = ccond
+        return value
 
     def test_info_make_guards_guard_compatible_with_conditions(self):
-        value1 = info.PtrInfo()
-        ccond = self.make_ccond()
-        value1._compatibility_conditions = ccond
+        value1 = self.make_ccond_info()
 
         box = InputArgRef()
         guards = []
@@ -532,12 +531,8 @@
         self.compare(guards, expected, [box])
 
     def test_virtualstate_guard_compatible(self):
-        value1 = info.PtrInfo()
-        ccond1 = self.make_ccond()
-        value1._compatibility_conditions = ccond1
-        value2 = info.PtrInfo()
-        ccond2 = self.make_ccond()
-        value2._compatibility_conditions = ccond2
+        value1 = self.make_ccond_info()
+        value2 = self.make_ccond_info()
 
         state1 = not_virtual(self.cpu, 'r', value1)
         state2 = not_virtual(self.cpu, 'r', value2)
@@ -553,6 +548,26 @@
         ccond1.conditions = []
         self.check_no_guards(state1, state2)
 
+    def test_virtualstate_guard_compatible_make_guards(self):
+        value1 = self.make_ccond_info()
+        value2 = self.make_ccond_info()
+
+        state1 = not_virtual(self.cpu, 'r', value1)
+        state2 = not_virtual(self.cpu, 'r', value2)
+
+
+        cond = ccond2.conditions[:]
+        ccond2.conditions = [cond[0]]
+        box = InputArgRef(self.nodeaddr)
+        self.guards(state1, state2)
+
+        ccond2.conditions = [cond[1]]
+        self.check_no_guards(state1, state2)
+
+        ccond2.conditions = []
+        self.check_no_guards(state1, state2)
+        self.check_no_guards(state1, state2)
+
 
     def test_equal_inputargs(self):
         classbox = self.cpu.ts.cls_of_box(InputArgRef(self.nodeaddr))
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
@@ -402,3 +402,82 @@
         # trace, one bridge, a finish bridge
         self.check_trace_count(3)
 
+
+    def test_quasi_immutable_merge(self):
+        from rpython.rlib.objectmodel import we_are_translated
+        class C(object):
+            _immutable_fields_ = ['version?']
+
+        class Version(object):
+            def __init__(self, cls):
+                self.cls = cls
+        p1 = C()
+        p1.version = Version(p1)
+        p1.x = 1
+        p2 = C()
+        p2.version = Version(p2)
+        p2.x = 1
+        p3 = C()
+        p3.version = Version(p3)
+        p3.x = 3
+
+        driver = jit.JitDriver(greens = [], reds = ['n', 'x'])
+
+        class Counter(object):
+            pass
+
+        c = Counter()
+        c.count = 0
+        @jit.elidable_compatible()
+        def g(cls, v):
+            if we_are_translated():
+                c.count += 1
+            return cls.x
+
+        def f(n, x):
+            res = 0
+            while n > 0:
+                driver.can_enter_jit(n=n, x=x)
+                driver.jit_merge_point(n=n, x=x)
+                x = jit.hint(x, promote_compatible=True)
+                v = x.version
+                res = g(x, x.version)
+                n -= res
+                if n % 11 == 5:
+                    n -= 1
+            return res
+
+        def main(x):
+            res = f(100, p1)
+            assert res == 1
+            res = f(100, p2)
+            assert res == 1
+            res = f(100, p3)
+            assert res == 3
+            # invalidate p1 or p2
+            if x:
+                p1.x = 2
+                p1.version = Version(p1)
+                res = f(100, p1)
+                assert res == 2
+                p1.x = 1
+                p1.version = Version(p1)
+            else:
+                p2.x = 2
+                p2.version = Version(p2)
+                res = f(100, p2)
+                assert res == 2
+                p2.x = 1
+                p2.version = Version(p2)
+            return c.count
+        main(True)
+        main(False)
+
+        x = self.meta_interp(main, [True])
+        assert x < 30
+
+        x = self.meta_interp(main, [False])
+        assert x < 30
+        self.check_trace_count(7)
+
+
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to