001/* 002 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.nodes; 024 025import java.util.*; 026 027import com.oracle.graal.compiler.common.type.*; 028import com.oracle.graal.graph.*; 029import com.oracle.graal.graph.iterators.*; 030import com.oracle.graal.graph.spi.*; 031import com.oracle.graal.nodeinfo.*; 032import com.oracle.graal.nodes.extended.*; 033import com.oracle.graal.nodes.spi.*; 034 035@NodeInfo(allowedUsageTypes = {InputType.Guard, InputType.Anchor}) 036public abstract class AbstractBeginNode extends FixedWithNextNode implements LIRLowerable, Simplifiable, GuardingNode, AnchoringNode, IterableNodeType { 037 038 public static final NodeClass<AbstractBeginNode> TYPE = NodeClass.create(AbstractBeginNode.class); 039 040 protected AbstractBeginNode(NodeClass<? extends AbstractBeginNode> c) { 041 this(c, StampFactory.forVoid()); 042 } 043 044 protected AbstractBeginNode(NodeClass<? extends AbstractBeginNode> c, Stamp stamp) { 045 super(c, stamp); 046 } 047 048 @Override 049 public void simplify(SimplifierTool tool) { 050 FixedNode prev = (FixedNode) this.predecessor(); 051 if (prev == null) { 052 // This is the start node. 053 } else if (prev instanceof ControlSplitNode) { 054 // This begin node is necessary. 055 } else { 056 // This begin node can be removed and all guards moved up to the preceding begin node. 057 prepareDelete(); 058 tool.addToWorkList(next()); 059 graph().removeFixed(this); 060 } 061 } 062 063 public static AbstractBeginNode prevBegin(FixedNode from) { 064 Node next = from; 065 while (next != null) { 066 if (next instanceof AbstractBeginNode) { 067 AbstractBeginNode begin = (AbstractBeginNode) next; 068 return begin; 069 } 070 next = next.predecessor(); 071 } 072 return null; 073 } 074 075 private void evacuateGuards(FixedNode evacuateFrom) { 076 if (!hasNoUsages()) { 077 AbstractBeginNode prevBegin = prevBegin(evacuateFrom); 078 assert prevBegin != null; 079 for (Node anchored : anchored().snapshot()) { 080 anchored.replaceFirstInput(this, prevBegin); 081 } 082 } 083 } 084 085 public void prepareDelete() { 086 prepareDelete((FixedNode) predecessor()); 087 } 088 089 public void prepareDelete(FixedNode evacuateFrom) { 090 removeProxies(); 091 evacuateGuards(evacuateFrom); 092 } 093 094 public void removeProxies() { 095 if (this.hasUsages()) { 096 outer: while (true) { 097 for (ProxyNode vpn : proxies().snapshot()) { 098 ValueNode value = vpn.value(); 099 vpn.replaceAtUsages(value); 100 vpn.safeDelete(); 101 if (value == this) { 102 // Guard proxy could have this input as value. 103 continue outer; 104 } 105 } 106 break; 107 } 108 } 109 } 110 111 @Override 112 public boolean verify() { 113 assertTrue(predecessor() != null || this == graph().start() || this instanceof AbstractMergeNode, "begin nodes must be connected"); 114 return super.verify(); 115 } 116 117 @Override 118 public void generate(NodeLIRBuilderTool gen) { 119 // nop 120 } 121 122 public NodeIterable<GuardNode> guards() { 123 return usages().filter(GuardNode.class); 124 } 125 126 public NodeIterable<Node> anchored() { 127 return usages().filter(n -> { 128 if (n instanceof ProxyNode) { 129 ProxyNode proxyNode = (ProxyNode) n; 130 return proxyNode.proxyPoint() != this; 131 } 132 return true; 133 }); 134 } 135 136 @SuppressWarnings({"unchecked", "rawtypes"}) 137 public NodeIterable<ProxyNode> proxies() { 138 return (NodeIterable) usages().filter(n -> { 139 if (n instanceof ProxyNode) { 140 ProxyNode proxyNode = (ProxyNode) n; 141 return proxyNode.proxyPoint() == this; 142 } 143 return false; 144 }); 145 } 146 147 public NodeIterable<FixedNode> getBlockNodes() { 148 return new NodeIterable<FixedNode>() { 149 150 @Override 151 public Iterator<FixedNode> iterator() { 152 return new BlockNodeIterator(AbstractBeginNode.this); 153 } 154 }; 155 } 156 157 private class BlockNodeIterator implements Iterator<FixedNode> { 158 159 private FixedNode current; 160 161 public BlockNodeIterator(FixedNode next) { 162 this.current = next; 163 } 164 165 @Override 166 public boolean hasNext() { 167 return current != null; 168 } 169 170 @Override 171 public FixedNode next() { 172 FixedNode ret = current; 173 if (ret == null) { 174 throw new NoSuchElementException(); 175 } 176 if (!(current instanceof FixedWithNextNode) || (current instanceof AbstractBeginNode && current != AbstractBeginNode.this)) { 177 current = null; 178 } else { 179 current = ((FixedWithNextNode) current).next(); 180 } 181 return ret; 182 } 183 184 @Override 185 public void remove() { 186 throw new UnsupportedOperationException(); 187 } 188 } 189}