Index: sdk/lib/_internal/compiler/implementation/ssa/builder.dart |
=================================================================== |
--- sdk/lib/_internal/compiler/implementation/ssa/builder.dart (revision 14518) |
+++ sdk/lib/_internal/compiler/implementation/ssa/builder.dart (working copy) |
@@ -926,6 +926,7 @@ |
List<InliningState> inliningStack; |
Element returnElement; |
DartType returnType; |
+ bool inTryStatement = false; |
void disableMethodInterception() { |
assert(methodInterceptionEnabled); |
@@ -3444,6 +3445,14 @@ |
dup(); |
} |
+ void handleInTryStatement() { |
+ if (!inTryStatement) return; |
+ HBasicBlock block = close(new HExitTry()); |
+ HBasicBlock newBlock = graph.addNewBlock(); |
+ block.addSuccessor(newBlock); |
+ open(newBlock); |
+ } |
+ |
visitReturn(Return node) { |
if (identical(node.getBeginToken().stringValue, 'native')) { |
native.handleSsaNative(this, node.expression); |
@@ -3461,6 +3470,9 @@ |
value = pop(); |
value = potentiallyCheckType(value, returnType); |
} |
+ |
+ handleInTryStatement(); |
+ |
if (!inliningStack.isEmpty) { |
localsHandler.updateLocal(returnElement, value); |
} else { |
@@ -3551,6 +3563,7 @@ |
visitBreakStatement(BreakStatement node) { |
assert(!isAborted()); |
+ handleInTryStatement(); |
TargetElement target = elements[node]; |
assert(target != null); |
JumpHandler handler = jumpTargets[target]; |
@@ -3564,6 +3577,7 @@ |
} |
visitContinueStatement(ContinueStatement node) { |
+ handleInTryStatement(); |
TargetElement target = elements[node]; |
assert(target != null); |
JumpHandler handler = jumpTargets[target]; |
@@ -4103,6 +4117,8 @@ |
HBasicBlock enterBlock = openNewBlock(); |
HTry tryInstruction = new HTry(); |
close(tryInstruction); |
+ bool oldInTryStatement = inTryStatement; |
+ inTryStatement = true; |
HBasicBlock startTryBlock; |
HBasicBlock endTryBlock; |
@@ -4217,6 +4233,22 @@ |
HBasicBlock exitBlock = graph.addNewBlock(); |
addOptionalSuccessor(b1, b2) { if (b2 != null) b1.addSuccessor(b2); } |
+ addExitTrySuccessor(successor) { |
+ if (successor == null) return; |
+ // Iterate over all blocks created inside this try/catch, and |
+ // attach successor information to blocks that end with |
+ // [HExitTry]. |
+ for (int i = startTryBlock.id; i < successor.id; i++) { |
+ HBasicBlock block = graph.blocks[i]; |
+ var last = block.last; |
+ if (last is HExitTry) { |
+ block.addSuccessor(successor); |
+ } else if (last is HTry) { |
+ // Skip all blocks inside this nested try/catch. |
+ i = last.joinBlock.id; |
+ } |
+ } |
+ } |
// Setup all successors. The entry block that contains the [HTry] |
// has 1) the body, 2) the catch, 3) the finally, and 4) the exit |
@@ -4244,6 +4276,12 @@ |
if (endFinallyBlock != null) { |
endFinallyBlock.addSuccessor(exitBlock); |
} |
+ |
+ // If a block inside try/catch aborts (eg with a return statement), |
+ // we explicitely mark this block a predecessor of the catch |
+ // block and the finally block. |
+ addExitTrySuccessor(startCatchBlock); |
+ addExitTrySuccessor(startFinallyBlock); |
// Use the locals handler not altered by the catch and finally |
// blocks. |
@@ -4256,6 +4294,7 @@ |
wrapStatementGraph(catchGraph), |
wrapStatementGraph(finallyGraph)), |
exitBlock); |
+ inTryStatement = oldInTryStatement; |
} |
visitScriptTag(ScriptTag node) { |