changeset 22231:a85ef0434dba

TypeCheckNode should fold obviously failing types
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Wed, 15 Jul 2015 09:49:14 -0700
parents fc0892fed0f5
children 4a500b3783fb
files graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeCheckNode.java graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java
diffstat 3 files changed, 67 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java	Wed Jul 15 09:49:11 2015 -0700
+++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java	Wed Jul 15 09:49:14 2015 -0700
@@ -3026,7 +3026,9 @@
                 ResolvedJavaType singleType = profile.asSingleType();
                 if (singleType != null) {
                     LogicNode typeCheck = append(TypeCheckNode.create(singleType, object));
-                    append(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile));
+                    if (!typeCheck.isTautology()) {
+                        append(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile));
+                    }
                     instanceOfNode = LogicConstantNode.forBoolean(resolvedType.isAssignableFrom(singleType));
                 }
             }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeCheckNode.java	Wed Jul 15 09:49:11 2015 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeCheckNode.java	Wed Jul 15 09:49:14 2015 -0700
@@ -104,7 +104,7 @@
                 return LogicConstantNode.tautology();
             }
         } else {
-            if (exactType) {
+            if (exactType || !inputType.isAssignableFrom(type)) {
                 // since this type check failed for an exact type we know that it can never
                 // succeed at run time. we also don't care about null values, since they will
                 // also make the check fail.
--- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java	Wed Jul 15 09:49:11 2015 -0700
+++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java	Wed Jul 15 09:49:14 2015 -0700
@@ -25,11 +25,14 @@
 import java.util.*;
 
 import jdk.internal.jvmci.code.CompilationResult.*;
+import jdk.internal.jvmci.debug.*;
+import jdk.internal.jvmci.debug.Debug.*;
 import jdk.internal.jvmci.meta.*;
 
 import org.junit.*;
 
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.replacements.test.CheckCastTest.Depth12;
@@ -430,4 +433,64 @@
         test("conditionalInstantiation", new StringBuilder());
         test("conditionalInstantiation", 1);
     }
+
+    public boolean exactlyObject(Thread thread) {
+        return thread != null && ((Object) thread).getClass() == Object.class;
+    }
+
+    public boolean exactlyObjectArray(Thread[] threads) {
+        return threads != null && ((Object[]) threads).getClass() == Object[].class;
+    }
+
+    public boolean exactlyString(Thread thread) {
+        return thread != null && ((Object) thread).getClass() == String.class;
+    }
+
+    public boolean exactlyStringArray(Thread[] threads) {
+        return threads != null && ((Object[]) threads).getClass() == String[].class;
+    }
+
+    @SuppressWarnings("cast")
+    public boolean instanceofStringArray(Thread[] threads) {
+        return threads != null && ((Object[]) threads) instanceof String[];
+    }
+
+    @SuppressWarnings("cast")
+    public boolean instanceofString(Thread thread) {
+        return thread != null && ((Object) thread) instanceof String;
+    }
+
+    /**
+     * {@link TypeCheckNode} and {@link InstanceOfNode} should be equivalently powerful when
+     * comparing disjoint types.
+     */
+    @Test
+    public void testTypeCheck() {
+        testConstantReturn("exactlyObject", 0);
+        testConstantReturn("exactlyObjectArray", 0);
+        testConstantReturn("exactlyString", 0);
+        testConstantReturn("exactlyStringArray", 0);
+        testConstantReturn("instanceofString", 0);
+        testConstantReturn("instanceofStringArray", 0);
+    }
+
+    private void testConstantReturn(String name, Object value) {
+        StructuredGraph result = buildGraph(name);
+        ReturnNode ret = result.getNodes(ReturnNode.TYPE).first();
+        assertDeepEquals(1, result.getNodes(ReturnNode.TYPE).count());
+
+        assertDeepEquals(true, ret.result().isConstant());
+        assertDeepEquals(value, ret.result().asJavaConstant().asBoxedPrimitive());
+    }
+
+    protected StructuredGraph buildGraph(final String snippet) {
+        try (Scope s = Debug.scope("InstanceOfTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) {
+            StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
+            compile(graph.method(), graph);
+            Debug.dump(graph, snippet);
+            return graph;
+        } catch (Throwable e) {
+            throw Debug.handle(e);
+        }
+    }
 }