| 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) {
|
|
|