src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File
*** old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java	Mon Mar 20 17:38:00 2017
--- new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java	Mon Mar 20 17:38:00 2017

*** 27,50 **** --- 27,46 ---- import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled; import static org.graalvm.compiler.graph.UnsafeAccess.UNSAFE; import java.lang.annotation.ElementType; import java.lang.annotation.RetentionPolicy; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.Formattable; import java.util.FormattableFlags; import java.util.Formatter; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.function.Predicate; import org.graalvm.compiler.core.common.CollectionsFactory; import org.graalvm.compiler.core.common.Fields; import org.graalvm.compiler.debug.DebugCloseable; import org.graalvm.compiler.debug.Fingerprint; import org.graalvm.compiler.graph.Graph.NodeEvent; import org.graalvm.compiler.graph.Graph.NodeEventListener;
*** 54,63 **** --- 50,60 ---- import org.graalvm.compiler.graph.spi.Simplifiable; import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodeinfo.Verbosity; + import org.graalvm.compiler.options.OptionValues; import sun.misc.Unsafe; /** * This class is the base class for all nodes. It represents a node that can be inserted in a
*** 69,93 **** --- 66,75 ---- * {@link Input} and {@link Successor} is not null, then there is an edge from this node to the node * this field points to. * <p> * Nodes which are be value numberable should implement the {@link ValueNumberable} interface. * * <h1>Replay Compilation</h1> * * To enable deterministic replay compilation, node sets and node maps should be instantiated with * the following methods: * <ul> * <li>{@link #newSet()}</li> * <li>{@link #newSet(Collection)}</li> * <li>{@link #newMap()}</li> * <li>{@link #newMap(int)}</li> * <li>{@link #newMap(Map)}</li> * <li>{@link #newIdentityMap()}</li> * <li>{@link #newIdentityMap(int)}</li> * <li>{@link #newIdentityMap(Map)}</li> * </ul> * * <h1>Assertions and Verification</h1> * * The Node class supplies the {@link #assertTrue(boolean, String, Object...)} and * {@link #assertFalse(boolean, String, Object...)} methods, which will check the supplied boolean * and throw a VerificationError if it has the wrong value. Both methods will always either throw an
*** 96,106 **** --- 78,88 ---- */ @NodeInfo public abstract class Node implements Cloneable, Formattable, NodeInterface { public static final NodeClass<?> TYPE = null; ! public static final boolean USE_UNSAFE_TO_CLONE = Graph.Options.CloneNodesWithUnsafe.getValue(); ! public static final boolean USE_UNSAFE_TO_CLONE = true; static final int DELETED_ID_START = -1000000000; static final int INITIAL_ID = -1; static final int ALIVE_ID_START = 0;
*** 256,319 **** --- 238,258 ---- public Node asNode() { return this; } /** * @see CollectionsFactory#newSet() */ public static <E extends Node> Set<E> newSet() { return CollectionsFactory.newSet(); } /** * @see #newSet() + * Gets the graph context of this node. */ ! public static <E extends Node> Set<E> newSet(Collection<? extends E> c) { ! return CollectionsFactory.newSet(c); } public static <K extends Node, V> Map<K, V> newMap() { // Node.equals() and Node.hashCode() are final and are implemented // purely in terms of identity so HashMap and IdentityHashMap with // Node's as keys will behave the same. We choose to use the latter // due to its lighter memory footprint. return newIdentityMap(); } public static <K extends Node, V> Map<K, V> newMap(Map<K, V> m) { // Node.equals() and Node.hashCode() are final and are implemented // purely in terms of identity so HashMap and IdentityHashMap with // Node's as keys will behave the same. We choose to use the latter // due to its lighter memory footprint. return newIdentityMap(m); } public static <K extends Node, V> Map<K, V> newMap(int expectedMaxSize) { // Node.equals() and Node.hashCode() are final and are implemented // purely in terms of identity so HashMap and IdentityHashMap with // Node's as keys will behave the same. We choose to use the latter // due to its lighter memory footprint. return newIdentityMap(expectedMaxSize); } public static <K extends Node, V> Map<K, V> newIdentityMap() { return CollectionsFactory.newIdentityMap(); } public static <K extends Node, V> Map<K, V> newIdentityMap(Map<K, V> m) { return CollectionsFactory.newIdentityMap(m); } public static <K extends Node, V> Map<K, V> newIdentityMap(int expectedMaxSize) { return CollectionsFactory.newIdentityMap(expectedMaxSize); ! public Graph graph() { ! return graph; } /** ! * Gets the graph context of this node. ! * Gets the option values associated with this node's graph. */ ! public Graph graph() { ! return graph; ! public final OptionValues getOptions() { ! return graph == null ? null : graph.getOptions(); } /** * Returns an {@link NodeIterable iterable} which can be used to traverse all non-null input * edges of this node.
*** 411,429 **** --- 350,371 ---- */ public final boolean hasUsages() { return this.usage0 != null; } void reverseUsageOrder() { List<Node> snapshot = this.usages().snapshot(); for (Node n : snapshot) { this.removeUsage(n); } Collections.reverse(snapshot); for (Node n : snapshot) { this.addUsage(n); + /** + * Checks whether this node has more than one usages. + */ + public final boolean hasMoreThanOneUsage() { + return this.usage1 != null; } + + /** + * Checks whether this node has exactly one usgae. + */ + public final boolean hasExactlyOneUsage() { + return hasUsages() && !hasMoreThanOneUsage(); } /** * Adds a given node to this node's {@linkplain #usages() usages}. *
*** 531,548 **** --- 473,494 ---- if (isModificationCountsEnabled() && graph != null) { graph.incUsageModCount(this); } } ! public final boolean isDeleted() { return id <= DELETED_ID_START; } ! public final boolean isAlive() { return id >= ALIVE_ID_START; } + public final boolean isUnregistered() { + return id == INITIAL_ID; + } + /** * Updates the usages sets of the given nodes after an input slot is changed from * {@code oldInput} to {@code newInput} by removing this node from {@code oldInput}'s usages and * adds this node to {@code newInput}'s usages. */
*** 759,769 **** --- 705,717 ---- } public void replaceAndDelete(Node other) { assert checkReplaceWith(other); assert other != null; + if (this.hasUsages()) { replaceAtUsages(other); + } replaceAtPredecessor(other); this.safeDelete(); } public void replaceFirstSuccessor(Node oldSuccessor, Node newSuccessor) {
*** 850,865 **** --- 798,809 ---- */ private void copyOrClearEdgesForClone(Node newNode, Edges.Type type, EnumSet<Edges.Type> edgesToCopy) { if (edgesToCopy.contains(type)) { getNodeClass().getEdges(type).copy(this, newNode); } else { if (USE_UNSAFE_TO_CLONE) { // The direct edges are already null getNodeClass().getEdges(type).initializeLists(newNode, this); } else { getNodeClass().getEdges(type).clear(newNode); } } } public static final EnumSet<Edges.Type> WithNoEdges = EnumSet.noneOf(Edges.Type.class); public static final EnumSet<Edges.Type> WithAllEdges = EnumSet.allOf(Edges.Type.class);
*** 889,914 **** --- 833,847 ---- } } Node newNode = null; try { if (USE_UNSAFE_TO_CLONE) { newNode = (Node) UNSAFE.allocateInstance(getClass()); newNode.nodeClass = nodeClassTmp; nodeClassTmp.getData().copy(this, newNode); copyOrClearEdgesForClone(newNode, Inputs, edgesToCopy); copyOrClearEdgesForClone(newNode, Successors, edgesToCopy); } else { newNode = (Node) this.clone(); newNode.typeCacheNext = null; newNode.usage0 = null; newNode.usage1 = null; newNode.predecessor = null; newNode.extraUsagesCount = 0; copyOrClearEdgesForClone(newNode, Inputs, edgesToCopy); copyOrClearEdgesForClone(newNode, Successors, edgesToCopy); } } catch (Exception e) { throw new GraalGraphError(e).addContext(this); } newNode.graph = into; newNode.id = INITIAL_ID;
*** 934,944 **** --- 867,877 ---- for (Position pos : inputPositions()) { Node input = pos.get(this); if (input == null) { assertTrue(pos.isInputOptional(), "non-optional input %s cannot be null in %s (fix nullness or use @OptionalInput)", pos, this); } else { ! assertFalse(input.isDeleted(), "input was deleted %s", input); assertTrue(input.isAlive(), "input is not alive yet, i.e., it was not yet added to the graph"); assertTrue(pos.getInputType() == InputType.Unchecked || input.isAllowedUsageType(pos.getInputType()), "invalid usage type %s %s", input, pos.getInputType()); } } return true;
*** 946,956 **** --- 879,889 ---- public boolean verify() { assertTrue(isAlive(), "cannot verify inactive nodes (id=%d)", id); assertTrue(graph() != null, "null graph"); verifyInputs(); ! if (Options.VerifyGraalGraphEdges.getValue(getOptions())) { verifyEdges(); } return true; }
*** 1026,1049 **** --- 959,985 ---- public Iterable<? extends Node> cfgSuccessors() { return successors(); } /** ! * Nodes always use an {@linkplain System#identityHashCode(Object) identity} hash code. ! * Nodes using their {@link #id} as the hash code. This works very well when nodes of the same + * graph are stored in sets. It can give bad behavior when storing nodes of different graphs in + * the same set. */ @Override public final int hashCode() { ! return System.identityHashCode(this); ! assert !this.isUnregistered() : "node not yet constructed"; + if (this.isDeleted()) { + return -id + DELETED_ID_START; + } + return id; } /** * Equality tests must rely solely on identity. + * Do not overwrite the equality test of a node in subclasses. Equality tests must rely solely + * on identity. */ @Override public final boolean equals(Object obj) { return super.equals(obj); } /** * Provides a {@link Map} of properties of this node for use in debugging (e.g., to view in the * ideal graph visualizer). */

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File