1 /* 2 * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.nodes.cfg; 24 25 import java.util.ArrayList; 26 import java.util.Iterator; 27 28 import org.graalvm.compiler.core.common.LocationIdentity; 29 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; 30 import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; 31 import org.graalvm.compiler.core.common.cfg.Loop; 32 import org.graalvm.compiler.graph.Node; 33 import org.graalvm.compiler.nodes.AbstractBeginNode; 34 import org.graalvm.compiler.nodes.FixedNode; 35 import org.graalvm.compiler.nodes.FixedWithNextNode; 36 import org.graalvm.compiler.nodes.InvokeWithExceptionNode; 37 import org.graalvm.compiler.nodes.LoopBeginNode; 38 import org.graalvm.compiler.nodes.LoopEndNode; 39 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; 40 41 public final class Block extends AbstractBlockBase<Block> { 42 43 public static final Block[] EMPTY_ARRAY = new Block[0]; 44 45 protected final AbstractBeginNode beginNode; 46 47 protected FixedNode endNode; 48 49 protected double probability; 50 protected Loop<Block> loop; 51 52 protected Block postdominator; 53 protected Block distancedDominatorCache; 54 private LocationSet killLocations; 55 private LocationSet killLocationsBetweenThisAndDominator; 56 57 protected Block(AbstractBeginNode node) { 58 this.beginNode = node; 59 } 60 61 public AbstractBeginNode getBeginNode() { 62 return beginNode; 63 } 64 65 public FixedNode getEndNode() { 66 return endNode; 67 } 68 69 @Override 70 public Loop<Block> getLoop() { 71 return loop; 72 } 73 74 public void setLoop(Loop<Block> loop) { 75 this.loop = loop; 76 } 77 78 @Override 79 public int getLoopDepth() { 80 return loop == null ? 0 : loop.getDepth(); 81 } 82 83 @Override 84 public boolean isLoopHeader() { 85 return getBeginNode() instanceof LoopBeginNode; 86 } 87 88 @Override 89 public boolean isLoopEnd() { 90 return getEndNode() instanceof LoopEndNode; 91 } 92 93 @Override 94 public boolean isExceptionEntry() { 95 Node predecessor = getBeginNode().predecessor(); 96 return predecessor != null && predecessor instanceof InvokeWithExceptionNode && getBeginNode() == ((InvokeWithExceptionNode) predecessor).exceptionEdge(); 97 } 98 99 public Block getFirstPredecessor() { 100 return getPredecessors()[0]; 101 } 102 103 public Block getFirstSuccessor() { 104 return getSuccessors()[0]; 105 } 106 107 public Block getEarliestPostDominated() { 108 Block b = this; 109 while (true) { 110 Block dom = b.getDominator(); 111 if (dom != null && dom.getPostdominator() == b) { 112 b = dom; 113 } else { 114 break; 115 } 116 } 117 return b; 118 } 119 120 @Override 121 public Block getPostdominator() { 122 return postdominator; 123 } 124 125 private class NodeIterator implements Iterator<FixedNode> { 126 127 private FixedNode cur; 128 129 NodeIterator() { 130 cur = getBeginNode(); 131 } 132 133 @Override 134 public boolean hasNext() { 135 return cur != null; 136 } 137 138 @Override 139 public FixedNode next() { 140 FixedNode result = cur; 141 if (result instanceof FixedWithNextNode) { 142 FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) result; 143 FixedNode next = fixedWithNextNode.next(); 144 if (next instanceof AbstractBeginNode) { 145 next = null; 146 } 147 cur = next; 148 } else { 149 cur = null; 150 } 151 assert !(cur instanceof AbstractBeginNode); 152 return result; 153 } 154 155 @Override 156 public void remove() { 157 throw new UnsupportedOperationException(); 158 } 159 } 160 161 public Iterable<FixedNode> getNodes() { 162 return new Iterable<FixedNode>() { 163 164 @Override 165 public Iterator<FixedNode> iterator() { 166 return new NodeIterator(); 167 } 168 169 @Override 170 public String toString() { 171 StringBuilder str = new StringBuilder().append('['); 172 for (FixedNode node : this) { 173 str.append(node).append(", "); 174 } 175 if (str.length() > 1) { 176 str.setLength(str.length() - 2); 177 } 178 return str.append(']').toString(); 179 } 180 }; 181 } 182 183 @Override 184 public String toString() { 185 return "B" + id; 186 } 187 188 @Override 189 public double probability() { 190 return probability; 191 } 192 193 public void setProbability(double probability) { 194 assert probability >= 0 && Double.isFinite(probability); 195 this.probability = probability; 196 } 197 198 @Override 199 public Block getDominator(int distance) { 200 Block result = this; 201 for (int i = 0; i < distance; ++i) { 202 result = result.getDominator(); 203 } 204 return result; 205 } 206 207 public boolean canKill(LocationIdentity location) { 208 if (location.isImmutable()) { 209 return false; 210 } 211 return getKillLocations().contains(location); 212 } 213 214 public LocationSet getKillLocations() { 215 if (killLocations == null) { 216 killLocations = calcKillLocations(); 217 } 218 return killLocations; 219 } 220 221 private LocationSet calcKillLocations() { 222 LocationSet result = new LocationSet(); 223 for (FixedNode node : this.getNodes()) { 224 if (node instanceof MemoryCheckpoint.Single) { 225 LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity(); 226 result.add(identity); 227 } else if (node instanceof MemoryCheckpoint.Multi) { 228 for (LocationIdentity identity : ((MemoryCheckpoint.Multi) node).getLocationIdentities()) { 229 result.add(identity); 230 } 231 } 232 if (result.isAny()) { 233 break; 234 } 235 } 236 return result; 237 } 238 239 public boolean canKillBetweenThisAndDominator(LocationIdentity location) { 240 if (location.isImmutable()) { 241 return false; 242 } 243 return this.getKillLocationsBetweenThisAndDominator().contains(location); 244 } 245 246 private LocationSet getKillLocationsBetweenThisAndDominator() { 247 if (this.killLocationsBetweenThisAndDominator == null) { 248 LocationSet dominatorResult = new LocationSet(); 249 Block stopBlock = getDominator(); 250 if (this.isLoopHeader()) { 251 assert stopBlock.getLoopDepth() < this.getLoopDepth(); 252 dominatorResult.addAll(((HIRLoop) this.getLoop()).getKillLocations()); 253 } else { 254 for (Block b : this.getPredecessors()) { 255 assert !this.isLoopHeader(); 256 if (b != stopBlock) { 257 dominatorResult.addAll(b.getKillLocations()); 258 if (dominatorResult.isAny()) { 259 break; 260 } 261 b.calcKillLocationsBetweenThisAndTarget(dominatorResult, stopBlock); 262 if (dominatorResult.isAny()) { 263 break; 264 } 265 } 266 } 267 } 268 this.killLocationsBetweenThisAndDominator = dominatorResult; 269 } 270 return this.killLocationsBetweenThisAndDominator; 271 } 272 273 private void calcKillLocationsBetweenThisAndTarget(LocationSet result, Block stopBlock) { 274 assert AbstractControlFlowGraph.dominates(stopBlock, this); 275 if (stopBlock == this || result.isAny()) { 276 // We reached the stop block => nothing to do. 277 return; 278 } else { 279 if (stopBlock == this.getDominator()) { 280 result.addAll(this.getKillLocationsBetweenThisAndDominator()); 281 } else { 282 // Divide and conquer: Aggregate kill locations from this to the dominator and then 283 // from the dominator onwards. 284 calcKillLocationsBetweenThisAndTarget(result, this.getDominator()); 285 result.addAll(this.getDominator().getKillLocations()); 286 if (result.isAny()) { 287 return; 288 } 289 this.getDominator().calcKillLocationsBetweenThisAndTarget(result, stopBlock); 290 } 291 } 292 } 293 294 @Override 295 public void delete() { 296 297 // adjust successor and predecessor lists 298 Block next = getSuccessors()[0]; 299 for (Block pred : getPredecessors()) { 300 Block[] predSuccs = pred.successors; 301 Block[] newPredSuccs = new Block[predSuccs.length]; 302 for (int i = 0; i < predSuccs.length; ++i) { 303 if (predSuccs[i] == this) { 304 newPredSuccs[i] = next; 305 } else { 306 newPredSuccs[i] = predSuccs[i]; 307 } 308 } 309 pred.setSuccessors(newPredSuccs); 310 } 311 312 ArrayList<Block> newPreds = new ArrayList<>(); 313 for (int i = 0; i < next.getPredecessorCount(); i++) { 314 Block curPred = next.getPredecessors()[i]; 315 if (curPred == this) { 316 for (Block b : getPredecessors()) { 317 newPreds.add(b); 318 } 319 } else { 320 newPreds.add(curPred); 321 } 322 } 323 324 next.setPredecessors(newPreds.toArray(new Block[0])); 325 } 326 }