# HG changeset patch # User Roland Schatz # Date 1385395822 -3600 # Node ID ae0001b445c0a482c831478c821a8fe587cf9147 # Parent 640516a8ca6b68772c00c0c4cb69ee3fb45ca892 Common base interface for nodes in the memory graph. diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -37,7 +37,7 @@ * is locked (ensuring the GC sees and updates the object) so it must come after any null pointer * check on the object. */ -public final class BeginLockScopeNode extends AbstractStateSplit implements LIRGenLowerable, MonitorEnter, MemoryCheckpoint.Single { +public final class BeginLockScopeNode extends AbstractMemoryCheckpoint implements LIRGenLowerable, MonitorEnter, MemoryCheckpoint.Single { private int lockDepth; diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -95,4 +95,12 @@ */ @NodeIntrinsic public static native Word compareAndSwap(Object object, long offset, Word expectedValue, Word newValue, @ConstantNodeParameter LocationIdentity locationIdentity); + + public MemoryCheckpoint asMemoryCheckpoint() { + return this; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -33,7 +33,7 @@ * Intrinsic for closing a {@linkplain BeginLockScopeNode scope} binding a stack-based lock with an * object. */ -public final class EndLockScopeNode extends AbstractStateSplit implements LIRGenLowerable, MonitorExit, MemoryCheckpoint.Single { +public final class EndLockScopeNode extends AbstractMemoryCheckpoint implements LIRGenLowerable, MonitorExit, MemoryCheckpoint.Single { public EndLockScopeNode() { super(StampFactory.forVoid()); diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -83,4 +83,12 @@ } return super.toString(verbosity); } + + public MemoryCheckpoint asMemoryCheckpoint() { + return this; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractMemoryCheckpoint.java Mon Nov 25 17:10:22 2013 +0100 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 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.nodes; + +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.type.*; + +/** + * Provides an implementation of {@link StateSplit}. + */ +public abstract class AbstractMemoryCheckpoint extends AbstractStateSplit implements MemoryCheckpoint { + + protected AbstractMemoryCheckpoint(Stamp stamp) { + super(stamp); + } + + protected AbstractMemoryCheckpoint(Stamp stamp, FrameState stateAfter) { + super(stamp, stateAfter); + } + + public MemoryCheckpoint asMemoryCheckpoint() { + return this; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } +} diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -35,7 +35,7 @@ * The {@code InvokeNode} represents all kinds of method calls. */ @NodeInfo(nameTemplate = "Invoke#{p#targetMethod/s}") -public final class InvokeNode extends AbstractStateSplit implements Invoke, LIRLowerable, MemoryCheckpoint.Single { +public final class InvokeNode extends AbstractMemoryCheckpoint implements Invoke, LIRLowerable, MemoryCheckpoint.Single { @Input private CallTargetNode callTarget; @Input private FrameState deoptState; diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -253,4 +253,12 @@ return stateAfter(); } } + + public MemoryCheckpoint asMemoryCheckpoint() { + return this; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -46,4 +46,12 @@ public LocationIdentity getLocationIdentity() { return locationIdentity; } + + public MemoryCheckpoint asMemoryCheckpoint() { + return this; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -23,8 +23,8 @@ package com.oracle.graal.nodes; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.type.*; public abstract class MemoryMapNode extends FloatingNode { @@ -33,5 +33,5 @@ super(StampFactory.forVoid()); } - public abstract Node getLastLocationAccess(LocationIdentity locationIdentity); + public abstract MemoryNode getLastLocationAccess(LocationIdentity locationIdentity); } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -23,11 +23,12 @@ package com.oracle.graal.nodes; import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.extended.*; /** * The {@code PhiNode} represents the merging of dataflow in the memory graph. */ -public class MemoryPhiNode extends PhiNode { +public class MemoryPhiNode extends PhiNode implements MemoryNode { private final LocationIdentity identity; @@ -39,4 +40,12 @@ public LocationIdentity getLocationIdentity() { return identity; } + + public MemoryCheckpoint asMemoryCheckpoint() { + return null; + } + + public MemoryPhiNode asMemoryPhi() { + return this; + } } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.PhiNode.PhiType; +import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; public class MemoryProxyNode extends ProxyNode implements MemoryProxy, LIRLowerable { @@ -32,6 +33,7 @@ public MemoryProxyNode(ValueNode value, AbstractBeginNode exit, LocationIdentity identity) { super(value, exit, PhiType.Memory); + assert value instanceof MemoryNode; this.identity = identity; } @@ -43,7 +45,25 @@ public void generate(LIRGeneratorTool generator) { } - public static MemoryProxyNode forMemory(ValueNode value, AbstractBeginNode exit, LocationIdentity location, StructuredGraph graph) { - return graph.unique(new MemoryProxyNode(value, exit, location)); + @Override + public boolean verify() { + assert value() instanceof MemoryNode; + return super.verify(); + } + + public static MemoryProxyNode forMemory(MemoryNode value, AbstractBeginNode exit, LocationIdentity location, StructuredGraph graph) { + return graph.unique(new MemoryProxyNode(ValueNodeUtil.asNode(value), exit, location)); + } + + public MemoryNode getOriginalMemoryNode() { + return (MemoryNode) value(); + } + + public MemoryCheckpoint asMemoryCheckpoint() { + return getOriginalMemoryNode().asMemoryCheckpoint(); + } + + public MemoryPhiNode asMemoryPhi() { + return getOriginalMemoryNode().asMemoryPhi(); } } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -34,4 +34,12 @@ public LocationIdentity getLocationIdentity() { return LocationIdentity.ANY_LOCATION; } + + public MemoryCheckpoint asMemoryCheckpoint() { + return this; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java Mon Nov 25 17:10:22 2013 +0100 @@ -27,6 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.Verbosity; +import com.oracle.graal.nodes.extended.*; public class ValueNodeUtil { @@ -95,4 +96,12 @@ public static String valueString(ValueNode value) { return (value == null) ? "-" : ("" + value.kind().getTypeChar() + value.toString(Verbosity.Id)); } + + public static ValueNode asNode(MemoryNode node) { + if (node == null) { + return null; + } else { + return node.asNode(); + } + } } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -28,7 +28,7 @@ /** * Base class for nodes that modify a range of an array. */ -public abstract class ArrayRangeWriteNode extends AbstractStateSplit { +public abstract class ArrayRangeWriteNode extends AbstractMemoryCheckpoint { protected ArrayRangeWriteNode(Stamp stamp) { super(stamp); diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -43,7 +43,7 @@ super(object, location, stamp, barrierType, compressible); } - public abstract FloatingAccessNode asFloatingNode(ValueNode lastLocationAccess); + public abstract FloatingAccessNode asFloatingNode(MemoryNode lastLocationAccess); /** * AccessNodes can float only if their location identities are not ANY_LOCATION. Furthermore, in diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -26,7 +26,6 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -36,27 +35,27 @@ */ public final class FloatingReadNode extends FloatingAccessNode implements IterableNodeType, LIRLowerable, Canonicalizable { - @Input private Node lastLocationAccess; + @Input private MemoryNode lastLocationAccess; - public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp) { + public FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp) { this(object, location, lastLocationAccess, stamp, null, BarrierType.NONE, false); } - public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp, GuardingNode guard) { + public FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard) { this(object, location, lastLocationAccess, stamp, guard, BarrierType.NONE, false); } - public FloatingReadNode(ValueNode object, LocationNode location, Node lastLocationAccess, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean compressible) { + public FloatingReadNode(ValueNode object, LocationNode location, MemoryNode lastLocationAccess, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean compressible) { super(object, location, stamp, guard, barrierType, compressible); this.lastLocationAccess = lastLocationAccess; } - public Node getLastLocationAccess() { + public MemoryNode getLastLocationAccess() { return lastLocationAccess; } - public void setLastLocationAccess(Node newlla) { - updateUsages(lastLocationAccess, newlla); + public void setLastLocationAccess(MemoryNode newlla) { + updateUsages(ValueNodeUtil.asNode(lastLocationAccess), ValueNodeUtil.asNode(newlla)); lastLocationAccess = newlla; } @@ -76,22 +75,10 @@ return graph().add(new ReadNode(object(), nullCheckLocation(), stamp(), getGuard(), getBarrierType(), isCompressible())); } - private static boolean isMemoryCheckPoint(Node n) { - return n instanceof MemoryCheckpoint.Single || n instanceof MemoryCheckpoint.Multi; - } - - private static boolean isMemoryPhi(Node n) { - return n instanceof PhiNode && ((PhiNode) n).type() == PhiType.Memory; - } - - private static boolean isMemoryProxy(Node n) { - return n instanceof ProxyNode && ((ProxyNode) n).type() == PhiType.Memory; - } - @Override public boolean verify() { - Node lla = getLastLocationAccess(); - assert lla == null || isMemoryCheckPoint(lla) || isMemoryPhi(lla) || isMemoryProxy(lla) : "lastLocationAccess of " + this + " should be a MemoryCheckpoint, but is " + lla; + MemoryNode lla = getLastLocationAccess(); + assert lla == null || lla.asMemoryCheckpoint() != null || lla.asMemoryPhi() != null : "lastLocationAccess of " + this + " should be a MemoryCheckpoint, but is " + lla; return super.verify(); } } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -33,7 +33,7 @@ * Node for a {@linkplain ForeignCallDescriptor foreign} call. */ @NodeInfo(nameTemplate = "ForeignCall#{p#descriptor/s}") -public class ForeignCallNode extends AbstractStateSplit implements LIRLowerable, DeoptimizingNode, MemoryCheckpoint.Multi { +public class ForeignCallNode extends AbstractMemoryCheckpoint implements LIRLowerable, DeoptimizingNode, MemoryCheckpoint.Multi { @Input private final NodeInputList arguments; private final ForeignCallsProvider foreignCalls; diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -60,6 +60,14 @@ generator.emitMembar(barriers); } + public MemoryCheckpoint asMemoryCheckpoint() { + return this; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } + @SuppressWarnings("unused") @NodeIntrinsic public static void memoryBarrier(@ConstantNodeParameter int barriers) { diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAccess.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAccess.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAccess.java Mon Nov 25 17:10:22 2013 +0100 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; /** * This interface marks nodes that access some memory location, and that have an edge to the last @@ -33,7 +32,7 @@ LocationIdentity getLocationIdentity(); - Node getLastLocationAccess(); + MemoryNode getLastLocationAccess(); - void setLastLocationAccess(Node lla); + void setLastLocationAccess(MemoryNode lla); } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java Mon Nov 25 17:10:22 2013 +0100 @@ -31,7 +31,9 @@ * represented by location identities (i.e. change a value at one or more locations that belong to * these location identities). */ -public interface MemoryCheckpoint { +public interface MemoryCheckpoint extends MemoryNode { + + FixedNode asNode(); interface Single extends MemoryCheckpoint { diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 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.nodes.extended; + +import com.oracle.graal.nodes.*; + +/** + * This interface marks nodes that are part of the memory graph. + */ +public interface MemoryNode { + + ValueNode asNode(); + + MemoryCheckpoint asMemoryCheckpoint(); + + MemoryPhiNode asMemoryPhi(); +} diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -64,7 +64,7 @@ } @Override - public FloatingAccessNode asFloatingNode(ValueNode lastLocationAccess) { + public FloatingAccessNode asFloatingNode(MemoryNode lastLocationAccess) { return graph().unique(new FloatingReadNode(object(), location(), lastLocationAccess, stamp(), getGuard(), getBarrierType(), isCompressible())); } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -111,6 +111,14 @@ return stateAfter; } + public MemoryCheckpoint asMemoryCheckpoint() { + return this; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } + // specialized on value type until boxing/unboxing is sorted out in intrinsification @SuppressWarnings("unused") diff -r 640516a8ca6b -r ae0001b445c0 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 Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -102,13 +102,14 @@ return location().getLocationIdentity(); } - public Node getLastLocationAccess() { - return lastLocationAccess; + public MemoryNode getLastLocationAccess() { + return (MemoryNode) lastLocationAccess; } - public void setLastLocationAccess(Node lla) { - updateUsages(lastLocationAccess, lla); - lastLocationAccess = lla; + public void setLastLocationAccess(MemoryNode lla) { + Node newLla = ValueNodeUtil.asNode(lla); + updateUsages(lastLocationAccess, newLla); + lastLocationAccess = newLla; } @Override @@ -126,4 +127,12 @@ } } } + + public MemoryCheckpoint asMemoryCheckpoint() { + return this; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -33,7 +33,7 @@ * The Java bytecode specification allows non-balanced locking. Graal does not handle such cases and * throws a {@link BailoutException} instead during graph building. */ -public abstract class AccessMonitorNode extends AbstractStateSplit implements MemoryCheckpoint { +public abstract class AccessMonitorNode extends AbstractMemoryCheckpoint implements MemoryCheckpoint { @Input private ValueNode object; diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -34,7 +34,7 @@ * Represents an atomic compare-and-swap operation The result is a boolean that contains whether the * value matched the expected value. */ -public class CompareAndSwapNode extends AbstractStateSplit implements Lowerable, MemoryCheckpoint.Single { +public class CompareAndSwapNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { @Input private ValueNode object; @Input private ValueNode offset; diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -101,4 +101,12 @@ assertTrue(stateAfter() != null || stamp() == StampFactory.forVoid(), "an exception handler needs a frame state"); return super.verify(); } + + public MemoryCheckpoint asMemoryCheckpoint() { + return this; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -75,4 +75,12 @@ public void generate(LIRGeneratorTool gen) { gen.visitCompareAndSwap(this, location().generateAddress(gen, gen.operand(object()))); } + + public MemoryCheckpoint asMemoryCheckpoint() { + return this; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MemoryProxy.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MemoryProxy.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MemoryProxy.java Mon Nov 25 17:10:22 2013 +0100 @@ -23,8 +23,11 @@ package com.oracle.graal.nodes.spi; import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.extended.*; -public interface MemoryProxy extends ValueProxy { +public interface MemoryProxy extends ValueProxy, MemoryNode { LocationIdentity getLocationIdentity(); + + MemoryNode getOriginalMemoryNode(); } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Mon Nov 25 17:10:22 2013 +0100 @@ -42,7 +42,7 @@ public static class MemoryMapImpl extends MemoryMapNode { - private IdentityHashMap lastMemorySnapshot; + private IdentityHashMap lastMemorySnapshot; public MemoryMapImpl(MemoryMapImpl memoryMap) { lastMemorySnapshot = new IdentityHashMap<>(memoryMap.lastMemorySnapshot); @@ -58,8 +58,8 @@ } @Override - public ValueNode getLastLocationAccess(LocationIdentity locationIdentity) { - ValueNode lastLocationAccess; + public MemoryNode getLastLocationAccess(LocationIdentity locationIdentity) { + MemoryNode lastLocationAccess; if (locationIdentity == FINAL_LOCATION) { return null; } else { @@ -197,7 +197,7 @@ private static void processAccess(MemoryAccess access, MemoryMapImpl state) { LocationIdentity locationIdentity = access.getLocationIdentity(); if (locationIdentity != LocationIdentity.ANY_LOCATION) { - ValueNode lastLocationAccess = state.getLastLocationAccess(locationIdentity); + MemoryNode lastLocationAccess = state.getLastLocationAccess(locationIdentity); access.setLastLocationAccess(lastLocationAccess); } } @@ -216,7 +216,7 @@ if (identity == ANY_LOCATION) { state.lastMemorySnapshot.clear(); } - state.lastMemorySnapshot.put(identity, (ValueNode) checkpoint); + state.lastMemorySnapshot.put(identity, checkpoint); } private static void processFloatable(FloatableAccessNode accessNode, MemoryMapImpl state) { @@ -224,7 +224,7 @@ assert accessNode.getNullCheck() == false; LocationIdentity locationIdentity = accessNode.location().getLocationIdentity(); if (accessNode.canFloat()) { - ValueNode lastLocationAccess = state.getLastLocationAccess(locationIdentity); + MemoryNode lastLocationAccess = state.getLastLocationAccess(locationIdentity); FloatingAccessNode floatingNode = accessNode.asFloatingNode(lastLocationAccess); floatingNode.setNullCheck(accessNode.getNullCheck()); ValueAnchorNode anchor = null; @@ -250,11 +250,11 @@ for (LocationIdentity key : keys) { int mergedStatesCount = 0; boolean isPhi = false; - ValueNode merged = null; + MemoryNode merged = null; for (MemoryMapImpl state : states) { - ValueNode last = state.getLastLocationAccess(key); + MemoryNode last = state.getLastLocationAccess(key); if (isPhi) { - ((PhiNode) merged).addInput(last); + merged.asMemoryPhi().addInput(ValueNodeUtil.asNode(last)); } else { if (merged == last) { // nothing to do @@ -263,9 +263,9 @@ } else { MemoryPhiNode phi = merge.graph().addWithoutUnique(new MemoryPhiNode(merge, key)); for (int j = 0; j < mergedStatesCount; j++) { - phi.addInput(merged); + phi.addInput(ValueNodeUtil.asNode(merged)); } - phi.addInput(last); + phi.addInput(ValueNodeUtil.asNode(last)); merged = phi; isPhi = true; } @@ -289,7 +289,7 @@ * side it needs to choose by putting in the location identity on both successors. */ InvokeWithExceptionNode invoke = (InvokeWithExceptionNode) node.predecessor(); - result.lastMemorySnapshot.put(invoke.getLocationIdentity(), node); + result.lastMemorySnapshot.put(invoke.getLocationIdentity(), (MemoryCheckpoint) node); } return result; } @@ -306,7 +306,7 @@ Map phis = new HashMap<>(); for (LocationIdentity location : modifiedLocations) { MemoryPhiNode phi = loop.graph().addWithoutUnique(new MemoryPhiNode(loop, location)); - phi.addInput(initialState.getLastLocationAccess(location)); + phi.addInput(ValueNodeUtil.asNode(initialState.getLastLocationAccess(location))); phis.put(location, phi); initialState.lastMemorySnapshot.put(location, phi); } @@ -318,14 +318,14 @@ for (Map.Entry phiEntry : phis.entrySet()) { LocationIdentity key = phiEntry.getKey(); PhiNode phi = phiEntry.getValue(); - phi.initializeValueAt(endIndex, entry.getValue().getLastLocationAccess(key)); + phi.initializeValueAt(endIndex, ValueNodeUtil.asNode(entry.getValue().getLastLocationAccess(key))); } } for (Map.Entry entry : loopInfo.exitStates.entrySet()) { LoopExitNode exit = entry.getKey(); MemoryMapImpl state = entry.getValue(); for (LocationIdentity location : modifiedLocations) { - ValueNode lastAccessAtExit = state.lastMemorySnapshot.get(location); + MemoryNode lastAccessAtExit = state.lastMemorySnapshot.get(location); if (lastAccessAtExit != null) { state.lastMemorySnapshot.put(location, MemoryProxyNode.forMemory(lastAccessAtExit, exit, location, loop.graph())); } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java Mon Nov 25 17:10:22 2013 +0100 @@ -46,24 +46,24 @@ return isWrites(n, n.getLastLocationAccess(), n.graph().createNodeBitMap()); } - private static boolean isWrites(FloatingReadNode n, Node lastLocationAccess, NodeBitMap visited) { + private static boolean isWrites(FloatingReadNode n, MemoryNode lastLocationAccess, NodeBitMap visited) { if (lastLocationAccess == null) { return false; } - if (visited.isMarked(lastLocationAccess)) { + if (visited.isMarked(ValueNodeUtil.asNode(lastLocationAccess))) { return true; // dataflow loops must come from Phis assume them ok until proven wrong } if (lastLocationAccess instanceof ProxyNode) { - return isWrites(n, ((ProxyNode) lastLocationAccess).value(), visited); + return isWrites(n, (MemoryNode) ((ProxyNode) lastLocationAccess).value(), visited); } if (lastLocationAccess instanceof WriteNode) { WriteNode other = (WriteNode) lastLocationAccess; return other.object() == n.object() && other.location() == n.location(); } if (lastLocationAccess instanceof PhiNode) { - visited.mark(lastLocationAccess); + visited.mark(ValueNodeUtil.asNode(lastLocationAccess)); for (ValueNode value : ((PhiNode) lastLocationAccess).values()) { - if (!isWrites(n, value, visited)) { + if (!isWrites(n, (MemoryNode) value, visited)) { return false; } } @@ -72,15 +72,15 @@ return false; } - private static ValueNode getValue(FloatingReadNode n, Node lastLocationAccess, NodeMap nodeMap) { - ValueNode exisiting = nodeMap.get(lastLocationAccess); + private static ValueNode getValue(FloatingReadNode n, MemoryNode lastLocationAccess, NodeMap nodeMap) { + ValueNode exisiting = nodeMap.get(ValueNodeUtil.asNode(lastLocationAccess)); if (exisiting != null) { return exisiting; } - if (lastLocationAccess instanceof ProxyNode) { - ProxyNode proxy = (ProxyNode) lastLocationAccess; - ValueNode value = getValue(n, proxy.value(), nodeMap); - return ProxyNode.forValue(value, proxy.proxyPoint(), (StructuredGraph) lastLocationAccess.graph()); + if (lastLocationAccess instanceof MemoryProxyNode) { + MemoryProxyNode proxy = (MemoryProxyNode) lastLocationAccess; + ValueNode value = getValue(n, proxy.getOriginalMemoryNode(), nodeMap); + return ProxyNode.forValue(value, proxy.proxyPoint(), proxy.graph()); } if (lastLocationAccess instanceof WriteNode) { return ((WriteNode) lastLocationAccess).value(); @@ -88,9 +88,9 @@ if (lastLocationAccess instanceof PhiNode) { PhiNode phi = (PhiNode) lastLocationAccess; PhiNode newPhi = phi.graph().addWithoutUnique(new PhiNode(n.kind(), phi.merge())); - nodeMap.set(lastLocationAccess, newPhi); + nodeMap.set(phi, newPhi); for (ValueNode value : phi.values()) { - newPhi.addInput(getValue(n, value, nodeMap)); + newPhi.addInput(getValue(n, (MemoryNode) value, nodeMap)); } return newPhi; } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Mon Nov 25 17:10:22 2013 +0100 @@ -400,8 +400,12 @@ } } - private Block blockForFixedNode(Node n) { - Block b = cfg.getNodeToBlock().get(n); + private Block blockForMemoryNode(MemoryNode memory) { + MemoryNode current = memory; + while (current instanceof MemoryProxy) { + current = ((MemoryProxy) current).getOriginalMemoryNode(); + } + Block b = cfg.getNodeToBlock().get(current.asNode()); assert b != null : "all lastAccess locations should have a block assignment from CFG"; return b; } @@ -543,13 +547,11 @@ if (assertionEnabled()) { if (scheduleRead) { FloatingReadNode read = (FloatingReadNode) node; - Node lastLocationAccess = read.getLastLocationAccess(); - Block upperBound = blockForFixedNode(lastLocationAccess); - if (!blockForFixedNode(lastLocationAccess).dominates(block)) { - assert false : String.format("out of loop movement voilated memory semantics for %s (location %s). moved to %s but upper bound is %s (earliest: %s, latest: %s)", read, - read.getLocationIdentity(), block, upperBound, earliestBlock, latest); - } - + MemoryNode lastLocationAccess = read.getLastLocationAccess(); + Block upperBound = blockForMemoryNode(lastLocationAccess); + assert upperBound.dominates(block) : String.format( + "out of loop movement voilated memory semantics for %s (location %s). moved to %s but upper bound is %s (earliest: %s, latest: %s)", read, + read.getLocationIdentity(), block, upperBound, earliestBlock, latest); } } break; @@ -596,7 +598,7 @@ LocationIdentity locid = n.location().getLocationIdentity(); assert locid != FINAL_LOCATION; - Block upperBoundBlock = blockForFixedNode(n.getLastLocationAccess()); + Block upperBoundBlock = blockForMemoryNode(n.getLastLocationAccess()); Block earliestBlock = earliestBlock(n); assert upperBoundBlock.dominates(earliestBlock) : "upper bound (" + upperBoundBlock + ") should dominate earliest (" + earliestBlock + ")"; @@ -627,7 +629,7 @@ if (currentBlock == upperBoundBlock) { assert earliestBlock == upperBoundBlock; // don't treat lastLocationAccess node as a kill for this read. - closure = new NewMemoryScheduleClosure(n.getLastLocationAccess(), upperBoundBlock); + closure = new NewMemoryScheduleClosure(ValueNodeUtil.asNode(n.getLastLocationAccess()), upperBoundBlock); } else { closure = new NewMemoryScheduleClosure(); } @@ -643,7 +645,7 @@ } else { if (currentBlock == upperBoundBlock) { assert earliestBlock == upperBoundBlock; - KillSet ks = computeKillSet(upperBoundBlock, n.getLastLocationAccess()); + KillSet ks = computeKillSet(upperBoundBlock, ValueNodeUtil.asNode(n.getLastLocationAccess())); if (ks.isKilled(locid)) { return upperBoundBlock; } diff -r 640516a8ca6b -r ae0001b445c0 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 Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Mon Nov 25 17:10:22 2013 +0100 @@ -854,25 +854,43 @@ */ public static final UsageReplacer DEFAULT_REPLACER = new UsageReplacer() { + private LocationIdentity getLocationIdentity(Node node) { + if (node instanceof MemoryAccess) { + return ((MemoryAccess) node).getLocationIdentity(); + } else if (node instanceof MemoryProxy) { + return ((MemoryProxy) node).getLocationIdentity(); + } else if (node instanceof MemoryPhiNode) { + return ((MemoryPhiNode) node).getLocationIdentity(); + } else { + return null; + } + } + @Override public void replace(ValueNode oldNode, ValueNode newNode, MemoryMapNode mmap) { - oldNode.replaceAtUsages(newNode); - if (mmap == null || newNode == null) { - return; - } - for (Node usage : newNode.usages().snapshot()) { - if (usage instanceof FloatingReadNode && ((FloatingReadNode) usage).getLastLocationAccess() == newNode) { - assert newNode.graph().isAfterFloatingReadPhase(); + if (mmap != null && newNode != null) { + for (Node usage : oldNode.usages().snapshot()) { + LocationIdentity identity = getLocationIdentity(usage); + if (identity != null && identity != LocationIdentity.FINAL_LOCATION) { + // lastLocationAccess points into the snippet graph. find a proper + // MemoryCheckPoint inside the snippet graph + MemoryNode lastAccess = mmap.getLastLocationAccess(identity); - // lastLocationAccess points into the snippet graph. find a proper - // MemoryCheckPoint inside the snippet graph - FloatingReadNode read = (FloatingReadNode) usage; - Node lastAccess = mmap.getLastLocationAccess(read.location().getLocationIdentity()); - - assert lastAccess != null : "no mapping found for lowerable node " + oldNode + ". (No node in the snippet kill the same location as the lowerable node?)"; - read.setLastLocationAccess(lastAccess); + assert lastAccess != null : "no mapping found for lowerable node " + oldNode + ". (No node in the snippet kill the same location as the lowerable node?)"; + if (usage instanceof MemoryAccess) { + MemoryAccess access = (MemoryAccess) usage; + if (access.getLastLocationAccess() == oldNode) { + assert newNode.graph().isAfterFloatingReadPhase(); + access.setLastLocationAccess(lastAccess); + } + } else { + assert usage instanceof MemoryProxy || usage instanceof MemoryPhiNode; + usage.replaceFirstInput(oldNode, lastAccess.asNode()); + } + } } } + oldNode.replaceAtUsages(newNode); } }; @@ -933,14 +951,14 @@ } @Override - public Node getLastLocationAccess(LocationIdentity locationIdentity) { + public MemoryNode getLastLocationAccess(LocationIdentity locationIdentity) { assert memoryMap != null : "no memory map stored for this snippet graph (snippet doesn't have a ReturnNode?)"; - Node lastLocationAccess = memoryMap.getLastLocationAccess(locationIdentity); + MemoryNode lastLocationAccess = memoryMap.getLastLocationAccess(locationIdentity); assert lastLocationAccess != null; if (lastLocationAccess instanceof StartNode) { return replaceeStart; } else { - return duplicates.get(lastLocationAccess); + return (MemoryNode) duplicates.get(ValueNodeUtil.asNode(lastLocationAccess)); } } } diff -r 640516a8ca6b -r ae0001b445c0 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Mon Nov 25 17:06:00 2013 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Mon Nov 25 17:10:22 2013 +0100 @@ -37,7 +37,7 @@ import com.oracle.graal.phases.common.*; import com.oracle.graal.phases.tiers.*; -public class MacroNode extends AbstractStateSplit implements Lowerable, MemoryCheckpoint.Single { +public class MacroNode extends AbstractMemoryCheckpoint implements Lowerable, MemoryCheckpoint.Single { @Input protected final NodeInputList arguments;