1 /*
   2  * Copyright (c) 2011, 2015, 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.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.core.common.type.AbstractPointerStamp;
  44 import org.graalvm.compiler.core.common.type.Stamp;
  45 import org.graalvm.compiler.debug.DebugCloseable;
  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.NodeCycles;
  54 import org.graalvm.compiler.nodeinfo.NodeInfo;
  55 import org.graalvm.compiler.nodeinfo.NodeSize;
  56 import org.graalvm.compiler.nodeinfo.Verbosity;
  57 import org.graalvm.compiler.options.OptionValues;
  58 
  59 import sun.misc.Unsafe;
  60 
  61 /**
  62  * This class is the base class for all nodes. It represents a node that can be inserted in a
  63  * {@link Graph}.
  64  * <p>
  65  * Once a node has been added to a graph, it has a graph-unique {@link #id()}. Edges in the
  66  * subclasses are represented with annotated fields. There are two kind of edges : {@link Input} and
  67  * {@link Successor}. If a field, of a type compatible with {@link Node}, annotated with either
  68  * {@link Input} and {@link Successor} is not null, then there is an edge from this node to the node
  69  * this field points to.
  70  * <p>
  71  * Nodes which are be value numberable should implement the {@link ValueNumberable} interface.
  72  *
  73  * <h1>Assertions and Verification</h1>
  74  *
  75  * The Node class supplies the {@link #assertTrue(boolean, String, Object...)} and
  76  * {@link #assertFalse(boolean, String, Object...)} methods, which will check the supplied boolean
  77  * and throw a VerificationError if it has the wrong value. Both methods will always either throw an
  78  * exception or return true. They can thus be used within an assert statement, so that the check is
  79  * only performed if assertions are enabled.
  80  */
  81 @NodeInfo
  82 public abstract class Node implements Cloneable, Formattable, NodeInterface {
  83 
  84     public static final NodeClass<?> TYPE = null;
  85     public static final boolean USE_UNSAFE_TO_CLONE = true;
  86 
  87     static final int DELETED_ID_START = -1000000000;
  88     static final int INITIAL_ID = -1;
  89     static final int ALIVE_ID_START = 0;
  90 
  91     // The use of fully qualified class names here and in the rest
  92     // of this file works around a problem javac has resolving symbols
  93 
  94     /**
  95      * Denotes a non-optional (non-null) node input. This should be applied to exactly the fields of
  96      * a node that are of type {@link Node} or {@link NodeInputList}. Nodes that update fields of
  97      * type {@link Node} outside of their constructor should call
  98      * {@link Node#updateUsages(Node, Node)} just prior to doing the update of the input.
  99      */
 100     @java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
 101     @java.lang.annotation.Target(ElementType.FIELD)
 102     public static @interface Input {
 103         InputType value() default InputType.Value;
 104     }
 105 
 106     /**
 107      * Denotes an optional (nullable) node input. This should be applied to exactly the fields of a
 108      * node that are of type {@link Node} or {@link NodeInputList}. Nodes that update fields of type
 109      * {@link Node} outside of their constructor should call {@link Node#updateUsages(Node, Node)}
 110      * just prior to doing the update of the input.
 111      */
 112     @java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
 113     @java.lang.annotation.Target(ElementType.FIELD)
 114     public static @interface OptionalInput {
 115         InputType value() default InputType.Value;
 116     }
 117 
 118     @java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
 119     @java.lang.annotation.Target(ElementType.FIELD)
 120     public static @interface Successor {
 121     }
 122 
 123     /**
 124      * Denotes that a parameter of an {@linkplain NodeIntrinsic intrinsic} method must be a compile
 125      * time constant at all call sites to the intrinsic method.
 126      */
 127     @java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
 128     @java.lang.annotation.Target(ElementType.PARAMETER)
 129     public static @interface ConstantNodeParameter {
 130     }
 131 
 132     /**
 133      * Denotes an injected parameter in a {@linkplain NodeIntrinsic node intrinsic} constructor. If
 134      * the constructor is called as part of node intrinsification, the node intrinsifier will inject
 135      * an argument for the annotated parameter. Injected parameters must precede all non-injected
 136      * parameters in a constructor. If the type of the annotated parameter is {@link Stamp}, the
 137      * {@linkplain Stamp#javaType type} of the injected stamp is the return type of the annotated
 138      * method (which cannot be {@code void}).
 139      */
 140     @java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
 141     @java.lang.annotation.Target(ElementType.PARAMETER)
 142     public static @interface InjectedNodeParameter {
 143     }
 144 
 145     /**
 146      * Annotates a method that can be replaced by a compiler intrinsic. A (resolved) call to the
 147      * annotated method will be processed by a generated {@code InvocationPlugin} that calls either
 148      * a factory method or a constructor corresponding with the annotated method.
 149      * <p>
 150      * A factory method corresponding to an annotated method is a static method named
 151      * {@code intrinsify} defined in the class denoted by {@link #value()}. In order, its signature
 152      * is as follows:
 153      * <ol>
 154      * <li>A {@code GraphBuilderContext} parameter.</li>
 155      * <li>A {@code ResolvedJavaMethod} parameter.</li>
 156      * <li>A sequence of zero or more {@linkplain InjectedNodeParameter injected} parameters.</li>
 157      * <li>Remaining parameters that match the declared parameters of the annotated method.</li>
 158      * </ol>
 159      * A constructor corresponding to an annotated method is defined in the class denoted by
 160      * {@link #value()}. In order, its signature is as follows:
 161      * <ol>
 162      * <li>A sequence of zero or more {@linkplain InjectedNodeParameter injected} parameters.</li>
 163      * <li>Remaining parameters that match the declared parameters of the annotated method.</li>
 164      * </ol>
 165      * There must be exactly one such factory method or constructor corresponding to a
 166      * {@link NodeIntrinsic} annotated method.
 167      */
 168     @java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
 169     @java.lang.annotation.Target(ElementType.METHOD)
 170     public static @interface NodeIntrinsic {
 171 
 172         /**
 173          * The class declaring the factory method or {@link Node} subclass declaring the constructor
 174          * used to intrinsify a call to the annotated method. The default value is the class in
 175          * which the annotated method is declared.
 176          */
 177         Class<?> value() default NodeIntrinsic.class;
 178 
 179         /**
 180          * If {@code true}, the factory method or constructor selected by the annotation must have
 181          * an {@linkplain InjectedNodeParameter injected} {@link Stamp} parameter. Calling
 182          * {@link AbstractPointerStamp#nonNull()} on the injected stamp is guaranteed to return
 183          * {@code true}.
 184          */
 185         boolean injectedStampIsNonNull() default false;
 186     }
 187 
 188     /**
 189      * Marker for a node that can be replaced by another node via global value numbering. A
 190      * {@linkplain NodeClass#isLeafNode() leaf} node can be replaced by another node of the same
 191      * type that has exactly the same {@linkplain NodeClass#getData() data} values. A non-leaf node
 192      * can be replaced by another node of the same type that has exactly the same data values as
 193      * well as the same {@linkplain Node#inputs() inputs} and {@linkplain Node#successors()
 194      * successors}.
 195      */
 196     public interface ValueNumberable {
 197     }
 198 
 199     /**
 200      * Marker interface for nodes that contains other nodes. When the inputs to this node changes,
 201      * users of this node should also be placed on the work list for canonicalization.
 202      */
 203     public interface IndirectCanonicalization {
 204     }
 205 
 206     private Graph graph;
 207     int id;
 208 
 209     // this next pointer is used in Graph to implement fast iteration over NodeClass types, it
 210     // therefore points to the next Node of the same type.
 211     Node typeCacheNext;
 212 
 213     static final int INLINE_USAGE_COUNT = 2;
 214     private static final Node[] NO_NODES = {};
 215 
 216     /**
 217      * Head of usage list. The elements of the usage list in order are {@link #usage0},
 218      * {@link #usage1} and {@link #extraUsages}. The first null entry terminates the list.
 219      */
 220     Node usage0;
 221     Node usage1;
 222     Node[] extraUsages;
 223     int extraUsagesCount;
 224 
 225     private Node predecessor;
 226     private NodeClass<? extends Node> nodeClass;
 227 
 228     public static final int NODE_LIST = -2;
 229     public static final int NOT_ITERABLE = -1;
 230 
 231     public Node(NodeClass<? extends Node> c) {
 232         init(c);
 233     }
 234 
 235     final void init(NodeClass<? extends Node> c) {
 236         assert c.getJavaClass() == this.getClass();
 237         this.nodeClass = c;
 238         id = INITIAL_ID;
 239         extraUsages = NO_NODES;
 240     }
 241 
 242     final int id() {
 243         return id;
 244     }
 245 
 246     @Override
 247     public Node asNode() {
 248         return this;
 249     }
 250 
 251     /**
 252      * Gets the graph context of this node.
 253      */
 254     public Graph graph() {
 255         return graph;
 256     }
 257 
 258     /**
 259      * Gets the option values associated with this node's graph.
 260      */
 261     public final OptionValues getOptions() {
 262         return graph == null ? null : graph.getOptions();
 263     }
 264 
 265     /**
 266      * Returns an {@link NodeIterable iterable} which can be used to traverse all non-null input
 267      * edges of this node.
 268      *
 269      * @return an {@link NodeIterable iterable} for all non-null input edges.
 270      */
 271     public NodeIterable<Node> inputs() {
 272         return nodeClass.getInputIterable(this);
 273     }
 274 
 275     /**
 276      * Returns an {@link Iterable iterable} which can be used to traverse all non-null input edges
 277      * of this node.
 278      *
 279      * @return an {@link Iterable iterable} for all non-null input edges.
 280      */
 281     public Iterable<Position> inputPositions() {
 282         return nodeClass.getInputEdges().getPositionsIterable(this);
 283     }
 284 
 285     public abstract static class EdgeVisitor {
 286 
 287         public abstract Node apply(Node source, Node target);
 288 
 289     }
 290 
 291     /**
 292      * Applies the given visitor to all inputs of this node.
 293      *
 294      * @param visitor the visitor to be applied to the inputs
 295      */
 296     public void applyInputs(EdgeVisitor visitor) {
 297         nodeClass.applyInputs(this, visitor);
 298     }
 299 
 300     /**
 301      * Applies the given visitor to all successors of this node.
 302      *
 303      * @param visitor the visitor to be applied to the successors
 304      */
 305     public void applySuccessors(EdgeVisitor visitor) {
 306         nodeClass.applySuccessors(this, visitor);
 307     }
 308 
 309     /**
 310      * Returns an {@link NodeIterable iterable} which can be used to traverse all non-null successor
 311      * edges of this node.
 312      *
 313      * @return an {@link NodeIterable iterable} for all non-null successor edges.
 314      */
 315     public NodeIterable<Node> successors() {
 316         assert !this.isDeleted() : this;
 317         return nodeClass.getSuccessorIterable(this);
 318     }
 319 
 320     /**
 321      * Returns an {@link Iterable iterable} which can be used to traverse all successor edge
 322      * positions of this node.
 323      *
 324      * @return an {@link Iterable iterable} for all successor edge positoins.
 325      */
 326     public Iterable<Position> successorPositions() {
 327         return nodeClass.getSuccessorEdges().getPositionsIterable(this);
 328     }
 329 
 330     /**
 331      * Gets the maximum number of usages this node has had at any point in time.
 332      */
 333     public int getUsageCount() {
 334         if (usage0 == null) {
 335             return 0;
 336         }
 337         if (usage1 == null) {
 338             return 1;
 339         }
 340         return INLINE_USAGE_COUNT + extraUsagesCount;
 341     }
 342 
 343     /**
 344      * Gets the list of nodes that use this node (i.e., as an input).
 345      */
 346     public final NodeIterable<Node> usages() {
 347         return new NodeUsageIterable(this);
 348     }
 349 
 350     /**
 351      * Checks whether this node has no usages.
 352      */
 353     public final boolean hasNoUsages() {
 354         return this.usage0 == null;
 355     }
 356 
 357     /**
 358      * Checks whether this node has usages.
 359      */
 360     public final boolean hasUsages() {
 361         return this.usage0 != null;
 362     }
 363 
 364     /**
 365      * Checks whether this node has more than one usages.
 366      */
 367     public final boolean hasMoreThanOneUsage() {
 368         return this.usage1 != null;
 369     }
 370 
 371     /**
 372      * Checks whether this node has exactly one usgae.
 373      */
 374     public final boolean hasExactlyOneUsage() {
 375         return hasUsages() && !hasMoreThanOneUsage();
 376     }
 377 
 378     /**
 379      * Adds a given node to this node's {@linkplain #usages() usages}.
 380      *
 381      * @param node the node to add
 382      */
 383     void addUsage(Node node) {
 384         incUsageModCount();
 385         if (usage0 == null) {
 386             usage0 = node;
 387         } else if (usage1 == null) {
 388             usage1 = node;
 389         } else {
 390             int length = extraUsages.length;
 391             if (length == 0) {
 392                 extraUsages = new Node[4];
 393             } else if (extraUsagesCount == length) {
 394                 Node[] newExtraUsages = new Node[length * 2 + 1];
 395                 System.arraycopy(extraUsages, 0, newExtraUsages, 0, length);
 396                 extraUsages = newExtraUsages;
 397             }
 398             extraUsages[extraUsagesCount++] = node;
 399         }
 400     }
 401 
 402     private void movUsageFromEndTo(int destIndex) {
 403         if (destIndex >= INLINE_USAGE_COUNT) {
 404             movUsageFromEndToExtraUsages(destIndex - INLINE_USAGE_COUNT);
 405         } else if (destIndex == 1) {
 406             movUsageFromEndToIndexOne();
 407         } else {
 408             assert destIndex == 0;
 409             movUsageFromEndToIndexZero();
 410         }
 411     }
 412 
 413     private void movUsageFromEndToExtraUsages(int destExtraIndex) {
 414         this.extraUsagesCount--;
 415         Node n = extraUsages[extraUsagesCount];
 416         extraUsages[destExtraIndex] = n;
 417         extraUsages[extraUsagesCount] = null;
 418     }
 419 
 420     private void movUsageFromEndToIndexZero() {
 421         if (extraUsagesCount > 0) {
 422             this.extraUsagesCount--;
 423             usage0 = extraUsages[extraUsagesCount];
 424             extraUsages[extraUsagesCount] = null;
 425         } else if (usage1 != null) {
 426             usage0 = usage1;
 427             usage1 = null;
 428         } else {
 429             usage0 = null;
 430         }
 431     }
 432 
 433     private void movUsageFromEndToIndexOne() {
 434         if (extraUsagesCount > 0) {
 435             this.extraUsagesCount--;
 436             usage1 = extraUsages[extraUsagesCount];
 437             extraUsages[extraUsagesCount] = null;
 438         } else {
 439             assert usage1 != null;
 440             usage1 = null;
 441         }
 442     }
 443 
 444     /**
 445      * Removes a given node from this node's {@linkplain #usages() usages}.
 446      *
 447      * @param node the node to remove
 448      * @return whether or not {@code usage} was in the usage list
 449      */
 450     public boolean removeUsage(Node node) {
 451         assert node != null;
 452         // For large graphs, usage removal is performance critical.
 453         // Furthermore, it is critical that this method maintains the invariant that the usage list
 454         // has no null element preceding a non-null element.
 455         incUsageModCount();
 456         if (usage0 == node) {
 457             movUsageFromEndToIndexZero();
 458             return true;
 459         }
 460         if (usage1 == node) {
 461             movUsageFromEndToIndexOne();
 462             return true;
 463         }
 464         for (int i = this.extraUsagesCount - 1; i >= 0; i--) {
 465             if (extraUsages[i] == node) {
 466                 movUsageFromEndToExtraUsages(i);
 467                 return true;
 468             }
 469         }
 470         return false;
 471     }
 472 
 473     public final Node predecessor() {
 474         return predecessor;
 475     }
 476 
 477     public final int modCount() {
 478         if (isModificationCountsEnabled() && graph != null) {
 479             return graph.modCount(this);
 480         }
 481         return 0;
 482     }
 483 
 484     final void incModCount() {
 485         if (isModificationCountsEnabled() && graph != null) {
 486             graph.incModCount(this);
 487         }
 488     }
 489 
 490     final int usageModCount() {
 491         if (isModificationCountsEnabled() && graph != null) {
 492             return graph.usageModCount(this);
 493         }
 494         return 0;
 495     }
 496 
 497     final void incUsageModCount() {
 498         if (isModificationCountsEnabled() && graph != null) {
 499             graph.incUsageModCount(this);
 500         }
 501     }
 502 
 503     public final boolean isDeleted() {
 504         return id <= DELETED_ID_START;
 505     }
 506 
 507     public final boolean isAlive() {
 508         return id >= ALIVE_ID_START;
 509     }
 510 
 511     public final boolean isUnregistered() {
 512         return id == INITIAL_ID;
 513     }
 514 
 515     /**
 516      * Updates the usages sets of the given nodes after an input slot is changed from
 517      * {@code oldInput} to {@code newInput} by removing this node from {@code oldInput}'s usages and
 518      * adds this node to {@code newInput}'s usages.
 519      */
 520     protected void updateUsages(Node oldInput, Node newInput) {
 521         assert isAlive() && (newInput == null || newInput.isAlive()) : "adding " + newInput + " to " + this + " instead of " + oldInput;
 522         if (oldInput != newInput) {
 523             if (oldInput != null) {
 524                 boolean result = removeThisFromUsages(oldInput);
 525                 assert assertTrue(result, "not found in usages, old input: %s", oldInput);
 526             }
 527             maybeNotifyInputChanged(this);
 528             if (newInput != null) {
 529                 newInput.addUsage(this);
 530             }
 531             if (oldInput != null && oldInput.hasNoUsages()) {
 532                 maybeNotifyZeroUsages(oldInput);
 533             }
 534         }
 535     }
 536 
 537     protected void updateUsagesInterface(NodeInterface oldInput, NodeInterface newInput) {
 538         updateUsages(oldInput == null ? null : oldInput.asNode(), newInput == null ? null : newInput.asNode());
 539     }
 540 
 541     /**
 542      * Updates the predecessor of the given nodes after a successor slot is changed from
 543      * oldSuccessor to newSuccessor: removes this node from oldSuccessor's predecessors and adds
 544      * this node to newSuccessor's predecessors.
 545      */
 546     protected void updatePredecessor(Node oldSuccessor, Node newSuccessor) {
 547         assert isAlive() && (newSuccessor == null || newSuccessor.isAlive()) || newSuccessor == null && !isAlive() : "adding " + newSuccessor + " to " + this + " instead of " + oldSuccessor;
 548         assert graph == null || !graph.isFrozen();
 549         if (oldSuccessor != newSuccessor) {
 550             if (oldSuccessor != null) {
 551                 assert assertTrue(newSuccessor == null || oldSuccessor.predecessor == this, "wrong predecessor in old successor (%s): %s, should be %s", oldSuccessor, oldSuccessor.predecessor, this);
 552                 oldSuccessor.predecessor = null;
 553             }
 554             if (newSuccessor != null) {
 555                 assert assertTrue(newSuccessor.predecessor == null, "unexpected non-null predecessor in new successor (%s): %s, this=%s", newSuccessor, newSuccessor.predecessor, this);
 556                 newSuccessor.predecessor = this;
 557             }
 558         }
 559     }
 560 
 561     void initialize(Graph newGraph) {
 562         assert assertTrue(id == INITIAL_ID, "unexpected id: %d", id);
 563         this.graph = newGraph;
 564         newGraph.register(this);
 565         NodeClass<? extends Node> nc = nodeClass;
 566         nc.registerAtInputsAsUsage(this);
 567         nc.registerAtSuccessorsAsPredecessor(this);
 568     }
 569 
 570     /**
 571      * The position of the bytecode that generated this node.
 572      */
 573     NodeSourcePosition sourcePosition;
 574 
 575     /**
 576      * Gets the source position information for this node or null if it doesn't exist.
 577      */
 578 
 579     public NodeSourcePosition getNodeSourcePosition() {
 580         return sourcePosition;
 581     }
 582 
 583     /**
 584      * Set the source position to {@code sourcePosition}.
 585      */
 586     public void setNodeSourcePosition(NodeSourcePosition sourcePosition) {
 587         this.sourcePosition = sourcePosition;
 588         if (sourcePosition != null && graph != null && !graph.seenNodeSourcePosition) {
 589             graph.seenNodeSourcePosition = true;
 590         }
 591     }
 592 
 593     public DebugCloseable withNodeSourcePosition() {
 594         return graph.withNodeSourcePosition(this);
 595     }
 596 
 597     public final NodeClass<? extends Node> getNodeClass() {
 598         return nodeClass;
 599     }
 600 
 601     public boolean isAllowedUsageType(InputType type) {
 602         if (type == InputType.Value) {
 603             return false;
 604         }
 605         return getNodeClass().getAllowedUsageTypes().contains(type);
 606     }
 607 
 608     private boolean checkReplaceWith(Node other) {
 609         if (graph != null && graph.isFrozen()) {
 610             fail("cannot modify frozen graph");
 611         }
 612         if (other == this) {
 613             fail("cannot replace a node with itself");
 614         }
 615         if (isDeleted()) {
 616             fail("cannot replace deleted node");
 617         }
 618         if (other != null && other.isDeleted()) {
 619             fail("cannot replace with deleted node %s", other);
 620         }
 621         return true;
 622     }
 623 
 624     public final void replaceAtUsages(Node other) {
 625         replaceAtAllUsages(other, (Node) null);
 626     }
 627 
 628     public final void replaceAtUsages(Node other, Predicate<Node> filter) {
 629         replaceAtUsages(other, filter, null);
 630     }
 631 
 632     public final void replaceAtUsagesAndDelete(Node other) {
 633         replaceAtUsages(other, null, this);
 634         safeDelete();
 635     }
 636 
 637     public final void replaceAtUsagesAndDelete(Node other, Predicate<Node> filter) {
 638         replaceAtUsages(other, filter, this);
 639         safeDelete();
 640     }
 641 
 642     protected void replaceAtUsages(Node other, Predicate<Node> filter, Node toBeDeleted) {
 643         if (filter == null) {
 644             replaceAtAllUsages(other, toBeDeleted);
 645         } else {
 646             replaceAtMatchingUsages(other, filter, toBeDeleted);
 647         }
 648     }
 649 
 650     protected void replaceAtAllUsages(Node other, Node toBeDeleted) {
 651         checkReplaceWith(other);
 652         if (usage0 == null) {
 653             return;
 654         }
 655         replaceAtUsage(other, toBeDeleted, usage0);
 656         usage0 = null;
 657 
 658         if (usage1 == null) {
 659             return;
 660         }
 661         replaceAtUsage(other, toBeDeleted, usage1);
 662         usage1 = null;
 663 
 664         if (extraUsagesCount <= 0) {
 665             return;
 666         }
 667         for (int i = 0; i < extraUsagesCount; i++) {
 668             Node usage = extraUsages[i];
 669             replaceAtUsage(other, toBeDeleted, usage);
 670         }
 671         this.extraUsages = NO_NODES;
 672         this.extraUsagesCount = 0;
 673     }
 674 
 675     private void replaceAtUsage(Node other, Node toBeDeleted, Node usage) {
 676         boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other);
 677         assert assertTrue(result, "not found in inputs, usage: %s", usage);
 678         /*
 679          * Don't notify for nodes which are about to be deleted.
 680          */
 681         if (toBeDeleted == null || usage != toBeDeleted) {
 682             maybeNotifyInputChanged(usage);
 683         }
 684         if (other != null) {
 685             other.addUsage(usage);
 686         }
 687     }
 688 
 689     private void replaceAtMatchingUsages(Node other, Predicate<Node> filter, Node toBeDeleted) {
 690         if (filter == null) {
 691             fail("filter cannot be null");
 692         }
 693         checkReplaceWith(other);
 694         int i = 0;
 695         while (i < this.getUsageCount()) {
 696             Node usage = this.getUsageAt(i);
 697             if (filter.test(usage)) {
 698                 replaceAtUsage(other, toBeDeleted, usage);
 699                 this.movUsageFromEndTo(i);
 700             } else {
 701                 ++i;
 702             }
 703         }
 704     }
 705 
 706     public Node getUsageAt(int index) {
 707         if (index == 0) {
 708             return this.usage0;
 709         } else if (index == 1) {
 710             return this.usage1;
 711         } else {
 712             return this.extraUsages[index - INLINE_USAGE_COUNT];
 713         }
 714     }
 715 
 716     public void replaceAtMatchingUsages(Node other, NodePredicate usagePredicate) {
 717         checkReplaceWith(other);
 718         replaceAtMatchingUsages(other, usagePredicate, null);
 719     }
 720 
 721     public void replaceAtUsages(InputType type, Node other) {
 722         checkReplaceWith(other);
 723         for (Node usage : usages().snapshot()) {
 724             for (Position pos : usage.inputPositions()) {
 725                 if (pos.getInputType() == type && pos.get(usage) == this) {
 726                     pos.set(usage, other);
 727                 }
 728             }
 729         }
 730     }
 731 
 732     private void maybeNotifyInputChanged(Node node) {
 733         if (graph != null) {
 734             assert !graph.isFrozen();
 735             NodeEventListener listener = graph.nodeEventListener;
 736             if (listener != null) {
 737                 listener.inputChanged(node);
 738             }
 739         }
 740     }
 741 
 742     public void maybeNotifyZeroUsages(Node node) {
 743         if (graph != null) {
 744             assert !graph.isFrozen();
 745             NodeEventListener listener = graph.nodeEventListener;
 746             if (listener != null && node.isAlive()) {
 747                 listener.usagesDroppedToZero(node);
 748             }
 749         }
 750     }
 751 
 752     public void replaceAtPredecessor(Node other) {
 753         checkReplaceWith(other);
 754         if (predecessor != null) {
 755             if (!predecessor.getNodeClass().replaceFirstSuccessor(predecessor, this, other)) {
 756                 fail("not found in successors, predecessor: %s", predecessor);
 757             }
 758             predecessor.updatePredecessor(this, other);
 759         }
 760     }
 761 
 762     public void replaceAndDelete(Node other) {
 763         checkReplaceWith(other);
 764         if (other == null) {
 765             fail("cannot replace with null");
 766         }
 767         if (this.hasUsages()) {
 768             replaceAtUsages(other);
 769         }
 770         replaceAtPredecessor(other);
 771         this.safeDelete();
 772     }
 773 
 774     public void replaceFirstSuccessor(Node oldSuccessor, Node newSuccessor) {
 775         if (nodeClass.replaceFirstSuccessor(this, oldSuccessor, newSuccessor)) {
 776             updatePredecessor(oldSuccessor, newSuccessor);
 777         }
 778     }
 779 
 780     public void replaceFirstInput(Node oldInput, Node newInput) {
 781         if (nodeClass.replaceFirstInput(this, oldInput, newInput)) {
 782             updateUsages(oldInput, newInput);
 783         }
 784     }
 785 
 786     public void clearInputs() {
 787         assert assertFalse(isDeleted(), "cannot clear inputs of deleted node");
 788         getNodeClass().unregisterAtInputsAsUsage(this);
 789     }
 790 
 791     boolean removeThisFromUsages(Node n) {
 792         return n.removeUsage(this);
 793     }
 794 
 795     public void clearSuccessors() {
 796         assert assertFalse(isDeleted(), "cannot clear successors of deleted node");
 797         getNodeClass().unregisterAtSuccessorsAsPredecessor(this);
 798     }
 799 
 800     private boolean checkDeletion() {
 801         assertTrue(isAlive(), "must be alive");
 802         assertTrue(hasNoUsages(), "cannot delete node %s because of usages: %s", this, usages());
 803         assertTrue(predecessor == null, "cannot delete node %s because of predecessor: %s", this, predecessor);
 804         return true;
 805     }
 806 
 807     /**
 808      * Removes this node from its graph. This node must have no {@linkplain Node#usages() usages}
 809      * and no {@linkplain #predecessor() predecessor}.
 810      */
 811     public void safeDelete() {
 812         assert checkDeletion();
 813         this.clearInputs();
 814         this.clearSuccessors();
 815         markDeleted();
 816     }
 817 
 818     public void markDeleted() {
 819         graph.unregister(this);
 820         id = DELETED_ID_START - id;
 821         assert isDeleted();
 822     }
 823 
 824     public final Node copyWithInputs() {
 825         return copyWithInputs(true);
 826     }
 827 
 828     public final Node copyWithInputs(boolean insertIntoGraph) {
 829         Node newNode = clone(insertIntoGraph ? graph : null, WithOnlyInputEdges);
 830         if (insertIntoGraph) {
 831             for (Node input : inputs()) {
 832                 input.addUsage(newNode);
 833             }
 834         }
 835         return newNode;
 836     }
 837 
 838     /**
 839      * Must be overridden by subclasses that implement {@link Simplifiable}. The implementation in
 840      * {@link Node} exists to obviate the need to cast a node before invoking
 841      * {@link Simplifiable#simplify(SimplifierTool)}.
 842      *
 843      * @param tool
 844      */
 845     public void simplify(SimplifierTool tool) {
 846         throw new UnsupportedOperationException();
 847     }
 848 
 849     /**
 850      * @param newNode the result of cloning this node or {@link Unsafe#allocateInstance(Class) raw
 851      *            allocating} a copy of this node
 852      * @param type the type of edges to process
 853      * @param edgesToCopy if {@code type} is in this set, the edges are copied otherwise they are
 854      *            cleared
 855      */
 856     private void copyOrClearEdgesForClone(Node newNode, Edges.Type type, EnumSet<Edges.Type> edgesToCopy) {
 857         if (edgesToCopy.contains(type)) {
 858             getNodeClass().getEdges(type).copy(this, newNode);
 859         } else {
 860             // The direct edges are already null
 861             getNodeClass().getEdges(type).initializeLists(newNode, this);
 862         }
 863     }
 864 
 865     public static final EnumSet<Edges.Type> WithNoEdges = EnumSet.noneOf(Edges.Type.class);
 866     public static final EnumSet<Edges.Type> WithAllEdges = EnumSet.allOf(Edges.Type.class);
 867     public static final EnumSet<Edges.Type> WithOnlyInputEdges = EnumSet.of(Inputs);
 868     public static final EnumSet<Edges.Type> WithOnlySucessorEdges = EnumSet.of(Successors);
 869 
 870     /**
 871      * Makes a copy of this node in(to) a given graph.
 872      *
 873      * @param into the graph in which the copy will be registered (which may be this node's graph)
 874      *            or null if the copy should not be registered in a graph
 875      * @param edgesToCopy specifies the edges to be copied. The edges not specified in this set are
 876      *            initialized to their default value (i.e., {@code null} for a direct edge, an empty
 877      *            list for an edge list)
 878      * @return the copy of this node
 879      */
 880     final Node clone(Graph into, EnumSet<Edges.Type> edgesToCopy) {
 881         final NodeClass<? extends Node> nodeClassTmp = getNodeClass();
 882         boolean useIntoLeafNodeCache = false;
 883         if (into != null) {
 884             if (nodeClassTmp.valueNumberable() && nodeClassTmp.isLeafNode()) {
 885                 useIntoLeafNodeCache = true;
 886                 Node otherNode = into.findNodeInCache(this);
 887                 if (otherNode != null) {
 888                     return otherNode;
 889                 }
 890             }
 891         }
 892 
 893         Node newNode = null;
 894         try {
 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         } catch (Exception e) {
 901             throw new GraalGraphError(e).addContext(this);
 902         }
 903         newNode.graph = into;
 904         newNode.id = INITIAL_ID;
 905         if (into != null) {
 906             into.register(newNode);
 907         }
 908         newNode.extraUsages = NO_NODES;
 909 
 910         if (into != null && useIntoLeafNodeCache) {
 911             into.putNodeIntoCache(newNode);
 912         }
 913         if (graph != null && into != null && sourcePosition != null) {
 914             newNode.setNodeSourcePosition(sourcePosition);
 915         }
 916         newNode.afterClone(this);
 917         return newNode;
 918     }
 919 
 920     protected void afterClone(@SuppressWarnings("unused") Node other) {
 921     }
 922 
 923     protected boolean verifyInputs() {
 924         for (Position pos : inputPositions()) {
 925             Node input = pos.get(this);
 926             if (input == null) {
 927                 assertTrue(pos.isInputOptional(), "non-optional input %s cannot be null in %s (fix nullness or use @OptionalInput)", pos, this);
 928             } else {
 929                 assertFalse(input.isDeleted(), "input was deleted %s", input);
 930                 assertTrue(input.isAlive(), "input is not alive yet, i.e., it was not yet added to the graph");
 931                 assertTrue(pos.getInputType() == InputType.Unchecked || input.isAllowedUsageType(pos.getInputType()), "invalid usage type %s %s", input, pos.getInputType());
 932             }
 933         }
 934         return true;
 935     }
 936 
 937     public boolean verify() {
 938         assertTrue(isAlive(), "cannot verify inactive nodes (id=%d)", id);
 939         assertTrue(graph() != null, "null graph");
 940         verifyInputs();
 941         if (Options.VerifyGraalGraphEdges.getValue(getOptions())) {
 942             verifyEdges();
 943         }
 944         return true;
 945     }
 946 
 947     /**
 948      * Perform expensive verification of inputs, usages, predecessors and successors.
 949      *
 950      * @return true
 951      */
 952     public boolean verifyEdges() {
 953         for (Node input : inputs()) {
 954             assertTrue(input == null || input.usages().contains(this), "missing usage of %s in input %s", this, input);
 955         }
 956 
 957         for (Node successor : successors()) {
 958             assertTrue(successor.predecessor() == this, "missing predecessor in %s (actual: %s)", successor, successor.predecessor());
 959             assertTrue(successor.graph() == graph(), "mismatching graph in successor %s", successor);
 960         }
 961         for (Node usage : usages()) {
 962             assertFalse(usage.isDeleted(), "usage %s must never be deleted", usage);
 963             assertTrue(usage.inputs().contains(this), "missing input in usage %s", usage);
 964             boolean foundThis = false;
 965             for (Position pos : usage.inputPositions()) {
 966                 if (pos.get(usage) == this) {
 967                     foundThis = true;
 968                     if (pos.getInputType() != InputType.Unchecked) {
 969                         assertTrue(isAllowedUsageType(pos.getInputType()), "invalid input of type %s from %s to %s (%s)", pos.getInputType(), usage, this, pos.getName());
 970                     }
 971                 }
 972             }
 973             assertTrue(foundThis, "missing input in usage %s", usage);
 974         }
 975 
 976         if (predecessor != null) {
 977             assertFalse(predecessor.isDeleted(), "predecessor %s must never be deleted", predecessor);
 978             assertTrue(predecessor.successors().contains(this), "missing successor in predecessor %s", predecessor);
 979         }
 980         return true;
 981     }
 982 
 983     public boolean assertTrue(boolean condition, String message, Object... args) {
 984         if (condition) {
 985             return true;
 986         } else {
 987             throw fail(message, args);
 988         }
 989     }
 990 
 991     public boolean assertFalse(boolean condition, String message, Object... args) {
 992         if (condition) {
 993             throw fail(message, args);
 994         } else {
 995             return true;
 996         }
 997     }
 998 
 999     protected VerificationError fail(String message, Object... args) throws GraalGraphError {
1000         throw new VerificationError(message, args).addContext(this);
1001     }
1002 
1003     public Iterable<? extends Node> cfgPredecessors() {
1004         if (predecessor == null) {
1005             return Collections.emptySet();
1006         } else {
1007             return Collections.singleton(predecessor);
1008         }
1009     }
1010 
1011     /**
1012      * Returns an iterator that will provide all control-flow successors of this node. Normally this
1013      * will be the contents of all fields annotated with {@link Successor}, but some node classes
1014      * (like EndNode) may return different nodes.
1015      */
1016     public Iterable<? extends Node> cfgSuccessors() {
1017         return successors();
1018     }
1019 
1020     /**
1021      * Nodes using their {@link #id} as the hash code. This works very well when nodes of the same
1022      * graph are stored in sets. It can give bad behavior when storing nodes of different graphs in
1023      * the same set.
1024      */
1025     @Override
1026     public final int hashCode() {
1027         assert !this.isUnregistered() : "node not yet constructed";
1028         if (this.isDeleted()) {
1029             return -id + DELETED_ID_START;
1030         }
1031         return id;
1032     }
1033 
1034     /**
1035      * Do not overwrite the equality test of a node in subclasses. Equality tests must rely solely
1036      * on identity.
1037      */
1038 
1039     /**
1040      * Provides a {@link Map} of properties of this node for use in debugging (e.g., to view in the
1041      * ideal graph visualizer).
1042      */
1043     public final Map<Object, Object> getDebugProperties() {
1044         return getDebugProperties(new HashMap<>());
1045     }
1046 
1047     /**
1048      * Fills a {@link Map} with properties of this node for use in debugging (e.g., to view in the
1049      * ideal graph visualizer). Subclasses overriding this method should also fill the map using
1050      * their superclass.
1051      *
1052      * @param map
1053      */
1054     public Map<Object, Object> getDebugProperties(Map<Object, Object> map) {
1055         Fields properties = getNodeClass().getData();
1056         for (int i = 0; i < properties.getCount(); i++) {
1057             map.put(properties.getName(i), properties.get(this, i));
1058         }
1059         NodeSourcePosition pos = getNodeSourcePosition();
1060         if (pos != null) {
1061             map.put("nodeSourcePosition", pos);
1062         }
1063         return map;
1064     }
1065 
1066     /**
1067      * This method is a shortcut for {@link #toString(Verbosity)} with {@link Verbosity#Short}.
1068      */
1069     @Override
1070     public final String toString() {
1071         return toString(Verbosity.Short);
1072     }
1073 
1074     /**
1075      * Creates a String representation for this node with a given {@link Verbosity}.
1076      */
1077     public String toString(Verbosity verbosity) {
1078         switch (verbosity) {
1079             case Id:
1080                 return Integer.toString(id);
1081             case Name:
1082                 return getNodeClass().shortName();
1083             case Short:
1084                 return toString(Verbosity.Id) + "|" + toString(Verbosity.Name);
1085             case Long:
1086                 return toString(Verbosity.Short);
1087             case Debugger:
1088             case All: {
1089                 StringBuilder str = new StringBuilder();
1090                 str.append(toString(Verbosity.Short)).append(" { ");
1091                 for (Map.Entry<Object, Object> entry : getDebugProperties().entrySet()) {
1092                     str.append(entry.getKey()).append("=").append(entry.getValue()).append(", ");
1093                 }
1094                 str.append(" }");
1095                 return str.toString();
1096             }
1097             default:
1098                 throw new RuntimeException("unknown verbosity: " + verbosity);
1099         }
1100     }
1101 
1102     @Deprecated
1103     public int getId() {
1104         return id;
1105     }
1106 
1107     @Override
1108     public void formatTo(Formatter formatter, int flags, int width, int precision) {
1109         if ((flags & FormattableFlags.ALTERNATE) == FormattableFlags.ALTERNATE) {
1110             formatter.format("%s", toString(Verbosity.Id));
1111         } else if ((flags & FormattableFlags.UPPERCASE) == FormattableFlags.UPPERCASE) {
1112             // Use All here since Long is only slightly longer than Short.
1113             formatter.format("%s", toString(Verbosity.All));
1114         } else {
1115             formatter.format("%s", toString(Verbosity.Short));
1116         }
1117 
1118         boolean neighborsAlternate = ((flags & FormattableFlags.LEFT_JUSTIFY) == FormattableFlags.LEFT_JUSTIFY);
1119         int neighborsFlags = (neighborsAlternate ? FormattableFlags.ALTERNATE | FormattableFlags.LEFT_JUSTIFY : 0);
1120         if (width > 0) {
1121             if (this.predecessor != null) {
1122                 formatter.format(" pred={");
1123                 this.predecessor.formatTo(formatter, neighborsFlags, width - 1, 0);
1124                 formatter.format("}");
1125             }
1126 
1127             for (Position position : this.inputPositions()) {
1128                 Node input = position.get(this);
1129                 if (input != null) {
1130                     formatter.format(" ");
1131                     formatter.format(position.getName());
1132                     formatter.format("={");
1133                     input.formatTo(formatter, neighborsFlags, width - 1, 0);
1134                     formatter.format("}");
1135                 }
1136             }
1137         }
1138 
1139         if (precision > 0) {
1140             if (!hasNoUsages()) {
1141                 formatter.format(" usages={");
1142                 int z = 0;
1143                 for (Node usage : usages()) {
1144                     if (z != 0) {
1145                         formatter.format(", ");
1146                     }
1147                     usage.formatTo(formatter, neighborsFlags, 0, precision - 1);
1148                     ++z;
1149                 }
1150                 formatter.format("}");
1151             }
1152 
1153             for (Position position : this.successorPositions()) {
1154                 Node successor = position.get(this);
1155                 if (successor != null) {
1156                     formatter.format(" ");
1157                     formatter.format(position.getName());
1158                     formatter.format("={");
1159                     successor.formatTo(formatter, neighborsFlags, 0, precision - 1);
1160                     formatter.format("}");
1161                 }
1162             }
1163         }
1164     }
1165 
1166     /**
1167      * Determines if this node's {@link NodeClass#getData() data} fields are equal to the data
1168      * fields of another node of the same type. Primitive fields are compared by value and
1169      * non-primitive fields are compared by {@link Objects#equals(Object, Object)}.
1170      *
1171      * The result of this method undefined if {@code other.getClass() != this.getClass()}.
1172      *
1173      * @param other a node of exactly the same type as this node
1174      * @return true if the data fields of this object and {@code other} are equal
1175      */
1176     public boolean valueEquals(Node other) {
1177         return getNodeClass().dataEquals(this, other);
1178     }
1179 
1180     public final void pushInputs(NodeStack stack) {
1181         getNodeClass().pushInputs(this, stack);
1182     }
1183 
1184     public NodeSize estimatedNodeSize() {
1185         return nodeClass.size();
1186     }
1187 
1188     public NodeCycles estimatedNodeCycles() {
1189         return nodeClass.cycles();
1190     }
1191 
1192 }