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