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.graph; 24 25 import static org.graalvm.compiler.graph.Edges.Type.Inputs; 26 import static org.graalvm.compiler.graph.Edges.Type.Successors; 27 import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled; 28 import static org.graalvm.compiler.graph.UnsafeAccess.UNSAFE; 29 30 import java.lang.annotation.ElementType; 31 import java.lang.annotation.RetentionPolicy; 32 import java.util.Collection; 33 import java.util.Collections; 34 import java.util.EnumSet; 35 import java.util.Formattable; 36 import java.util.FormattableFlags; 37 import java.util.Formatter; 38 import java.util.HashMap; 39 import java.util.List; 40 import java.util.Map; 41 import java.util.Objects; 42 import java.util.Set; 43 import java.util.function.Predicate; 44 45 import org.graalvm.compiler.core.common.CollectionsFactory; 46 import org.graalvm.compiler.core.common.Fields; 47 import org.graalvm.compiler.debug.DebugCloseable; 48 import org.graalvm.compiler.debug.Fingerprint; 49 import org.graalvm.compiler.graph.Graph.NodeEvent; 50 import org.graalvm.compiler.graph.Graph.NodeEventListener; 51 import org.graalvm.compiler.graph.Graph.Options; 52 import org.graalvm.compiler.graph.iterators.NodeIterable; 53 import org.graalvm.compiler.graph.iterators.NodePredicate; 54 import org.graalvm.compiler.graph.spi.Simplifiable; 55 import org.graalvm.compiler.graph.spi.SimplifierTool; 56 import org.graalvm.compiler.nodeinfo.InputType; 57 import org.graalvm.compiler.nodeinfo.NodeInfo; 58 import org.graalvm.compiler.nodeinfo.Verbosity; 59 60 import sun.misc.Unsafe; 61 62 /** 63 * This class is the base class for all nodes. It represents a node that can be inserted in a 64 * {@link Graph}. 65 * <p> 66 * Once a node has been added to a graph, it has a graph-unique {@link #id()}. Edges in the 67 * subclasses are represented with annotated fields. There are two kind of edges : {@link Input} and 68 * {@link Successor}. If a field, of a type compatible with {@link Node}, annotated with either 69 * {@link Input} and {@link Successor} is not null, then there is an edge from this node to the node 70 * this field points to. 71 * <p> 72 * Nodes which are be value numberable should implement the {@link ValueNumberable} interface. 73 * 74 * <h1>Replay Compilation</h1> 75 * 76 * To enable deterministic replay compilation, node sets and node maps should be instantiated with 77 * the following methods: 78 * <ul> 79 * <li>{@link #newSet()}</li> 80 * <li>{@link #newSet(Collection)}</li> 81 * <li>{@link #newMap()}</li> 82 * <li>{@link #newMap(int)}</li> 83 * <li>{@link #newMap(Map)}</li> 84 * <li>{@link #newIdentityMap()}</li> 85 * <li>{@link #newIdentityMap(int)}</li> 86 * <li>{@link #newIdentityMap(Map)}</li> 87 * </ul> 88 * 89 * <h1>Assertions and Verification</h1> 90 * 91 * The Node class supplies the {@link #assertTrue(boolean, String, Object...)} and 92 * {@link #assertFalse(boolean, String, Object...)} methods, which will check the supplied boolean 93 * and throw a VerificationError if it has the wrong value. Both methods will always either throw an 94 * exception or return true. They can thus be used within an assert statement, so that the check is 95 * only performed if assertions are enabled. 96 */ 97 @NodeInfo 98 public abstract class Node implements Cloneable, Formattable, NodeInterface { 99 100 public static final NodeClass<?> TYPE = null; 101 public static final boolean USE_UNSAFE_TO_CLONE = Graph.Options.CloneNodesWithUnsafe.getValue(); 102 103 static final int DELETED_ID_START = -1000000000; 104 static final int INITIAL_ID = -1; 105 static final int ALIVE_ID_START = 0; 106 107 // The use of fully qualified class names here and in the rest 108 // of this file works around a problem javac has resolving symbols 109 110 /** 111 * Denotes a non-optional (non-null) node input. This should be applied to exactly the fields of 112 * a node that are of type {@link Node} or {@link NodeInputList}. Nodes that update fields of 113 * type {@link Node} outside of their constructor should call 114 * {@link Node#updateUsages(Node, Node)} just prior to doing the update of the input. 115 */ 116 @java.lang.annotation.Retention(RetentionPolicy.RUNTIME) 117 @java.lang.annotation.Target(ElementType.FIELD) 118 public static @interface Input { 119 InputType value() default InputType.Value; 120 } 121 241 init(c); 242 } 243 244 final void init(NodeClass<? extends Node> c) { 245 assert c.getJavaClass() == this.getClass(); 246 this.nodeClass = c; 247 id = INITIAL_ID; 248 extraUsages = NO_NODES; 249 } 250 251 final int id() { 252 return id; 253 } 254 255 @Override 256 public Node asNode() { 257 return this; 258 } 259 260 /** 261 * @see CollectionsFactory#newSet() 262 */ 263 public static <E extends Node> Set<E> newSet() { 264 return CollectionsFactory.newSet(); 265 } 266 267 /** 268 * @see #newSet() 269 */ 270 public static <E extends Node> Set<E> newSet(Collection<? extends E> c) { 271 return CollectionsFactory.newSet(c); 272 } 273 274 public static <K extends Node, V> Map<K, V> newMap() { 275 // Node.equals() and Node.hashCode() are final and are implemented 276 // purely in terms of identity so HashMap and IdentityHashMap with 277 // Node's as keys will behave the same. We choose to use the latter 278 // due to its lighter memory footprint. 279 return newIdentityMap(); 280 } 281 282 public static <K extends Node, V> Map<K, V> newMap(Map<K, V> m) { 283 // Node.equals() and Node.hashCode() are final and are implemented 284 // purely in terms of identity so HashMap and IdentityHashMap with 285 // Node's as keys will behave the same. We choose to use the latter 286 // due to its lighter memory footprint. 287 return newIdentityMap(m); 288 } 289 290 public static <K extends Node, V> Map<K, V> newMap(int expectedMaxSize) { 291 // Node.equals() and Node.hashCode() are final and are implemented 292 // purely in terms of identity so HashMap and IdentityHashMap with 293 // Node's as keys will behave the same. We choose to use the latter 294 // due to its lighter memory footprint. 295 return newIdentityMap(expectedMaxSize); 296 } 297 298 public static <K extends Node, V> Map<K, V> newIdentityMap() { 299 return CollectionsFactory.newIdentityMap(); 300 } 301 302 public static <K extends Node, V> Map<K, V> newIdentityMap(Map<K, V> m) { 303 return CollectionsFactory.newIdentityMap(m); 304 } 305 306 public static <K extends Node, V> Map<K, V> newIdentityMap(int expectedMaxSize) { 307 return CollectionsFactory.newIdentityMap(expectedMaxSize); 308 } 309 310 /** 311 * Gets the graph context of this node. 312 */ 313 public Graph graph() { 314 return graph; 315 } 316 317 /** 318 * Returns an {@link NodeIterable iterable} which can be used to traverse all non-null input 319 * edges of this node. 320 * 321 * @return an {@link NodeIterable iterable} for all non-null input edges. 322 */ 323 public NodeIterable<Node> inputs() { 324 return nodeClass.getInputIterable(this); 325 } 326 327 /** 328 * Returns an {@link Iterable iterable} which can be used to traverse all non-null input edges 329 * of this node. 330 * 331 * @return an {@link Iterable iterable} for all non-null input edges. 332 */ 333 public Iterable<Position> inputPositions() { 334 return nodeClass.getInputEdges().getPositionsIterable(this); 396 * Gets the list of nodes that use this node (i.e., as an input). 397 */ 398 public final NodeIterable<Node> usages() { 399 return new NodeUsageIterable(this); 400 } 401 402 /** 403 * Checks whether this node has no usages. 404 */ 405 public final boolean hasNoUsages() { 406 return this.usage0 == null; 407 } 408 409 /** 410 * Checks whether this node has usages. 411 */ 412 public final boolean hasUsages() { 413 return this.usage0 != null; 414 } 415 416 void reverseUsageOrder() { 417 List<Node> snapshot = this.usages().snapshot(); 418 for (Node n : snapshot) { 419 this.removeUsage(n); 420 } 421 Collections.reverse(snapshot); 422 for (Node n : snapshot) { 423 this.addUsage(n); 424 } 425 } 426 427 /** 428 * Adds a given node to this node's {@linkplain #usages() usages}. 429 * 430 * @param node the node to add 431 */ 432 void addUsage(Node node) { 433 incUsageModCount(); 434 if (usage0 == null) { 435 usage0 = node; 436 } else if (usage1 == null) { 437 usage1 = node; 438 } else { 439 int length = extraUsages.length; 440 if (length == 0) { 441 extraUsages = new Node[4]; 442 } else if (extraUsagesCount == length) { 443 Node[] newExtraUsages = new Node[length * 2 + 1]; 444 System.arraycopy(extraUsages, 0, newExtraUsages, 0, length); 516 517 final void incModCount() { 518 if (isModificationCountsEnabled() && graph != null) { 519 graph.incModCount(this); 520 } 521 } 522 523 final int usageModCount() { 524 if (isModificationCountsEnabled() && graph != null) { 525 return graph.usageModCount(this); 526 } 527 return 0; 528 } 529 530 final void incUsageModCount() { 531 if (isModificationCountsEnabled() && graph != null) { 532 graph.incUsageModCount(this); 533 } 534 } 535 536 public boolean isDeleted() { 537 return id <= DELETED_ID_START; 538 } 539 540 public boolean isAlive() { 541 return id >= ALIVE_ID_START; 542 } 543 544 /** 545 * Updates the usages sets of the given nodes after an input slot is changed from 546 * {@code oldInput} to {@code newInput} by removing this node from {@code oldInput}'s usages and 547 * adds this node to {@code newInput}'s usages. 548 */ 549 protected void updateUsages(Node oldInput, Node newInput) { 550 assert isAlive() && (newInput == null || newInput.isAlive()) : "adding " + newInput + " to " + this + " instead of " + oldInput; 551 if (oldInput != newInput) { 552 if (oldInput != null) { 553 boolean result = removeThisFromUsages(oldInput); 554 assert assertTrue(result, "not found in usages, old input: %s", oldInput); 555 } 556 maybeNotifyInputChanged(this); 557 if (newInput != null) { 558 newInput.addUsage(this); 559 } 560 if (oldInput != null && oldInput.hasNoUsages()) { 561 maybeNotifyZeroUsages(oldInput); 562 } 563 } 744 listener.usagesDroppedToZero(node); 745 } 746 if (Fingerprint.ENABLED) { 747 Fingerprint.submit("%s: %s", NodeEvent.ZERO_USAGES, node); 748 } 749 } 750 } 751 752 public void replaceAtPredecessor(Node other) { 753 assert checkReplaceWith(other); 754 if (predecessor != null) { 755 boolean result = predecessor.getNodeClass().replaceFirstSuccessor(predecessor, this, other); 756 assert assertTrue(result, "not found in successors, predecessor: %s", predecessor); 757 predecessor.updatePredecessor(this, other); 758 } 759 } 760 761 public void replaceAndDelete(Node other) { 762 assert checkReplaceWith(other); 763 assert other != null; 764 replaceAtUsages(other); 765 replaceAtPredecessor(other); 766 this.safeDelete(); 767 } 768 769 public void replaceFirstSuccessor(Node oldSuccessor, Node newSuccessor) { 770 if (nodeClass.replaceFirstSuccessor(this, oldSuccessor, newSuccessor)) { 771 updatePredecessor(oldSuccessor, newSuccessor); 772 } 773 } 774 775 public void replaceFirstInput(Node oldInput, Node newInput) { 776 if (nodeClass.replaceFirstInput(this, oldInput, newInput)) { 777 updateUsages(oldInput, newInput); 778 } 779 } 780 781 public void clearInputs() { 782 assert assertFalse(isDeleted(), "cannot clear inputs of deleted node"); 783 getNodeClass().unregisterAtInputsAsUsage(this); 784 } 835 * {@link Node} exists to obviate the need to cast a node before invoking 836 * {@link Simplifiable#simplify(SimplifierTool)}. 837 * 838 * @param tool 839 */ 840 public void simplify(SimplifierTool tool) { 841 throw new UnsupportedOperationException(); 842 } 843 844 /** 845 * @param newNode the result of cloning this node or {@link Unsafe#allocateInstance(Class) raw 846 * allocating} a copy of this node 847 * @param type the type of edges to process 848 * @param edgesToCopy if {@code type} is in this set, the edges are copied otherwise they are 849 * cleared 850 */ 851 private void copyOrClearEdgesForClone(Node newNode, Edges.Type type, EnumSet<Edges.Type> edgesToCopy) { 852 if (edgesToCopy.contains(type)) { 853 getNodeClass().getEdges(type).copy(this, newNode); 854 } else { 855 if (USE_UNSAFE_TO_CLONE) { 856 // The direct edges are already null 857 getNodeClass().getEdges(type).initializeLists(newNode, this); 858 } else { 859 getNodeClass().getEdges(type).clear(newNode); 860 } 861 } 862 } 863 864 public static final EnumSet<Edges.Type> WithNoEdges = EnumSet.noneOf(Edges.Type.class); 865 public static final EnumSet<Edges.Type> WithAllEdges = EnumSet.allOf(Edges.Type.class); 866 public static final EnumSet<Edges.Type> WithOnlyInputEdges = EnumSet.of(Inputs); 867 public static final EnumSet<Edges.Type> WithOnlySucessorEdges = EnumSet.of(Successors); 868 869 /** 870 * Makes a copy of this node in(to) a given graph. 871 * 872 * @param into the graph in which the copy will be registered (which may be this node's graph) 873 * or null if the copy should not be registered in a graph 874 * @param edgesToCopy specifies the edges to be copied. The edges not specified in this set are 875 * initialized to their default value (i.e., {@code null} for a direct edge, an empty 876 * list for an edge list) 877 * @return the copy of this node 878 */ 879 final Node clone(Graph into, EnumSet<Edges.Type> edgesToCopy) { 880 final NodeClass<? extends Node> nodeClassTmp = getNodeClass(); 881 boolean useIntoLeafNodeCache = false; 882 if (into != null) { 883 if (nodeClassTmp.valueNumberable() && nodeClassTmp.isLeafNode()) { 884 useIntoLeafNodeCache = true; 885 Node otherNode = into.findNodeInCache(this); 886 if (otherNode != null) { 887 return otherNode; 888 } 889 } 890 } 891 892 Node newNode = null; 893 try { 894 if (USE_UNSAFE_TO_CLONE) { 895 newNode = (Node) UNSAFE.allocateInstance(getClass()); 896 newNode.nodeClass = nodeClassTmp; 897 nodeClassTmp.getData().copy(this, newNode); 898 copyOrClearEdgesForClone(newNode, Inputs, edgesToCopy); 899 copyOrClearEdgesForClone(newNode, Successors, edgesToCopy); 900 } else { 901 newNode = (Node) this.clone(); 902 newNode.typeCacheNext = null; 903 newNode.usage0 = null; 904 newNode.usage1 = null; 905 newNode.predecessor = null; 906 newNode.extraUsagesCount = 0; 907 copyOrClearEdgesForClone(newNode, Inputs, edgesToCopy); 908 copyOrClearEdgesForClone(newNode, Successors, edgesToCopy); 909 } 910 } catch (Exception e) { 911 throw new GraalGraphError(e).addContext(this); 912 } 913 newNode.graph = into; 914 newNode.id = INITIAL_ID; 915 if (into != null) { 916 into.register(newNode); 917 } 918 newNode.extraUsages = NO_NODES; 919 920 if (into != null && useIntoLeafNodeCache) { 921 into.putNodeIntoCache(newNode); 922 } 923 if (graph != null && into != null && sourcePosition != null) { 924 newNode.setNodeSourcePosition(sourcePosition); 925 } 926 newNode.afterClone(this); 927 return newNode; 928 } 929 930 protected void afterClone(@SuppressWarnings("unused") Node other) { 931 } 932 933 protected boolean verifyInputs() { 934 for (Position pos : inputPositions()) { 935 Node input = pos.get(this); 936 if (input == null) { 937 assertTrue(pos.isInputOptional(), "non-optional input %s cannot be null in %s (fix nullness or use @OptionalInput)", pos, this); 938 } else { 939 assertFalse(input.isDeleted(), "input was deleted"); 940 assertTrue(input.isAlive(), "input is not alive yet, i.e., it was not yet added to the graph"); 941 assertTrue(pos.getInputType() == InputType.Unchecked || input.isAllowedUsageType(pos.getInputType()), "invalid usage type %s %s", input, pos.getInputType()); 942 } 943 } 944 return true; 945 } 946 947 public boolean verify() { 948 assertTrue(isAlive(), "cannot verify inactive nodes (id=%d)", id); 949 assertTrue(graph() != null, "null graph"); 950 verifyInputs(); 951 if (Options.VerifyGraalGraphEdges.getValue()) { 952 verifyEdges(); 953 } 954 return true; 955 } 956 957 /** 958 * Perform expensive verification of inputs, usages, predecessors and successors. 959 * 960 * @return true 961 */ 962 public boolean verifyEdges() { 963 for (Node input : inputs()) { 964 assertTrue(input == null || input.usages().contains(this), "missing usage of %s in input %s", this, input); 965 } 966 967 for (Node successor : successors()) { 968 assertTrue(successor.predecessor() == this, "missing predecessor in %s (actual: %s)", successor, successor.predecessor()); 969 assertTrue(successor.graph() == graph(), "mismatching graph in successor %s", successor); 970 } 971 for (Node usage : usages()) { 1011 } 1012 1013 public Iterable<? extends Node> cfgPredecessors() { 1014 if (predecessor == null) { 1015 return Collections.emptySet(); 1016 } else { 1017 return Collections.singleton(predecessor); 1018 } 1019 } 1020 1021 /** 1022 * Returns an iterator that will provide all control-flow successors of this node. Normally this 1023 * will be the contents of all fields annotated with {@link Successor}, but some node classes 1024 * (like EndNode) may return different nodes. 1025 */ 1026 public Iterable<? extends Node> cfgSuccessors() { 1027 return successors(); 1028 } 1029 1030 /** 1031 * Nodes always use an {@linkplain System#identityHashCode(Object) identity} hash code. 1032 */ 1033 @Override 1034 public final int hashCode() { 1035 return System.identityHashCode(this); 1036 } 1037 1038 /** 1039 * Equality tests must rely solely on identity. 1040 */ 1041 @Override 1042 public final boolean equals(Object obj) { 1043 return super.equals(obj); 1044 } 1045 1046 /** 1047 * Provides a {@link Map} of properties of this node for use in debugging (e.g., to view in the 1048 * ideal graph visualizer). 1049 */ 1050 public final Map<Object, Object> getDebugProperties() { 1051 return getDebugProperties(new HashMap<>()); 1052 } 1053 1054 /** 1055 * Fills a {@link Map} with properties of this node for use in debugging (e.g., to view in the 1056 * ideal graph visualizer). Subclasses overriding this method should also fill the map using 1057 * their superclass. 1058 * 1059 * @param map 1060 */ 1061 public Map<Object, Object> getDebugProperties(Map<Object, Object> map) { 1062 Fields properties = getNodeClass().getData(); 1063 for (int i = 0; i < properties.getCount(); i++) { 1064 map.put(properties.getName(i), properties.get(this, i)); | 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.graph; 24 25 import static org.graalvm.compiler.graph.Edges.Type.Inputs; 26 import static org.graalvm.compiler.graph.Edges.Type.Successors; 27 import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled; 28 import static org.graalvm.compiler.graph.UnsafeAccess.UNSAFE; 29 30 import java.lang.annotation.ElementType; 31 import java.lang.annotation.RetentionPolicy; 32 import java.util.Collections; 33 import java.util.EnumSet; 34 import java.util.Formattable; 35 import java.util.FormattableFlags; 36 import java.util.Formatter; 37 import java.util.HashMap; 38 import java.util.Map; 39 import java.util.Objects; 40 import java.util.function.Predicate; 41 42 import org.graalvm.compiler.core.common.Fields; 43 import org.graalvm.compiler.debug.DebugCloseable; 44 import org.graalvm.compiler.debug.Fingerprint; 45 import org.graalvm.compiler.graph.Graph.NodeEvent; 46 import org.graalvm.compiler.graph.Graph.NodeEventListener; 47 import org.graalvm.compiler.graph.Graph.Options; 48 import org.graalvm.compiler.graph.iterators.NodeIterable; 49 import org.graalvm.compiler.graph.iterators.NodePredicate; 50 import org.graalvm.compiler.graph.spi.Simplifiable; 51 import org.graalvm.compiler.graph.spi.SimplifierTool; 52 import org.graalvm.compiler.nodeinfo.InputType; 53 import org.graalvm.compiler.nodeinfo.NodeInfo; 54 import org.graalvm.compiler.nodeinfo.Verbosity; 55 import org.graalvm.compiler.options.OptionValues; 56 57 import sun.misc.Unsafe; 58 59 /** 60 * This class is the base class for all nodes. It represents a node that can be inserted in a 61 * {@link Graph}. 62 * <p> 63 * Once a node has been added to a graph, it has a graph-unique {@link #id()}. Edges in the 64 * subclasses are represented with annotated fields. There are two kind of edges : {@link Input} and 65 * {@link Successor}. If a field, of a type compatible with {@link Node}, annotated with either 66 * {@link Input} and {@link Successor} is not null, then there is an edge from this node to the node 67 * this field points to. 68 * <p> 69 * Nodes which are be value numberable should implement the {@link ValueNumberable} interface. 70 * 71 * <h1>Assertions and Verification</h1> 72 * 73 * The Node class supplies the {@link #assertTrue(boolean, String, Object...)} and 74 * {@link #assertFalse(boolean, String, Object...)} methods, which will check the supplied boolean 75 * and throw a VerificationError if it has the wrong value. Both methods will always either throw an 76 * exception or return true. They can thus be used within an assert statement, so that the check is 77 * only performed if assertions are enabled. 78 */ 79 @NodeInfo 80 public abstract class Node implements Cloneable, Formattable, NodeInterface { 81 82 public static final NodeClass<?> TYPE = null; 83 public static final boolean USE_UNSAFE_TO_CLONE = true; 84 85 static final int DELETED_ID_START = -1000000000; 86 static final int INITIAL_ID = -1; 87 static final int ALIVE_ID_START = 0; 88 89 // The use of fully qualified class names here and in the rest 90 // of this file works around a problem javac has resolving symbols 91 92 /** 93 * Denotes a non-optional (non-null) node input. This should be applied to exactly the fields of 94 * a node that are of type {@link Node} or {@link NodeInputList}. Nodes that update fields of 95 * type {@link Node} outside of their constructor should call 96 * {@link Node#updateUsages(Node, Node)} just prior to doing the update of the input. 97 */ 98 @java.lang.annotation.Retention(RetentionPolicy.RUNTIME) 99 @java.lang.annotation.Target(ElementType.FIELD) 100 public static @interface Input { 101 InputType value() default InputType.Value; 102 } 103 223 init(c); 224 } 225 226 final void init(NodeClass<? extends Node> c) { 227 assert c.getJavaClass() == this.getClass(); 228 this.nodeClass = c; 229 id = INITIAL_ID; 230 extraUsages = NO_NODES; 231 } 232 233 final int id() { 234 return id; 235 } 236 237 @Override 238 public Node asNode() { 239 return this; 240 } 241 242 /** 243 * Gets the graph context of this node. 244 */ 245 public Graph graph() { 246 return graph; 247 } 248 249 /** 250 * Gets the option values associated with this node's graph. 251 */ 252 public final OptionValues getOptions() { 253 return graph == null ? null : graph.getOptions(); 254 } 255 256 /** 257 * Returns an {@link NodeIterable iterable} which can be used to traverse all non-null input 258 * edges of this node. 259 * 260 * @return an {@link NodeIterable iterable} for all non-null input edges. 261 */ 262 public NodeIterable<Node> inputs() { 263 return nodeClass.getInputIterable(this); 264 } 265 266 /** 267 * Returns an {@link Iterable iterable} which can be used to traverse all non-null input edges 268 * of this node. 269 * 270 * @return an {@link Iterable iterable} for all non-null input edges. 271 */ 272 public Iterable<Position> inputPositions() { 273 return nodeClass.getInputEdges().getPositionsIterable(this); 335 * Gets the list of nodes that use this node (i.e., as an input). 336 */ 337 public final NodeIterable<Node> usages() { 338 return new NodeUsageIterable(this); 339 } 340 341 /** 342 * Checks whether this node has no usages. 343 */ 344 public final boolean hasNoUsages() { 345 return this.usage0 == null; 346 } 347 348 /** 349 * Checks whether this node has usages. 350 */ 351 public final boolean hasUsages() { 352 return this.usage0 != null; 353 } 354 355 /** 356 * Checks whether this node has more than one usages. 357 */ 358 public final boolean hasMoreThanOneUsage() { 359 return this.usage1 != null; 360 } 361 362 /** 363 * Checks whether this node has exactly one usgae. 364 */ 365 public final boolean hasExactlyOneUsage() { 366 return hasUsages() && !hasMoreThanOneUsage(); 367 } 368 369 /** 370 * Adds a given node to this node's {@linkplain #usages() usages}. 371 * 372 * @param node the node to add 373 */ 374 void addUsage(Node node) { 375 incUsageModCount(); 376 if (usage0 == null) { 377 usage0 = node; 378 } else if (usage1 == null) { 379 usage1 = node; 380 } else { 381 int length = extraUsages.length; 382 if (length == 0) { 383 extraUsages = new Node[4]; 384 } else if (extraUsagesCount == length) { 385 Node[] newExtraUsages = new Node[length * 2 + 1]; 386 System.arraycopy(extraUsages, 0, newExtraUsages, 0, length); 458 459 final void incModCount() { 460 if (isModificationCountsEnabled() && graph != null) { 461 graph.incModCount(this); 462 } 463 } 464 465 final int usageModCount() { 466 if (isModificationCountsEnabled() && graph != null) { 467 return graph.usageModCount(this); 468 } 469 return 0; 470 } 471 472 final void incUsageModCount() { 473 if (isModificationCountsEnabled() && graph != null) { 474 graph.incUsageModCount(this); 475 } 476 } 477 478 public final boolean isDeleted() { 479 return id <= DELETED_ID_START; 480 } 481 482 public final boolean isAlive() { 483 return id >= ALIVE_ID_START; 484 } 485 486 public final boolean isUnregistered() { 487 return id == INITIAL_ID; 488 } 489 490 /** 491 * Updates the usages sets of the given nodes after an input slot is changed from 492 * {@code oldInput} to {@code newInput} by removing this node from {@code oldInput}'s usages and 493 * adds this node to {@code newInput}'s usages. 494 */ 495 protected void updateUsages(Node oldInput, Node newInput) { 496 assert isAlive() && (newInput == null || newInput.isAlive()) : "adding " + newInput + " to " + this + " instead of " + oldInput; 497 if (oldInput != newInput) { 498 if (oldInput != null) { 499 boolean result = removeThisFromUsages(oldInput); 500 assert assertTrue(result, "not found in usages, old input: %s", oldInput); 501 } 502 maybeNotifyInputChanged(this); 503 if (newInput != null) { 504 newInput.addUsage(this); 505 } 506 if (oldInput != null && oldInput.hasNoUsages()) { 507 maybeNotifyZeroUsages(oldInput); 508 } 509 } 690 listener.usagesDroppedToZero(node); 691 } 692 if (Fingerprint.ENABLED) { 693 Fingerprint.submit("%s: %s", NodeEvent.ZERO_USAGES, node); 694 } 695 } 696 } 697 698 public void replaceAtPredecessor(Node other) { 699 assert checkReplaceWith(other); 700 if (predecessor != null) { 701 boolean result = predecessor.getNodeClass().replaceFirstSuccessor(predecessor, this, other); 702 assert assertTrue(result, "not found in successors, predecessor: %s", predecessor); 703 predecessor.updatePredecessor(this, other); 704 } 705 } 706 707 public void replaceAndDelete(Node other) { 708 assert checkReplaceWith(other); 709 assert other != null; 710 if (this.hasUsages()) { 711 replaceAtUsages(other); 712 } 713 replaceAtPredecessor(other); 714 this.safeDelete(); 715 } 716 717 public void replaceFirstSuccessor(Node oldSuccessor, Node newSuccessor) { 718 if (nodeClass.replaceFirstSuccessor(this, oldSuccessor, newSuccessor)) { 719 updatePredecessor(oldSuccessor, newSuccessor); 720 } 721 } 722 723 public void replaceFirstInput(Node oldInput, Node newInput) { 724 if (nodeClass.replaceFirstInput(this, oldInput, newInput)) { 725 updateUsages(oldInput, newInput); 726 } 727 } 728 729 public void clearInputs() { 730 assert assertFalse(isDeleted(), "cannot clear inputs of deleted node"); 731 getNodeClass().unregisterAtInputsAsUsage(this); 732 } 783 * {@link Node} exists to obviate the need to cast a node before invoking 784 * {@link Simplifiable#simplify(SimplifierTool)}. 785 * 786 * @param tool 787 */ 788 public void simplify(SimplifierTool tool) { 789 throw new UnsupportedOperationException(); 790 } 791 792 /** 793 * @param newNode the result of cloning this node or {@link Unsafe#allocateInstance(Class) raw 794 * allocating} a copy of this node 795 * @param type the type of edges to process 796 * @param edgesToCopy if {@code type} is in this set, the edges are copied otherwise they are 797 * cleared 798 */ 799 private void copyOrClearEdgesForClone(Node newNode, Edges.Type type, EnumSet<Edges.Type> edgesToCopy) { 800 if (edgesToCopy.contains(type)) { 801 getNodeClass().getEdges(type).copy(this, newNode); 802 } else { 803 // The direct edges are already null 804 getNodeClass().getEdges(type).initializeLists(newNode, this); 805 } 806 } 807 808 public static final EnumSet<Edges.Type> WithNoEdges = EnumSet.noneOf(Edges.Type.class); 809 public static final EnumSet<Edges.Type> WithAllEdges = EnumSet.allOf(Edges.Type.class); 810 public static final EnumSet<Edges.Type> WithOnlyInputEdges = EnumSet.of(Inputs); 811 public static final EnumSet<Edges.Type> WithOnlySucessorEdges = EnumSet.of(Successors); 812 813 /** 814 * Makes a copy of this node in(to) a given graph. 815 * 816 * @param into the graph in which the copy will be registered (which may be this node's graph) 817 * or null if the copy should not be registered in a graph 818 * @param edgesToCopy specifies the edges to be copied. The edges not specified in this set are 819 * initialized to their default value (i.e., {@code null} for a direct edge, an empty 820 * list for an edge list) 821 * @return the copy of this node 822 */ 823 final Node clone(Graph into, EnumSet<Edges.Type> edgesToCopy) { 824 final NodeClass<? extends Node> nodeClassTmp = getNodeClass(); 825 boolean useIntoLeafNodeCache = false; 826 if (into != null) { 827 if (nodeClassTmp.valueNumberable() && nodeClassTmp.isLeafNode()) { 828 useIntoLeafNodeCache = true; 829 Node otherNode = into.findNodeInCache(this); 830 if (otherNode != null) { 831 return otherNode; 832 } 833 } 834 } 835 836 Node newNode = null; 837 try { 838 newNode = (Node) UNSAFE.allocateInstance(getClass()); 839 newNode.nodeClass = nodeClassTmp; 840 nodeClassTmp.getData().copy(this, newNode); 841 copyOrClearEdgesForClone(newNode, Inputs, edgesToCopy); 842 copyOrClearEdgesForClone(newNode, Successors, edgesToCopy); 843 } catch (Exception e) { 844 throw new GraalGraphError(e).addContext(this); 845 } 846 newNode.graph = into; 847 newNode.id = INITIAL_ID; 848 if (into != null) { 849 into.register(newNode); 850 } 851 newNode.extraUsages = NO_NODES; 852 853 if (into != null && useIntoLeafNodeCache) { 854 into.putNodeIntoCache(newNode); 855 } 856 if (graph != null && into != null && sourcePosition != null) { 857 newNode.setNodeSourcePosition(sourcePosition); 858 } 859 newNode.afterClone(this); 860 return newNode; 861 } 862 863 protected void afterClone(@SuppressWarnings("unused") Node other) { 864 } 865 866 protected boolean verifyInputs() { 867 for (Position pos : inputPositions()) { 868 Node input = pos.get(this); 869 if (input == null) { 870 assertTrue(pos.isInputOptional(), "non-optional input %s cannot be null in %s (fix nullness or use @OptionalInput)", pos, this); 871 } else { 872 assertFalse(input.isDeleted(), "input was deleted %s", input); 873 assertTrue(input.isAlive(), "input is not alive yet, i.e., it was not yet added to the graph"); 874 assertTrue(pos.getInputType() == InputType.Unchecked || input.isAllowedUsageType(pos.getInputType()), "invalid usage type %s %s", input, pos.getInputType()); 875 } 876 } 877 return true; 878 } 879 880 public boolean verify() { 881 assertTrue(isAlive(), "cannot verify inactive nodes (id=%d)", id); 882 assertTrue(graph() != null, "null graph"); 883 verifyInputs(); 884 if (Options.VerifyGraalGraphEdges.getValue(getOptions())) { 885 verifyEdges(); 886 } 887 return true; 888 } 889 890 /** 891 * Perform expensive verification of inputs, usages, predecessors and successors. 892 * 893 * @return true 894 */ 895 public boolean verifyEdges() { 896 for (Node input : inputs()) { 897 assertTrue(input == null || input.usages().contains(this), "missing usage of %s in input %s", this, input); 898 } 899 900 for (Node successor : successors()) { 901 assertTrue(successor.predecessor() == this, "missing predecessor in %s (actual: %s)", successor, successor.predecessor()); 902 assertTrue(successor.graph() == graph(), "mismatching graph in successor %s", successor); 903 } 904 for (Node usage : usages()) { 944 } 945 946 public Iterable<? extends Node> cfgPredecessors() { 947 if (predecessor == null) { 948 return Collections.emptySet(); 949 } else { 950 return Collections.singleton(predecessor); 951 } 952 } 953 954 /** 955 * Returns an iterator that will provide all control-flow successors of this node. Normally this 956 * will be the contents of all fields annotated with {@link Successor}, but some node classes 957 * (like EndNode) may return different nodes. 958 */ 959 public Iterable<? extends Node> cfgSuccessors() { 960 return successors(); 961 } 962 963 /** 964 * Nodes using their {@link #id} as the hash code. This works very well when nodes of the same 965 * graph are stored in sets. It can give bad behavior when storing nodes of different graphs in 966 * the same set. 967 */ 968 @Override 969 public final int hashCode() { 970 assert !this.isUnregistered() : "node not yet constructed"; 971 if (this.isDeleted()) { 972 return -id + DELETED_ID_START; 973 } 974 return id; 975 } 976 977 /** 978 * Do not overwrite the equality test of a node in subclasses. Equality tests must rely solely 979 * on identity. 980 */ 981 982 /** 983 * Provides a {@link Map} of properties of this node for use in debugging (e.g., to view in the 984 * ideal graph visualizer). 985 */ 986 public final Map<Object, Object> getDebugProperties() { 987 return getDebugProperties(new HashMap<>()); 988 } 989 990 /** 991 * Fills a {@link Map} with properties of this node for use in debugging (e.g., to view in the 992 * ideal graph visualizer). Subclasses overriding this method should also fill the map using 993 * their superclass. 994 * 995 * @param map 996 */ 997 public Map<Object, Object> getDebugProperties(Map<Object, Object> map) { 998 Fields properties = getNodeClass().getData(); 999 for (int i = 0; i < properties.getCount(); i++) { 1000 map.put(properties.getName(i), properties.get(this, i)); |