# HG changeset patch # User Doug Simon # Date 1385420999 -3600 # Node ID 787357a6de3e7e5fe06de04d3d3acc83bf90d11b # Parent 107fee7fa3bbbca60d9fca54d65c7a50dae07eb6# Parent 1dd9aa5a9ee52b1ce36aa190cde96725f14806f9 Merge. diff -r 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java Tue Nov 26 00:09:59 2013 +0100 @@ -40,4 +40,5 @@ ArithmeticException, RuntimeConstraint, LoopLimitCheck, + Aliasing, } diff -r 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java Tue Nov 26 00:09:59 2013 +0100 @@ -938,6 +938,8 @@ Node newInput = duplicationReplacement.replacement(input, true); node.updateUsages(null, newInput); assert Node.verifyUniqueIfExternal(newInput, node.graph()); + assert newInput == null || fieldTypes.get(inputOffsets[index]).isAssignableFrom(newInput.getClass()) : "Can not assign " + newInput.getClass() + " to " + + fieldTypes.get(inputOffsets[index]) + " in " + node; putNode(node, inputOffsets[index], newInput); } index++; @@ -953,6 +955,8 @@ if (successor != null) { Node newSucc = duplicationReplacement.replacement(successor, false); node.updatePredecessor(null, newSucc); + assert newSucc == null || fieldTypes.get(successorOffsets[index]).isAssignableFrom(newSucc.getClass()) : fieldTypes.get(successorOffsets[index]) + " is not compatible with " + + newSucc.getClass(); putNode(node, successorOffsets[index], newSucc); } index++; diff -r 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Nov 26 00:09:59 2013 +0100 @@ -1129,6 +1129,7 @@ @HotSpotVMConstant(name = "Deoptimization::Reason_div0_check") @Stable public int deoptReasonDiv0Check; @HotSpotVMConstant(name = "Deoptimization::Reason_constraint") @Stable public int deoptReasonConstraint; @HotSpotVMConstant(name = "Deoptimization::Reason_loop_limit_check") @Stable public int deoptReasonLoopLimitCheck; + @HotSpotVMConstant(name = "Deoptimization::Reason_aliasing") @Stable public int deoptReasonAliasing; @HotSpotVMConstant(name = "Deoptimization::Action_none") @Stable public int deoptActionNone; @HotSpotVMConstant(name = "Deoptimization::Action_maybe_recompile") @Stable public int deoptActionMaybeRecompile; diff -r 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMetaAccessProvider.java Tue Nov 26 00:09:59 2013 +0100 @@ -187,6 +187,8 @@ return runtime.getConfig().deoptReasonConstraint; case LoopLimitCheck: return runtime.getConfig().deoptReasonLoopLimitCheck; + case Aliasing: + return runtime.getConfig().deoptReasonAliasing; default: throw GraalInternalError.shouldNotReachHere(); } @@ -221,6 +223,8 @@ return DeoptimizationReason.RuntimeConstraint; } else if (reason == runtime.getConfig().deoptReasonLoopLimitCheck) { return DeoptimizationReason.LoopLimitCheck; + } else if (reason == runtime.getConfig().deoptReasonAliasing) { + return DeoptimizationReason.Aliasing; } else { throw GraalInternalError.shouldNotReachHere(Integer.toHexString(reason)); } diff -r 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/BeginLockScopeNode.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DirectCompareAndSwapNode.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/EndLockScopeNode.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/StubForeignCallNode.java Tue Nov 26 00:09:59 2013 +0100 @@ -83,4 +83,12 @@ } return super.toString(verbosity); } + + public MemoryCheckpoint asMemoryCheckpoint() { + return this; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } } diff -r 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/NewObjectSnippets.java Tue Nov 26 00:09:59 2013 +0100 @@ -246,12 +246,12 @@ new_seqInit.inc(); explodeLoop(); for (int offset = instanceHeaderSize(); offset < size; offset += wordSize()) { - memory.writeWord(offset, Word.zero(), INIT_LOCATION); + memory.initializeWord(offset, Word.zero(), INIT_LOCATION); } } else { new_loopInit.inc(); for (int offset = instanceHeaderSize(); offset < size; offset += wordSize()) { - memory.writeWord(offset, Word.zero(), INIT_LOCATION); + memory.initializeWord(offset, Word.zero(), INIT_LOCATION); } } } @@ -270,7 +270,7 @@ initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { for (int offset = headerSize; offset < allocationSize; offset += wordSize()) { - memory.writeWord(offset, Word.zero(), INIT_LOCATION); + memory.initializeWord(offset, Word.zero(), INIT_LOCATION); } } return memory.toObject(); diff -r 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragment.java Tue Nov 26 00:09:59 2013 +0100 @@ -28,7 +28,6 @@ import com.oracle.graal.graph.Graph.DuplicationReplacement; import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.VirtualState.NodeClosure; import com.oracle.graal.nodes.VirtualState.VirtualClosure; import com.oracle.graal.nodes.cfg.*; @@ -313,7 +312,20 @@ final ValueNode replaceWith; ProxyNode newVpn = getDuplicatedNode(vpn); if (newVpn != null) { - PhiNode phi = graph.addWithoutUnique(vpn.type() == PhiType.Value ? new PhiNode(vpn.kind(), merge) : new PhiNode(vpn.type(), merge, vpn.getIdentity())); + PhiNode phi; + switch (vpn.type()) { + case Value: + phi = graph.addWithoutUnique(new PhiNode(vpn.kind(), merge)); + break; + case Guard: + phi = graph.addWithoutUnique(new PhiNode(vpn.type(), merge)); + break; + case Memory: + phi = graph.addWithoutUnique(new MemoryPhiNode(merge, ((MemoryProxyNode) vpn).getLocationIdentity())); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } phi.addInput(vpn); phi.addInput(newVpn); replaceWith = phi; diff -r 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopFragmentInside.java Tue Nov 26 00:09:59 2013 +0100 @@ -166,6 +166,24 @@ // TODO (gd) ? } + private static PhiNode patchPhi(StructuredGraph graph, PhiNode phi, MergeNode merge) { + PhiNode ret; + switch (phi.type()) { + case Value: + ret = new PhiNode(phi.kind(), merge); + break; + case Guard: + ret = new PhiNode(PhiType.Guard, merge); + break; + case Memory: + ret = new MemoryPhiNode(merge, ((MemoryPhiNode) phi).getLocationIdentity()); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + return graph.addWithoutUnique(ret); + } + private void patchPeeling(LoopFragmentInside peel) { LoopBeginNode loopBegin = loop().loopBegin(); StructuredGraph graph = loopBegin.graph(); @@ -180,7 +198,7 @@ } // create a new phi (we don't patch the old one since some usages of the old one may // still be valid) - PhiNode newPhi = graph.addWithoutUnique(phi.type() == PhiType.Value ? new PhiNode(phi.kind(), loopBegin) : new PhiNode(phi.type(), loopBegin, phi.getIdentity())); + PhiNode newPhi = patchPhi(graph, phi, loopBegin); newPhi.addInput(first); for (LoopEndNode end : loopBegin.orderedLoopEnds()) { newPhi.addInput(phi.valueAt(end)); @@ -270,7 +288,7 @@ } for (final PhiNode phi : loopBegin.phis().snapshot()) { - final PhiNode firstPhi = graph.addWithoutUnique(phi.type() == PhiType.Value ? new PhiNode(phi.kind(), newExitMerge) : new PhiNode(phi.type(), newExitMerge, phi.getIdentity())); + final PhiNode firstPhi = patchPhi(graph, phi, newExitMerge); for (AbstractEndNode end : newExitMerge.forwardEnds()) { LoopEndNode loopEnd = reverseEnds.get(end); ValueNode prim = prim(phi.valueAt(loopEnd)); diff -r 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/AbstractFixedGuardNode.java Tue Nov 26 00:09:59 2013 +0100 @@ -0,0 +1,108 @@ +/* + * 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.api.meta.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; + +public abstract class AbstractFixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, GuardingNode { + + @Input private LogicNode condition; + private final DeoptimizationReason reason; + private final DeoptimizationAction action; + private boolean negated; + + public LogicNode condition() { + return condition; + } + + public void setCondition(LogicNode x) { + updateUsages(condition, x); + condition = x; + } + + protected AbstractFixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) { + super(StampFactory.dependency()); + this.action = action; + this.negated = negated; + this.condition = condition; + this.reason = deoptReason; + } + + public DeoptimizationReason getReason() { + return reason; + } + + public DeoptimizationAction getAction() { + return action; + } + + public boolean isNegated() { + return negated; + } + + @Override + public String toString(Verbosity verbosity) { + if (verbosity == Verbosity.Name && negated) { + return "!" + super.toString(verbosity); + } else { + return super.toString(verbosity); + } + } + + @Override + public void simplify(SimplifierTool tool) { + while (condition instanceof LogicNegationNode) { + LogicNegationNode negation = (LogicNegationNode) condition; + setCondition(negation.getInput()); + negated = !negated; + } + } + + public void lowerToIf() { + FixedNode next = next(); + setNext(null); + DeoptimizeNode deopt = graph().add(new DeoptimizeNode(action, reason)); + deopt.setDeoptimizationState(getDeoptimizationState()); + IfNode ifNode; + AbstractBeginNode noDeoptSuccessor; + if (negated) { + ifNode = graph().add(new IfNode(condition, deopt, next, 0)); + noDeoptSuccessor = ifNode.falseSuccessor(); + } else { + ifNode = graph().add(new IfNode(condition, next, deopt, 1)); + noDeoptSuccessor = ifNode.trueSuccessor(); + } + ((FixedWithNextNode) predecessor()).setNext(ifNode); + this.replaceAtUsages(noDeoptSuccessor); + GraphUtil.killWithUnusedFloatingInputs(this); + } + + @Override + public boolean canDeoptimize() { + return true; + } +} diff -r 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Tue Nov 26 00:09:59 2013 +0100 @@ -27,78 +27,31 @@ import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.util.*; @NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}") -public final class FixedGuardNode extends DeoptimizingFixedWithNextNode implements Simplifiable, Lowerable, IterableNodeType, GuardingNode { - - @Input private LogicNode condition; - private final DeoptimizationReason reason; - private final DeoptimizationAction action; - private boolean negated; - - public LogicNode condition() { - return condition; - } - - public void setCondition(LogicNode x) { - updateUsages(condition, x); - condition = x; - } +public final class FixedGuardNode extends AbstractFixedGuardNode implements Lowerable, IterableNodeType { public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) { this(condition, deoptReason, action, false); } public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action, boolean negated) { - super(StampFactory.dependency()); - this.action = action; - this.negated = negated; - this.condition = condition; - this.reason = deoptReason; - - assert action != null && reason != null; - } - - public DeoptimizationReason getReason() { - return reason; - } - - public DeoptimizationAction getAction() { - return action; - } - - public boolean isNegated() { - return negated; - } - - @Override - public String toString(Verbosity verbosity) { - if (verbosity == Verbosity.Name && negated) { - return "!" + super.toString(verbosity); - } else { - return super.toString(verbosity); - } + super(condition, deoptReason, action, negated); } @Override public void simplify(SimplifierTool tool) { - while (condition instanceof LogicNegationNode) { - LogicNegationNode negation = (LogicNegationNode) condition; - setCondition(negation.getInput()); - negated = !negated; - } + super.simplify(tool); - if (condition instanceof LogicConstantNode) { - LogicConstantNode c = (LogicConstantNode) condition; - if (c.getValue() == negated) { + if (condition() instanceof LogicConstantNode) { + LogicConstantNode c = (LogicConstantNode) condition(); + if (c.getValue() == isNegated()) { FixedNode next = this.next(); if (next != null) { tool.deleteBranch(next); } - DeoptimizeNode deopt = graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, reason)); + DeoptimizeNode deopt = graph().add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, getReason())); deopt.setDeoptimizationState(getDeoptimizationState()); setNext(deopt); } @@ -115,22 +68,7 @@ ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(guard.asNode())); graph().replaceFixedWithFixed(this, newAnchor); } else { - FixedNode next = next(); - setNext(null); - DeoptimizeNode deopt = graph().add(new DeoptimizeNode(action, reason)); - deopt.setDeoptimizationState(getDeoptimizationState()); - IfNode ifNode; - AbstractBeginNode noDeoptSuccessor; - if (negated) { - ifNode = graph().add(new IfNode(condition, deopt, next, 0)); - noDeoptSuccessor = ifNode.falseSuccessor(); - } else { - ifNode = graph().add(new IfNode(condition, next, deopt, 1)); - noDeoptSuccessor = ifNode.trueSuccessor(); - } - ((FixedWithNextNode) predecessor()).setNext(ifNode); - this.replaceAtUsages(noDeoptSuccessor); - GraphUtil.killWithUnusedFloatingInputs(this); + lowerToIf(); } } diff -r 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GuardNode.java Tue Nov 26 00:09:59 2013 +0100 @@ -25,6 +25,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.type.*; @@ -41,7 +42,7 @@ * control flow would have reached the guarded node (without taking exceptions into account). */ @NodeInfo(nameTemplate = "Guard(!={p#negated}) {p#reason/s}") -public final class GuardNode extends FloatingGuardedNode implements Canonicalizable, IterableNodeType, GuardingNode, GuardedNode { +public class GuardNode extends FloatingGuardedNode implements Canonicalizable, IterableNodeType, GuardingNode, GuardedNode { @Input private LogicNode condition; private final DeoptimizationReason reason; @@ -104,6 +105,20 @@ return this; } + public FixedWithNextNode lowerGuard() { + if (negated() && condition() instanceof IsNullNode) { + IsNullNode isNull = (IsNullNode) condition(); + NullCheckNode nullCheck = graph().add(new NullCheckNode(isNull.object())); + setCondition(null); + if (isNull.usages().isEmpty()) { + isNull.safeDelete(); + } + return nullCheck; + } + + return null; + } + public void negate() { negated = !negated; } diff -r 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeNode.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/InvokeWithExceptionNode.java Tue Nov 26 00:09:59 2013 +0100 @@ -253,4 +253,12 @@ return stateAfter(); } } + + public MemoryCheckpoint asMemoryCheckpoint() { + return this; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } } diff -r 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/KillingBeginNode.java Tue Nov 26 00:09:59 2013 +0100 @@ -46,4 +46,12 @@ public LocationIdentity getLocationIdentity() { return locationIdentity; } + + public MemoryCheckpoint asMemoryCheckpoint() { + return this; + } + + public MemoryPhiNode asMemoryPhi() { + return null; + } } diff -r 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryMapNode.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryPhiNode.java Tue Nov 26 00:09:59 2013 +0100 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2009, 2011, 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.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 implements MemoryNode { + + private final LocationIdentity identity; + + public MemoryPhiNode(MergeNode merge, LocationIdentity identity) { + super(PhiType.Memory, merge); + this.identity = identity; + } + + public LocationIdentity getLocationIdentity() { + return identity; + } + + public MemoryCheckpoint asMemoryCheckpoint() { + return null; + } + + public MemoryPhiNode asMemoryPhi() { + return this; + } +} diff -r 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/MemoryProxyNode.java Tue Nov 26 00:09:59 2013 +0100 @@ -0,0 +1,69 @@ +/* + * 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.nodes; + +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 { + + private final LocationIdentity identity; + + public MemoryProxyNode(ValueNode value, AbstractBeginNode exit, LocationIdentity identity) { + super(value, exit, PhiType.Memory); + assert value instanceof MemoryNode; + this.identity = identity; + } + + public LocationIdentity getLocationIdentity() { + return identity; + } + + @Override + public void generate(LIRGeneratorTool generator) { + } + + @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 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Tue Nov 26 00:09:59 2013 +0100 @@ -51,7 +51,6 @@ @Input(notDataflow = true) private MergeNode merge; @Input private final NodeInputList values = new NodeInputList<>(this); private final PhiType type; - private final LocationIdentity identity; /** * Create a value phi ({@link PhiType#Value}) with the specified kind. @@ -68,7 +67,6 @@ assert stamp != StampFactory.forVoid(); this.type = PhiType.Value; this.merge = merge; - this.identity = null; } /** @@ -77,12 +75,11 @@ * @param type the type of the new phi * @param merge the merge that the new phi belongs to */ - public PhiNode(PhiType type, MergeNode merge, LocationIdentity identity) { + public PhiNode(PhiType type, MergeNode merge) { super(type.stamp); assert type.stamp != null : merge + " " + type; this.type = type; this.merge = merge; - this.identity = identity; } public PhiType type() { @@ -93,11 +90,6 @@ return merge; } - public LocationIdentity getIdentity() { - assert type != PhiType.Value; - return identity; - } - public void setMerge(MergeNode x) { updateUsages(merge, x); merge = x; diff -r 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ProxyNode.java Tue Nov 26 00:09:59 2013 +0100 @@ -22,7 +22,6 @@ */ package com.oracle.graal.nodes; -import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.ValueNumberable; import com.oracle.graal.graph.spi.*; @@ -37,17 +36,15 @@ * loop. */ @NodeInfo(nameTemplate = "{p#type/s}Proxy") -public class ProxyNode extends FloatingNode implements IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable, LIRLowerable, ValueProxy, GuardingNode { +public class ProxyNode extends FloatingNode implements IterableNodeType, ValueNumberable, Canonicalizable, Virtualizable, ValueProxy, GuardingNode { @Input(notDataflow = true) private AbstractBeginNode proxyPoint; @Input private ValueNode value; private final PhiType type; - private final LocationIdentity identity; - public ProxyNode(ValueNode value, AbstractBeginNode exit, PhiType type, LocationIdentity identity) { + public ProxyNode(ValueNode value, AbstractBeginNode exit, PhiType type) { super(type == PhiType.Value ? value.stamp() : type.stamp); this.type = type; - this.identity = identity; assert exit != null; this.proxyPoint = exit; this.value = value; @@ -70,11 +67,6 @@ return type; } - public LocationIdentity getIdentity() { - assert type != PhiType.Value; - return identity; - } - @Override public boolean verify() { assert value != null; @@ -84,11 +76,6 @@ } @Override - public void generate(LIRGeneratorTool generator) { - assert type == PhiType.Memory; - } - - @Override public Node canonical(CanonicalizerTool tool) { if (type == PhiType.Value && value.isConstant()) { return value; @@ -107,15 +94,11 @@ } public static ProxyNode forGuard(ValueNode value, AbstractBeginNode exit, StructuredGraph graph) { - return graph.unique(new ProxyNode(value, exit, PhiType.Guard, null)); + return graph.unique(new ProxyNode(value, exit, PhiType.Guard)); } public static ProxyNode forValue(ValueNode value, AbstractBeginNode exit, StructuredGraph graph) { - return graph.unique(new ProxyNode(value, exit, PhiType.Value, null)); - } - - public static ProxyNode forMemory(ValueNode value, AbstractBeginNode exit, LocationIdentity location, StructuredGraph graph) { - return graph.unique(new ProxyNode(value, exit, PhiType.Memory, location)); + return graph.unique(new ProxyNode(value, exit, PhiType.Value)); } @Override diff -r 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StartNode.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNodeUtil.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ArrayRangeWriteNode.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatableAccessNode.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ForeignCallNode.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MembarNode.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryAccess.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/MemoryCheckpoint.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeStoreNode.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/AccessMonitorNode.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/CompareAndSwapNode.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/ExceptionObjectNode.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/LoweredCompareAndSwapNode.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MemoryProxy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MemoryProxy.java Tue Nov 26 00:09:59 2013 +0100 @@ -0,0 +1,33 @@ +/* + * 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.spi; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.nodes.extended.*; + +public interface MemoryProxy extends ValueProxy, MemoryNode { + + LocationIdentity getLocationIdentity(); + + MemoryNode getOriginalMemoryNode(); +} diff -r 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/FloatingReadPhase.java Tue Nov 26 00:09:59 2013 +0100 @@ -28,7 +28,6 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.phases.*; import com.oracle.graal.phases.graph.*; @@ -43,7 +42,7 @@ public static class MemoryMapImpl extends MemoryMapNode { - private IdentityHashMap lastMemorySnapshot; + private IdentityHashMap lastMemorySnapshot; public MemoryMapImpl(MemoryMapImpl memoryMap) { lastMemorySnapshot = new IdentityHashMap<>(memoryMap.lastMemorySnapshot); @@ -59,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 { @@ -198,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); } } @@ -217,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) { @@ -225,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; @@ -251,22 +250,22 @@ 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 } else if (merged == null) { merged = last; } else { - PhiNode phi = merge.graph().addWithoutUnique(new PhiNode(PhiType.Memory, merge, key)); + 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; } @@ -290,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,8 +305,8 @@ Map phis = new HashMap<>(); for (LocationIdentity location : modifiedLocations) { - PhiNode phi = loop.graph().addWithoutUnique(new PhiNode(PhiType.Memory, loop, location)); - phi.addInput(initialState.getLastLocationAccess(location)); + MemoryPhiNode phi = loop.graph().addWithoutUnique(new MemoryPhiNode(loop, location)); + phi.addInput(ValueNodeUtil.asNode(initialState.getLastLocationAccess(location))); phis.put(location, phi); initialState.lastMemorySnapshot.put(location, phi); } @@ -319,16 +318,16 @@ 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, ProxyNode.forMemory(lastAccessAtExit, exit, location, loop.graph())); + state.lastMemorySnapshot.put(location, MemoryProxyNode.forMemory(lastAccessAtExit, exit, location, loop.graph())); } } } diff -r 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Tue Nov 26 00:09:59 2013 +0100 @@ -142,8 +142,9 @@ protected void processNode(Node node) { if (node instanceof GuardNode) { GuardNode guard = (GuardNode) node; - if (guard.negated() && guard.condition() instanceof IsNullNode) { - lowerToNullCheck(guard); + FixedWithNextNode lowered = guard.lowerGuard(); + if (lowered != null) { + replaceCurrent(lowered); } else { lowerToIf(guard); } @@ -171,15 +172,6 @@ insert(ifNode, fastPath); } - private void lowerToNullCheck(GuardNode guard) { - IsNullNode isNull = (IsNullNode) guard.condition(); - NullCheckNode nullCheck = guard.graph().add(new NullCheckNode(isNull.object())); - replaceCurrent(nullCheck); - if (isNull.usages().isEmpty()) { - isNull.safeDelete(); - } - } - private void insertLoopExits(DeoptimizeNode deopt) { Loop loop = block.getLoop(); StructuredGraph graph = deopt.graph(); diff -r 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/OptimizeGuardAnchors.java Tue Nov 26 00:09:59 2013 +0100 @@ -72,7 +72,7 @@ } } for (ControlSplitNode controlSplit : graph.getNodes(ControlSplitNode.class)) { - otpimizeAtControlSplit(controlSplit, cfg); + optimizeAtControlSplit(controlSplit, cfg); } } @@ -84,7 +84,7 @@ return anchor.getBeginNode(); } - private static void otpimizeAtControlSplit(ControlSplitNode controlSplit, LazyCFG cfg) { + private static void optimizeAtControlSplit(ControlSplitNode controlSplit, LazyCFG cfg) { AbstractBeginNode successor = findMinimumUsagesSuccessor(controlSplit); int successorCount = controlSplit.successors().count(); List otherGuards = new ArrayList<>(successorCount - 1); diff -r 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ReadEliminationPhase.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Tue Nov 26 00:09:59 2013 +0100 @@ -33,7 +33,6 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.Verbosity; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.PhiNode.PhiType; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.nodes.extended.*; @@ -286,14 +285,12 @@ KillSet excludedLocations = new KillSet(); if (block.getBeginNode() instanceof MergeNode) { MergeNode mergeNode = (MergeNode) block.getBeginNode(); - for (PhiNode phi : mergeNode.usages().filter(PhiNode.class)) { - if (phi.type() == PhiType.Memory) { - if (foundExcludeNode) { - set.add(phi.getIdentity()); - } else { - excludedLocations.add(phi.getIdentity()); - foundExcludeNode = phi == excludeNode; - } + for (MemoryPhiNode phi : mergeNode.usages().filter(MemoryPhiNode.class)) { + if (foundExcludeNode) { + set.add(phi.getLocationIdentity()); + } else { + excludedLocations.add(phi.getLocationIdentity()); + foundExcludeNode = phi == excludeNode; } } } @@ -403,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; } @@ -546,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; @@ -599,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 + ")"; @@ -630,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(); } @@ -646,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 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/NodeIntrinsificationPhase.java Tue Nov 26 00:09:59 2013 +0100 @@ -380,7 +380,7 @@ } else if (usage instanceof ProxyNode) { ProxyNode proxy = (ProxyNode) usage; assert proxy.type() == PhiType.Value; - ProxyNode newProxy = graph.unique(new ProxyNode((ValueNode) intrinsifiedNode, proxy.proxyPoint(), PhiType.Value, proxy.getIdentity())); + ProxyNode newProxy = graph.unique(new ProxyNode((ValueNode) intrinsifiedNode, proxy.proxyPoint(), PhiType.Value)); for (Node proxyUsage : usage.usages().snapshot()) { checkCheckCastUsage(graph, newProxy, proxy, proxyUsage); } diff -r 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/SnippetTemplate.java Tue Nov 26 00:09:59 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 107fee7fa3bb -r 787357a6de3e 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 Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MacroNode.java Tue Nov 26 00:09:59 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; diff -r 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java Tue Nov 26 00:09:59 2013 +0100 @@ -114,7 +114,7 @@ if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) { ValueNode value = exitState.getReadCache(entry.getKey().object, entry.getKey().identity, this); if (!(value instanceof ProxyNode) || ((ProxyNode) value).proxyPoint() != exitNode) { - ProxyNode proxy = new ProxyNode(value, exitNode, PhiType.Value, null); + ProxyNode proxy = new ProxyNode(value, exitNode, PhiType.Value); effects.addFloatingNode(proxy, "readCacheProxy"); entry.setValue(proxy); } diff -r 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java Tue Nov 26 00:09:59 2013 +0100 @@ -247,7 +247,7 @@ ValueNode value = obj.getEntry(i); if (!(value instanceof VirtualObjectNode || value.isConstant())) { if (exitNode.loopBegin().isPhiAtMerge(value) || initialObj == null || !initialObj.isVirtual() || initialObj.getEntry(i) != value) { - ProxyNode proxy = new ProxyNode(value, exitNode, PhiType.Value, null); + ProxyNode proxy = new ProxyNode(value, exitNode, PhiType.Value); obj.setEntry(i, proxy); effects.addFloatingNode(proxy, "virtualProxy"); } @@ -257,7 +257,7 @@ if (initialObj == null || initialObj.isVirtual()) { ProxyNode proxy = proxies.get(obj.virtual); if (proxy == null) { - proxy = new ProxyNode(obj.getMaterializedValue(), exitNode, PhiType.Value, null); + proxy = new ProxyNode(obj.getMaterializedValue(), exitNode, PhiType.Value); effects.addFloatingNode(proxy, "proxy"); } else { effects.replaceFirstInput(proxy, proxy.value(), obj.getMaterializedValue()); diff -r 107fee7fa3bb -r 787357a6de3e graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java --- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java Tue Nov 26 00:09:17 2013 +0100 +++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/ReadEliminationClosure.java Tue Nov 26 00:09:59 2013 +0100 @@ -171,7 +171,7 @@ protected void processLoopExit(LoopExitNode exitNode, ReadEliminationBlockState initialState, ReadEliminationBlockState exitState, GraphEffectList effects) { for (Map.Entry, ValueNode> entry : exitState.getReadCache().entrySet()) { if (initialState.getReadCache().get(entry.getKey()) != entry.getValue()) { - ProxyNode proxy = new ProxyNode(exitState.getCacheEntry(entry.getKey()), exitNode, PhiType.Value, null); + ProxyNode proxy = new ProxyNode(exitState.getCacheEntry(entry.getKey()), exitNode, PhiType.Value); effects.addFloatingNode(proxy, "readCacheProxy"); entry.setValue(proxy); } diff -r 107fee7fa3bb -r 787357a6de3e src/share/vm/runtime/deoptimization.hpp --- a/src/share/vm/runtime/deoptimization.hpp Tue Nov 26 00:09:17 2013 +0100 +++ b/src/share/vm/runtime/deoptimization.hpp Tue Nov 26 00:09:59 2013 +0100 @@ -72,6 +72,9 @@ Reason_age, // nmethod too old; tier threshold reached Reason_predicate, // compiler generated predicate failed Reason_loop_limit_check, // compiler generated loop limits check failed +#ifdef GRAAL + Reason_aliasing, // optimistic assumption about aliasing failed +#endif Reason_LIMIT, #ifdef GRAAL diff -r 107fee7fa3bb -r 787357a6de3e src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Tue Nov 26 00:09:17 2013 +0100 +++ b/src/share/vm/runtime/vmStructs.cpp Tue Nov 26 00:09:59 2013 +0100 @@ -2196,7 +2196,8 @@ declare_preprocessor_constant, \ declare_c1_constant, \ declare_c2_constant, \ - declare_c2_preprocessor_constant) \ + declare_c2_preprocessor_constant, \ + declare_graal_constant) \ \ /******************/ \ /* Useful globals */ \ @@ -2505,6 +2506,7 @@ declare_constant(Deoptimization::Reason_age) \ declare_constant(Deoptimization::Reason_predicate) \ declare_constant(Deoptimization::Reason_loop_limit_check) \ + declare_graal_constant(Deoptimization::Reason_aliasing) \ declare_constant(Deoptimization::Reason_LIMIT) \ declare_constant(Deoptimization::Reason_RECORDED_LIMIT) \ \ @@ -2867,6 +2869,13 @@ # define GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY(name, value) #endif /* COMPILER1 */ +// Generate an int constant for a Graal build +#ifdef GRAAL +# define GENERATE_GRAAL_VM_INT_CONSTANT_ENTRY(name) GENERATE_VM_INT_CONSTANT_ENTRY(name) +#else +# define GENERATE_GRAAL_VM_INT_CONSTANT_ENTRY(name) +#endif + //-------------------------------------------------------------------------------- // VMLongConstantEntry macros // @@ -3009,7 +3018,8 @@ GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, GENERATE_C1_VM_INT_CONSTANT_ENTRY, GENERATE_C2_VM_INT_CONSTANT_ENTRY, - GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY) + GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY, + GENERATE_GRAAL_VM_INT_CONSTANT_ENTRY) #if INCLUDE_ALL_GCS VM_INT_CONSTANTS_CMS(GENERATE_VM_INT_CONSTANT_ENTRY)