Index: lib/compiler/implementation/ssa/builder.dart |
diff --git a/lib/compiler/implementation/ssa/builder.dart b/lib/compiler/implementation/ssa/builder.dart |
index 094733ea990a3aedde02cae5e19edd3bb5a0d615..6feb26e04488f8480af89ef4e21ebf26e0bd48d9 100644 |
--- a/lib/compiler/implementation/ssa/builder.dart |
+++ b/lib/compiler/implementation/ssa/builder.dart |
@@ -817,7 +817,7 @@ class SsaBuilder implements Visitor { |
compiledArguments); |
if (!succeeded) { |
// Non-matching super and redirects are compile-time errors and thus |
- // checked by the resolver. |
+ // checked by the resolver. |
compiler.internalError( |
"Parameters and arguments didn't match for super/redirect call", |
element: constructor); |
@@ -1030,6 +1030,17 @@ class SsaBuilder implements Visitor { |
return current === null; |
} |
+ /** |
+ * Creates a new block, transitions to it from any current block, and |
+ * opens the new block. |
+ */ |
+ HBasicBlock openNewBlock() { |
+ HBasicBlock newBlock = addNewBlock(); |
+ if (!isAborted()) goto(current, newBlock); |
+ open(newBlock); |
+ return newBlock; |
+ } |
+ |
void add(HInstruction instruction) { |
current.add(instruction); |
} |
@@ -1150,16 +1161,14 @@ class SsaBuilder implements Visitor { |
localsHandler.startLoop(loop); |
// The initializer. |
- HBasicBlock initializerBlock = graph.addNewBlock(); |
- goto(current, initializerBlock); |
- open(initializerBlock); |
+ HBasicBlock initializerBlock = openNewBlock(); |
initialize(); |
assert(!isAborted()); |
SubGraph initializerGraph = new SubGraph(initializerBlock, current); |
JumpHandler jumpHandler = beginLoopHeader(loop); |
HBasicBlock conditionBlock = current; |
- HLoopInformation loopInfo = current.loopInformation; |
+ HLoopInformation loopInfo = current.blockInformation; |
// The initializer graph is currently unused due to the way we |
// generate code. |
loopInfo.initializer = initializerGraph; |
@@ -1207,11 +1216,11 @@ class SsaBuilder implements Visitor { |
List<LabelElement> labels = jumpHandler.labels(); |
TargetElement target = elements[loop]; |
if (!labels.isEmpty()) { |
- beginBodyBlock.labeledBlockInformation = |
+ beginBodyBlock.blockInformation = |
new HLabeledBlockInformation(bodyGraph, updateBlock, |
jumpHandler.labels(), isContinue: true); |
} else if (target !== null && target.isContinueTarget) { |
- beginBodyBlock.labeledBlockInformation = |
+ beginBodyBlock.blockInformation = |
new HLabeledBlockInformation.implicit(bodyGraph, updateBlock, |
target, isContinue: true); |
} |
@@ -1280,7 +1289,7 @@ class SsaBuilder implements Visitor { |
LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
localsHandler.startLoop(node); |
JumpHandler jumpHandler = beginLoopHeader(node); |
- HLoopInformation loopInfo = current.loopInformation; |
+ HLoopInformation loopInfo = current.blockInformation; |
HBasicBlock loopEntryBlock = current; |
HBasicBlock bodyEntryBlock = current; |
TargetElement target = elements[node]; |
@@ -1293,9 +1302,7 @@ class SsaBuilder implements Visitor { |
// either handled twice, or it's handled after the labeled block info, |
// both of which generate the wrong code. |
// Using a separate block is just a simple workaround. |
- bodyEntryBlock = graph.addNewBlock(); |
- goto(current, bodyEntryBlock); |
- open(bodyEntryBlock); |
+ bodyEntryBlock = openNewBlock(); |
} |
localsHandler.enterLoopBody(node); |
hackAroundPossiblyAbortingBody(node, () { visit(node.body); }); |
@@ -1317,13 +1324,13 @@ class SsaBuilder implements Visitor { |
SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); |
List<LabelElement> labels = jumpHandler.labels(); |
if (!labels.isEmpty()) { |
- bodyEntryBlock.labeledBlockInformation = |
+ bodyEntryBlock.blockInformation = |
new HLabeledBlockInformation(bodyGraph, |
conditionBlock, |
labels, |
isContinue: true); |
} else { |
- bodyEntryBlock.labeledBlockInformation = |
+ bodyEntryBlock.blockInformation = |
new HLabeledBlockInformation.implicit(bodyGraph, |
conditionBlock, |
target, |
@@ -1395,20 +1402,20 @@ class SsaBuilder implements Visitor { |
} |
visitIf(If node) { |
- visit(node.condition); |
- Function visitElse; |
- if (node.elsePart != null) { |
- visitElse = () { |
- visit(node.elsePart); |
- }; |
- } |
- handleIf(() => visit(node.thenPart), visitElse); |
+ handleIf(() => visit(node.condition), |
+ () => visit(node.thenPart), |
+ node.elsePart != null ? () => visit(node.elsePart) : null); |
} |
- void handleIf(void visitThen(), void visitElse()) { |
+ void handleIf(void visitCondition(), void visitThen(), void visitElse()) { |
+ HBasicBlock conditionStartBlock = openNewBlock(); |
+ visitCondition(); |
+ SubExpression conditionGraph = |
+ new SubExpression(conditionStartBlock, lastOpenedBlock, stack.last()); |
bool hasElse = visitElse != null; |
- HIf condition = new HIf(popBoolified(), hasElse); |
- HBasicBlock conditionBlock = close(condition); |
+ HInstruction condition = popBoolified(); |
+ HIf branch = new HIf(condition, hasElse); |
+ HBasicBlock conditionBlock = close(branch); |
LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
@@ -1456,8 +1463,12 @@ class SsaBuilder implements Visitor { |
localsHandler = thenLocals; |
} |
} |
- condition.blockInformation = |
- new HIfBlockInformation(condition, thenGraph, elseGraph, joinBlock); |
+ HIfBlockInformation info = new HIfBlockInformation(conditionGraph, |
+ thenGraph, |
+ elseGraph, |
+ joinBlock); |
+ conditionStartBlock.blockInformation = info; |
+ branch.blockInformation = info; |
} |
void visitLogicalAndOr(Send node, Operator op) { |
@@ -1477,6 +1488,7 @@ class SsaBuilder implements Visitor { |
// t0 = boolify(x); |
// if (not(t0)) t1 = boolify(y); |
// result = phi(t0, t1); |
+ HBasicBlock leftBlock = openNewBlock(); |
left(); |
HInstruction boolifiedLeft = popBoolified(); |
HInstruction condition; |
@@ -1486,8 +1498,10 @@ class SsaBuilder implements Visitor { |
condition = new HNot(boolifiedLeft); |
add(condition); |
} |
+ SubExpression leftGraph = |
+ new SubExpression(leftBlock, lastOpenedBlock, boolifiedLeft); |
HIf branch = new HIf(condition, false); |
- HBasicBlock leftBlock = close(branch); |
+ leftBlock = close(branch); |
LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
HBasicBlock rightBlock = addNewBlock(); |
@@ -1496,7 +1510,8 @@ class SsaBuilder implements Visitor { |
right(); |
HInstruction boolifiedRight = popBoolified(); |
- SubGraph rightGraph = new SubGraph(rightBlock, current); |
+ SubExpression rightGraph = |
+ new SubExpression(rightBlock, current, boolifiedRight); |
rightBlock = close(new HGoto()); |
HBasicBlock joinBlock = addNewBlock(); |
@@ -1504,8 +1519,10 @@ class SsaBuilder implements Visitor { |
rightBlock.addSuccessor(joinBlock); |
open(joinBlock); |
+ leftGraph.start.blockInformation = |
+ new HAndOrBlockInformation(isAnd, leftGraph, rightGraph, joinBlock); |
branch.blockInformation = |
- new HIfBlockInformation(branch, rightGraph, null, joinBlock); |
+ new HIfBlockInformation(leftGraph, rightGraph, null, joinBlock); |
localsHandler.mergeWith(savedLocals, joinBlock); |
HPhi result = new HPhi.manyInputs(null, |
@@ -2584,9 +2601,7 @@ class SsaBuilder implements Visitor { |
assert(targetElement.isBreakTarget); |
JumpHandler handler = new JumpHandler(this, targetElement); |
// Introduce a new basic block. |
- HBasicBlock entryBlock = graph.addNewBlock(); |
- goto(current, entryBlock); |
- open(entryBlock); |
+ HBasicBlock entryBlock = openNewBlock(); |
hackAroundPossiblyAbortingBody(node, () { visit(body); }); |
SubGraph bodyGraph = new SubGraph(entryBlock, lastOpenedBlock); |
@@ -2606,9 +2621,8 @@ class SsaBuilder implements Visitor { |
if (hasBreak) { |
// There was at least one reachable break, so the label is needed. |
- HLabeledBlockInformation blockInfo = |
+ entryBlock.blockInformation = |
new HLabeledBlockInformation(bodyGraph, joinBlock, handler.labels()); |
- entryBlock.labeledBlockInformation = blockInfo; |
} |
handler.close(); |
} |
@@ -2648,9 +2662,7 @@ class SsaBuilder implements Visitor { |
visitSwitchStatement(SwitchStatement node) { |
work.allowSpeculativeOptimization = false; |
LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
- HBasicBlock startBlock = graph.addNewBlock(); |
- goto(current, startBlock); |
- open(startBlock); |
+ HBasicBlock startBlock = openNewBlock(); |
visit(node.expression); |
HInstruction expression = pop(); |
if (node.cases.isEmpty()) { |
@@ -2690,7 +2702,7 @@ class SsaBuilder implements Visitor { |
// The joinblock is not used. |
joinBlock = null; |
} |
- startBlock.labeledBlockInformation = new HLabeledBlockInformation.implicit( |
+ startBlock.blockInformation = new HLabeledBlockInformation.implicit( |
new SubGraph(startBlock, lastBlock), |
joinBlock, |
elements[node]); |
@@ -2755,19 +2767,19 @@ class SsaBuilder implements Visitor { |
handleLogicalAndOr(left, right, isAnd: false); |
} |
- buildTests(expressions); |
- HInstruction result = popBoolified(); |
- |
if (node.isDefaultCase) { |
- // Don't actually use the condition result. |
- // This must be final case, so don't check for abort. |
+ buildTests(expressions); |
+ // Throw away the test result. We always execute the default case. |
+ pop(); |
visit(node.statements); |
} else { |
- stack.add(result); |
if (cases.tail.isEmpty()) { |
- handleIf(() { visit(node.statements); }, null); |
+ handleIf(() { buildTests(expressions); }, |
+ () { visit(node.statements); }, |
+ null); |
} else { |
- handleIf(() { visitStatementsAndAbort(); }, |
+ handleIf(() { buildTests(expressions); }, |
+ () { visitStatementsAndAbort(); }, |
() { buildSwitchCases(cases.tail, expression); }); |
} |
} |
@@ -2779,9 +2791,7 @@ class SsaBuilder implements Visitor { |
visitTryStatement(TryStatement node) { |
work.allowSpeculativeOptimization = false; |
- HBasicBlock enterBlock = graph.addNewBlock(); |
- close(new HGoto()).addSuccessor(enterBlock); |
- open(enterBlock); |
+ HBasicBlock enterBlock = openNewBlock(); |
HTry tryInstruction = new HTry(); |
List<HBasicBlock> blocks = <HBasicBlock>[]; |
blocks.add(close(tryInstruction)); |
@@ -2849,14 +2859,13 @@ class SsaBuilder implements Visitor { |
close(new HThrow(exception, isRethrow: true)); |
} else { |
CatchBlock newBlock = link.head; |
- pushCondition(newBlock); |
- handleIf(visitThen, visitElse); |
+ handleIf(() { pushCondition(newBlock); }, |
+ visitThen, visitElse); |
} |
} |
CatchBlock firstBlock = link.head; |
- pushCondition(firstBlock); |
- handleIf(visitThen, visitElse); |
+ handleIf(() { pushCondition(firstBlock); }, visitThen, visitElse); |
if (!isAborted()) blocks.add(close(new HGoto())); |
rethrowableException = oldRethrowableException; |
} |
@@ -2911,7 +2920,9 @@ class SsaBuilder implements Visitor { |
/** HACK HACK HACK */ |
void hackAroundPossiblyAbortingBody(Node statement, void body()) { |
- stack.add(graph.addConstantBool(true)); |
+ visitCondition() { |
+ stack.add(graph.addConstantBool(true)); |
+ } |
buildBody() { |
// TODO(lrn): Make sure to take continue into account. |
body(); |
@@ -2919,7 +2930,7 @@ class SsaBuilder implements Visitor { |
compiler.reportWarning(statement, "aborting loop body"); |
} |
} |
- handleIf(buildBody, null); |
+ handleIf(visitCondition, buildBody, null); |
} |
} |