changeset 15518:fbe9e7088e35

Merge
author Miguel Garcia <miguel.m.garcia@oracle.com>
date Mon, 05 May 2014 21:23:25 +0200
parents 4f603d776ecc (diff) 77eca555014f (current diff)
children f8cf483ba31e a3f897fb3289
files
diffstat 4 files changed, 75 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CheckCastReduction.java	Mon May 05 18:45:03 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/CheckCastReduction.java	Mon May 05 21:23:25 2014 +0200
@@ -122,7 +122,7 @@
         assert !StampTool.isObjectAlwaysNull(subject) : "Null as per stamp subjects should have been handled above";
 
         // --------- checkCast deemed unsatisfiable by subject-stamp alone ---------
-        if (state.knownNotToConform(subject, toType)) {
+        if (state.knownNotToPassCheckCast(subject, toType)) {
             postponedDeopts.addDeoptBefore(checkCast, checkCast.isForStoreCheck() ? ArrayStoreException : ClassCastException);
             state.impossiblePath();
             // let FixedGuardNode(false).simplify() prune the dead-code control-path
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java	Mon May 05 18:45:03 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/EquationalReasoner.java	Mon May 05 21:23:25 2014 +0200
@@ -237,6 +237,17 @@
             // picked cached substitution
             return result;
         }
+        if (FlowUtil.hasLegalObjectStamp(v) && state.isNull(v)) {
+            // it's ok to return nullConstant in deverbosify unlike in downcast
+            metricNullInserted.increment();
+            return nullConstant;
+        }
+        if (v instanceof ValueProxy) {
+            return v;
+        }
+        if (!(n instanceof FloatingNode)) {
+            return n;
+        }
         if ((visited != null && visited.contains(n)) || added.contains(v)) {
             return v;
         }
@@ -254,30 +265,13 @@
          * Past this point, if we ever want `n` to be deverbosified, it must be looked-up by one of
          * the cases above. One sure way to achieve that is with `rememberSubstitution(old, new)`
          */
-        if (v instanceof ValueProxy) {
-            return downcast(v);
-        }
 
-        if (n instanceof FloatingNode) {
-            /*
-             * `deverbosifyFloatingNode()` will drill down over floating inputs, when that not
-             * possible anymore it resorts to calling `downcast()`. Thus it's ok to take the
-             * `deverbosifyFloatingNode()` route first, as no downcasting opportunity will be
-             * missed.
-             */
-            return deverbosifyFloatingNode((FloatingNode) n);
-        }
-
-        if (FlowUtil.hasLegalObjectStamp(v)) {
-            if (state.isNull(v)) {
-                // it's ok to return nullConstant in deverbosify unlike in downcast
-                metricNullInserted.increment();
-                return nullConstant;
-            }
-            return downcast(v);
-        }
-
-        return n;
+        /*
+         * `deverbosifyFloatingNode()` will drill down over floating inputs, when that not possible
+         * anymore it resorts to calling `downcast()`. Thus it's ok to take the
+         * `deverbosifyFloatingNode()` route first, as no downcasting opportunity will be missed.
+         */
+        return deverbosifyFloatingNode((FloatingNode) n);
     }
 
     /**
@@ -341,16 +335,7 @@
         }
         if (changed == null) {
             assert visited.contains(f) || added.contains(f);
-            if (FlowUtil.hasLegalObjectStamp(f)) {
-                /*
-                 * No input has changed doesn't imply there's no witness to refine the
-                 * floating-object value.
-                 */
-                ValueNode d = downcast(f);
-                return d;
-            } else {
-                return f;
-            }
+            return f;
         }
         FlowUtil.inferStampAndCheck(changed);
         added.add(changed);
@@ -474,6 +459,11 @@
         if (state.isNull(scrutinee)) {
             metricInstanceOfRemoved.increment();
             return falseConstant;
+        } else if (state.knownNotToPassInstanceOf(scrutinee, instanceOf.type())) {
+            // scrutinee turns out to be null -> falseConstant right answer
+            // scrutinee not null, but known-not-to-conform -> falseConstant
+            metricInstanceOfRemoved.increment();
+            return falseConstant;
         } else if (state.isNonNull(scrutinee) && state.knownToConform(scrutinee, instanceOf.type())) {
             metricInstanceOfRemoved.increment();
             return trueConstant;
@@ -486,21 +476,19 @@
      *         performed; otherwise the unmodified argument.
      *
      */
-    private FloatingNode baseCaseIsNullNode(IsNullNode isNull) {
-        ValueNode object = isNull.object();
+    private FloatingNode baseCaseIsNullNode(IsNullNode isNu) {
+        ValueNode object = isNu.object();
         if (!FlowUtil.hasLegalObjectStamp(object)) {
-            return isNull;
+            return isNu;
         }
-        ValueNode scrutinee = GraphUtil.unproxify(isNull.object());
-        GuardingNode evidence = state.nonTrivialNullAnchor(scrutinee);
-        if (evidence != null) {
+        if (state.isNull(object)) {
             metricNullCheckRemoved.increment();
             return trueConstant;
-        } else if (state.isNonNull(scrutinee)) {
+        } else if (state.isNonNull(object)) {
             metricNullCheckRemoved.increment();
             return falseConstant;
         }
-        return isNull;
+        return isNu;
     }
 
     /**
@@ -547,7 +535,7 @@
         if (cast != null) {
             if (state.knownToConform(cast.subject, cast.type)) {
                 return trueConstant;
-            } else if (state.knownNotToConform(cast.subject, cast.type)) {
+            } else if (state.knownNotToPassCheckCast(cast.subject, cast.type)) {
                 return falseConstant;
             }
             return orNode;
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java	Mon May 05 18:45:03 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/FlowSensitiveReduction.java	Mon May 05 21:23:25 2014 +0200
@@ -232,13 +232,8 @@
                 // `begin` denotes the default case of the TypeSwitchNode
                 return;
             }
-            if (state.knownNotToConform(loadHub.object(), type)) {
-                postponedDeopts.addDeoptAfter(begin, UnreachedCode);
-                state.impossiblePath();
-                return;
-            }
             // it's unwarranted to assume loadHub.object() to be non-null
-            // it also seems unwarranted state.trackCC(loadHub.object(), type, begin);
+            state.trackCC(loadHub.object(), type, begin);
         }
     }
 
@@ -310,9 +305,16 @@
      *
      */
     private MethodCallTargetNode deverbosifyInputsCopyOnWrite(MethodCallTargetNode parent) {
+        final MethodCallTargetNode.InvokeKind ik = parent.invokeKind();
+        final boolean shouldTryDevirt = (ik == MethodCallTargetNode.InvokeKind.Interface || ik == MethodCallTargetNode.InvokeKind.Virtual);
+        boolean shouldDowncastReceiver = shouldTryDevirt;
         MethodCallTargetNode changed = null;
         for (ValueNode i : FlowUtil.distinctValueAndConditionInputs(parent)) {
-            Node j = reasoner.deverbosify(i);
+            ValueNode j = (ValueNode) reasoner.deverbosify(i);
+            if (shouldDowncastReceiver) {
+                shouldDowncastReceiver = false;
+                j = reasoner.downcast(j);
+            }
             if (i != j) {
                 assert j != parent;
                 if (changed == null) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/State.java	Mon May 05 18:45:03 2014 +0200
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/cfs/State.java	Mon May 05 21:23:25 2014 +0200
@@ -408,7 +408,8 @@
     }
 
     /**
-     * @return true iff the argument is known to stand for an object conforming to the given type.
+     * @return true iff the argument definitely stands for an object-value that conforms to the
+     *         given type.
      */
     public boolean knownToConform(ValueNode object, ResolvedJavaType to) {
         assert FlowUtil.hasLegalObjectStamp(object);
@@ -430,15 +431,16 @@
     }
 
     /**
-     * @return true iff the argument is known to stand for an object that definitely does not
-     *         conform to the given type.
+     * @return true iff the argument is known to stand for an object that is definitely non-null and
+     *         moreover does not conform to the given type.
      */
-    public boolean knownNotToConform(ValueNode object, ResolvedJavaType to) {
+    public boolean knownNotToPassCheckCast(ValueNode object, ResolvedJavaType to) {
         assert FlowUtil.hasLegalObjectStamp(object);
         assert !to.isPrimitive();
         final ValueNode scrutinee = GraphUtil.unproxify(object);
         if (isNull(scrutinee)) {
             // known-null means it conforms to whatever `to`
+            // and thus passes the check-cast
             return false;
         }
         if (!isNonNull(scrutinee)) {
@@ -457,6 +459,34 @@
         return false;
     }
 
+    /**
+     * @return true iff the argument is known to stand for an object that definitely does not
+     *         conform to the given type (no matter whether the object turns out to be null or
+     *         non-null).
+     */
+    public boolean knownNotToPassInstanceOf(ValueNode object, ResolvedJavaType to) {
+        assert FlowUtil.hasLegalObjectStamp(object);
+        assert !to.isPrimitive();
+        final ValueNode scrutinee = GraphUtil.unproxify(object);
+        if (isNull(scrutinee)) {
+            return true;
+        }
+        ResolvedJavaType stampType = StampTool.typeOrNull(object);
+        if (stampType != null && knownNotToConform(stampType, to)) {
+            // object turns out to be null, positive answer is correct
+            // object turns out non-null, positive answer is also correct
+            return true;
+        }
+        Witness w = typeInfo(scrutinee);
+        boolean witnessAnswer = w != null && !w.cluelessAboutType() && knownNotToConform(w.type(), to);
+        if (witnessAnswer) {
+            // object turns out to be null, positive answer is correct
+            // object turns out non-null, positive answer is also correct
+            return true;
+        }
+        return false;
+    }
+
     // @formatter:off
     /**
      *   \   |     |     |     |
@@ -699,7 +729,7 @@
     private void addFactInstanceOf(boolean isTrue, InstanceOfNode instanceOf, GuardingNode anchor) {
         ValueNode object = instanceOf.object();
         if (isTrue) {
-            if (knownNotToConform(object, instanceOf.type())) {
+            if (knownNotToPassInstanceOf(object, instanceOf.type())) {
                 impossiblePath();
                 return;
             }