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
hotspot Cdiff src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java
Print this page
*** 27,50 ****
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;
--- 27,46 ----
*** 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 ****
* {@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
--- 66,75 ----
*** 96,106 ****
*/
@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();
static final int DELETED_ID_START = -1000000000;
static final int INITIAL_ID = -1;
static final int ALIVE_ID_START = 0;
--- 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 = true;
static final int DELETED_ID_START = -1000000000;
static final int INITIAL_ID = -1;
static final int ALIVE_ID_START = 0;
*** 256,319 ****
public Node asNode() {
return this;
}
/**
! * @see CollectionsFactory#newSet()
! */
! public static <E extends Node> Set<E> newSet() {
! return CollectionsFactory.newSet();
! }
!
! /**
! * @see #newSet()
*/
! 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);
}
/**
! * Gets the graph context of this node.
*/
! public Graph graph() {
! return graph;
}
/**
* Returns an {@link NodeIterable iterable} which can be used to traverse all non-null input
* edges of this node.
--- 238,258 ----
public Node asNode() {
return this;
}
/**
! * Gets the graph context of this node.
*/
! public Graph graph() {
! return graph;
}
/**
! * Gets the option values associated with this node's 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 ****
*/
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);
}
}
/**
* Adds a given node to this node's {@linkplain #usages() usages}.
*
--- 350,371 ----
*/
public final boolean hasUsages() {
return this.usage0 != null;
}
! /**
! * 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 ****
if (isModificationCountsEnabled() && graph != null) {
graph.incUsageModCount(this);
}
}
! public boolean isDeleted() {
return id <= DELETED_ID_START;
}
! public boolean isAlive() {
return id >= ALIVE_ID_START;
}
/**
* 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.
*/
--- 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 ****
*/
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);
--- 798,809 ----
*** 889,914 ****
}
}
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;
--- 833,847 ----
*** 934,944 ****
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");
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;
--- 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 ****
public boolean verify() {
assertTrue(isAlive(), "cannot verify inactive nodes (id=%d)", id);
assertTrue(graph() != null, "null graph");
verifyInputs();
! if (Options.VerifyGraalGraphEdges.getValue()) {
verifyEdges();
}
return true;
}
--- 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 ****
public Iterable<? extends Node> cfgSuccessors() {
return successors();
}
/**
! * Nodes always use an {@linkplain System#identityHashCode(Object) identity} hash code.
*/
@Override
public final int hashCode() {
! return System.identityHashCode(this);
}
/**
! * 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).
*/
--- 959,985 ----
public Iterable<? extends Node> cfgSuccessors() {
return successors();
}
/**
! * 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() {
! assert !this.isUnregistered() : "node not yet constructed";
! if (this.isDeleted()) {
! return -id + DELETED_ID_START;
! }
! return id;
}
/**
! * Do not overwrite the equality test of a node in subclasses. Equality tests must rely solely
! * on identity.
*/
/**
* 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