< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java

Print this page




 497         return node;
 498     }
 499 
 500     /**
 501      * The type of events sent to a {@link NodeEventListener}.
 502      */
 503     public enum NodeEvent {
 504         /**
 505          * A node's input is changed.
 506          */
 507         INPUT_CHANGED,
 508 
 509         /**
 510          * A node's {@linkplain Node#usages() usages} count dropped to zero.
 511          */
 512         ZERO_USAGES,
 513 
 514         /**
 515          * A node was added to a graph.
 516          */
 517         NODE_ADDED;





 518     }
 519 
 520     /**
 521      * Client interested in one or more node related events.
 522      */
 523     public interface NodeEventListener {
 524 
 525         /**
 526          * Default handler for events.



 527          *
 528          * @param e an event
 529          * @param node the node related to {@code e}
 530          */
 531         default void event(NodeEvent e, Node node) {















 532         }
 533 
 534         /**
 535          * Notifies this listener of a change in a node's inputs.









 536          *
 537          * @param node a node who has had one of its inputs changed
 538          */
 539         default void inputChanged(Node node) {
 540             event(NodeEvent.INPUT_CHANGED, node);
 541         }
 542 
 543         /**
 544          * Notifies this listener of a node becoming unused.
 545          *
 546          * @param node a node whose {@link Node#usages()} just became empty
 547          */
 548         default void usagesDroppedToZero(Node node) {
 549             event(NodeEvent.ZERO_USAGES, node);
 550         }
 551 
 552         /**
 553          * Notifies this listener of an added node.
 554          *
 555          * @param node a node that was just added to the graph
 556          */
 557         default void nodeAdded(Node node) {
 558             event(NodeEvent.NODE_ADDED, node);







 559         }
 560     }
 561 
 562     /**
 563      * Registers a given {@link NodeEventListener} with the enclosing graph until this object is
 564      * {@linkplain #close() closed}.
 565      */
 566     public final class NodeEventScope implements AutoCloseable {
 567         NodeEventScope(NodeEventListener listener) {
 568             if (nodeEventListener == null) {
 569                 nodeEventListener = listener;
 570             } else {
 571                 nodeEventListener = new ChainedNodeEventListener(listener, nodeEventListener);
 572             }
 573         }
 574 
 575         @Override
 576         public void close() {
 577             assert nodeEventListener != null;
 578             if (nodeEventListener instanceof ChainedNodeEventListener) {
 579                 nodeEventListener = ((ChainedNodeEventListener) nodeEventListener).next;
 580             } else {
 581                 nodeEventListener = null;
 582             }
 583         }
 584     }
 585 
 586     private static class ChainedNodeEventListener implements NodeEventListener {
 587 
 588         NodeEventListener head;
 589         NodeEventListener next;
 590 
 591         ChainedNodeEventListener(NodeEventListener head, NodeEventListener next) {
 592             this.head = head;
 593             this.next = next;
 594         }
 595 
 596         @Override
 597         public void nodeAdded(Node node) {
 598             head.nodeAdded(node);
 599             next.nodeAdded(node);
 600         }
 601 
 602         @Override
 603         public void inputChanged(Node node) {
 604             head.inputChanged(node);
 605             next.inputChanged(node);
 606         }
 607 
 608         @Override
 609         public void usagesDroppedToZero(Node node) {
 610             head.usagesDroppedToZero(node);
 611             next.usagesDroppedToZero(node);












 612         }
 613     }
 614 
 615     /**
 616      * Registers a given {@link NodeEventListener} with this graph. This should be used in
 617      * conjunction with try-with-resources statement as follows:
 618      *
 619      * <pre>
 620      * try (NodeEventScope nes = graph.trackNodeEvents(listener)) {
 621      *     // make changes to the graph
 622      * }
 623      * </pre>
 624      */
 625     public NodeEventScope trackNodeEvents(NodeEventListener listener) {
 626         return new NodeEventScope(listener);
 627     }
 628 
 629     /**
 630      * Looks for a node <i>similar</i> to {@code node} and returns it if found. Otherwise
 631      * {@code node} is added to this graph and returned.


1006         return new NodeWorkList.IterativeNodeWorkList(this, fill, iterationLimitPerNode);
1007     }
1008 
1009     void register(Node node) {
1010         assert !isFrozen();
1011         assert node.id() == Node.INITIAL_ID;
1012         if (nodes.length == nodesSize) {
1013             grow();
1014         }
1015         int id = nodesSize++;
1016         nodes[id] = node;
1017         node.id = id;
1018         if (currentNodeSourcePosition != null) {
1019             node.setNodeSourcePosition(currentNodeSourcePosition);
1020         }
1021         seenNodeSourcePosition = seenNodeSourcePosition || node.getNodeSourcePosition() != null;
1022 
1023         updateNodeCaches(node);
1024 
1025         if (nodeEventListener != null) {
1026             nodeEventListener.nodeAdded(node);
1027         }
1028         afterRegister(node);
1029     }
1030 
1031     private void grow() {
1032         Node[] newNodes = new Node[(nodesSize * 2) + 1];
1033         System.arraycopy(nodes, 0, newNodes, 0, nodesSize);
1034         nodes = newNodes;
1035     }
1036 
1037     @SuppressWarnings("unused")
1038     protected void afterRegister(Node node) {
1039 
1040     }
1041 
1042     @SuppressWarnings("unused")
1043     private void postDeserialization() {
1044         recomputeIterableNodeLists();
1045     }
1046 


1067                 iterableNodesLast.add(null);
1068             }
1069             Node prev = iterableNodesLast.get(nodeClassId);
1070             if (prev != null) {
1071                 prev.typeCacheNext = node;
1072             } else {
1073                 iterableNodesFirst.set(nodeClassId, node);
1074             }
1075             iterableNodesLast.set(nodeClassId, node);
1076         }
1077     }
1078 
1079     void unregister(Node node) {
1080         assert !isFrozen();
1081         assert !node.isDeleted() : node;
1082         if (node.getNodeClass().isLeafNode() && node.getNodeClass().valueNumberable()) {
1083             removeNodeFromCache(node);
1084         }
1085         nodes[node.id] = null;
1086         nodesDeletedSinceLastCompression++;




1087 
1088         // nodes aren't removed from the type cache here - they will be removed during iteration
1089     }
1090 
1091     public boolean verify() {
1092         if (Options.VerifyGraalGraphs.getValue(options)) {
1093             for (Node node : getNodes()) {
1094                 try {
1095                     try {
1096                         assert node.verify();
1097                     } catch (AssertionError t) {
1098                         throw new GraalError(t);
1099                     } catch (RuntimeException t) {
1100                         throw new GraalError(t);
1101                     }
1102                 } catch (GraalError e) {
1103                     throw GraalGraphError.transformAndAddContext(e, node).addContext(this);
1104                 }
1105             }
1106         }




 497         return node;
 498     }
 499 
 500     /**
 501      * The type of events sent to a {@link NodeEventListener}.
 502      */
 503     public enum NodeEvent {
 504         /**
 505          * A node's input is changed.
 506          */
 507         INPUT_CHANGED,
 508 
 509         /**
 510          * A node's {@linkplain Node#usages() usages} count dropped to zero.
 511          */
 512         ZERO_USAGES,
 513 
 514         /**
 515          * A node was added to a graph.
 516          */
 517         NODE_ADDED,
 518 
 519         /**
 520          * A node was removed from the graph.
 521          */
 522         NODE_REMOVED;
 523     }
 524 
 525     /**
 526      * Client interested in one or more node related events.
 527      */
 528     public abstract static class NodeEventListener {
 529 
 530         /**
 531          * A method called when a change event occurs.
 532          *
 533          * This method dispatches the event to user-defined triggers. The methods that change the
 534          * graph (typically in Graph and Node) must call this method to dispatch the event.
 535          *
 536          * @param e an event
 537          * @param node the node related to {@code e}
 538          */
 539         final void event(NodeEvent e, Node node) {
 540             switch (e) {
 541                 case INPUT_CHANGED:
 542                     inputChanged(node);
 543                     break;
 544                 case ZERO_USAGES:
 545                     usagesDroppedToZero(node);
 546                     break;
 547                 case NODE_ADDED:
 548                     nodeAdded(node);
 549                     break;
 550                 case NODE_REMOVED:
 551                     nodeRemoved(node);
 552                     break;
 553             }
 554             changed(e, node);
 555         }
 556 
 557         /**
 558          * Notifies this listener about any change event in the graph.
 559          *
 560          * @param e an event
 561          * @param node the node related to {@code e}
 562          */
 563         public void changed(NodeEvent e, Node node) {
 564         }
 565 
 566         /**
 567          * Notifies this listener about a change in a node's inputs.
 568          *
 569          * @param node a node who has had one of its inputs changed
 570          */
 571         public void inputChanged(Node node) {

 572         }
 573 
 574         /**
 575          * Notifies this listener of a node becoming unused.
 576          *
 577          * @param node a node whose {@link Node#usages()} just became empty
 578          */
 579         public void usagesDroppedToZero(Node node) {

 580         }
 581 
 582         /**
 583          * Notifies this listener of an added node.
 584          *
 585          * @param node a node that was just added to the graph
 586          */
 587         public void nodeAdded(Node node) {
 588         }
 589 
 590         /**
 591          * Notifies this listener of a removed node.
 592          *
 593          * @param node
 594          */
 595         public void nodeRemoved(Node node) {
 596         }
 597     }
 598 
 599     /**
 600      * Registers a given {@link NodeEventListener} with the enclosing graph until this object is
 601      * {@linkplain #close() closed}.
 602      */
 603     public final class NodeEventScope implements AutoCloseable {
 604         NodeEventScope(NodeEventListener listener) {
 605             if (nodeEventListener == null) {
 606                 nodeEventListener = listener;
 607             } else {
 608                 nodeEventListener = new ChainedNodeEventListener(listener, nodeEventListener);
 609             }
 610         }
 611 
 612         @Override
 613         public void close() {
 614             assert nodeEventListener != null;
 615             if (nodeEventListener instanceof ChainedNodeEventListener) {
 616                 nodeEventListener = ((ChainedNodeEventListener) nodeEventListener).next;
 617             } else {
 618                 nodeEventListener = null;
 619             }
 620         }
 621     }
 622 
 623     private static class ChainedNodeEventListener extends NodeEventListener {
 624 
 625         NodeEventListener head;
 626         NodeEventListener next;
 627 
 628         ChainedNodeEventListener(NodeEventListener head, NodeEventListener next) {
 629             this.head = head;
 630             this.next = next;
 631         }
 632 
 633         @Override
 634         public void nodeAdded(Node node) {
 635             head.event(NodeEvent.NODE_ADDED, node);
 636             next.event(NodeEvent.NODE_ADDED, node);
 637         }
 638 
 639         @Override
 640         public void inputChanged(Node node) {
 641             head.event(NodeEvent.INPUT_CHANGED, node);
 642             next.event(NodeEvent.INPUT_CHANGED, node);
 643         }
 644 
 645         @Override
 646         public void usagesDroppedToZero(Node node) {
 647             head.event(NodeEvent.ZERO_USAGES, node);
 648             next.event(NodeEvent.ZERO_USAGES, node);
 649         }
 650 
 651         @Override
 652         public void nodeRemoved(Node node) {
 653             head.event(NodeEvent.NODE_REMOVED, node);
 654             next.event(NodeEvent.NODE_REMOVED, node);
 655         }
 656 
 657         @Override
 658         public void changed(NodeEvent e, Node node) {
 659             head.event(e, node);
 660             next.event(e, node);
 661         }
 662     }
 663 
 664     /**
 665      * Registers a given {@link NodeEventListener} with this graph. This should be used in
 666      * conjunction with try-with-resources statement as follows:
 667      *
 668      * <pre>
 669      * try (NodeEventScope nes = graph.trackNodeEvents(listener)) {
 670      *     // make changes to the graph
 671      * }
 672      * </pre>
 673      */
 674     public NodeEventScope trackNodeEvents(NodeEventListener listener) {
 675         return new NodeEventScope(listener);
 676     }
 677 
 678     /**
 679      * Looks for a node <i>similar</i> to {@code node} and returns it if found. Otherwise
 680      * {@code node} is added to this graph and returned.


1055         return new NodeWorkList.IterativeNodeWorkList(this, fill, iterationLimitPerNode);
1056     }
1057 
1058     void register(Node node) {
1059         assert !isFrozen();
1060         assert node.id() == Node.INITIAL_ID;
1061         if (nodes.length == nodesSize) {
1062             grow();
1063         }
1064         int id = nodesSize++;
1065         nodes[id] = node;
1066         node.id = id;
1067         if (currentNodeSourcePosition != null) {
1068             node.setNodeSourcePosition(currentNodeSourcePosition);
1069         }
1070         seenNodeSourcePosition = seenNodeSourcePosition || node.getNodeSourcePosition() != null;
1071 
1072         updateNodeCaches(node);
1073 
1074         if (nodeEventListener != null) {
1075             nodeEventListener.event(NodeEvent.NODE_ADDED, node);
1076         }
1077         afterRegister(node);
1078     }
1079 
1080     private void grow() {
1081         Node[] newNodes = new Node[(nodesSize * 2) + 1];
1082         System.arraycopy(nodes, 0, newNodes, 0, nodesSize);
1083         nodes = newNodes;
1084     }
1085 
1086     @SuppressWarnings("unused")
1087     protected void afterRegister(Node node) {
1088 
1089     }
1090 
1091     @SuppressWarnings("unused")
1092     private void postDeserialization() {
1093         recomputeIterableNodeLists();
1094     }
1095 


1116                 iterableNodesLast.add(null);
1117             }
1118             Node prev = iterableNodesLast.get(nodeClassId);
1119             if (prev != null) {
1120                 prev.typeCacheNext = node;
1121             } else {
1122                 iterableNodesFirst.set(nodeClassId, node);
1123             }
1124             iterableNodesLast.set(nodeClassId, node);
1125         }
1126     }
1127 
1128     void unregister(Node node) {
1129         assert !isFrozen();
1130         assert !node.isDeleted() : node;
1131         if (node.getNodeClass().isLeafNode() && node.getNodeClass().valueNumberable()) {
1132             removeNodeFromCache(node);
1133         }
1134         nodes[node.id] = null;
1135         nodesDeletedSinceLastCompression++;
1136 
1137         if (nodeEventListener != null) {
1138             nodeEventListener.event(NodeEvent.NODE_ADDED, node);
1139         }
1140 
1141         // nodes aren't removed from the type cache here - they will be removed during iteration
1142     }
1143 
1144     public boolean verify() {
1145         if (Options.VerifyGraalGraphs.getValue(options)) {
1146             for (Node node : getNodes()) {
1147                 try {
1148                     try {
1149                         assert node.verify();
1150                     } catch (AssertionError t) {
1151                         throw new GraalError(t);
1152                     } catch (RuntimeException t) {
1153                         throw new GraalError(t);
1154                     }
1155                 } catch (GraalError e) {
1156                     throw GraalGraphError.transformAndAddContext(e, node).addContext(this);
1157                 }
1158             }
1159         }


< prev index next >