1 /* 2 * Copyright (c) 2012, 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.virtual.phases.ea; 24 25 import java.util.ArrayList; 26 27 import org.graalvm.compiler.graph.Node; 28 import org.graalvm.compiler.nodes.ControlSinkNode; 29 import org.graalvm.compiler.nodes.FixedNode; 30 import org.graalvm.compiler.nodes.FixedWithNextNode; 31 import org.graalvm.compiler.nodes.FrameState; 32 import org.graalvm.compiler.nodes.IfNode; 33 import org.graalvm.compiler.nodes.PhiNode; 34 import org.graalvm.compiler.nodes.StructuredGraph; 35 import org.graalvm.compiler.nodes.ValueNode; 36 import org.graalvm.compiler.nodes.debug.DynamicCounterNode; 37 import org.graalvm.compiler.nodes.debug.WeakCounterNode; 38 import org.graalvm.compiler.nodes.util.GraphUtil; 39 import org.graalvm.compiler.nodes.virtual.EscapeObjectState; 40 import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; 41 42 public class GraphEffectList extends EffectList { 43 44 public void addCounterBefore(String group, String name, int increment, boolean addContext, FixedNode position) { 45 add("add counter", graph -> DynamicCounterNode.addCounterBefore(group, name, increment, addContext, position)); 46 } 47 48 public void addCounterAfter(String group, String name, int increment, boolean addContext, FixedWithNextNode position) { 49 FixedNode nextPosition = position.next(); 50 add("add counter after", graph -> DynamicCounterNode.addCounterBefore(group, name, increment, addContext, nextPosition)); 51 } 52 53 public void addWeakCounterCounterBefore(String group, String name, int increment, boolean addContext, ValueNode checkedValue, FixedNode position) { 54 add("add weak counter", graph -> WeakCounterNode.addCounterBefore(group, name, increment, addContext, checkedValue, position)); 55 } 56 57 /** 58 * Adds the given fixed node to the graph's control flow, before position (so that the original 59 * predecessor of position will then be node's predecessor). 60 * 61 * @param node The fixed node to be added to the graph. 62 * @param position The fixed node before which the node should be added. 63 */ 64 public void addFixedNodeBefore(FixedWithNextNode node, FixedNode position) { 65 add("add fixed node", graph -> { 66 assert !node.isAlive() && !node.isDeleted() && position.isAlive(); 67 graph.addBeforeFixed(position, graph.add(node)); 68 }); 69 } 70 71 public void ensureAdded(ValueNode node, FixedNode position) { 72 add("ensure added", graph -> { 73 assert position.isAlive(); 74 if (!node.isAlive()) { 75 graph.addWithoutUniqueWithInputs(node); 76 if (node instanceof FixedWithNextNode) { 77 graph.addBeforeFixed(position, (FixedWithNextNode) node); 78 } 79 } 80 }); 81 } 82 83 /** 84 * Add the given floating node to the graph. 85 * 86 * @param node The floating node to be added. 87 */ 88 public void addFloatingNode(ValueNode node, @SuppressWarnings("unused") String cause) { 89 add("add floating node", graph -> graph.addWithoutUnique(node)); 90 } 91 92 /** 93 * Sets the phi node's input at the given index to the given value, adding new phi inputs as 94 * needed. 95 * 96 * @param node The phi node whose input should be changed. 97 * @param index The index of the phi input to be changed. 98 * @param value The new value for the phi input. 99 */ 100 public void initializePhiInput(PhiNode node, int index, ValueNode value) { 101 add("set phi input", (graph, obsoleteNodes) -> { 102 assert node.isAlive() && value.isAlive() && index >= 0; 103 node.initializeValueAt(index, value); 104 }); 105 } 106 107 /** 108 * Adds a virtual object's state to the given frame state. If the given reusedVirtualObjects set 109 * contains the virtual object then old states for this object will be removed. 110 * 111 * @param node The frame state to which the state should be added. 112 * @param state The virtual object state to add. 113 */ 114 public void addVirtualMapping(FrameState node, EscapeObjectState state) { 115 add("add virtual mapping", new Effect() { 116 @Override 117 public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { 118 if (node.isAlive()) { 119 assert !state.isDeleted(); 120 FrameState stateAfter = node; 121 for (int i = 0; i < stateAfter.virtualObjectMappingCount(); i++) { 122 if (stateAfter.virtualObjectMappingAt(i).object() == state.object()) { 123 stateAfter.virtualObjectMappings().remove(i); 124 } 125 } 126 stateAfter.addVirtualObjectMapping(state.isAlive() ? state : graph.unique(state)); 127 } 128 } 129 130 @Override 131 public boolean isVisible() { 132 return false; 133 } 134 }); 135 } 136 137 /** 138 * Removes the given fixed node from the control flow and deletes it. 139 * 140 * @param node The fixed node that should be deleted. 141 */ 142 public void deleteNode(Node node) { 143 add("delete fixed node", (graph, obsoleteNodes) -> { 144 if (node instanceof FixedWithNextNode) { 145 GraphUtil.unlinkFixedNode((FixedWithNextNode) node); 146 } 147 obsoleteNodes.add(node); 148 }); 149 } 150 151 public void killIfBranch(IfNode ifNode, boolean constantCondition) { 152 add("kill if branch", new Effect() { 153 @Override 154 public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { 155 graph.removeSplitPropagate(ifNode, ifNode.getSuccessor(constantCondition)); 156 } 157 158 @Override 159 public boolean isCfgKill() { 160 return true; 161 } 162 }); 163 } 164 165 public void replaceWithSink(FixedWithNextNode node, ControlSinkNode sink) { 166 add("kill if branch", new Effect() { 167 @Override 168 public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { 169 node.replaceAtPredecessor(sink); 170 GraphUtil.killCFG(node); 171 } 172 173 @Override 174 public boolean isCfgKill() { 175 return true; 176 } 177 }); 178 } 179 180 /** 181 * Replaces the given node at its usages without deleting it. If the current node is a fixed 182 * node it will be disconnected from the control flow, so that it will be deleted by a 183 * subsequent {@link DeadCodeEliminationPhase} 184 * 185 * @param node The node to be replaced. 186 * @param replacement The node that should replace the original value. If the replacement is a 187 * non-connected {@link FixedWithNextNode} it will be added to the control flow. 188 * 189 */ 190 public void replaceAtUsages(ValueNode node, ValueNode replacement) { 191 assert node != null && replacement != null : node + " " + replacement; 192 add("replace at usages", (graph, obsoleteNodes) -> { 193 assert node.isAlive() && replacement.isAlive() : node + " " + replacement; 194 if (replacement instanceof FixedWithNextNode && ((FixedWithNextNode) replacement).next() == null) { 195 assert node instanceof FixedNode; 196 graph.addBeforeFixed((FixedNode) node, (FixedWithNextNode) replacement); 197 } 198 node.replaceAtUsages(replacement); 199 if (node instanceof FixedWithNextNode) { 200 GraphUtil.unlinkFixedNode((FixedWithNextNode) node); 201 } 202 obsoleteNodes.add(node); 203 }); 204 } 205 206 /** 207 * Replaces the first occurrence of oldInput in node with newInput. 208 * 209 * @param node The node whose input should be changed. 210 * @param oldInput The value to look for. 211 * @param newInput The value to replace with. 212 */ 213 public void replaceFirstInput(Node node, Node oldInput, Node newInput) { 214 assert node.isAlive() && oldInput.isAlive() && !newInput.isDeleted(); 215 add("replace first input", new Effect() { 216 @Override 217 public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) { 218 if (node.isAlive()) { 219 assert oldInput.isAlive() && newInput.isAlive(); 220 node.replaceFirstInput(oldInput, newInput); 221 } 222 } 223 224 @Override 225 public boolean isVisible() { 226 return !(node instanceof FrameState); 227 } 228 }); 229 } 230 }