# HG changeset patch # User Lukas Stadler # Date 1339579814 -7200 # Node ID 8f529640e43046df6fcdb1df92d45a872893e557 # Parent 300a1207f2146342ed1f727ce6b78e0317ae4a7e fix to SchedulePhase: correctly handle outer frame states that take a phi from the merge of the inner frame state as an input diff -r 300a1207f214 -r 8f529640e430 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/schedule/SchedulePhase.java --- 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)); }