# HG changeset patch # User Tom Rodriguez # Date 1436980588 25200 # Node ID 4a500b3783fb3d1efd55bce7a5866277ce30c30e # Parent a85ef0434dbaac66d23b49e92f6da0af3456e3b7# Parent a05f318a4a087ba0c9011102ee188829230c8ee2 Merge diff -r a05f318a4a08 -r 4a500b3783fb graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Wed Jul 15 18:23:44 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Wed Jul 15 10:16:28 2015 -0700 @@ -305,7 +305,7 @@ * * @param size number of bytes to zero * @param memory beginning of object which is being zeroed - * @param constantSize is @ size} known to be constant in the snippet + * @param constantSize is {@code size} known to be constant in the snippet * @param startOffset offset to begin zeroing. May not be word aligned. * @param manualUnroll maximally unroll zeroing */ @@ -356,12 +356,12 @@ } /** - * Full uninitialized memory with garbage value in a newly allocated object, unrolling as + * Fill uninitialized memory with garbage value in a newly allocated object, unrolling as * necessary and ensuring that stores are aligned. * * @param size number of bytes to zero * @param memory beginning of object which is being zeroed - * @param constantSize is @ size} known to be constant in the snippet + * @param constantSize is {@code size} known to be constant in the snippet * @param startOffset offset to begin zeroing. May not be word aligned. * @param manualUnroll maximally unroll zeroing */ diff -r a05f318a4a08 -r 4a500b3783fb graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java Wed Jul 15 18:23:44 2015 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BytecodeParser.java Wed Jul 15 10:16:28 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)); } } diff -r a05f318a4a08 -r 4a500b3783fb graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeCheckNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeCheckNode.java Wed Jul 15 18:23:44 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/TypeCheckNode.java Wed Jul 15 10:16:28 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. diff -r a05f318a4a08 -r 4a500b3783fb graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Wed Jul 15 18:23:44 2015 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/InstanceOfTest.java Wed Jul 15 10:16:28 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); + } + } }