--- /dev/null 2017-01-22 10:16:57.869617664 -0800 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopExitNode.java 2017-02-15 17:06:46.516977624 -0800 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2012, 2015, 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 org.graalvm.compiler.nodes; + +import static org.graalvm.compiler.nodeinfo.InputType.Association; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; + +import org.graalvm.compiler.graph.IterableNodeType; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.iterators.NodeIterable; +import org.graalvm.compiler.graph.spi.Simplifiable; +import org.graalvm.compiler.graph.spi.SimplifierTool; +import org.graalvm.compiler.nodeinfo.NodeInfo; + +@NodeInfo(allowedUsageTypes = {Association}, cycles = CYCLES_0, size = SIZE_0) +public final class LoopExitNode extends BeginStateSplitNode implements IterableNodeType, Simplifiable { + + public static final NodeClass TYPE = NodeClass.create(LoopExitNode.class); + + /* + * The declared type of the field cannot be LoopBeginNode, because loop explosion during partial + * evaluation can temporarily assign a non-loop begin. This node will then be deleted shortly + * after - but we still must not have type system violations for that short amount of time. + */ + @Input(Association) AbstractBeginNode loopBegin; + + public LoopExitNode(LoopBeginNode loop) { + super(TYPE); + assert loop != null; + loopBegin = loop; + } + + public LoopBeginNode loopBegin() { + return (LoopBeginNode) loopBegin; + } + + @Override + public NodeIterable anchored() { + return super.anchored().filter(n -> { + if (n instanceof ProxyNode) { + ProxyNode proxyNode = (ProxyNode) n; + return proxyNode.proxyPoint() != this; + } + return true; + }); + } + + @Override + public void prepareDelete(FixedNode evacuateFrom) { + removeProxies(); + super.prepareDelete(evacuateFrom); + } + + public void removeProxies() { + if (this.hasUsages()) { + outer: while (true) { + for (ProxyNode vpn : proxies().snapshot()) { + ValueNode value = vpn.value(); + vpn.replaceAtUsagesAndDelete(value); + if (value == this) { + // Guard proxy could have this input as value. + continue outer; + } + } + break; + } + } + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + public NodeIterable proxies() { + return (NodeIterable) usages().filter(n -> { + if (n instanceof ProxyNode) { + ProxyNode proxyNode = (ProxyNode) n; + return proxyNode.proxyPoint() == this; + } + return false; + }); + } + + @Override + public void simplify(SimplifierTool tool) { + Node prev = this.predecessor(); + while (tool.allUsagesAvailable() && prev instanceof BeginNode && prev.hasNoUsages()) { + AbstractBeginNode begin = (AbstractBeginNode) prev; + prev = prev.predecessor(); + graph().removeFixed(begin); + } + } +}