# HG changeset patch # User Christian Wimmer # Date 1379972160 25200 # Node ID 7e7edb86fb4333784f086f2373b287340b9596a8 # Parent 29de278b7c1b317b9b6e89bb706c39ba428dc28b Refactor the handling of unsafe casts to distinguish between word-object-conversions, PiNode-like type information, and real unsafe casts. diff -r 29de278b7c1b -r 7e7edb86fb43 graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java --- a/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Sun Sep 22 02:24:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.test/src/com/oracle/graal/hotspot/test/AheadOfTimeCompilationTest.java Mon Sep 23 14:36:00 2013 -0700 @@ -175,7 +175,7 @@ StructuredGraph result = compile("getBoxedBoolean", true); assertEquals(2, result.getNodes(FloatingReadNode.class).count()); - assertEquals(1, result.getNodes(UnsafeCastNode.class).count()); + assertEquals(1, result.getNodes(PiNode.class).count()); assertEquals(1, result.getNodes().filter(ConstantNode.class).count()); ConstantNode constant = result.getNodes().filter(ConstantNode.class).first(); assertEquals(Kind.Long, constant.kind()); @@ -186,7 +186,7 @@ public void testBoxedBoolean() { StructuredGraph result = compile("getBoxedBoolean", false); assertEquals(0, result.getNodes(FloatingReadNode.class).count()); - assertEquals(0, result.getNodes(UnsafeCastNode.class).count()); + assertEquals(0, result.getNodes(PiNode.class).count()); assertEquals(1, result.getNodes().filter(ConstantNode.class).count()); ConstantNode constant = result.getNodes().filter(ConstantNode.class).first(); assertEquals(Kind.Object, constant.kind()); diff -r 29de278b7c1b -r 7e7edb86fb43 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java Sun Sep 22 02:24:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CheckCastDynamicSnippets.java Mon Sep 23 14:36:00 2013 -0700 @@ -26,8 +26,8 @@ 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.PiNode.*; 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.*; @@ -59,7 +59,7 @@ } } BeginNode anchorNode = BeginNode.anchor(); - return unsafeCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode); + return piCast(verifyOop(object), StampFactory.forNodeIntrinsic(), anchorNode); } public static class Templates extends AbstractTemplates { diff -r 29de278b7c1b -r 7e7edb86fb43 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java Sun Sep 22 02:24:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ClassSubstitutions.java Mon Sep 23 14:36:00 2013 -0700 @@ -23,7 +23,7 @@ package com.oracle.graal.hotspot.replacements; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; -import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; +import static com.oracle.graal.nodes.PiNode.*; import java.lang.reflect.*; @@ -96,7 +96,7 @@ if (superKlass.equal(0)) { return null; } else { - return unsafeCast(superKlass.readObject(classMirrorOffset(), LocationIdentity.FINAL_LOCATION), Class.class, true, true); + return piCast(superKlass.readObject(classMirrorOffset(), LocationIdentity.FINAL_LOCATION), Class.class, true, true); } } } @@ -110,7 +110,7 @@ Word klass = loadWordFromObject(thisObj, klassOffset()); if (klass.notEqual(0)) { if ((readLayoutHelper(klass) & arrayKlassLayoutHelperIdentifier()) != 0) { - return unsafeCast(klass.readObject(arrayKlassComponentMirrorOffset(), LocationIdentity.FINAL_LOCATION), Class.class, true, true); + return piCast(klass.readObject(arrayKlassComponentMirrorOffset(), LocationIdentity.FINAL_LOCATION), Class.class, true, true); } } return null; diff -r 29de278b7c1b -r 7e7edb86fb43 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Sun Sep 22 02:24:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LoadExceptionObjectSnippets.java Mon Sep 23 14:36:00 2013 -0700 @@ -24,7 +24,7 @@ import static com.oracle.graal.hotspot.meta.HotSpotRuntime.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; -import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; +import static com.oracle.graal.nodes.PiNode.*; import static com.oracle.graal.replacements.SnippetTemplate.*; import com.oracle.graal.api.code.*; @@ -57,7 +57,7 @@ Object exception = readExceptionOop(thread); writeExceptionOop(thread, null); writeExceptionPc(thread, Word.zero()); - return unsafeCast(exception, StampFactory.forNodeIntrinsic()); + return piCast(exception, StampFactory.forNodeIntrinsic()); } public static class Templates extends AbstractTemplates { diff -r 29de278b7c1b -r 7e7edb86fb43 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 Sun Sep 22 02:24:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Mon Sep 23 14:36:00 2013 -0700 @@ -25,9 +25,9 @@ import static com.oracle.graal.api.code.UnsignedMath.*; import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; +import static com.oracle.graal.nodes.PiArrayNode.*; +import static com.oracle.graal.nodes.PiNode.*; import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; -import static com.oracle.graal.nodes.extended.UnsafeArrayCastNode.*; -import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; import static com.oracle.graal.phases.GraalOptions.*; import static com.oracle.graal.replacements.SnippetTemplate.*; import static com.oracle.graal.replacements.nodes.ExplodeLoopNode.*; @@ -35,6 +35,8 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; +import com.oracle.graal.graph.Node.ConstantNodeParameter; +import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.*; @@ -87,8 +89,7 @@ new_stub.inc(); result = NewInstanceStubCall.call(hub); } - BeginNode anchorNode = BeginNode.anchor(); - return unsafeCast(verifyOop(result), StampFactory.forNodeIntrinsic(), anchorNode); + return piCast(verifyOop(result), StampFactory.forNodeIntrinsic()); } /** @@ -121,8 +122,7 @@ newarray_stub.inc(); result = NewArrayStubCall.call(hub, length); } - BeginNode anchorNode = BeginNode.anchor(); - return unsafeArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic(), anchorNode); + return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic()); } public static final ForeignCallDescriptor DYNAMIC_NEW_ARRAY = new ForeignCallDescriptor("dynamic_new_array", Object.class, Class.class, int.class); diff -r 29de278b7c1b -r 7e7edb86fb43 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java Sun Sep 22 02:24:13 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/ObjectSubstitutions.java Mon Sep 23 14:36:00 2013 -0700 @@ -23,7 +23,7 @@ package com.oracle.graal.hotspot.replacements; import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; -import static com.oracle.graal.nodes.extended.UnsafeCastNode.*; +import static com.oracle.graal.nodes.PiNode.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.replacements.*; @@ -41,7 +41,7 @@ @MethodSubstitution(isStatic = false, forced = true) public static Class getClass(final Object thisObj) { Word hub = loadHub(thisObj); - return unsafeCast(hub.readObject(Word.signed(classMirrorOffset()), LocationIdentity.FINAL_LOCATION), Class.class, true, true); + return piCast(hub.readObject(Word.signed(classMirrorOffset()), LocationIdentity.FINAL_LOCATION), Class.class, true, true); } @MethodSubstitution(isStatic = false) diff -r 29de278b7c1b -r 7e7edb86fb43 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 Sun Sep 22 02:24:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardingPiNode.java Mon Sep 23 14:36:00 2013 -0700 @@ -82,7 +82,7 @@ } GuardingNode guard = tool.createGuard(condition, reason, action, negated); ValueAnchorNode anchor = graph().add(new ValueAnchorNode((ValueNode) guard)); - PiNode pi = graph().unique(new PiNode(object, stamp(), guard)); + PiNode pi = graph().unique(new PiNode(object, stamp(), (ValueNode) guard)); replaceAtUsages(pi); graph().replaceFixedWithFixed(this, anchor); } diff -r 29de278b7c1b -r 7e7edb86fb43 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiArrayNode.java Mon Sep 23 14:36:00 2013 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2012, 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.nodes; + +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * The {@code UnsafeCastNode} produces the same value as its input, but with a different type. + */ +public final class PiArrayNode extends PiNode implements ArrayLengthProvider { + + @Input private ValueNode length; + + public ValueNode length() { + return length; + } + + public PiArrayNode(ValueNode object, ValueNode length, Stamp stamp) { + super(object, stamp); + this.length = length; + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (!(object() instanceof ArrayLengthProvider) || length() != ((ArrayLengthProvider) object()).length()) { + return this; + } + return super.canonical(tool); + } + + @NodeIntrinsic + public static native T piArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp); +} diff -r 29de278b7c1b -r 7e7edb86fb43 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Sun Sep 22 02:24:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PiNode.java Mon Sep 23 14:36:00 2013 -0700 @@ -49,13 +49,21 @@ this.object = object; } - public PiNode(ValueNode object, Stamp stamp, GuardingNode anchor) { - super(stamp, anchor); + public PiNode(ValueNode object, Stamp stamp, ValueNode anchor) { + super(stamp, (GuardingNode) anchor); this.object = object; } + public PiNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { + this(object, StampFactory.object(toType, exactType, nonNull || ObjectStamp.isObjectNonNull(object.stamp()))); + } + @Override public void generate(LIRGeneratorTool generator) { + assert kind() == Kind.Object && object.kind() == Kind.Object; + assert ObjectStamp.typeOrNull(object) == null || ObjectStamp.typeOrNull(this).isInterface() || ObjectStamp.typeOrNull(object).isInterface() || + ObjectStamp.typeOrNull(object).isAssignableFrom(ObjectStamp.typeOrNull(this)); + if (object.kind() != Kind.Void && object.kind() != Kind.Illegal) { generator.setResult(this, generator.operand(object)); } @@ -63,6 +71,9 @@ @Override public boolean inferStamp() { + if (stamp() == StampFactory.forNodeIntrinsic()) { + return false; + } return updateStamp(stamp().join(object().stamp())); } @@ -70,14 +81,7 @@ public void virtualize(VirtualizerTool tool) { State state = tool.getObjectState(object); if (state != null && state.getState() == EscapeState.Virtual) { - ResolvedJavaType virtualObjectType = state.getVirtualObject().type(); - if (this.kind() == Kind.Object) { - ObjectStamp myStamp = ((ObjectStamp) this.stamp()); - ResolvedJavaType myType = myStamp.type(); - if (!myType.isAssignableFrom(virtualObjectType)) { - return; - } - } + assert ObjectStamp.typeOrNull(this).isAssignableFrom(state.getVirtualObject().type()); tool.replaceWithVirtual(state.getVirtualObject()); } } @@ -95,4 +99,16 @@ public ValueNode getOriginalValue() { return object; } + + @NodeIntrinsic + public static native T piCast(Object object, @ConstantNodeParameter Stamp stamp); + + @NodeIntrinsic + public static native T piCast(Object object, @ConstantNodeParameter Stamp stamp, GuardingNode anchor); + + @SuppressWarnings("unused") + @NodeIntrinsic + public static T piCast(Object object, @ConstantNodeParameter Class toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull) { + return toType.cast(object); + } } diff -r 29de278b7c1b -r 7e7edb86fb43 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java Sun Sep 22 02:24:13 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2012, 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.nodes.extended; - -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -/** - * The {@code UnsafeCastNode} produces the same value as its input, but with a different type. - */ -public final class UnsafeArrayCastNode extends UnsafeCastNode implements ArrayLengthProvider { - - @Input private ValueNode length; - - public ValueNode length() { - return length; - } - - public UnsafeArrayCastNode(ValueNode object, ValueNode length, Stamp stamp) { - super(object, stamp); - this.length = length; - } - - public UnsafeArrayCastNode(ValueNode object, ValueNode length, Stamp stamp, GuardingNode anchor) { - super(object, stamp, anchor); - this.length = length; - } - - private UnsafeArrayCastNode(ValueNode object, ValueNode length, Stamp stamp, ValueNode anchor) { - this(object, length, stamp, (GuardingNode) anchor); - } - - @Override - public ValueNode canonical(CanonicalizerTool tool) { - if (!(object() instanceof ArrayLengthProvider) || length() != ((ArrayLengthProvider) object()).length()) { - return this; - } - return super.canonical(tool); - } - - @NodeIntrinsic - public static native T unsafeArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp); - - @NodeIntrinsic - public static native T unsafeArrayCast(Object object, int length, @ConstantNodeParameter Stamp stamp, Object anchor); -} diff -r 29de278b7c1b -r 7e7edb86fb43 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Sun Sep 22 02:24:13 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeCastNode.java Mon Sep 23 14:36:00 2013 -0700 @@ -23,25 +23,29 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; /** - * The {@code UnsafeCastNode} produces the same value as its input, but with a different type. + * The {@code UnsafeCastNode} produces the same value as its input, but with a different type. It + * allows unsafe casts "sideways" in the type hierarchy. It does not allow to "drop" type + * information, i.e., an unsafe cast is removed if the input object has a more precise or equal type + * than the type this nodes casts to. */ -public class UnsafeCastNode extends PiNode implements Canonicalizable, LIRLowerable { +public class UnsafeCastNode extends FloatingGuardedNode implements LIRLowerable, GuardingNode, IterableNodeType, Canonicalizable, ValueProxy { + + @Input private ValueNode object; public UnsafeCastNode(ValueNode object, Stamp stamp) { - super(object, stamp); - } - - public UnsafeCastNode(ValueNode object, Stamp stamp, GuardingNode anchor) { - super(object, stamp, anchor); + super(stamp); + this.object = object; } public UnsafeCastNode(ValueNode object, Stamp stamp, ValueNode anchor) { - this(object, stamp, (GuardingNode) anchor); + super(stamp, (GuardingNode) anchor); + this.object = object; } public UnsafeCastNode(ValueNode object, ResolvedJavaType toType, boolean exactType, boolean nonNull) { @@ -49,66 +53,44 @@ } @Override - public boolean inferStamp() { - if (stamp() == StampFactory.forNodeIntrinsic()) { - return false; - } - if (stamp() instanceof ObjectStamp && object().stamp() instanceof ObjectStamp) { - return updateStamp(((ObjectStamp) object().stamp()).castTo((ObjectStamp) stamp())); - } - return false; + public ValueNode getOriginalValue() { + return object; } @Override public ValueNode canonical(CanonicalizerTool tool) { - if (kind() != object().kind()) { + assert kind() == Kind.Object && object.kind() == Kind.Object; + + ObjectStamp my = (ObjectStamp) stamp(); + ObjectStamp other = (ObjectStamp) object.stamp(); + + if (my.type() == null || other.type() == null) { + return this; + } + if (my.isExactType() && !other.isExactType()) { return this; } - - if (stamp() instanceof ObjectStamp && object().stamp() instanceof ObjectStamp) { - ObjectStamp my = (ObjectStamp) stamp(); - ObjectStamp other = (ObjectStamp) object().stamp(); - - if (my.type() == null || other.type() == null) { - return this; - } - if (my.isExactType() && !other.isExactType()) { - return this; - } - if (my.nonNull() && !other.nonNull()) { - return this; - } - if (!my.type().isAssignableFrom(other.type())) { - return this; - } + if (my.nonNull() && !other.nonNull()) { + return this; + } + if (!my.type().isAssignableFrom(other.type())) { + return this; } - return object(); + /* + * The unsafe cast does not add any new type information, so it can be removed. Note that + * this means that the unsafe cast cannot be used to "drop" type information (in which case + * it must not be canonicalized in any case). + */ + return object; } @Override public void generate(LIRGeneratorTool generator) { - if (kind() != object().kind()) { - assert generator.target().arch.getSizeInBytes(kind()) == generator.target().arch.getSizeInBytes(object().kind()) : "unsafe cast cannot be used to change the size of a value"; - AllocatableValue result = generator.newVariable(kind()); - generator.emitMove(result, generator.operand(object())); - generator.setResult(this, result); - } else { - // The LIR only cares about the kind of an operand, not the actual type of an object. So - // we do not have to - // introduce a new operand when the kind is the same. - generator.setResult(this, generator.operand(object())); - } - } - - @NodeIntrinsic - public static native T unsafeCast(Object object, @ConstantNodeParameter Stamp stamp); - - @NodeIntrinsic - public static native T unsafeCast(Object object, @ConstantNodeParameter Stamp stamp, GuardingNode anchor); - - @SuppressWarnings("unused") - @NodeIntrinsic - public static T unsafeCast(Object object, @ConstantNodeParameter Class toType, @ConstantNodeParameter boolean exactType, @ConstantNodeParameter boolean nonNull) { - return toType.cast(object); + assert kind() == Kind.Object && object.kind() == Kind.Object; + /* + * The LIR only cares about the kind of an operand, not the actual type of an object. So we + * do not have to introduce a new operand. + */ + generator.setResult(this, generator.operand(object)); } } diff -r 29de278b7c1b -r 7e7edb86fb43 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Sun Sep 22 02:24:13 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ConditionalEliminationPhase.java Mon Sep 23 14:36:00 2013 -0700 @@ -511,9 +511,9 @@ PiNode piNode; if (isNull) { ConstantNode nullObject = ConstantNode.forObject(null, metaAccessProvider, graph); - piNode = graph.unique(new PiNode(nullObject, StampFactory.forConstant(nullObject.value, metaAccessProvider), replacementAnchor)); + piNode = graph.unique(new PiNode(nullObject, StampFactory.forConstant(nullObject.value, metaAccessProvider), replacementAnchor.asNode())); } else { - piNode = graph.unique(new PiNode(object, StampFactory.declared(type, nonNull), replacementAnchor)); + piNode = graph.unique(new PiNode(object, StampFactory.declared(type, nonNull), replacementAnchor.asNode())); } checkCast.replaceAtUsages(piNode); if (anchor != null) { diff -r 29de278b7c1b -r 7e7edb86fb43 graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java --- a/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Sun Sep 22 02:24:13 2013 +0200 +++ b/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/PointerTest.java Mon Sep 23 14:36:00 2013 -0700 @@ -36,6 +36,7 @@ import com.oracle.graal.replacements.*; import com.oracle.graal.replacements.Snippet.*; import com.oracle.graal.word.*; +import com.oracle.graal.word.nodes.*; /** * Tests for the {@link Pointer} read and write operations. @@ -103,11 +104,13 @@ } private void assertRead(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) { - ReadNode read = (ReadNode) graph.start().next(); + WordCastNode cast = (WordCastNode) graph.start().next(); + + ReadNode read = (ReadNode) cast.next(); Assert.assertEquals(kind.getStackKind(), read.kind()); - UnsafeCastNode cast = (UnsafeCastNode) read.object(); - Assert.assertEquals(graph.getLocal(0), cast.object()); + Assert.assertEquals(cast, read.object()); + Assert.assertEquals(graph.getLocal(0), cast.getInput()); Assert.assertEquals(target.wordKind, cast.kind()); IndexedLocationNode location = (IndexedLocationNode) read.location(); @@ -128,13 +131,15 @@ } private void assertWrite(StructuredGraph graph, Kind kind, boolean indexConvert, LocationIdentity locationIdentity) { - WriteNode write = (WriteNode) graph.start().next(); + WordCastNode cast = (WordCastNode) graph.start().next(); + + WriteNode write = (WriteNode) cast.next(); Assert.assertEquals(graph.getLocal(2), write.value()); Assert.assertEquals(Kind.Void, write.kind()); Assert.assertEquals(FrameState.AFTER_BCI, write.stateAfter().bci); - UnsafeCastNode cast = (UnsafeCastNode) write.object(); - Assert.assertEquals(graph.getLocal(0), cast.object()); + Assert.assertEquals(cast, write.object()); + Assert.assertEquals(graph.getLocal(0), cast.getInput()); Assert.assertEquals(target.wordKind, cast.kind()); IndexedLocationNode location = (IndexedLocationNode) write.location(); diff -r 29de278b7c1b -r 7e7edb86fb43 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java Sun Sep 22 02:24:13 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/BoxingSnippets.java Mon Sep 23 14:36:00 2013 -0700 @@ -79,49 +79,49 @@ @Snippet(inlining = BoxingSnippetInliningPolicy.class) public static Boolean booleanValueOf(boolean value) { valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic()); + return PiNode.piCast(Boolean.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) public static Byte byteValueOf(byte value) { valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic()); + return PiNode.piCast(Byte.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) public static Character charValueOf(char value) { valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Character.valueOf(value), StampFactory.forNodeIntrinsic()); + return PiNode.piCast(Character.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) public static Double doubleValueOf(double value) { valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Double.valueOf(value), StampFactory.forNodeIntrinsic()); + return PiNode.piCast(Double.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) public static Float floatValueOf(float value) { valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Float.valueOf(value), StampFactory.forNodeIntrinsic()); + return PiNode.piCast(Float.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) public static Integer intValueOf(int value) { valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic()); + return PiNode.piCast(Integer.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) public static Long longValueOf(long value) { valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Long.valueOf(value), StampFactory.forNodeIntrinsic()); + return PiNode.piCast(Long.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) public static Short shortValueOf(short value) { valueOfCounter.inc(); - return UnsafeCastNode.unsafeCast(Short.valueOf(value), StampFactory.forNodeIntrinsic()); + return PiNode.piCast(Short.valueOf(value), StampFactory.forNodeIntrinsic()); } @Snippet(inlining = BoxingSnippetInliningPolicy.class) diff -r 29de278b7c1b -r 7e7edb86fb43 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeClassSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeClassSubstitutions.java Sun Sep 22 02:24:13 2013 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeClassSubstitutions.java Mon Sep 23 14:36:00 2013 -0700 @@ -36,8 +36,8 @@ * Substitutions for improving the performance of some critical methods in {@link NodeClass} * methods. These substitutions improve the performance by forcing the relevant methods to be * inlined (intrinsification being a special form of inlining) and removing a checked cast. The - * latter cannot be done directly in Java code as {@link UnsafeCastNode} is not available to the - * project containing {@link NodeClass}. + * latter cannot be done directly in Java code as {@link PiNode} is not available to the project + * containing {@link NodeClass}. */ @ClassSubstitution(NodeClass.class) public class NodeClassSubstitutions { @@ -64,12 +64,12 @@ @MethodSubstitution private static Node getNode(Node node, long offset) { - return UnsafeCastNode.unsafeCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), Node.class, false, false); + return PiNode.piCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), Node.class, false, false); } @MethodSubstitution private static NodeList getNodeList(Node node, long offset) { - return UnsafeCastNode.unsafeCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), NodeList.class, false, false); + return PiNode.piCast(UnsafeLoadNode.load(node, 0, offset, Kind.Object), NodeList.class, false, false); } @MethodSubstitution diff -r 29de278b7c1b -r 7e7edb86fb43 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/TypeCastNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/TypeCastNode.java Sun Sep 22 02:24:13 2013 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/typesystem/TypeCastNode.java Mon Sep 23 14:36:00 2013 -0700 @@ -62,8 +62,8 @@ public void lower(LoweringTool tool) { if (graph().getGuardsStage() == StructuredGraph.GuardsStage.FLOATING_GUARDS) { ValueAnchorNode valueAnchorNode = graph().add(new ValueAnchorNode(null)); - UnsafeCastNode unsafeCast = graph().unique(new UnsafeCastNode(object, this.stamp(), (GuardingNode) valueAnchorNode)); - this.replaceAtUsages(unsafeCast); + PiNode piCast = graph().unique(new PiNode(object, this.stamp(), valueAnchorNode)); + this.replaceAtUsages(piCast); graph().replaceFixedWithFixed(this, valueAnchorNode); } } diff -r 29de278b7c1b -r 7e7edb86fb43 graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/nodes/WordCastNode.java Mon Sep 23 14:36:00 2013 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013, 2013, 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.word.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.word.phases.*; + +/** + * Cast between Word and Object that is introduced by the {@link WordTypeRewriterPhase}. It has an + * impact on the pointer maps for the GC, so it must not be scheduled or optimized away. + */ +public final class WordCastNode extends FixedWithNextNode implements LIRLowerable { + + public static WordCastNode wordToObject(ValueNode input, Kind wordKind) { + assert input.kind() == wordKind; + return new WordCastNode(StampFactory.object(), input); + } + + public static WordCastNode objectToWord(ValueNode input, Kind wordKind) { + assert input.kind() == Kind.Object; + return new WordCastNode(StampFactory.forKind(wordKind), input); + } + + @Input private ValueNode input; + + private WordCastNode(Stamp stamp, ValueNode input) { + super(stamp); + this.input = input; + } + + public ValueNode getInput() { + return input; + } + + @Override + public void generate(LIRGeneratorTool generator) { + assert kind() != input.kind(); + assert generator.target().arch.getSizeInBytes(kind()) == generator.target().arch.getSizeInBytes(input.kind()); + + AllocatableValue result = generator.newVariable(kind()); + generator.emitMove(result, generator.operand(input)); + generator.setResult(this, result); + } +} diff -r 29de278b7c1b -r 7e7edb86fb43 graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Sun Sep 22 02:24:13 2013 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/phases/WordTypeRewriterPhase.java Mon Sep 23 14:36:00 2013 -0700 @@ -39,6 +39,7 @@ import com.oracle.graal.word.*; import com.oracle.graal.word.Word.Opcode; import com.oracle.graal.word.Word.Operation; +import com.oracle.graal.word.nodes.*; /** * Transforms all uses of the {@link Word} class into unsigned operations on {@code int} or @@ -129,8 +130,6 @@ protected void rewriteNode(StructuredGraph graph, Node node) { if (node instanceof CheckCastNode) { rewriteCheckCast(graph, (CheckCastNode) node); - } else if (node instanceof UnsafeCastNode) { - rewriteUnsafeCast(graph, (UnsafeCastNode) node); } else if (node instanceof LoadFieldNode) { rewriteLoadField(graph, (LoadFieldNode) node); } else if (node instanceof AccessIndexedNode) { @@ -151,16 +150,6 @@ } /** - * Remove unnecessary/redundant unsafe casts. - */ - protected void rewriteUnsafeCast(StructuredGraph graph, UnsafeCastNode node) { - if (node.object().stamp() == node.stamp()) { - node.replaceAtUsages(node.object()); - graph.removeFloating(node); - } - } - - /** * Fold constant field reads, e.g. enum constants. */ protected void rewriteLoadField(StructuredGraph graph, LoadFieldNode node) { @@ -295,7 +284,9 @@ case FROM_OBJECT: assert arguments.size() == 1; - replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), StampFactory.forKind(wordKind)))); + WordCastNode objectToWord = graph.add(WordCastNode.objectToWord(arguments.get(0), wordKind)); + graph.addBeforeFixed(invoke.asNode(), objectToWord); + replace(invoke, objectToWord); break; case FROM_ARRAY: @@ -305,7 +296,9 @@ case TO_OBJECT: assert arguments.size() == 1; - replace(invoke, graph.unique(new UnsafeCastNode(arguments.get(0), invoke.asNode().stamp()))); + WordCastNode wordToObject = graph.add(WordCastNode.wordToObject(arguments.get(0), wordKind)); + graph.addBeforeFixed(invoke.asNode(), wordToObject); + replace(invoke, wordToObject); break; default: