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
24
25 package org.graalvm.compiler.core.phases;
26
27 import jdk.internal.vm.compiler.collections.EconomicSet;
28 import jdk.internal.vm.compiler.collections.Equivalence;
29 import org.graalvm.compiler.debug.DebugContext;
30 import org.graalvm.compiler.graph.Graph.NodeEvent;
31 import org.graalvm.compiler.graph.Graph.NodeEventScope;
32 import org.graalvm.compiler.graph.Node;
33 import org.graalvm.compiler.nodes.LogicConstantNode;
34 import org.graalvm.compiler.nodes.StructuredGraph;
35 import org.graalvm.compiler.phases.BasePhase;
36 import org.graalvm.compiler.phases.PhaseSuite;
37 import org.graalvm.compiler.phases.common.util.HashSetNodeEventListener;
38 import org.graalvm.compiler.phases.tiers.PhaseContext;
39
40 /**
41 * A utility phase for detecting when a phase would change the graph and reporting extra information
42 * about the effects. The phase is first run on a copy of the graph and if a change in that graph is
43 * detected then it's rerun on the original graph inside a new debug scope under
44 * GraphChangeMonitoringPhase. The message argument can be used to distinguish between the same
45 * phase run at different points.
46 *
47 * @param <C>
48 */
49 public class GraphChangeMonitoringPhase<C extends PhaseContext> extends PhaseSuite<C> {
50
51 private final String message;
52
53 public GraphChangeMonitoringPhase(String message, BasePhase<C> phase) {
54 super();
55 this.message = message;
56 appendPhase(phase);
57 }
58
59 public GraphChangeMonitoringPhase(String message) {
60 super();
61 this.message = message;
62 }
63
64 @Override
65 @SuppressWarnings("try")
66 protected void run(StructuredGraph graph, C context) {
67 /*
68 * Phase may add nodes but not end up using them so ignore additions. Nodes going dead and
69 * having their inputs change are the main interesting differences.
70 */
71 HashSetNodeEventListener listener = new HashSetNodeEventListener().exclude(NodeEvent.NODE_ADDED);
72 StructuredGraph graphCopy = (StructuredGraph) graph.copy(graph.getDebug());
73 DebugContext debug = graph.getDebug();
74 try (NodeEventScope s = graphCopy.trackNodeEvents(listener)) {
75 try (DebugContext.Scope s2 = debug.sandbox("WithoutMonitoring", null)) {
76 super.run(graphCopy, context);
77 } catch (Throwable t) {
78 debug.handle(t);
79 }
80 }
81
82 EconomicSet<Node> filteredNodes = EconomicSet.create(Equivalence.IDENTITY);
83 for (Node n : listener.getNodes()) {
84 if (n instanceof LogicConstantNode) {
85 // Ignore LogicConstantNode since those are sometimes created and deleted as part of
86 // running a phase.
87 } else {
88 filteredNodes.add(n);
89 }
90 }
91 if (!filteredNodes.isEmpty()) {
92 /* rerun it on the real graph in a new Debug scope so Dump and Log can find it. */
93 listener = new HashSetNodeEventListener();
94 try (NodeEventScope s = graph.trackNodeEvents(listener)) {
95 try (DebugContext.Scope s2 = debug.scope("WithGraphChangeMonitoring")) {
96 if (debug.isDumpEnabled(DebugContext.DETAILED_LEVEL)) {
97 debug.dump(DebugContext.DETAILED_LEVEL, graph, "*** Before phase %s", getName());
98 }
99 super.run(graph, context);
100 if (debug.isDumpEnabled(DebugContext.DETAILED_LEVEL)) {
101 debug.dump(DebugContext.DETAILED_LEVEL, graph, "*** After phase %s %s", getName(), filteredNodes);
102 }
103 debug.log("*** %s %s %s\n", message, graph, filteredNodes);
104 }
105 }
106 } else {
107 // Go ahead and run it normally even though it should have no effect
108 super.run(graph, context);
109 }
110 }
111 }
|
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
24
25 package org.graalvm.compiler.core.phases;
26
27 import jdk.internal.vm.compiler.collections.EconomicSet;
28 import jdk.internal.vm.compiler.collections.Equivalence;
29 import org.graalvm.compiler.debug.DebugContext;
30 import org.graalvm.compiler.graph.Graph.NodeEvent;
31 import org.graalvm.compiler.graph.Graph.NodeEventScope;
32 import org.graalvm.compiler.graph.Node;
33 import org.graalvm.compiler.nodes.LogicConstantNode;
34 import org.graalvm.compiler.nodes.StructuredGraph;
35 import org.graalvm.compiler.phases.BasePhase;
36 import org.graalvm.compiler.phases.PhaseSuite;
37 import org.graalvm.compiler.phases.common.util.EconomicSetNodeEventListener;
38 import org.graalvm.compiler.phases.tiers.PhaseContext;
39
40 /**
41 * A utility phase for detecting when a phase would change the graph and reporting extra information
42 * about the effects. The phase is first run on a copy of the graph and if a change in that graph is
43 * detected then it's rerun on the original graph inside a new debug scope under
44 * GraphChangeMonitoringPhase. The message argument can be used to distinguish between the same
45 * phase run at different points.
46 *
47 * @param <C>
48 */
49 public class GraphChangeMonitoringPhase<C extends PhaseContext> extends PhaseSuite<C> {
50
51 private final String message;
52
53 public GraphChangeMonitoringPhase(String message, BasePhase<C> phase) {
54 super();
55 this.message = message;
56 appendPhase(phase);
57 }
58
59 public GraphChangeMonitoringPhase(String message) {
60 super();
61 this.message = message;
62 }
63
64 @Override
65 @SuppressWarnings("try")
66 protected void run(StructuredGraph graph, C context) {
67 /*
68 * Phase may add nodes but not end up using them so ignore additions. Nodes going dead and
69 * having their inputs change are the main interesting differences.
70 */
71 EconomicSetNodeEventListener listener = new EconomicSetNodeEventListener().exclude(NodeEvent.NODE_ADDED);
72 StructuredGraph graphCopy = (StructuredGraph) graph.copy(graph.getDebug());
73 DebugContext debug = graph.getDebug();
74 try (NodeEventScope s = graphCopy.trackNodeEvents(listener)) {
75 try (DebugContext.Scope s2 = debug.sandbox("WithoutMonitoring", null)) {
76 super.run(graphCopy, context);
77 } catch (Throwable t) {
78 debug.handle(t);
79 }
80 }
81
82 EconomicSet<Node> filteredNodes = EconomicSet.create(Equivalence.IDENTITY);
83 for (Node n : listener.getNodes()) {
84 if (n instanceof LogicConstantNode) {
85 // Ignore LogicConstantNode since those are sometimes created and deleted as part of
86 // running a phase.
87 } else {
88 filteredNodes.add(n);
89 }
90 }
91 if (!filteredNodes.isEmpty()) {
92 /* rerun it on the real graph in a new Debug scope so Dump and Log can find it. */
93 listener = new EconomicSetNodeEventListener();
94 try (NodeEventScope s = graph.trackNodeEvents(listener)) {
95 try (DebugContext.Scope s2 = debug.scope("WithGraphChangeMonitoring")) {
96 if (debug.isDumpEnabled(DebugContext.DETAILED_LEVEL)) {
97 debug.dump(DebugContext.DETAILED_LEVEL, graph, "*** Before phase %s", getName());
98 }
99 super.run(graph, context);
100 if (debug.isDumpEnabled(DebugContext.DETAILED_LEVEL)) {
101 debug.dump(DebugContext.DETAILED_LEVEL, graph, "*** After phase %s %s", getName(), filteredNodes);
102 }
103 debug.log("*** %s %s %s\n", message, graph, filteredNodes);
104 }
105 }
106 } else {
107 // Go ahead and run it normally even though it should have no effect
108 super.run(graph, context);
109 }
110 }
111 }
|