# HG changeset patch # User Doug Simon # Date 1375798385 -7200 # Node ID 422b0e9b9aedb43416ae97a6761524ce3a829f09 # Parent 3718acd022dbd0f91ca7738bf2504f511b4cfea5 removed obsolete checkcast snippets diff -r 3718acd022db -r 422b0e9b9aed 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 Mon Aug 05 20:20:32 2013 -0700 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Aug 06 16:13:05 2013 +0200 @@ -109,7 +109,7 @@ protected final HotSpotGraalRuntime graalRuntime; private final Suites defaultSuites; - private CheckCastSnippets.Templates checkcastSnippets; + private CheckCastDynamicSnippets.Templates checkcastDynamicSnippets; private InstanceOfSnippets.Templates instanceofSnippets; private NewObjectSnippets.Templates newObjectSnippets; private MonitorSnippets.Templates monitorSnippets; @@ -336,7 +336,7 @@ r.registerSubstitutions(ReflectionSubstitutions.class); } - checkcastSnippets = new CheckCastSnippets.Templates(this, r, graalRuntime.getTarget()); + checkcastDynamicSnippets = new CheckCastDynamicSnippets.Templates(this, r, graalRuntime.getTarget()); instanceofSnippets = new InstanceOfSnippets.Templates(this, r, graalRuntime.getTarget()); newObjectSnippets = new NewObjectSnippets.Templates(this, r, graalRuntime.getTarget()); monitorSnippets = new MonitorSnippets.Templates(this, r, graalRuntime.getTarget(), c.useFastLocking); @@ -759,8 +759,6 @@ } graph.removeFixed(commit); } - } else if (n instanceof CheckCastNode) { - checkcastSnippets.lower((CheckCastNode) n, tool); } else if (n instanceof OSRStartNode) { if (tool.getLoweringType() == LoweringType.AFTER_GUARDS) { OSRStartNode osrStart = (OSRStartNode) n; @@ -789,7 +787,7 @@ osrStart.safeDelete(); } } else if (n instanceof CheckCastDynamicNode) { - checkcastSnippets.lower((CheckCastDynamicNode) n); + checkcastDynamicSnippets.lower((CheckCastDynamicNode) n); } else if (n instanceof InstanceOfNode) { instanceofSnippets.lower((InstanceOfNode) n, tool); } else if (n instanceof InstanceOfDynamicNode) { diff -r 3718acd022db -r 422b0e9b9aed graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java Tue Aug 06 16:13:05 2013 +0200 @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.replacements; + +import static com.oracle.graal.api.code.DeoptimizationAction.*; +import static com.oracle.graal.api.meta.DeoptimizationReason.*; +import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; +import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*; +import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; +import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; +import static com.oracle.graal.replacements.SnippetTemplate.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.java.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.replacements.*; +import com.oracle.graal.replacements.Snippet.ConstantParameter; +import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.replacements.SnippetTemplate.Arguments; +import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; +import com.oracle.graal.word.*; + +/** + * Snippet used for lowering {@link CheckCastDynamicNode}. + */ +public class CheckCastDynamicSnippets implements Snippets { + + @Snippet + public static Object checkcastDynamic(Word hub, Object object, @ConstantParameter boolean checkNull) { + if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) { + isNull.inc(); + } else { + Word objectHub = loadHub(object); + if (!checkUnknownSubType(hub, objectHub)) { + DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException); + } + } + BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic()); + return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode); + } + + public static class Templates extends AbstractTemplates { + + private final SnippetInfo dynamic = snippet(CheckCastDynamicSnippets.class, "checkcastDynamic"); + + public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { + super(runtime, replacements, target); + } + + public void lower(CheckCastDynamicNode checkcast) { + StructuredGraph graph = checkcast.graph(); + ValueNode object = checkcast.object(); + + Arguments args = new Arguments(dynamic); + args.add("hub", checkcast.hub()); + args.add("object", object); + args.addConst("checkNull", !object.stamp().nonNull()); + + SnippetTemplate template = template(args); + Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args); + template.instantiate(runtime, checkcast, DEFAULT_REPLACER, args); + } + } +} diff -r 3718acd022db -r 422b0e9b9aed graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastSnippets.java Mon Aug 05 20:20:32 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,215 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.replacements; - -import static com.oracle.graal.api.code.DeoptimizationAction.*; -import static com.oracle.graal.api.meta.DeoptimizationReason.*; -import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; -import static com.oracle.graal.hotspot.replacements.TypeCheckSnippetUtils.*; -import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; -import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; -import static com.oracle.graal.phases.GraalOptions.*; -import static com.oracle.graal.replacements.SnippetTemplate.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.java.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.Snippet.ConstantParameter; -import com.oracle.graal.replacements.Snippet.VarargsParameter; -import com.oracle.graal.replacements.SnippetTemplate.AbstractTemplates; -import com.oracle.graal.replacements.SnippetTemplate.Arguments; -import com.oracle.graal.replacements.SnippetTemplate.SnippetInfo; -import com.oracle.graal.replacements.nodes.*; -import com.oracle.graal.word.*; - -/** - * Snippets used for implementing the type test of a checkcast instruction. - * - * The type tests implemented are described in the paper Fast subtype checking in the HotSpot JVM by - * Cliff Click and John Rose. - */ -public class CheckCastSnippets implements Snippets { - - @NodeIntrinsic(BreakpointNode.class) - static native void bkpt(Object object, Word hub, Word objectHub); - - /** - * Type test used when the type being tested against is a final type. - */ - @Snippet - public static Object checkcastExact(Object object, Word exactHub, @ConstantParameter boolean checkNull) { - if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); - } else { - Word objectHub = loadHub(object); - if (objectHub.notEqual(exactHub)) { - exactMiss.inc(); - DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException); - } - exactHit.inc(); - } - /* - * make sure that the unsafeCast is done *after* the check above, cf. ReadAfterCheckCast - */ - BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic()); - return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode); - } - - /** - * Type test used when the type being tested against is a restricted primary type. - * - * This test ignores use of hints altogether as the display-based type check only involves one - * extra load where the second load should hit the same cache line as the first. - */ - @Snippet - public static Object checkcastPrimary(Word hub, Object object, @ConstantParameter int superCheckOffset, @ConstantParameter boolean checkNull) { - if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); - } else { - Word objectHub = loadHub(object); - if (objectHub.readWord(superCheckOffset, LocationIdentity.FINAL_LOCATION).notEqual(hub)) { - displayMiss.inc(); - DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException); - } - displayHit.inc(); - } - BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic()); - return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode); - } - - /** - * Type test used when the type being tested against is a restricted secondary type. - */ - @Snippet - public static Object checkcastSecondary(Word hub, Object object, @VarargsParameter Word[] hints, @ConstantParameter boolean checkNull) { - if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); - } else { - Word objectHub = loadHub(object); - // if we get an exact match: succeed immediately - ExplodeLoopNode.explodeLoop(); - for (int i = 0; i < hints.length; i++) { - Word hintHub = hints[i]; - if (hintHub.equal(objectHub)) { - hintsHit.inc(); - BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic()); - return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode); - } - } - if (!checkSecondarySubType(hub, objectHub)) { - DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException); - } - } - BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic()); - return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode); - } - - /** - * Type test used when the type being tested against is not known at compile time (e.g. the type - * test in an object array store check). - */ - @Snippet - public static Object checkcastDynamic(Word hub, Object object, @ConstantParameter boolean checkNull) { - if (checkNull && probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); - } else { - Word objectHub = loadHub(object); - if (!checkUnknownSubType(hub, objectHub)) { - DeoptimizeNode.deopt(InvalidateReprofile, ClassCastException); - } - } - BeginNode anchorNode = BeginNode.anchor(StampFactory.forNodeIntrinsic()); - return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode); - } - - public static class Templates extends AbstractTemplates { - - private final SnippetInfo exact = snippet(CheckCastSnippets.class, "checkcastExact"); - private final SnippetInfo primary = snippet(CheckCastSnippets.class, "checkcastPrimary"); - private final SnippetInfo secondary = snippet(CheckCastSnippets.class, "checkcastSecondary"); - private final SnippetInfo dynamic = snippet(CheckCastSnippets.class, "checkcastDynamic"); - - public Templates(CodeCacheProvider runtime, Replacements replacements, TargetDescription target) { - super(runtime, replacements, target); - } - - /** - * Lowers a checkcast node. - */ - public void lower(CheckCastNode checkcast, LoweringTool tool) { - StructuredGraph graph = checkcast.graph(); - ValueNode object = checkcast.object(); - HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) checkcast.type(); - TypeCheckHints hintInfo = new TypeCheckHints(checkcast.type(), checkcast.profile(), tool.assumptions(), CheckcastMinHintHitProbability.getValue(), CheckcastMaxHints.getValue()); - ValueNode hub = ConstantNode.forConstant(type.klass(), runtime, checkcast.graph()); - - Arguments args; - if (hintInfo.exact != null) { - args = new Arguments(exact); - args.add("object", object); - args.add("exactHub", ConstantNode.forConstant(((HotSpotResolvedObjectType) hintInfo.exact).klass(), runtime, graph)); - } else if (type.isPrimaryType()) { - args = new Arguments(primary); - args.add("hub", hub); - args.add("object", object); - args.addConst("superCheckOffset", type.superCheckOffset()); - } else { - ConstantNode[] hints = createHints(hintInfo, runtime, true, graph).hubs; - args = new Arguments(secondary); - args.add("hub", hub); - args.add("object", object); - args.addVarargs("hints", Word.class, StampFactory.forKind(getWordKind()), hints); - } - args.addConst("checkNull", !object.stamp().nonNull()); - - SnippetTemplate template = template(args); - Debug.log("Lowering checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args); - template.instantiate(runtime, checkcast, DEFAULT_REPLACER, args); - } - - /** - * Lowers a dynamic checkcast node. - */ - public void lower(CheckCastDynamicNode checkcast) { - StructuredGraph graph = checkcast.graph(); - ValueNode object = checkcast.object(); - - Arguments args = new Arguments(dynamic); - args.add("hub", checkcast.type()); - args.add("object", object); - args.addConst("checkNull", !object.stamp().nonNull()); - - SnippetTemplate template = template(args); - Debug.log("Lowering dynamic checkcast in %s: node=%s, template=%s, arguments=%s", graph, checkcast, template, args); - template.instantiate(runtime, checkcast, DEFAULT_REPLACER, args); - } - } -} diff -r 3718acd022db -r 422b0e9b9aed 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 Mon Aug 05 20:20:32 2013 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastDynamicNode.java Tue Aug 06 16:13:05 2013 +0200 @@ -35,7 +35,7 @@ public final class CheckCastDynamicNode extends FixedWithNextNode implements Canonicalizable, Lowerable, Node.IterableNodeType { @Input private ValueNode object; - @Input private ValueNode type; + @Input private ValueNode hub; /** * Determines the exception thrown by this node if the check fails: {@link ClassCastException} @@ -44,12 +44,12 @@ private final boolean forStoreCheck; /** - * @param type the type being cast to - * @param object the instruction producing the object + * @param hub the type being cast to + * @param object the object being cast */ - public CheckCastDynamicNode(ValueNode type, ValueNode object, boolean forStoreCheck) { + public CheckCastDynamicNode(ValueNode hub, ValueNode object, boolean forStoreCheck) { super(object.stamp()); - this.type = type; + this.hub = hub; this.object = object; this.forStoreCheck = forStoreCheck; } @@ -79,8 +79,8 @@ if (object().objectStamp().alwaysNull()) { return object(); } - if (type().isConstant() && type().kind() == Kind.Object && type().asConstant().asObject() instanceof Class) { - Class clazz = (Class) type().asConstant().asObject(); + if (hub.isConstant() && hub.kind() == Kind.Object && hub.asConstant().asObject() instanceof Class) { + Class clazz = (Class) hub.asConstant().asObject(); ResolvedJavaType t = tool.runtime().lookupJavaType(clazz); return graph().add(new CheckCastNode(t, object(), null, forStoreCheck)); } @@ -94,8 +94,8 @@ /** * Gets the runtime-loaded type being cast to. */ - public ValueNode type() { - return type; + public ValueNode hub() { + return hub; } @NodeIntrinsic diff -r 3718acd022db -r 422b0e9b9aed 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 Mon Aug 05 20:20:32 2013 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CheckCastNode.java Tue Aug 06 16:13:05 2013 +0200 @@ -69,10 +69,6 @@ return forStoreCheck; } - // TODO (ds) remove once performance regression in compiler.sunflow (and other benchmarks) - // caused by new lowering is fixed - private static final boolean useNewLowering = true; // Boolean.getBoolean("graal.checkcast.useNewLowering"); - /** * Lowers a {@link CheckCastNode} to a {@link GuardingPiNode}. That is: * @@ -101,33 +97,29 @@ */ @Override public void lower(LoweringTool tool, LoweringType loweringType) { - if (useNewLowering) { - InstanceOfNode typeTest = graph().add(new InstanceOfNode(type, object, profile)); - Stamp stamp = StampFactory.declared(type).join(object.stamp()); - ValueNode condition; - if (stamp == null) { - // This is a check cast that will always fail - condition = LogicConstantNode.contradiction(graph()); - stamp = StampFactory.declared(type); - } else if (object.stamp().nonNull()) { + InstanceOfNode typeTest = graph().add(new InstanceOfNode(type, object, profile)); + Stamp stamp = StampFactory.declared(type).join(object.stamp()); + ValueNode condition; + if (stamp == null) { + // This is a check cast that will always fail + condition = LogicConstantNode.contradiction(graph()); + stamp = StampFactory.declared(type); + } else if (object.stamp().nonNull()) { + condition = typeTest; + } else { + if (profile != null && profile.getNullSeen() == TriState.FALSE) { + FixedGuardNode nullGuard = graph().add(new FixedGuardNode(graph().unique(new IsNullNode(object)), UnreachedCode, DeoptimizationAction.InvalidateReprofile, true)); + graph().addBeforeFixed(this, nullGuard); condition = typeTest; + stamp = stamp.join(StampFactory.objectNonNull()); } else { - if (profile != null && profile.getNullSeen() == TriState.FALSE) { - FixedGuardNode nullGuard = graph().add(new FixedGuardNode(graph().unique(new IsNullNode(object)), UnreachedCode, DeoptimizationAction.InvalidateReprofile, true)); - graph().addBeforeFixed(this, nullGuard); - condition = typeTest; - stamp = stamp.join(StampFactory.objectNonNull()); - } else { - // TODO (ds) replace with probability of null-seen when available - double shortCircuitProbability = NOT_FREQUENT_PROBABILITY; - condition = graph().unique(new ShortCircuitOrNode(graph().unique(new IsNullNode(object)), false, typeTest, false, shortCircuitProbability)); - } + // TODO (ds) replace with probability of null-seen when available + double shortCircuitProbability = NOT_FREQUENT_PROBABILITY; + condition = graph().unique(new ShortCircuitOrNode(graph().unique(new IsNullNode(object)), false, typeTest, false, shortCircuitProbability)); } - GuardingPiNode checkedObject = graph().add(new GuardingPiNode(object, condition, false, forStoreCheck ? ArrayStoreException : ClassCastException, InvalidateReprofile, stamp)); - graph().replaceFixedWithFixed(this, checkedObject); - } else { - tool.getRuntime().lower(this, tool); } + GuardingPiNode checkedObject = graph().add(new GuardingPiNode(object, condition, false, forStoreCheck ? ArrayStoreException : ClassCastException, InvalidateReprofile, stamp)); + graph().replaceFixedWithFixed(this, checkedObject); } @Override diff -r 3718acd022db -r 422b0e9b9aed graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Mon Aug 05 20:20:32 2013 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/InstanceOfDynamicNode.java Tue Aug 06 16:13:05 2013 +0200 @@ -39,16 +39,13 @@ @Input private ValueNode mirror; /** - * Constructs a new InstanceOfNode. - * - * @param mirror the {@link Class} value representing the target target type of the instanceof - * check - * @param object the object being tested by the instanceof + * @param mirror the {@link Class} value representing the target target type of the test + * @param object the object being tested */ public InstanceOfDynamicNode(ValueNode mirror, ValueNode object) { this.mirror = mirror; this.object = object; - assert mirror.kind() == Kind.Object; + assert mirror.kind() == Kind.Object : mirror.kind(); assert mirror.objectStamp().isExactType(); assert mirror.objectStamp().type().getName().equals("Ljava/lang/Class;"); }