# HG changeset patch # User Thomas Wuerthinger # Date 1432668120 -7200 # Node ID ce585b0ac3e2eef29a0c4423ab9a5c524a331a30 # Parent ac86179c56ad7eae552fc6b771821cebe5449157 Create different nodes in the graph builder when instanceof and checkcast have a single type profile. diff -r ac86179c56ad -r ce585b0ac3e2 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java Tue May 26 20:48:30 2015 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/JavaTypeProfile.java Tue May 26 21:22:00 2015 +0200 @@ -174,4 +174,22 @@ } return buf.append(String.format("], notRecorded:%.6f>", getNotRecordedProbability())).toString(); } + + /** + * Returns {@code true} if all types seen at this location have been recorded in the profile. + */ + public boolean allTypesRecorded() { + return this.getNotRecordedProbability() == 0.0; + } + + /** + * Returns the single monormorphic type representing this profile or {@code null} if no such + * type exists. + */ + public ResolvedJavaType asSingleType() { + if (allTypesRecorded() && this.getTypes().length == 1) { + return getTypes()[0].getType(); + } + return null; + } } diff -r ac86179c56ad -r ce585b0ac3e2 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 Tue May 26 20:48:30 2015 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue May 26 21:22:00 2015 +0200 @@ -3068,7 +3068,26 @@ JavaTypeProfile profile = getProfileForTypeCheck(resolvedType); TypeCheckPlugin typeCheckPlugin = this.graphBuilderConfig.getPlugins().getTypeCheckPlugin(); if (typeCheckPlugin == null || !typeCheckPlugin.checkCast(this, object, resolvedType, profile)) { - ValueNode checkCastNode = append(createCheckCast(resolvedType, object, profile, false)); + ValueNode checkCastNode = null; + if (profile != null) { + if (profile.getNullSeen().isFalse()) { + object = append(GuardingPiNode.createNullCheck(object)); + ResolvedJavaType singleType = profile.asSingleType(); + if (singleType != null) { + LogicNode typeCheck = append(TypeCheckNode.create(singleType, object)); + if (typeCheck.isTautology()) { + checkCastNode = object; + } else { + GuardingPiNode piNode = append(new GuardingPiNode(object, typeCheck, false, DeoptimizationReason.TypeCheckedInliningViolated, + DeoptimizationAction.InvalidateReprofile, StampFactory.exactNonNull(singleType))); + checkCastNode = piNode; + } + } + } + } + if (checkCastNode == null) { + checkCastNode = append(createCheckCast(resolvedType, object, profile, false)); + } frameState.apush(checkCastNode); } } else { @@ -3085,7 +3104,21 @@ JavaTypeProfile profile = getProfileForTypeCheck(resolvedType); TypeCheckPlugin typeCheckPlugin = this.graphBuilderConfig.getPlugins().getTypeCheckPlugin(); if (typeCheckPlugin == null || !typeCheckPlugin.instanceOf(this, object, resolvedType, profile)) { - ValueNode instanceOfNode = createInstanceOf(resolvedType, object, profile); + ValueNode instanceOfNode = null; + if (profile != null) { + if (profile.getNullSeen().isFalse()) { + object = append(GuardingPiNode.createNullCheck(object)); + ResolvedJavaType singleType = profile.asSingleType(); + if (singleType != null) { + LogicNode typeCheck = append(TypeCheckNode.create(singleType, object)); + append(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile)); + instanceOfNode = LogicConstantNode.forBoolean(resolvedType.isAssignableFrom(singleType)); + } + } + } + if (instanceOfNode == null) { + instanceOfNode = createInstanceOf(resolvedType, object, profile); + } frameState.ipush(append(genConditional(genUnique(instanceOfNode)))); } } else { diff -r ac86179c56ad -r ce585b0ac3e2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Tue May 26 20:48:30 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Tue May 26 21:22:00 2015 +0200 @@ -81,6 +81,15 @@ this.negated = negateCondition; } + public static ValueNode createNullCheck(ValueNode object) { + ObjectStamp objectStamp = (ObjectStamp) object.stamp(); + if (objectStamp.nonNull()) { + return object; + } else { + return new GuardingPiNode(object); + } + } + @Override public void lower(LoweringTool tool) { GuardingNode guard = tool.createGuard(next(), condition, reason, action, negated); diff -r ac86179c56ad -r ce585b0ac3e2 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java Tue May 26 20:48:30 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LogicNode.java Tue May 26 21:22:00 2015 +0200 @@ -55,4 +55,22 @@ public static LogicNode or(LogicNode a, boolean negateA, LogicNode b, boolean negateB, double shortCircuitProbability) { return a.graph().unique(new ShortCircuitOrNode(a, negateA, b, negateB, shortCircuitProbability)); } + + public final boolean isTautology() { + if (this instanceof LogicConstantNode) { + LogicConstantNode logicConstantNode = (LogicConstantNode) this; + return logicConstantNode.getValue(); + } + + return false; + } + + public final boolean isContradiction() { + if (this instanceof LogicConstantNode) { + LogicConstantNode logicConstantNode = (LogicConstantNode) this; + return !logicConstantNode.getValue(); + } + + return false; + } }