| Index: pkg/kernel/lib/transformations/continuation.dart
|
| diff --git a/pkg/kernel/lib/transformations/continuation.dart b/pkg/kernel/lib/transformations/continuation.dart
|
| index 185edc50eb6ae1742b2cba8d4f2a7fdd6e57bad3..7d6228e20c3dad0b6c3ecf56d366da6fa5eb49b3 100644
|
| --- a/pkg/kernel/lib/transformations/continuation.dart
|
| +++ b/pkg/kernel/lib/transformations/continuation.dart
|
| @@ -50,19 +50,22 @@ class RecursiveContinuationRewriter extends Transformer {
|
| abstract class ContinuationRewriterBase extends RecursiveContinuationRewriter {
|
| final FunctionNode enclosingFunction;
|
|
|
| - int currentTryDepth; // Nesting depth for try-blocks.
|
| + int currentTryDepth = 0; // Nesting depth for try-blocks.
|
| int currentCatchDepth = 0; // Nesting depth for catch-blocks.
|
| - int capturedTryDepth = 0; // Deepest yield point within a try-block.
|
| - int capturedCatchDepth = 0; // Deepest yield point within a catch-block.
|
|
|
| - ContinuationRewriterBase(HelperNodes helper, this.enclosingFunction,
|
| - {this.currentTryDepth: 0})
|
| + // For both, try-catch and try-finally, the VM needs to have saved-try-context
|
| + // and exception/stacktrace available (both need the correct context when
|
| + // entering catch/finally blocks and finally needs exception/stacktrace for
|
| + // rethrow).
|
| + int capturedDepth = 0; // Deepest yield point within try/catch-blocks.
|
| +
|
| + ContinuationRewriterBase(HelperNodes helper, this.enclosingFunction)
|
| : super(helper);
|
|
|
| Statement createContinuationPoint([Expression value]) {
|
| if (value == null) value = new NullLiteral();
|
| - capturedTryDepth = math.max(capturedTryDepth, currentTryDepth);
|
| - capturedCatchDepth = math.max(capturedCatchDepth, currentCatchDepth);
|
| + capturedDepth =
|
| + math.max(capturedDepth, currentTryDepth + currentCatchDepth);
|
| return new YieldStatement(value, isNative: true);
|
| }
|
|
|
| @@ -74,9 +77,9 @@ abstract class ContinuationRewriterBase extends RecursiveContinuationRewriter {
|
| currentTryDepth--;
|
| }
|
|
|
| - currentCatchDepth++;
|
| + ++currentCatchDepth;
|
| transformList(node.catches, this, node);
|
| - currentCatchDepth--;
|
| + --currentCatchDepth;
|
| return node;
|
| }
|
|
|
| @@ -95,11 +98,11 @@ abstract class ContinuationRewriterBase extends RecursiveContinuationRewriter {
|
| }
|
|
|
| Iterable<VariableDeclaration> createCapturedTryVariables() =>
|
| - new Iterable.generate(capturedTryDepth,
|
| + new Iterable.generate(capturedDepth,
|
| (depth) => new VariableDeclaration(":saved_try_context_var${depth}"));
|
|
|
| Iterable<VariableDeclaration> createCapturedCatchVariables() =>
|
| - new Iterable.generate(capturedCatchDepth).expand((depth) => [
|
| + new Iterable.generate(capturedDepth).expand((depth) => [
|
| new VariableDeclaration(":exception${depth}"),
|
| new VariableDeclaration(":stack_trace${depth}"),
|
| ]);
|
| @@ -189,8 +192,7 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
| ExpressionLifter expressionRewriter;
|
|
|
| AsyncRewriterBase(helper, enclosingFunction)
|
| - // Body is wrapped in the try-catch so initial currentTryDepth is 1.
|
| - : super(helper, enclosingFunction, currentTryDepth: 1) {}
|
| + : super(helper, enclosingFunction) {}
|
|
|
| void setupAsyncContinuations(List<Statement> statements) {
|
| expressionRewriter = new ExpressionLifter(this);
|
| @@ -247,6 +249,7 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
| }
|
|
|
| Statement buildWrappedBody() {
|
| + ++currentCatchDepth;
|
| labeledBody = new LabeledStatement(null);
|
| labeledBody.body = visitDelimited(enclosingFunction.body)
|
| ..parent = labeledBody;
|
| @@ -254,7 +257,9 @@ abstract class AsyncRewriterBase extends ContinuationRewriterBase {
|
| var exceptionVariable = new VariableDeclaration(":exception");
|
| var stackTraceVariable = new VariableDeclaration(":stack_trace");
|
|
|
| - return new TryCatch(buildReturn(labeledBody), <Catch>[
|
| + var body = buildReturn(labeledBody);
|
| + --currentCatchDepth;
|
| + return new TryCatch(body, <Catch>[
|
| new Catch(
|
| exceptionVariable,
|
| new Block(<Statement>[
|
| @@ -684,26 +689,38 @@ class AsyncStarFunctionRewriter extends AsyncRewriterBase {
|
| return enclosingFunction;
|
| }
|
|
|
| + Statement buildWrappedBody() {
|
| + ++currentTryDepth;
|
| + Statement body = super.buildWrappedBody();
|
| + --currentTryDepth;
|
| + var tryFinally =
|
| + new TryFinally(body, new Block(<Statement>[buildFinallyBody()]));
|
| + return tryFinally;
|
| + }
|
| +
|
| Statement buildCatchBody(exceptionVariable, stackTraceVariable) {
|
| return new ExpressionStatement(new MethodInvocation(
|
| new VariableGet(controllerVariable),
|
| - new Name("completeError", helper.asyncLibrary),
|
| + new Name("addError", helper.asyncLibrary),
|
| new Arguments(<Expression>[
|
| new VariableGet(exceptionVariable),
|
| new VariableGet(stackTraceVariable)
|
| ])));
|
| }
|
|
|
| + Statement buildFinallyBody() {
|
| + return new ExpressionStatement(new MethodInvocation(
|
| + new VariableGet(controllerVariable),
|
| + new Name("close", helper.asyncLibrary),
|
| + new Arguments(<Expression>[])));
|
| + }
|
| +
|
| Statement buildReturn(Statement body) {
|
| // Async* functions cannot return a value. The returns from the function
|
| // have been translated into breaks from the labeled body.
|
| return new Block(<Statement>[
|
| body,
|
| - new ExpressionStatement(new MethodInvocation(
|
| - new VariableGet(controllerVariable),
|
| - new Name("close", helper.asyncLibrary),
|
| - new Arguments(<Expression>[]))),
|
| - new ReturnStatement()..fileOffset = enclosingFunction.fileEndOffset
|
| + new ReturnStatement()..fileOffset = enclosingFunction.fileEndOffset,
|
| ]);
|
| }
|
|
|
|
|