[pypy-commit] pypy guard-compatible: fix a bug in the guard_compatible handling in optimizeopt.

cfbolz pypy.commits at gmail.com
Tue Jun 14 11:53:59 EDT 2016


Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: guard-compatible
Changeset: r85162:349d440cf935
Date: 2016-06-14 17:52 +0200
http://bitbucket.org/pypy/pypy/changeset/349d440cf935/

Log:	fix a bug in the guard_compatible handling in optimizeopt.

	(if the arguments to the call_pure were non-constants that the
	optimizer would discover to be constants, things would break)

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
@@ -56,6 +56,13 @@
 
     def prepare_const_arg_call(self, op, optimizer):
         from rpython.jit.metainterp.quasiimmut import QuasiImmutDescr
+        # replace further arguments by constants, if the optimizer knows them
+        # already
+        for i in range(2, op.numargs()):
+            arg = op.getarg(i)
+            constarg = optimizer.get_constant_box(arg)
+            if constarg is not None:
+                op.setarg(i, constarg)
         copied_op = op.copy()
         copied_op.setarg(1, self.known_valid)
         if op.numargs() == 2:
@@ -147,11 +154,17 @@
         return "<huh?>"
 
 class PureCallCondition(Condition):
+    const_args_start_at = 2
+
     def __init__(self, op, optimizer):
+        from rpython.jit.metainterp.history import Const
         Condition.__init__(self, optimizer)
         args = op.getarglist()[:]
         args[1] = None
         self.args = args
+        for index in range(self.const_args_start_at, len(args)):
+            arg = args[index]
+            assert isinstance(arg, Const)
         self.descr = op.getdescr()
         self.rpyfunc = op.rpyfunc
 
@@ -210,14 +223,11 @@
 
 
 class QuasiimmutGetfieldAndPureCallCondition(PureCallCondition):
+    const_args_start_at = 3
+
     def __init__(self, op, qmutdescr, optimizer):
-        Condition.__init__(self, optimizer)
-        args = op.getarglist()[:]
-        args[1] = None
-        args[2] = None
-        self.args = args
-        self.descr = op.getdescr()
-        self.rpyfunc = op.rpyfunc
+        PureCallCondition.__init__(self, op, optimizer)
+        self.args[2] = None
         self.qmut = qmutdescr.qmut
         self.mutatefielddescr = qmutdescr.mutatefielddescr
         self.fielddescr = qmutdescr.fielddescr
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_compatible.py b/rpython/jit/metainterp/optimizeopt/test/test_compatible.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_compatible.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_compatible.py
@@ -35,14 +35,14 @@
     def test_guard_compatible_and_guard_nonnull(self):
         ops = """
         [p1]
-        guard_nonnull(p1, ConstClass(node_vtable)) []
+        guard_nonnull(p1) []
         guard_compatible(p1, ConstPtr(myptr)) []
-        guard_nonnull(p1, ConstClass(node_vtable)) []
+        guard_nonnull(p1) []
         jump(ConstPtr(myptr))
         """
         expected = """
         [p1]
-        guard_nonnull(p1, ConstClass(node_vtable)) []
+        guard_nonnull(p1) []
         guard_compatible(p1, ConstPtr(myptr)) []
         jump(ConstPtr(myptr))
         """
@@ -126,6 +126,37 @@
             assert descr._compatibility_conditions.known_valid.same_constant(ConstPtr(self.myptr))
             assert len(descr._compatibility_conditions.conditions) == 2
 
+    def test_guard_compatible_call_pure_late_constant(self):
+        call_pure_results = {
+            (ConstInt(123), ConstPtr(self.myptr), ConstInt(5)): ConstInt(5),
+            (ConstInt(124), ConstPtr(self.myptr), ConstInt(5)): ConstInt(7),
+        }
+        ops = """
+        [p1]
+        pvirtual = new_with_vtable(descr=nodesize)
+        setfield_gc(pvirtual, 5, descr=valuedescr)
+        i1 = getfield_gc_i(pvirtual, descr=valuedescr)
+        guard_compatible(p1, ConstPtr(myptr)) []
+        i3 = call_pure_i(123, p1, i1, descr=plaincalldescr)
+        escape_n(i3)
+        i5 = call_pure_i(124, p1, i1, descr=plaincalldescr)
+        escape_n(i5)
+        jump(ConstPtr(myptr))
+        """
+        expected = """
+        [p1]
+        guard_compatible(p1, ConstPtr(myptr)) []
+        escape_n(5)
+        escape_n(7)
+        jump(ConstPtr(myptr))
+        """
+        self.optimize_loop(ops, expected, call_pure_results=call_pure_results)
+        # whitebox-test the guard_compatible descr a bit
+        descr = self.loop.operations[1].getdescr()
+        assert descr._compatibility_conditions is not None
+        assert descr._compatibility_conditions.known_valid.same_constant(ConstPtr(self.myptr))
+        assert len(descr._compatibility_conditions.conditions) == 2
+
     def test_deduplicate_conditions(self):
         call_pure_results = {
             (ConstInt(123), ConstPtr(self.myptr)): ConstInt(5),
diff --git a/rpython/rlib/jit.py b/rpython/rlib/jit.py
--- a/rpython/rlib/jit.py
+++ b/rpython/rlib/jit.py
@@ -384,7 +384,7 @@
     so its consquences are reflected into jitted code """
     # during testing we return something randomly, to emulate the real
     # behaviour where you can switch to tracing a arbitrary points.
-    return random.random() > 0.5
+    return False
 
 _we_are_jitted = CDefinedIntSymbolic('0 /* we are not jitted here */',
                                      default=0)


More information about the pypy-commit mailing list