Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/ssa/bailout.dart |
| =================================================================== |
| --- sdk/lib/_internal/compiler/implementation/ssa/bailout.dart (revision 17833) |
| +++ sdk/lib/_internal/compiler/implementation/ssa/bailout.dart (working copy) |
| @@ -394,9 +394,9 @@ |
| class SsaBailoutPropagator extends HBaseVisitor { |
| final Compiler compiler; |
| final List<HBasicBlock> blocks; |
| - final List<HLabeledBlockInformation> labeledBlockInformations; |
| - final Set<HInstruction> generateAtUseSite; |
| SubGraph subGraph; |
| + HBlockInformation currentBlockInformation; |
| + |
| /** |
| * Max number of arguments to the bailout (not counting the state). |
| */ |
| @@ -434,11 +434,8 @@ |
| * version. |
| */ |
| - SsaBailoutPropagator(this.compiler, |
| - this.generateAtUseSite, |
| - this.variableNames) |
| + SsaBailoutPropagator(this.compiler, this.variableNames) |
| : blocks = <HBasicBlock>[], |
| - labeledBlockInformations = <HLabeledBlockInformation>[], |
| bailoutArity = 0, |
| parameterNames = new Map<String, int>(); |
| @@ -451,18 +448,56 @@ |
| } |
| } |
| + bool handleBlockFlow(HBlockFlow blockFlow) { |
|
kasperl
2013/01/31 01:50:06
This method deserves a comment.
ngeoffray
2013/01/31 08:17:24
Done.
|
| + HBlockInformation body = blockFlow.body; |
| + |
| + // We reach here again when starting to visit a subgraph. Just |
| + // return to visiting the block. |
| + if (currentBlockInformation == body) return false; |
| + |
| + HBlockInformation oldInformation = currentBlockInformation; |
| + if (body is HLabeledBlockInformation) { |
| + currentBlockInformation = body; |
| + HLabeledBlockInformation info = body; |
| + visitStatements(info.body, newFlow: true); |
| + } else if (body is HLoopBlockInformation) { |
| + currentBlockInformation = body; |
| + HLoopBlockInformation info = body; |
| + if (info.initializer != null) { |
| + visitExpression(info.initializer); |
| + } |
| + blocks.addLast(info.loopHeader); |
| + if (!info.isDoWhile()) { |
| + visitExpression(info.condition); |
| + } |
| + visitStatements(info.body, newFlow: false); |
| + if (info.isDoWhile()) { |
| + visitExpression(info.condition); |
| + } |
| + if (info.updates != null) { |
| + visitExpression(info.updates); |
| + } |
| + blocks.removeLast(); |
| + } else { |
| + assert(body is! HTryBlockInformation); |
| + assert(body is! HSwitchBlockInformation); |
| + // [HIfBlockInformation] is handled by visitIf. |
| + return false; |
| + } |
| + |
| + currentBlockInformation = oldInformation; |
| + if (blockFlow.continuation != null) { |
| + visitBasicBlock(blockFlow.continuation); |
| + } |
| + return true; |
| + } |
| + |
| void visitBasicBlock(HBasicBlock block) { |
| // Abort traversal if we are leaving the currently active sub-graph. |
| if (!subGraph.contains(block)) return; |
| - if (block.isLoopHeader()) { |
| - blocks.addLast(block); |
| - } else if (block.isLabeledBlock() |
| - && (blocks.isEmpty || !identical(blocks.last, block))) { |
| - HLabeledBlockInformation info = block.blockFlow.body; |
| - visitStatements(info.body); |
| - return; |
| - } |
| + HBlockFlow blockFlow = block.blockFlow; |
| + if (blockFlow != null && handleBlockFlow(blockFlow)) return; |
| HInstruction instruction = block.first; |
| while (instruction != null) { |
| @@ -471,35 +506,30 @@ |
| } |
| } |
| - void visitStatements(HStatementInformation info) { |
| - assert(info is HSubGraphBlockInformation); |
| - HSubGraphBlockInformation graph = info; |
| - visitSubGraph(graph.subGraph); |
| + void visitExpression(HSubExpressionBlockInformation info) { |
| + visitSubGraph(info.subExpression); |
| } |
| + void visitStatements(HSubGraphBlockInformation info, {bool newFlow}) { |
|
kasperl
2013/01/31 01:50:06
Add a comment that explains how this works and wha
ngeoffray
2013/01/31 08:17:24
Done.
|
| + SubGraph graph = info.subGraph; |
| + if (newFlow) blocks.addLast(graph.start); |
| + visitSubGraph(graph); |
| + if (newFlow) blocks.removeLast(); |
| + } |
| + |
| void visitSubGraph(SubGraph graph) { |
| SubGraph oldSubGraph = subGraph; |
| subGraph = graph; |
| - HBasicBlock start = graph.start; |
| - blocks.addLast(start); |
| - visitBasicBlock(start); |
| - blocks.removeLast(); |
| + visitBasicBlock(graph.start); |
| subGraph = oldSubGraph; |
| - |
| - if (start.isLabeledBlock()) { |
| - HBasicBlock continuation = start.blockFlow.continuation; |
| - if (continuation != null) { |
| - visitBasicBlock(continuation); |
| - } |
| - } |
| } |
| void visitIf(HIf instruction) { |
| int preVisitedBlocks = 0; |
| HIfBlockInformation info = instruction.blockInformation.body; |
| - visitStatements(info.thenGraph); |
| + visitStatements(info.thenGraph, newFlow: true); |
| preVisitedBlocks++; |
| - visitStatements(info.elseGraph); |
| + visitStatements(info.elseGraph, newFlow: true); |
| preVisitedBlocks++; |
| HBasicBlock joinBlock = instruction.joinBlock; |
| @@ -532,25 +562,10 @@ |
| } |
| void visitLoopBranch(HLoopBranch branch) { |
| - HBasicBlock branchBlock = branch.block; |
| - List<HBasicBlock> dominated = branchBlock.dominatedBlocks; |
| // For a do-while loop, the body has already been visited. |
| if (!branch.isDoWhile()) { |
| - visitBasicBlock(dominated[0]); |
| + visitBasicBlock(branch.block.dominatedBlocks[0]); |
| } |
| - blocks.removeLast(); |
| - |
| - // If the branch does not dominate the code after the loop, the |
| - // dominator will visit it. |
| - if (!identical(branchBlock.successors[1].dominator, branchBlock)) return; |
| - |
| - visitBasicBlock(branchBlock.successors[1]); |
| - // With labeled breaks we can have more dominated blocks. |
| - if (dominated.length >= 3) { |
| - for (int i = 2; i < dominated.length; i++) { |
| - visitBasicBlock(dominated[i]); |
| - } |
| - } |
| } |
| visitBailoutTarget(HBailoutTarget target) { |