# HG changeset patch # User Christian Wimmer # Date 1367427677 25200 # Node ID d9fd6af5d2009a4cc88bcc2c1d154c3d9771cdd4 # Parent fd2e12d41d1838b9e0c0b5cb2fae457a96a15601# Parent e4e2686f30df52d6882781347124035b0c95929d Merge diff -r e4e2686f30df -r d9fd6af5d200 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Wed May 01 18:04:28 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaUtil.java Wed May 01 10:01:17 2013 -0700 @@ -162,6 +162,13 @@ return (type == null) ? null : internalNameToJava(type.getName(), true, false); } + /** + * Returns the type name in the same format as {@link Class#getName()}. + */ + public static String toClassName(JavaType type) { + return internalNameToJava(type.getName(), true, true); + } + private static String internalNameToJava(String name, boolean qualified, boolean classForNameCompatible) { switch (name.charAt(0)) { case 'L': { diff -r e4e2686f30df -r d9fd6af5d200 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Wed May 01 18:04:28 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Wed May 01 10:01:17 2013 -0700 @@ -722,7 +722,7 @@ if (arrayType != null && array.objectStamp().isExactType()) { ResolvedJavaType elementType = arrayType.getComponentType(); if (!MetaUtil.isJavaLangObject(elementType)) { - CheckCastNode checkcast = graph.add(new CheckCastNode(elementType, value, null)); + CheckCastNode checkcast = graph.add(new CheckCastNode(elementType, value, null, true)); graph.addBeforeFixed(storeIndexed, checkcast); value = checkcast; } @@ -730,7 +730,7 @@ LoadHubNode arrayClass = graph.add(new LoadHubNode(array, wordKind)); LocationNode location = ConstantLocationNode.create(LocationNode.FINAL_LOCATION, wordKind, config.arrayClassElementOffset, graph); FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, location, null, StampFactory.forKind(wordKind()))); - CheckCastDynamicNode checkcast = graph.add(new CheckCastDynamicNode(arrayElementKlass, value)); + CheckCastDynamicNode checkcast = graph.add(new CheckCastDynamicNode(arrayElementKlass, value, true)); graph.addBeforeFixed(storeIndexed, checkcast); graph.addBeforeFixed(checkcast, arrayClass); value = checkcast; diff -r e4e2686f30df -r d9fd6af5d200 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed May 01 18:04:28 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed May 01 10:01:17 2013 -0700 @@ -803,7 +803,7 @@ ValueNode object = frameState.apop(); if (type instanceof ResolvedJavaType) { JavaTypeProfile profileForTypeCheck = getProfileForTypeCheck((ResolvedJavaType) type); - CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) type, object, profileForTypeCheck)); + CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) type, object, profileForTypeCheck, false)); append(checkCast); frameState.apush(checkCast); } else { @@ -1661,7 +1661,7 @@ if (typeInstruction != null) { Block nextBlock = block.successors.size() == 1 ? unwindBlock(block.deoptBci) : block.successors.get(1); ValueNode exception = frameState.stackAt(0); - CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) catchType, exception, null)); + CheckCastNode checkCast = currentGraph.add(new CheckCastNode((ResolvedJavaType) catchType, exception, null, false)); frameState.apop(); frameState.push(Kind.Object, checkCast); FixedNode catchSuccessor = createTarget(block.successors.get(0), frameState); diff -r e4e2686f30df -r d9fd6af5d200 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Wed May 01 18:04:28 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Wed May 01 10:01:17 2013 -0700 @@ -90,7 +90,7 @@ } @NodeIntrinsic - public static native void writeMemory(Object object, Object value, Object location, @ConstantNodeParameter boolean usePreciseWriteBarriers); + public static native void writeMemory(Object object, Object value, Object location, @ConstantNodeParameter WriteBarrierType barrierType); @Override public Object[] getLocationIdentities() { diff -r e4e2686f30df -r d9fd6af5d200 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Wed May 01 18:04:28 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Wed May 01 10:01:17 2013 -0700 @@ -22,6 +22,7 @@ */ package com.oracle.graal.nodes.java; +import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -37,13 +38,27 @@ @Input private ValueNode type; /** + * Determines the exception thrown by this node if the check fails: {@link ClassCastException} + * if false; {@link ArrayStoreException} if true. + */ + private final boolean forStoreCheck; + + /** * @param type the type being cast to * @param object the instruction producing the object */ - public CheckCastDynamicNode(ValueNode type, ValueNode object) { + public CheckCastDynamicNode(ValueNode type, ValueNode object, boolean forStoreCheck) { super(object.stamp()); this.type = type; this.object = object; + this.forStoreCheck = forStoreCheck; + assert type.kind() == Kind.Object; + assert type.objectStamp().isExactType(); + assert type.objectStamp().type().getName().equals("Ljava/lang/Class;"); + } + + public boolean isForStoreCheck() { + return forStoreCheck; } @Override @@ -67,6 +82,11 @@ if (object().objectStamp().alwaysNull()) { return object(); } + if (type().isConstant()) { + Class clazz = (Class) type().asConstant().asObject(); + ResolvedJavaType t = tool.runtime().lookupJavaType(clazz); + return graph().add(new CheckCastNode(t, object(), null, forStoreCheck)); + } return this; } @@ -80,4 +100,7 @@ public ValueNode type() { return type; } + + @NodeIntrinsic + public static native T checkCastDynamic(Class type, Object object, @ConstantNodeParameter boolean forStoreCheck); } diff -r e4e2686f30df -r d9fd6af5d200 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Wed May 01 18:04:28 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Wed May 01 10:01:17 2013 -0700 @@ -38,17 +38,28 @@ private final JavaTypeProfile profile; /** + * Determines the exception thrown by this node if the check fails: {@link ClassCastException} + * if false; {@link ArrayStoreException} if true. + */ + private final boolean forStoreCheck; + + /** * Creates a new CheckCast instruction. * * @param type the type being cast to * @param object the instruction producing the object */ - public CheckCastNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile) { + public CheckCastNode(ResolvedJavaType type, ValueNode object, JavaTypeProfile profile, boolean forStoreCheck) { super(StampFactory.declared(type)); assert type != null; this.type = type; this.object = object; this.profile = profile; + this.forStoreCheck = forStoreCheck; + } + + public boolean isForStoreCheck() { + return forStoreCheck; } @Override @@ -68,26 +79,31 @@ public ValueNode canonical(CanonicalizerTool tool) { assert object() != null : this; - if (type != null) { - ResolvedJavaType objectType = object().objectStamp().type(); - if (objectType != null && type.isAssignableFrom(objectType)) { - // we don't have to check for null types here because they will also pass the - // checkcast. + ResolvedJavaType objectType = object().objectStamp().type(); + if (objectType != null && type.isAssignableFrom(objectType)) { + // we don't have to check for null types here because they will also pass the + // checkcast. + return object(); + } + // remove checkcast if the only usage is a more specific checkcast + if (usages().count() == 1) { + CheckCastNode ccn = usages().filter(CheckCastNode.class).first(); + if (ccn != null && ccn.type() != null && type.isAssignableFrom(ccn.type())) { return object(); } - - // remove checkcast if the only usage is a more specific checkcast - if (usages().count() == 1) { - CheckCastNode ccn = usages().filter(CheckCastNode.class).first(); - if (ccn != null && ccn.type() != null && type.isAssignableFrom(ccn.type())) { - return object(); - } - } } if (object().objectStamp().alwaysNull()) { return object(); } + if (tool.assumptions().useOptimisticAssumptions()) { + ResolvedJavaType exactType = type.findUniqueConcreteSubtype(); + if (exactType != null && exactType != type) { + // Propagate more precise type information to usages of the checkcast. + tool.assumptions().recordConcreteSubtype(type, exactType); + return graph().add(new CheckCastNode(exactType, object, profile, forStoreCheck)); + } + } return this; } diff -r e4e2686f30df -r d9fd6af5d200 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Wed May 01 18:04:28 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoadIndexedNode.java Wed May 01 10:01:17 2013 -0700 @@ -53,6 +53,11 @@ } @Override + public boolean inferStamp() { + return updateStamp(createStamp(array(), elementKind())); + } + + @Override public void virtualize(VirtualizerTool tool) { State arrayState = tool.getObjectState(array()); if (arrayState != null && arrayState.getState() == EscapeState.Virtual) { diff -r e4e2686f30df -r d9fd6af5d200 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java Wed May 01 18:04:28 2013 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java Wed May 01 10:01:17 2013 -0700 @@ -22,7 +22,6 @@ */ package com.oracle.graal.replacements.test; - import com.oracle.graal.api.meta.*; import com.oracle.graal.test.*; import com.oracle.graal.nodes.*; @@ -37,7 +36,7 @@ protected void replaceProfile(StructuredGraph graph, JavaTypeProfile profile) { CheckCastNode ccn = graph.getNodes(CheckCastNode.class).first(); if (ccn != null) { - CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.type(), ccn.object(), profile)); + CheckCastNode ccnNew = graph.add(new CheckCastNode(ccn.type(), ccn.object(), profile, false)); graph.replaceFixedWithFixed(ccn, ccnNew); } } diff -r e4e2686f30df -r d9fd6af5d200 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Wed May 01 18:04:28 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Wed May 01 10:01:17 2013 -0700 @@ -366,9 +366,10 @@ afterInline(graph, originalGraph); substituteCallsOriginal = true; } else { - if ((callTarget.invokeKind() == InvokeKind.Static || callTarget.invokeKind() == InvokeKind.Special) && policy.shouldInline(callee, methodToParse)) { + StructuredGraph intrinsicGraph = InliningUtil.getIntrinsicGraph(ReplacementsImpl.this, callee); + if ((callTarget.invokeKind() == InvokeKind.Static || callTarget.invokeKind() == InvokeKind.Special) && + (policy.shouldInline(callee, methodToParse) || (intrinsicGraph != null && policy.shouldUseReplacement(callee, methodToParse)))) { StructuredGraph targetGraph; - StructuredGraph intrinsicGraph = InliningUtil.getIntrinsicGraph(ReplacementsImpl.this, callee); if (intrinsicGraph != null && policy.shouldUseReplacement(callee, methodToParse)) { targetGraph = intrinsicGraph; } else { diff -r e4e2686f30df -r d9fd6af5d200 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Wed May 01 18:04:28 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Wed May 01 10:01:17 2013 -0700 @@ -440,7 +440,7 @@ if (loopBegin != null) { LoopEx loop = new LoopsData(snippetCopy).loop(loopBegin); int mark = snippetCopy.getMark(); - LoopTransformations.fullUnroll(loop, runtime, null); + LoopTransformations.fullUnroll(loop, runtime, replacements.getAssumptions()); new CanonicalizerPhase.Instance(runtime, replacements.getAssumptions(), mark, null).apply(snippetCopy); } FixedNode explodeLoopNext = explodeLoop.next();