changeset 5583:8f529640e430

fix to SchedulePhase: correctly handle outer frame states that take a phi from the merge of the inner frame state as an input
author Lukas Stadler <lukas.stadler@jku.at>
date Wed, 13 Jun 2012 11:30:14 +0200
parents 300a1207f214
children 2f8712779899 728cf399b18d
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/schedule/SchedulePhase.java
diffstat 1 files changed, 17 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/schedule/SchedulePhase.java	Wed Jun 13 11:10:57 2012 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/schedule/SchedulePhase.java	Wed Jun 13 11:30:14 2012 +0200
@@ -126,7 +126,7 @@
         } else if (GraalOptions.ScheduleOutOfLoops && !(n instanceof VirtualObjectFieldNode) && !(n instanceof VirtualObjectNode)) {
             Block earliestBlock = earliestBlock(n);
             block = scheduleOutOfLoops(n, latestBlock, earliestBlock);
-            assert earliestBlock.dominates(block) : "Graph can not be scheduled : inconsistent for " + n;
+            assert earliestBlock.dominates(block) : "Graph can not be scheduled : inconsistent for " + n + " (" + earliestBlock + " needs to dominate " + block + ")";
         } else {
             block = latestBlock;
         }
@@ -216,8 +216,19 @@
         return result;
     }
 
+    /**
+     * Passes all blocks that a specific usage of a node is in to a given closure.
+     * This is more complex than just taking the usage's block because of of PhiNodes and FrameStates.
+     *
+     * @param node the node that needs to be scheduled
+     * @param usage the usage whose blocks need to be considered
+     * @param closure the closure that will be called for each block
+     */
     private void blocksForUsage(Node node, Node usage, BlockClosure closure) {
+        assert !(node instanceof PhiNode);
         if (usage instanceof PhiNode) {
+            // An input to a PhiNode is used at the end of the predecessor block that corresponds to the PhiNode input.
+            // One PhiNode can use an input multiple times, the closure will be called for each usage.
             PhiNode phi = (PhiNode) usage;
             MergeNode merge = phi.merge();
             Block mergeBlock = cfg.getNodeToBlock().get(merge);
@@ -235,7 +246,10 @@
                     closure.apply(mergeBlock.getPredecessors().get(i));
                 }
             }
-        } else if (usage instanceof FrameState && ((FrameState) usage).block() != null) {
+        } else if (usage instanceof FrameState && ((FrameState) usage).block() != null && !(node instanceof FrameState)) {
+            // If a FrameState belongs to a MergeNode then it's inputs will be placed at the common dominator of all EndNodes.
+            // BUT only if the input is neither a PhiNode (this method is never called for PhiNodes) nor a FrameState.
+            // A FrameState input is an outer FrameState. They should be placed into the same block as the usage, which is handled by the else.
             MergeNode merge = ((FrameState) usage).block();
             Block block = null;
             for (Node pred : merge.cfgPredecessors()) {
@@ -243,6 +257,7 @@
             }
             closure.apply(block);
         } else {
+            // All other types of usages: Just put the input into the same block as the usage.
             assignBlockToNode(usage);
             closure.apply(cfg.getNodeToBlock().get(usage));
         }