Mercurial > hg > graal-compiler
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)); }