Author: Carl Friedrich Bolz <cfb...@gmx.de>
Branch: guard-compatible
Changeset: r87246:70a901ab0437
Date: 2016-08-18 15:41 +0200
http://bitbucket.org/pypy/pypy/changeset/70a901ab0437/

Log:    somewhat obscure: if there is a condition on the "version" (ie
        second argument of a elidable_compatible call) then that condition
        was emmitted *after* the guard_compatible in the short preamble.
        that's nonsense, fix it with a hack for now.

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
@@ -146,11 +146,13 @@
         """ re-emit the conditions about variable op into the short preamble
         """
         from rpython.jit.metainterp.resoperation import rop, ResOperation
-        short.append(
+        localshort = []
+        localshort.append(
             ResOperation(rop.GUARD_COMPATIBLE, [
                 op, self.known_valid]))
         for cond in self.conditions:
-            cond.emit_condition(op, short, optimizer)
+            cond.emit_condition(op, localshort, short, optimizer)
+        short.extend(localshort)
 
     def emit_needed_conditions_if_const_matches(
             self, other, const, op, extra_guards, optimizer, cpu):
@@ -160,6 +162,7 @@
         at the end. """
         from rpython.jit.metainterp.resoperation import rop, ResOperation
         have_guard = False
+        local_extra_guards = []
         for cond in self.conditions:
             if other is None or not other.contains_condition(cond):
                 if const is None:
@@ -169,13 +172,16 @@
                     if not have_guard:
                         # NB: the guard_compatible here needs to use const,
                         # otherwise the optimizer will just complain
-                        extra_guards.append(ResOperation(
+                        local_extra_guards.append(ResOperation(
                             rop.GUARD_COMPATIBLE,
                                 [op, const]))
                         have_guard = True
-                    cond.emit_condition(op, extra_guards, optimizer, const)
+                    cond.emit_condition(
+                            op, local_extra_guards,
+                            extra_guards, optimizer, const)
                 else:
                     return False
+        extra_guards.extend(local_extra_guards)
         return True
 
     def attach_to_descr(self, descr, guard_value_op, optimizer):
@@ -263,7 +269,7 @@
     def repr(self):
         return ""
 
-    def emit_condition(self, op, short, optimizer, const=None):
+    def emit_condition(self, op, guards, pre_guards, optimizer, const=None):
         raise NotImplementedError("abstract base class")
 
     def _repr_const(self, arg):
@@ -341,7 +347,7 @@
                 return False
         return True
 
-    def emit_condition(self, op, short, optimizer, const=None):
+    def emit_condition(self, op, short, pre_short, optimizer, const=None):
         from rpython.jit.metainterp.history import INT, REF, FLOAT, VOID
         from rpython.jit.metainterp.resoperation import rop, ResOperation
         # woah, mess
@@ -387,11 +393,14 @@
             res = self.debug_mp_str + "\n" + res
         return res
 
+class UnsupportedInfoInGuardCompatibleError(Exception):
+    pass
 
 class QuasiimmutGetfieldAndPureCallCondition(PureCallCondition):
     const_args_start_at = 3
 
     def __init__(self, op, qmutdescr, optimizer):
+        from rpython.jit.metainterp.optimizeopt import info
         PureCallCondition.__init__(self, op, optimizer)
         self.args[2] = None
         # XXX not 100% sure whether it's save to store the whole descr
@@ -399,6 +408,17 @@
         self.qmut = qmutdescr.qmut
         self.mutatefielddescr = qmutdescr.mutatefielddescr
         self.fielddescr = qmutdescr.fielddescr
+        self.need_nonnull_arg2 = False
+        if self.fielddescr.is_pointer_field():
+            fieldinfo = optimizer.getptrinfo(op.getarg(2))
+            if fieldinfo is not None:
+                if type(fieldinfo) != info.NonNullPtrInfo:
+                    # XXX PyPy only needs non-null versions. if another
+                    # interpreter needs something more specific we need to
+                    # generalize this code
+                    raise UnsupportedInfoInGuardCompatible()
+                else:
+                    self.need_nonnull_arg2 = True
 
     def activate(self, ref, optimizer):
         # record the quasi-immutable
@@ -458,7 +478,7 @@
                 return False
         return True
 
-    def emit_condition(self, op, short, optimizer, const=None):
+    def emit_condition(self, op, short, pre_short, optimizer, const=None):
         from rpython.jit.metainterp.resoperation import rop, ResOperation
         from rpython.jit.metainterp.quasiimmut import QuasiImmutDescr
         # more mess
@@ -466,6 +486,13 @@
         if fielddescr.is_pointer_field():
             getfield_op = ResOperation(
                 rop.GETFIELD_GC_R, [op], fielddescr)
+            if self.need_nonnull_arg2:
+                # XXX atm it's emmitted n times
+                getfield_op2 = ResOperation(
+                    rop.GETFIELD_GC_R, [op], fielddescr)
+                guard_nonnull = ResOperation(rop.GUARD_NONNULL, [getfield_op2])
+                pre_short.append(getfield_op2)
+                pre_short.append(guard_nonnull)
         elif fielddescr.is_float_field():
             getfield_op = ResOperation(
                 rop.GETFIELD_GC_F, [op], fielddescr)
@@ -485,7 +512,7 @@
                 rop.GUARD_NOT_INVALIDATED, []),
             getfield_op])
         index = len(short)
-        PureCallCondition.emit_condition(self, op, short, optimizer, const)
+        PureCallCondition.emit_condition(self, op, short, pre_short, 
optimizer, const)
         call_op = short[index]
         # puh, not pretty
         args = call_op.getarglist()[:]
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
@@ -696,5 +696,7 @@
         main(False)
 
         self.meta_interp(main, [True], backendopt=True)
-        self.check_trace_count(2)
+         # XXX this should be 3, but hard to achieve without propagating more
+         # information across bridges
+        self.check_trace_count(4)
         self.check_resops(call_i=0)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to