# HG changeset patch # User Christian Wimmer # Date 1367425295 25200 # Node ID fb22b4d5f475a858c696fdab20fb634589e9f589 # Parent 3b02fe9e198380976ab4e857e4c9ec9529e97afd Allow distinction between ClassCastException and ArrayStoreException. Add more canonicalizations for check casts. diff -r 3b02fe9e1983 -r fb22b4d5f475 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 09:13:34 2013 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Wed May 01 09:21:35 2013 -0700 @@ -706,7 +706,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; } @@ -714,7 +714,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 3b02fe9e1983 -r fb22b4d5f475 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 09:13:34 2013 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed May 01 09:21:35 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 3b02fe9e1983 -r fb22b4d5f475 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 09:13:34 2013 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Wed May 01 09:21:35 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 3b02fe9e1983 -r fb22b4d5f475 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 09:13:34 2013 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Wed May 01 09:21:35 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 3b02fe9e1983 -r fb22b4d5f475 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 09:13:34 2013 -0700 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/CheckCastTest.java Wed May 01 09:21:35 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); } }