[vm/kernel/bytecode] Support async/async*/sync* in bytecode generator

Change-Id: If164289608322647c0ee5d1f1ed35eb2562b1a03
Reviewed-on: https://dart-review.googlesource.com/56627
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: RĂ©gis Crelier <regis@google.com>
diff --git a/pkg/kernel/lib/transformations/continuation.dart b/pkg/kernel/lib/transformations/continuation.dart
index 05b814d..d3d2c0c 100644
--- a/pkg/kernel/lib/transformations/continuation.dart
+++ b/pkg/kernel/lib/transformations/continuation.dart
@@ -12,6 +12,17 @@
 
 import 'async.dart';
 
+class ContinuationVariables {
+  static const awaitJumpVar = ':await_jump_var';
+  static const awaitContextVar = ':await_ctx_var';
+  static const exceptionParam = ':exception';
+  static const stackTraceParam = ':stack_trace';
+
+  static String savedTryContextVar(int depth) => ':saved_try_context_var$depth';
+  static String exceptionVar(int depth) => ':exception$depth';
+  static String stackTraceVar(int depth) => ':stack_trace$depth';
+}
+
 void transformLibraries(
     CoreTypes coreTypes, List<Library> libraries, bool syncAsync) {
   var helper = new HelperNodes.fromCoreTypes(coreTypes);
@@ -42,10 +53,10 @@
   final bool syncAsync;
 
   final VariableDeclaration asyncJumpVariable = new VariableDeclaration(
-      ":await_jump_var",
+      ContinuationVariables.awaitJumpVar,
       initializer: new IntLiteral(0));
   final VariableDeclaration asyncContextVariable =
-      new VariableDeclaration(":await_ctx_var");
+      new VariableDeclaration(ContinuationVariables.awaitContextVar);
 
   RecursiveContinuationRewriter(this.helper, this.syncAsync);
 
@@ -154,13 +165,15 @@
   }
 
   Iterable<VariableDeclaration> createCapturedTryVariables() =>
-      new Iterable.generate(capturedTryDepth,
-          (depth) => new VariableDeclaration(":saved_try_context_var${depth}"));
+      new Iterable.generate(
+          capturedTryDepth,
+          (depth) => new VariableDeclaration(
+              ContinuationVariables.savedTryContextVar(depth)));
 
   Iterable<VariableDeclaration> createCapturedCatchVariables() =>
       new Iterable.generate(capturedCatchDepth).expand((depth) => [
-            new VariableDeclaration(":exception${depth}"),
-            new VariableDeclaration(":stack_trace${depth}"),
+            new VariableDeclaration(ContinuationVariables.exceptionVar(depth)),
+            new VariableDeclaration(ContinuationVariables.stackTraceVar(depth)),
           ]);
 
   List<VariableDeclaration> variableDeclarations() =>
@@ -293,8 +306,8 @@
     // }
     final parameters = <VariableDeclaration>[
       expressionRewriter.asyncResult,
-      new VariableDeclaration(':exception'),
-      new VariableDeclaration(':stack_trace'),
+      new VariableDeclaration(ContinuationVariables.exceptionParam),
+      new VariableDeclaration(ContinuationVariables.stackTraceParam),
     ];
 
     // Note: SyncYielding functions have no Dart equivalent. Since they are
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index 5851ab6..8c92685 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -63,6 +63,7 @@
   Map<SwitchCase, Label> switchCases;
   Map<TryCatch, TryBlock> tryCatches;
   Map<TryFinally, List<FinallyBlock>> finallyBlocks;
+  List<Label> yieldPoints;
   Map<TreeNode, int> contextLevels;
   List<ClosureBytecode> closures;
   ConstantPool cp;
@@ -326,9 +327,10 @@
     }
   }
 
-  void _genPushContextForVariable(VariableDeclaration variable) {
-    int depth =
-        locals.currentContextLevel - locals.getContextLevelOfVar(variable);
+  void _genPushContextForVariable(VariableDeclaration variable,
+      {int currentContextLevel}) {
+    currentContextLevel ??= locals.currentContextLevel;
+    int depth = currentContextLevel - locals.getContextLevelOfVar(variable);
     assert(depth >= 0);
 
     asm.emitPush(locals.contextVarIndexInFrame);
@@ -346,9 +348,9 @@
     }
   }
 
-  void _genLoadVar(VariableDeclaration v) {
+  void _genLoadVar(VariableDeclaration v, {int currentContextLevel}) {
     if (locals.isCaptured(v)) {
-      _genPushContextForVariable(v);
+      _genPushContextForVariable(v, currentContextLevel: currentContextLevel);
       final int cpIndex = cp.add(
           new ConstantContextOffset.variable(locals.getVarIndexInContext(v)));
       asm.emitLoadFieldTOS(cpIndex);
@@ -447,6 +449,7 @@
     switchCases = <SwitchCase, Label>{};
     tryCatches = <TryCatch, TryBlock>{};
     finallyBlocks = <TryFinally, List<FinallyBlock>>{};
+    yieldPoints = null; // Initialized when entering sync-yielding closure.
     contextLevels = <TreeNode, int>{};
     closures = <ClosureBytecode>[];
     cp = new ConstantPool();
@@ -455,9 +458,10 @@
     savedAssemblers = <BytecodeAssembler>[];
 
     locals.enterScope(node);
+    assert(!locals.isSyncYieldingFrame);
 
     _genPrologue(node, node.function);
-
+    _setupInitialContext(node.function);
     _genEqualsOperatorNullHandling(node);
   }
 
@@ -498,6 +502,7 @@
     switchCases = null;
     tryCatches = null;
     finallyBlocks = null;
+    yieldPoints = null;
     contextLevels = null;
     closures = null;
     cp = null;
@@ -549,6 +554,27 @@
       asm.emitPopLocal(locals.contextVarIndexInFrame);
     }
 
+    if (locals.hasTypeArgsVar && isClosure) {
+      if (function.typeParameters.isNotEmpty) {
+        final int numParentTypeArgs = locals.numParentTypeArguments;
+        asm.emitPush(locals.typeArgsVarIndexInFrame);
+        asm.emitPush(locals.closureVarIndexInFrame);
+        asm.emitLoadFieldTOS(
+            cp.add(new ConstantFieldOffset(closureFunctionTypeArguments)));
+        _genPushInt(numParentTypeArgs);
+        _genPushInt(numParentTypeArgs + function.typeParameters.length);
+        _genStaticCall(prependTypeArguments, new ConstantArgDesc(4), 4);
+        asm.emitPopLocal(locals.typeArgsVarIndexInFrame);
+      } else {
+        asm.emitPush(locals.closureVarIndexInFrame);
+        asm.emitLoadFieldTOS(
+            cp.add(new ConstantFieldOffset(closureFunctionTypeArguments)));
+        asm.emitPopLocal(locals.typeArgsVarIndexInFrame);
+      }
+    }
+  }
+
+  void _setupInitialContext(FunctionNode function) {
     _allocateContextIfNeeded();
 
     if (locals.hasCapturedParameters) {
@@ -559,26 +585,6 @@
       function.positionalParameters.forEach(_copyParamIfCaptured);
       function.namedParameters.forEach(_copyParamIfCaptured);
     }
-
-    if (locals.hasTypeArgsVar && isClosure) {
-      if (function.typeParameters.isNotEmpty) {
-        final int numParentTypeArgs = locals.numParentTypeArguments;
-        asm.emitPush(locals.typeArgsVarIndexInFrame);
-        asm.emitPush(locals.closureVarIndexInFrame);
-        asm.emitLoadFieldTOS(
-            cp.add(new ConstantFieldOffset(closureFunctionTypeArguments)));
-        asm.emitPushConstant(cp.add(new ConstantInt(numParentTypeArgs)));
-        asm.emitPushConstant(cp.add(new ConstantInt(
-            numParentTypeArgs + function.typeParameters.length)));
-        _genStaticCall(prependTypeArguments, new ConstantArgDesc(4), 4);
-        asm.emitPopLocal(locals.typeArgsVarIndexInFrame);
-      } else {
-        asm.emitPush(locals.closureVarIndexInFrame);
-        asm.emitLoadFieldTOS(
-            cp.add(new ConstantFieldOffset(closureFunctionTypeArguments)));
-        asm.emitPopLocal(locals.typeArgsVarIndexInFrame);
-      }
-    }
   }
 
   void _copyParamIfCaptured(VariableDeclaration variable) {
@@ -604,28 +610,94 @@
     _pushAssemblerState();
 
     locals.enterScope(node);
+    List<Label> savedYieldPoints = yieldPoints;
+    yieldPoints = locals.isSyncYieldingFrame ? <Label>[] : null;
 
     final int closureFunctionIndex = cp.add(new ConstantClosureFunction(
         name, new CloneWithoutBody().visitFunctionNode(function)));
 
     _genPrologue(node, function);
+
+    Label continuationSwitchLabel;
+    int continuationSwitchVar;
+    if (locals.isSyncYieldingFrame) {
+      continuationSwitchLabel = new Label();
+      continuationSwitchVar = locals.scratchVarIndexInFrame;
+      _genSyncYieldingPrologue(
+          function, continuationSwitchLabel, continuationSwitchVar);
+    }
+
+    _setupInitialContext(function);
+
+    // TODO(alexmarkov): support --causal_async_stacks.
+
     function.body.accept(this);
 
     // TODO(alexmarkov): figure out when 'return null' should be generated.
     _genPushNull();
     _genReturnTOS();
 
+    if (locals.isSyncYieldingFrame) {
+      _genSyncYieldingEpilogue(
+          function, continuationSwitchLabel, continuationSwitchVar);
+    }
+
     cp.add(new ConstantEndClosureFunctionScope());
 
     locals.leaveScope();
 
     closures.add(new ClosureBytecode(
         closureFunctionIndex, asm.bytecode, asm.exceptionsTable));
+
     _popAssemblerState();
+    yieldPoints = savedYieldPoints;
 
     return closureFunctionIndex;
   }
 
+  void _genSyncYieldingPrologue(FunctionNode function, Label continuationLabel,
+      int switchVarIndexInFrame) {
+    // switch_var = :await_jump_var
+    _genLoadVar(locals.awaitJumpVar);
+    asm.emitStoreLocal(switchVarIndexInFrame);
+
+    // if (switch_var != 0) goto continuationLabel
+    _genPushInt(0);
+    asm.emitIfNeStrictNumTOS();
+    asm.emitJump(continuationLabel);
+
+    // Proceed to normal entry.
+  }
+
+  void _genSyncYieldingEpilogue(FunctionNode function, Label continuationLabel,
+      int switchVarIndexInFrame) {
+    asm.bind(continuationLabel);
+
+    if (yieldPoints.isEmpty) {
+      asm.emitTrap();
+      return;
+    }
+
+    // context = :await_ctx_var
+    _genLoadVar(locals.awaitContextVar);
+    asm.emitPopLocal(locals.contextVarIndexInFrame);
+
+    for (int i = 0; i < yieldPoints.length; i++) {
+      // 0 is reserved for normal entry, yield points are counted from 1.
+      final int index = i + 1;
+
+      // if (switch_var == #index) goto yieldPoints[i]
+      // There is no need to test switch_var for the last yield statement.
+      if (i != yieldPoints.length - 1) {
+        asm.emitPush(switchVarIndexInFrame);
+        _genPushInt(index);
+        asm.emitIfEqStrictNumTOS();
+      }
+
+      asm.emitJump(yieldPoints[i]);
+    }
+  }
+
   void _genAllocateClosureInstance(
       TreeNode node, int closureFunctionIndex, FunctionNode function) {
     // TODO(alexmarkov): Consider adding a bytecode to allocate closure.
@@ -1372,13 +1444,26 @@
     final iteratorTemp = locals.tempIndexInFrame(node);
     asm.emitPopLocal(iteratorTemp);
 
+    final capturedIteratorVar = locals.capturedIteratorVar(node);
+    if (capturedIteratorVar != null) {
+      _genPushContextForVariable(capturedIteratorVar);
+      asm.emitPush(iteratorTemp);
+      _genStoreVar(capturedIteratorVar);
+    }
+
     final Label done = new Label();
     final Label join = new Label();
 
     asm.bind(join);
     asm.emitCheckStack();
 
-    asm.emitPush(iteratorTemp);
+    if (capturedIteratorVar != null) {
+      _genLoadVar(capturedIteratorVar);
+      asm.emitStoreLocal(iteratorTemp);
+    } else {
+      asm.emitPush(iteratorTemp);
+    }
+
     asm.emitInstanceCall1(
         1,
         cp.add(new ConstantICData(InvocationKind.method, new Name(kMoveNext),
@@ -1551,6 +1636,7 @@
 
   int _savedContextVar(TreeNode node) {
     assert(_isTryBlock(node));
+    assert(locals.capturedSavedContextVar(node) == null);
     return locals.tempIndexInFrame(node, tempIndex: 0);
   }
 
@@ -1567,17 +1653,41 @@
   }
 
   _saveContextForTryBlock(TreeNode node) {
-    if (locals.hasContextVar) {
+    if (!locals.hasContextVar) {
+      return;
+    }
+    final capturedSavedContextVar = locals.capturedSavedContextVar(node);
+    if (capturedSavedContextVar != null) {
+      assert(locals.isSyncYieldingFrame);
+      _genPushContextForVariable(capturedSavedContextVar);
+      asm.emitPush(locals.contextVarIndexInFrame);
+      _genStoreVar(capturedSavedContextVar);
+    } else {
       asm.emitPush(locals.contextVarIndexInFrame);
       asm.emitPopLocal(_savedContextVar(node));
     }
   }
 
   _restoreContextForTryBlock(TreeNode node) {
-    if (locals.hasContextVar) {
-      asm.emitPush(_savedContextVar(node));
-      asm.emitPopLocal(locals.contextVarIndexInFrame);
+    if (!locals.hasContextVar) {
+      return;
     }
+    final capturedSavedContextVar = locals.capturedSavedContextVar(node);
+    if (capturedSavedContextVar != null) {
+      // 1. Restore context from closure var.
+      // This context has a context level at frame entry.
+      asm.emitPush(locals.closureVarIndexInFrame);
+      asm.emitLoadFieldTOS(cp.add(new ConstantFieldOffset(closureContext)));
+      asm.emitPopLocal(locals.contextVarIndexInFrame);
+
+      // 2. Restore context from captured :saved_try_context_var${depth}.
+      assert(locals.isCaptured(capturedSavedContextVar));
+      _genLoadVar(capturedSavedContextVar,
+          currentContextLevel: locals.contextLevelAtEntry);
+    } else {
+      asm.emitPush(_savedContextVar(node));
+    }
+    asm.emitPopLocal(locals.contextVarIndexInFrame);
   }
 
   /// Start try block
@@ -1601,11 +1711,39 @@
 
     asm.emitMoveSpecial(_exceptionVar(node), SpecialIndex.exception);
     asm.emitMoveSpecial(_stackTraceVar(node), SpecialIndex.stackTrace);
+
+    final capturedExceptionVar = locals.capturedExceptionVar(node);
+    if (capturedExceptionVar != null) {
+      _genPushContextForVariable(capturedExceptionVar);
+      asm.emitPush(_exceptionVar(node));
+      _genStoreVar(capturedExceptionVar);
+    }
+
+    final capturedStackTraceVar = locals.capturedStackTraceVar(node);
+    if (capturedStackTraceVar != null) {
+      _genPushContextForVariable(capturedStackTraceVar);
+      asm.emitPush(_stackTraceVar(node));
+      _genStoreVar(capturedStackTraceVar);
+    }
   }
 
   void _genRethrow(TreeNode node) {
-    asm.emitPush(_exceptionVar(node));
-    asm.emitPush(_stackTraceVar(node));
+    final capturedExceptionVar = locals.capturedExceptionVar(node);
+    if (capturedExceptionVar != null) {
+      assert(locals.isCaptured(capturedExceptionVar));
+      _genLoadVar(capturedExceptionVar);
+    } else {
+      asm.emitPush(_exceptionVar(node));
+    }
+
+    final capturedStackTraceVar = locals.capturedStackTraceVar(node);
+    if (capturedStackTraceVar != null) {
+      assert(locals.isCaptured(capturedStackTraceVar));
+      _genLoadVar(capturedStackTraceVar);
+    } else {
+      asm.emitPush(_stackTraceVar(node));
+    }
+
     asm.emitThrow(1);
   }
 
@@ -1751,9 +1889,53 @@
     asm.bind(done);
   }
 
-//  @override
-//  visitYieldStatement(YieldStatement node) {
-//  }
+  @override
+  visitYieldStatement(YieldStatement node) {
+    if (!node.isNative) {
+      throw 'YieldStatement must be desugared: $node';
+    }
+
+    // 0 is reserved for normal entry, yield points are counted from 1.
+    final int yieldIndex = yieldPoints.length + 1;
+    final Label continuationLabel = new Label();
+    yieldPoints.add(continuationLabel);
+
+    // :await_jump_var = #index
+    assert(locals.isCaptured(locals.awaitJumpVar));
+    _genPushContextForVariable(locals.awaitJumpVar);
+    _genPushInt(yieldIndex);
+    _genStoreVar(locals.awaitJumpVar);
+
+    // :await_ctx_var = context
+    assert(locals.isCaptured(locals.awaitContextVar));
+    _genPushContextForVariable(locals.awaitContextVar);
+    asm.emitPush(locals.contextVarIndexInFrame);
+    _genStoreVar(locals.awaitContextVar);
+
+    // return <expression>
+    // Note: finally blocks are *not* executed on the way out.
+    node.expression.accept(this);
+    asm.emitReturnTOS();
+
+    asm.bind(continuationLabel);
+
+    if (enclosingMember.function.dartAsyncMarker == AsyncMarker.Async ||
+        enclosingMember.function.dartAsyncMarker == AsyncMarker.AsyncStar) {
+      final int exceptionParam = locals.asyncExceptionParamIndexInFrame;
+      final int stackTraceParam = locals.asyncStackTraceParamIndexInFrame;
+
+      // if (:exception != null) rethrow (:exception, :stack_trace)
+      final Label cont = new Label();
+      asm.emitIfEqNull(exceptionParam);
+      asm.emitJump(cont);
+
+      asm.emitPush(exceptionParam);
+      asm.emitPush(stackTraceParam);
+      asm.emitThrow(1);
+
+      asm.bind(cont);
+    }
+  }
 
   @override
   visitFieldInitializer(FieldInitializer node) {
diff --git a/pkg/vm/lib/bytecode/local_vars.dart b/pkg/vm/lib/bytecode/local_vars.dart
index 1bae25a..14ed800 100644
--- a/pkg/vm/lib/bytecode/local_vars.dart
+++ b/pkg/vm/lib/bytecode/local_vars.dart
@@ -7,6 +7,8 @@
 import 'dart:math' show max;
 
 import 'package:kernel/ast.dart';
+import 'package:kernel/transformations/continuation.dart'
+    show ContinuationVariables;
 import 'package:vm/bytecode/dbc.dart';
 
 class LocalVariables {
@@ -14,6 +16,14 @@
   final Map<VariableDeclaration, VarDesc> _vars =
       <VariableDeclaration, VarDesc>{};
   final Map<TreeNode, List<int>> _temps = <TreeNode, List<int>>{};
+  final Map<TreeNode, VariableDeclaration> _capturedSavedContextVars =
+      <TreeNode, VariableDeclaration>{};
+  final Map<TreeNode, VariableDeclaration> _capturedExceptionVars =
+      <TreeNode, VariableDeclaration>{};
+  final Map<TreeNode, VariableDeclaration> _capturedStackTraceVars =
+      <TreeNode, VariableDeclaration>{};
+  final Map<ForInStatement, VariableDeclaration> _capturedIteratorVars =
+      <ForInStatement, VariableDeclaration>{};
 
   Scope _currentScope;
   Frame _currentFrame;
@@ -54,6 +64,10 @@
   int get currentContextSize => _currentScope.contextSize;
   int get currentContextLevel => _currentScope.contextLevel;
 
+  int get contextLevelAtEntry =>
+      _currentFrame.contextLevelAtEntry ??
+      (throw "Current frame is top level and it doesn't have a context at entry");
+
   int getContextLevelOfVar(VariableDeclaration variable) {
     final v = _getVarDesc(variable);
     assert(v.isCaptured);
@@ -86,6 +100,45 @@
 
   bool get hasReceiver => _currentFrame.receiverVar != null;
 
+  bool get isSyncYieldingFrame => _currentFrame.isSyncYielding;
+
+  VariableDeclaration get awaitJumpVar {
+    assert(_currentFrame.isSyncYielding);
+    return _currentFrame.parent
+        .getSyntheticVar(ContinuationVariables.awaitJumpVar);
+  }
+
+  VariableDeclaration get awaitContextVar {
+    assert(_currentFrame.isSyncYielding);
+    return _currentFrame.parent
+        .getSyntheticVar(ContinuationVariables.awaitContextVar);
+  }
+
+  VariableDeclaration capturedSavedContextVar(TreeNode node) =>
+      _capturedSavedContextVars[node];
+  VariableDeclaration capturedExceptionVar(TreeNode node) =>
+      _capturedExceptionVars[node];
+  VariableDeclaration capturedStackTraceVar(TreeNode node) =>
+      _capturedStackTraceVars[node];
+  VariableDeclaration capturedIteratorVar(ForInStatement node) =>
+      _capturedIteratorVars[node];
+
+  int get asyncExceptionParamIndexInFrame {
+    assert(_currentFrame.isSyncYielding);
+    final function = (_currentFrame.function as FunctionDeclaration).function;
+    final param = function.positionalParameters
+        .firstWhere((p) => p.name == ContinuationVariables.exceptionParam);
+    return getVarIndexInFrame(param);
+  }
+
+  int get asyncStackTraceParamIndexInFrame {
+    assert(_currentFrame.isSyncYielding);
+    final function = (_currentFrame.function as FunctionDeclaration).function;
+    final param = function.positionalParameters
+        .firstWhere((p) => p.name == ContinuationVariables.stackTraceParam);
+    return getVarIndexInFrame(param);
+  }
+
   int get frameSize => _currentFrame.frameSize;
 
   int get numParameters => _currentFrame.numParameters;
@@ -121,7 +174,9 @@
   int index;
   int originalParamSlotIndex;
 
-  VarDesc(this.declaration, this.scope);
+  VarDesc(this.declaration, this.scope) {
+    scope.vars.add(this);
+  }
 
   Frame get frame => scope.frame;
 
@@ -146,20 +201,29 @@
   bool hasOptionalParameters = false;
   bool hasCapturedParameters = false;
   bool hasClosures = false;
+  bool isDartSync = true;
+  bool isSyncYielding = false;
   VariableDeclaration receiverVar;
   VariableDeclaration typeArgsVar;
   VariableDeclaration closureVar;
   VariableDeclaration contextVar;
   VariableDeclaration scratchVar;
+  Map<String, VariableDeclaration> syntheticVars;
   int frameSize = 0;
   List<int> temporaries = <int>[];
+  int contextLevelAtEntry;
 
   Frame(this.function, this.parent);
+
+  VariableDeclaration getSyntheticVar(String name) =>
+      syntheticVars[name] ??
+      (throw '${name} variable is not declared in ${function}');
 }
 
 class Scope {
   final Scope parent;
   final Frame frame;
+  final List<VarDesc> vars = <VarDesc>[];
 
   int localsUsed;
   int tempsUsed;
@@ -176,6 +240,8 @@
 
   Scope _currentScope;
   Frame _currentFrame;
+  List<TreeNode> _enclosingTryBlocks;
+  List<TreeNode> _enclosingTryCatches;
 
   _ScopeBuilder(this.locals);
 
@@ -188,6 +254,11 @@
   void _visitFunction(TreeNode node) {
     _enterFrame(node);
 
+    final savedEnclosingTryBlocks = _enclosingTryBlocks;
+    _enclosingTryBlocks = <TreeNode>[];
+    final savedEnclosingTryCatches = _enclosingTryCatches;
+    _enclosingTryCatches = <TreeNode>[];
+
     if (node is Field) {
       node.initializer.accept(this);
     } else {
@@ -199,6 +270,11 @@
       FunctionNode function = (node as dynamic).function;
       assert(function != null);
 
+      _currentFrame.isDartSync = function.dartAsyncMarker == AsyncMarker.Sync;
+
+      _currentFrame.isSyncYielding =
+          function.asyncMarker == AsyncMarker.SyncYielding;
+
       _currentFrame.numTypeArguments =
           (_currentFrame.parent?.numTypeArguments ?? 0) +
               function.typeParameters.length;
@@ -224,6 +300,15 @@
       visitList(function.positionalParameters, this);
       visitList(function.namedParameters, this);
 
+      if (_currentFrame.isSyncYielding) {
+        // The following variables from parent frame are used implicitly and need
+        // to be captured to preserve state across closure invocations.
+        _useVariable(_currentFrame.parent
+            .getSyntheticVar(ContinuationVariables.awaitJumpVar));
+        _useVariable(_currentFrame.parent
+            .getSyntheticVar(ContinuationVariables.awaitContextVar));
+      }
+
       if (node is Constructor) {
         for (var field in node.enclosingClass.fields) {
           if (!field.isStatic && field.initializer != null) {
@@ -245,6 +330,9 @@
       _declareVariable(_currentFrame.scratchVar);
     }
 
+    _enclosingTryBlocks = savedEnclosingTryBlocks;
+    _enclosingTryCatches = savedEnclosingTryCatches;
+
     _leaveFrame();
   }
 
@@ -290,6 +378,56 @@
     _useVariable(_currentFrame.receiverVar);
   }
 
+  void _captureAllVisibleVariablesInCurrentFrame() {
+    assert(_currentFrame.isSyncYielding);
+    final transient = new Set<VariableDeclaration>();
+    transient
+      ..addAll([
+        _currentFrame.typeArgsVar,
+        _currentFrame.closureVar,
+        _currentFrame.contextVar,
+        _currentFrame.scratchVar,
+      ]);
+    transient.addAll((_currentFrame.function as FunctionDeclaration)
+        .function
+        .positionalParameters);
+    for (Scope scope = _currentScope;
+        scope != null && scope.frame == _currentFrame;
+        scope = scope.parent) {
+      for (VarDesc v in scope.vars) {
+        if (!transient.contains(v.declaration)) {
+          v.capture();
+        }
+      }
+    }
+  }
+
+  // Capture synthetic variables for control flow statements.
+  void _captureSyntheticVariables() {
+    int depth = 0;
+    for (TreeNode tryBlock in _enclosingTryBlocks) {
+      _captureSyntheticVariable(ContinuationVariables.savedTryContextVar(depth),
+          tryBlock, locals._capturedSavedContextVars);
+      ++depth;
+    }
+    depth = 0;
+    for (TreeNode tryBlock in _enclosingTryCatches) {
+      _captureSyntheticVariable(ContinuationVariables.exceptionVar(depth),
+          tryBlock, locals._capturedExceptionVars);
+      _captureSyntheticVariable(ContinuationVariables.stackTraceVar(depth),
+          tryBlock, locals._capturedStackTraceVars);
+      ++depth;
+    }
+  }
+
+  void _captureSyntheticVariable(
+      String name, TreeNode node, Map<TreeNode, VariableDeclaration> map) {
+    final variable = _currentFrame.parent.getSyntheticVar(name);
+    _useVariable(variable);
+    assert(map[node] == null || map[node] == variable);
+    map[node] = variable;
+  }
+
   void _visitWithScope(TreeNode node) {
     _enterScope(node);
     node.visitChildren(this);
@@ -317,6 +455,13 @@
   @override
   visitVariableDeclaration(VariableDeclaration node) {
     _declareVariable(node);
+
+    if (!_currentFrame.isDartSync && node.name[0] == ':') {
+      _currentFrame.syntheticVars ??= <String, VariableDeclaration>{};
+      assert(_currentFrame.syntheticVars[node.name] == null);
+      _currentFrame.syntheticVars[node.name] = node;
+    }
+
     node.visitChildren(this);
   }
 
@@ -381,10 +526,28 @@
   visitForInStatement(ForInStatement node) {
     node.iterable.accept(this);
 
+    VariableDeclaration iteratorVar;
+    if (_currentFrame.isSyncYielding) {
+      // Declare a variable to hold 'iterator' so it could be captured.
+      iteratorVar = new VariableDeclaration(null);
+      _declareVariable(iteratorVar);
+      locals._capturedIteratorVars[node] = iteratorVar;
+    }
+
     _enterScope(node);
     node.variable.accept(this);
     node.body.accept(this);
     _leaveScope();
+
+    if (_currentFrame.isSyncYielding && !locals.isCaptured(iteratorVar)) {
+      // Iterator variable was not captured, as there are no yield points
+      // inside for-in statement body. The variable is needed only if captured,
+      // so undeclare it.
+      assert(_currentScope.vars.last == locals._vars[iteratorVar]);
+      _currentScope.vars.removeLast();
+      locals._vars.remove(iteratorVar);
+      locals._capturedIteratorVars.remove(node);
+    }
   }
 
   @override
@@ -396,6 +559,36 @@
   visitLet(Let node) {
     _visitWithScope(node);
   }
+
+  @override
+  visitYieldStatement(YieldStatement node) {
+    assert(_currentFrame.isSyncYielding);
+    _captureAllVisibleVariablesInCurrentFrame();
+    _captureSyntheticVariables();
+    node.visitChildren(this);
+  }
+
+  @override
+  visitTryCatch(TryCatch node) {
+    _enclosingTryBlocks.add(node);
+    node.body?.accept(this);
+    _enclosingTryBlocks.removeLast();
+
+    _enclosingTryCatches.add(node);
+    visitList(node.catches, this);
+    _enclosingTryCatches.removeLast();
+  }
+
+  @override
+  visitTryFinally(TryFinally node) {
+    _enclosingTryBlocks.add(node);
+    node.body?.accept(this);
+    _enclosingTryBlocks.removeLast();
+
+    _enclosingTryCatches.add(node);
+    node.finalizer?.accept(this);
+    _enclosingTryCatches.removeLast();
+  }
 }
 
 class _Allocator extends RecursiveVisitor<Null> {
@@ -416,6 +609,10 @@
     if (_currentScope.frame != _currentFrame) {
       _currentFrame = _currentScope.frame;
 
+      if (_currentScope.parent != null) {
+        _currentFrame.contextLevelAtEntry = _currentScope.parent.contextLevel;
+      }
+
       _currentScope.localsUsed = 0;
       _currentScope.tempsUsed = 0;
     } else {
diff --git a/pkg/vm/testcases/bytecode/async.dart b/pkg/vm/testcases/bytecode/async.dart
new file mode 100644
index 0000000..e3900c7
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/async.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+Future<int> foo() async => 42;
+
+Future<int> simpleAsyncAwait(Future<int> a, Future<int> b) async {
+  return (await a) + (await b);
+}
+
+Future<int> loops(List<int> list) async {
+  int sum = 0;
+  for (int i = 0; i < 10; ++i) {
+    for (var j in list) {
+      sum += i + j + await foo();
+    }
+  }
+  for (int k = 0; k < 10; ++k) {
+    sum += k;
+  }
+  return sum;
+}
+
+Future<int> tryCatchRethrow(Future<int> a, Future<int> b, Future<int> c) async {
+  int x = 1;
+  try {
+    x = x + await a;
+  } catch (e) {
+    if (e is Error) {
+      return 42;
+    }
+    x = x + await b;
+    rethrow;
+  } finally {
+    print('fin');
+    x = x + await c;
+    return x;
+  }
+}
+
+closure(Future<int> a) {
+  int x = 3;
+  Future<int> nested() async {
+    int y = 4;
+    try {
+      x = 5;
+      y = await a;
+      return x + y;
+    } finally {
+      print('fin');
+    }
+  }
+
+  return nested;
+}
+
+main() {}
diff --git a/pkg/vm/testcases/bytecode/async.dart.expect b/pkg/vm/testcases/bytecode/async.dart.expect
new file mode 100644
index 0000000..cf1e13f
--- /dev/null
+++ b/pkg/vm/testcases/bytecode/async.dart.expect
@@ -0,0 +1,2193 @@
+library #lib;
+import self as self;
+import "dart:async" as asy;
+import "dart:core" as core;
+
+[@vm.bytecode=
+Bytecode {
+  Entry                7
+  CheckStack
+  AllocateContext      4
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  PushConstant         CP#1
+  PushConstant         CP#3
+  IndirectStaticCall   1, CP#2
+  StoreFieldTOS        CP#4
+  Push                 r0
+  PushConstant         CP#5
+  StoreFieldTOS        CP#6
+  PushConstant         CP#5
+  PopLocal             r2
+  PushConstant         CP#5
+  PopLocal             r3
+  PushConstant         CP#5
+  PopLocal             r4
+  Push                 r0
+  PushConstant         CP#7
+  StoreFieldTOS        CP#8
+  Push                 r0
+  PushConstant         CP#5
+  StoreFieldTOS        CP#9
+  Allocate             CP#19
+  StoreLocal           r6
+  Push                 r6
+  PushConstant         CP#5
+  StoreFieldTOS        CP#20
+  Push                 r6
+  PushConstant         CP#5
+  StoreFieldTOS        CP#21
+  Push                 r6
+  PushConstant         CP#10
+  StoreFieldTOS        CP#22
+  Push                 r6
+  Push                 r0
+  StoreFieldTOS        CP#11
+  PopLocal             r5
+  Push                 r5
+  PushConstant         CP#24
+  IndirectStaticCall   1, CP#23
+  StoreLocal           r2
+  Drop1
+  Push                 r5
+  PushConstant         CP#25
+  IndirectStaticCall   1, CP#23
+  StoreLocal           r3
+  Drop1
+  Push                 r5
+  PushConstant         CP#26
+  IndirectStaticCall   1, CP#23
+  StoreLocal           r4
+  Drop1
+  PushConstant         CP#27
+  Push                 r5
+  PushConstant         CP#29
+  IndirectStaticCall   2, CP#28
+  Drop1
+  Push                 r0
+  LoadFieldTOS         CP#4
+  InstanceCall1        1, CP#30
+  ReturnTOS
+  Push                 r0
+  LoadFieldTOS         CP#0
+  PopLocal             r0
+  PushConstant         CP#5
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ContextOffset parent
+  [1] = TypeArgs [dart.core::int]
+  [2] = ArgDesc num-args 0, num-type-args 1, names []
+  [3] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#2
+  [4] = ContextOffset var [3]
+  [5] = Null
+  [6] = ContextOffset var [2]
+  [7] = Int 0
+  [8] = ContextOffset var [0]
+  [9] = ContextOffset var [1]
+  [10] = ClosureFunction :async_op ([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding ;
+  [11] = FieldOffset dart.core::_Closure::_context
+  [12] = Int 42
+  [13] = ArgDesc num-args 2, num-type-args 0, names []
+  [14] = ICData target-name 'complete', arg-desc CP#13
+  [15] = Type dynamic
+  [16] = ArgDesc num-args 3, num-type-args 0, names []
+  [17] = ICData target-name 'completeError', arg-desc CP#16
+  [18] = EndClosureFunctionScope
+  [19] = Class dart.core::_Closure
+  [20] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
+  [21] = FieldOffset dart.core::_Closure::_function_type_arguments
+  [22] = FieldOffset dart.core::_Closure::_function
+  [23] = ArgDesc num-args 1, num-type-args 0, names []
+  [24] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#23
+  [25] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#23
+  [26] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#23
+  [27] = TypeArgs [dynamic]
+  [28] = ArgDesc num-args 1, num-type-args 1, names []
+  [29] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#28
+  [30] = ICData get target-name 'future', arg-desc CP#23
+}
+Closure CP#10 {
+  EntryOptional        1, 3, 0
+  LoadConstant         r1, CP#5
+  LoadConstant         r2, CP#5
+  LoadConstant         r3, CP#5
+  Frame                6
+  CheckStack
+  Push                 r0
+  LoadFieldTOS         CP#11
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#8
+  StoreLocal           r5
+  PushConstant         CP#7
+  IfNeStrictNumTOS
+  Jump                 L1
+  Push                 r4
+  PopLocal             r6
+Try #0 start:
+  Push                 r4
+  PushConstant         CP#12
+  StoreLocal           r8
+  StoreFieldTOS        CP#6
+  Push                 r8
+  Drop1
+  Jump                 L2
+L2:
+  Push                 r4
+  LoadFieldTOS         CP#4
+  Push                 r4
+  LoadFieldTOS         CP#6
+  InstanceCall1        2, CP#14
+  Drop1
+  PushConstant         CP#5
+  ReturnTOS
+  Jump                 L3
+Try #0 end:
+Try #0 handler:
+  Push                 r6
+  PopLocal             r4
+  MoveSpecial          r6, exception
+  MoveSpecial          r7, stackTrace
+  Push                 r6
+  PopLocal             r8
+  Push                 r7
+  PopLocal             r9
+  Push                 r4
+  LoadFieldTOS         CP#4
+  Push                 r8
+  Push                 r9
+  InstanceCall1        3, CP#17
+  Drop1
+  Jump                 L3
+L3:
+  PushConstant         CP#5
+  ReturnTOS
+L1:
+  Trap
+
+}
+]static method foo() → asy::Future<core::int> /* originally async */ {
+  final asy::Completer<core::int> :async_completer = asy::Completer::sync<core::int>();
+  asy::FutureOr<core::int> :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L1:
+      {
+        :return_value = 42;
+        break #L1;
+      }
+      :async_completer.{asy::Completer::complete}(:return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  asy::Future::microtask<dynamic>(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                4
+  CheckStack
+  AllocateContext      2
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  Push                 FP[-6]
+  StoreFieldTOS        CP#1
+  Push                 r0
+  Push                 FP[-5]
+  StoreFieldTOS        CP#2
+  AllocateContext      9
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  PushConstant         CP#3
+  PushConstant         CP#5
+  IndirectStaticCall   1, CP#4
+  StoreFieldTOS        CP#6
+  Push                 r0
+  PushConstant         CP#7
+  StoreFieldTOS        CP#8
+  PushConstant         CP#7
+  PopLocal             r2
+  Push                 r0
+  PushConstant         CP#7
+  StoreFieldTOS        CP#9
+  Push                 r0
+  PushConstant         CP#7
+  StoreFieldTOS        CP#10
+  Push                 r0
+  PushConstant         CP#11
+  StoreFieldTOS        CP#1
+  Push                 r0
+  PushConstant         CP#7
+  StoreFieldTOS        CP#2
+  Push                 r0
+  PushConstant         CP#7
+  StoreFieldTOS        CP#12
+  Push                 r0
+  PushConstant         CP#7
+  StoreFieldTOS        CP#13
+  Push                 r0
+  Allocate             CP#29
+  StoreLocal           r3
+  Push                 r3
+  PushConstant         CP#7
+  StoreFieldTOS        CP#30
+  Push                 r3
+  PushConstant         CP#7
+  StoreFieldTOS        CP#31
+  Push                 r3
+  PushConstant         CP#14
+  StoreFieldTOS        CP#32
+  Push                 r3
+  Push                 r0
+  StoreFieldTOS        CP#15
+  StoreFieldTOS        CP#17
+  Push                 r0
+  LoadFieldTOS         CP#17
+  PushConstant         CP#34
+  IndirectStaticCall   1, CP#33
+  StoreLocal           r2
+  Drop1
+  Push                 r0
+  Push                 r0
+  LoadFieldTOS         CP#17
+  PushConstant         CP#35
+  IndirectStaticCall   1, CP#33
+  StoreLocal           r3
+  StoreFieldTOS        CP#9
+  Push                 r3
+  Drop1
+  Push                 r0
+  Push                 r0
+  LoadFieldTOS         CP#17
+  PushConstant         CP#36
+  IndirectStaticCall   1, CP#33
+  StoreLocal           r3
+  StoreFieldTOS        CP#10
+  Push                 r3
+  Drop1
+  PushConstant         CP#37
+  Push                 r0
+  LoadFieldTOS         CP#17
+  PushConstant         CP#39
+  IndirectStaticCall   2, CP#38
+  Drop1
+  Push                 r0
+  LoadFieldTOS         CP#6
+  InstanceCall1        1, CP#40
+  ReturnTOS
+  Push                 r0
+  LoadFieldTOS         CP#0
+  PopLocal             r0
+  PushConstant         CP#7
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ContextOffset parent
+  [1] = ContextOffset var [0]
+  [2] = ContextOffset var [1]
+  [3] = TypeArgs [dart.core::int]
+  [4] = ArgDesc num-args 0, num-type-args 1, names []
+  [5] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#4
+  [6] = ContextOffset var [8]
+  [7] = Null
+  [8] = ContextOffset var [7]
+  [9] = ContextOffset var [3]
+  [10] = ContextOffset var [4]
+  [11] = Int 0
+  [12] = ContextOffset var [2]
+  [13] = ContextOffset var [6]
+  [14] = ClosureFunction :async_op ([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding ;
+  [15] = FieldOffset dart.core::_Closure::_context
+  [16] = Int 1
+  [17] = ContextOffset var [5]
+  [18] = ArgDesc num-args 4, num-type-args 0, names []
+  [19] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#18
+  [20] = Int 2
+  [21] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#18
+  [22] = ArgDesc num-args 2, num-type-args 0, names []
+  [23] = ICData target-name '+', arg-desc CP#22
+  [24] = ICData target-name 'complete', arg-desc CP#22
+  [25] = Type dynamic
+  [26] = ArgDesc num-args 3, num-type-args 0, names []
+  [27] = ICData target-name 'completeError', arg-desc CP#26
+  [28] = EndClosureFunctionScope
+  [29] = Class dart.core::_Closure
+  [30] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
+  [31] = FieldOffset dart.core::_Closure::_function_type_arguments
+  [32] = FieldOffset dart.core::_Closure::_function
+  [33] = ArgDesc num-args 1, num-type-args 0, names []
+  [34] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#33
+  [35] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#33
+  [36] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#33
+  [37] = TypeArgs [dynamic]
+  [38] = ArgDesc num-args 1, num-type-args 1, names []
+  [39] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#38
+  [40] = ICData get target-name 'future', arg-desc CP#33
+}
+Closure CP#14 {
+  EntryOptional        1, 3, 0
+  LoadConstant         r1, CP#7
+  LoadConstant         r2, CP#7
+  LoadConstant         r3, CP#7
+  Frame                6
+  CheckStack
+  Push                 r0
+  LoadFieldTOS         CP#15
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r5
+  PushConstant         CP#11
+  IfNeStrictNumTOS
+  Jump                 L1
+  Push                 r4
+  Push                 r4
+  StoreFieldTOS        CP#12
+Try #0 start:
+  Push                 r4
+  PushConstant         CP#16
+  StoreFieldTOS        CP#1
+  Push                 r4
+  Push                 r4
+  StoreFieldTOS        CP#2
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#1
+  Push                 r4
+  LoadFieldTOS         CP#9
+  Push                 r4
+  LoadFieldTOS         CP#10
+  Push                 r4
+  LoadFieldTOS         CP#17
+  PushConstant         CP#19
+  IndirectStaticCall   4, CP#18
+  PopLocal             r8
+  PushConstant         CP#7
+  ReturnTOS
+L6:
+  IfEqNull             r2
+  Jump                 L2
+  Push                 r2
+  Push                 r3
+  Throw                1
+L2:
+  Push                 r4
+  Push                 r1
+  StoreLocal           r8
+  StoreFieldTOS        CP#13
+  Push                 r8
+  Drop1
+  Push                 r4
+  PushConstant         CP#20
+  StoreFieldTOS        CP#1
+  Push                 r4
+  Push                 r4
+  StoreFieldTOS        CP#2
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#2
+  Push                 r4
+  LoadFieldTOS         CP#9
+  Push                 r4
+  LoadFieldTOS         CP#10
+  Push                 r4
+  LoadFieldTOS         CP#17
+  PushConstant         CP#21
+  IndirectStaticCall   4, CP#18
+  PopLocal             r9
+  PushConstant         CP#7
+  ReturnTOS
+L7:
+  IfEqNull             r2
+  Jump                 L3
+  Push                 r2
+  Push                 r3
+  Throw                1
+L3:
+  Push                 r4
+  Push                 r4
+  LoadFieldTOS         CP#13
+  Push                 r1
+  InstanceCall1        2, CP#23
+  StoreLocal           r8
+  StoreFieldTOS        CP#8
+  Push                 r8
+  Drop1
+  Jump                 L4
+L4:
+  Push                 r4
+  LoadFieldTOS         CP#6
+  Push                 r4
+  LoadFieldTOS         CP#8
+  InstanceCall1        2, CP#24
+  Drop1
+  PushConstant         CP#7
+  ReturnTOS
+  Jump                 L5
+Try #0 end:
+Try #0 handler:
+  Push                 r0
+  LoadFieldTOS         CP#15
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#12
+  PopLocal             r4
+  MoveSpecial          r6, exception
+  MoveSpecial          r7, stackTrace
+  Push                 r6
+  PopLocal             r8
+  Push                 r7
+  PopLocal             r9
+  Push                 r4
+  LoadFieldTOS         CP#6
+  Push                 r8
+  Push                 r9
+  InstanceCall1        3, CP#27
+  Drop1
+  Jump                 L5
+L5:
+  PushConstant         CP#7
+  ReturnTOS
+L1:
+  Push                 r4
+  LoadFieldTOS         CP#2
+  PopLocal             r4
+  Push                 r5
+  PushConstant         CP#16
+  IfEqStrictNumTOS
+  Jump                 L6
+  Jump                 L7
+
+}
+]static method simpleAsyncAwait(asy::Future<core::int> a, asy::Future<core::int> b) → asy::Future<core::int> /* originally async */ {
+  final asy::Completer<core::int> :async_completer = asy::Completer::sync<core::int>();
+  asy::FutureOr<core::int> :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  dynamic :async_temporary_0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L2:
+      {
+        [yield] let dynamic #t1 = asy::_awaitHelper(a, :async_op_then, :async_op_error, :async_op) in null;
+        :async_temporary_0 = :result;
+        [yield] let dynamic #t2 = asy::_awaitHelper(b, :async_op_then, :async_op_error, :async_op) in null;
+        :return_value = :async_temporary_0.{core::num::+}(:result);
+        break #L2;
+      }
+      :async_completer.{asy::Completer::complete}(:return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  asy::Future::microtask<dynamic>(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                4
+  CheckStack
+  AllocateContext      1
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  Push                 FP[-5]
+  StoreFieldTOS        CP#1
+  AllocateContext      10
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  PushConstant         CP#2
+  PushConstant         CP#4
+  IndirectStaticCall   1, CP#3
+  StoreFieldTOS        CP#5
+  Push                 r0
+  PushConstant         CP#6
+  StoreFieldTOS        CP#7
+  PushConstant         CP#6
+  PopLocal             r2
+  Push                 r0
+  PushConstant         CP#6
+  StoreFieldTOS        CP#8
+  Push                 r0
+  PushConstant         CP#6
+  StoreFieldTOS        CP#9
+  Push                 r0
+  PushConstant         CP#10
+  StoreFieldTOS        CP#1
+  Push                 r0
+  PushConstant         CP#6
+  StoreFieldTOS        CP#11
+  Push                 r0
+  PushConstant         CP#6
+  StoreFieldTOS        CP#12
+  Push                 r0
+  PushConstant         CP#6
+  StoreFieldTOS        CP#13
+  Push                 r0
+  PushConstant         CP#6
+  StoreFieldTOS        CP#14
+  Push                 r0
+  Allocate             CP#43
+  StoreLocal           r3
+  Push                 r3
+  PushConstant         CP#6
+  StoreFieldTOS        CP#44
+  Push                 r3
+  PushConstant         CP#6
+  StoreFieldTOS        CP#45
+  Push                 r3
+  PushConstant         CP#15
+  StoreFieldTOS        CP#46
+  Push                 r3
+  Push                 r0
+  StoreFieldTOS        CP#16
+  StoreFieldTOS        CP#29
+  Push                 r0
+  LoadFieldTOS         CP#29
+  PushConstant         CP#47
+  IndirectStaticCall   1, CP#21
+  StoreLocal           r2
+  Drop1
+  Push                 r0
+  Push                 r0
+  LoadFieldTOS         CP#29
+  PushConstant         CP#48
+  IndirectStaticCall   1, CP#21
+  StoreLocal           r3
+  StoreFieldTOS        CP#8
+  Push                 r3
+  Drop1
+  Push                 r0
+  Push                 r0
+  LoadFieldTOS         CP#29
+  PushConstant         CP#49
+  IndirectStaticCall   1, CP#21
+  StoreLocal           r3
+  StoreFieldTOS        CP#9
+  Push                 r3
+  Drop1
+  PushConstant         CP#50
+  Push                 r0
+  LoadFieldTOS         CP#29
+  PushConstant         CP#52
+  IndirectStaticCall   2, CP#51
+  Drop1
+  Push                 r0
+  LoadFieldTOS         CP#5
+  InstanceCall1        1, CP#53
+  ReturnTOS
+  Push                 r0
+  LoadFieldTOS         CP#0
+  PopLocal             r0
+  PushConstant         CP#6
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ContextOffset parent
+  [1] = ContextOffset var [0]
+  [2] = TypeArgs [dart.core::int]
+  [3] = ArgDesc num-args 0, num-type-args 1, names []
+  [4] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#3
+  [5] = ContextOffset var [9]
+  [6] = Null
+  [7] = ContextOffset var [8]
+  [8] = ContextOffset var [5]
+  [9] = ContextOffset var [6]
+  [10] = Int 0
+  [11] = ContextOffset var [1]
+  [12] = ContextOffset var [4]
+  [13] = ContextOffset var [3]
+  [14] = ContextOffset var [2]
+  [15] = ClosureFunction :async_op ([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding ;
+  [16] = FieldOffset dart.core::_Closure::_context
+  [17] = Int 10
+  [18] = ArgDesc num-args 2, num-type-args 0, names []
+  [19] = ICData target-name '<', arg-desc CP#18
+  [20] = Bool true
+  [21] = ArgDesc num-args 1, num-type-args 0, names []
+  [22] = ICData get target-name 'iterator', arg-desc CP#21
+  [23] = ICData target-name 'moveNext', arg-desc CP#21
+  [24] = ICData get target-name 'current', arg-desc CP#21
+  [25] = ICData target-name '+', arg-desc CP#18
+  [26] = Int 1
+  [27] = ArgDesc num-args 0, num-type-args 0, names []
+  [28] = StaticICData target '#lib::foo', arg-desc CP#27
+  [29] = ContextOffset var [7]
+  [30] = ArgDesc num-args 4, num-type-args 0, names []
+  [31] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#30
+  [32] = ICData target-name '+', arg-desc CP#18
+  [33] = ICData target-name '+', arg-desc CP#18
+  [34] = ICData target-name '+', arg-desc CP#18
+  [35] = ICData target-name '<', arg-desc CP#18
+  [36] = ICData target-name '+', arg-desc CP#18
+  [37] = ICData target-name '+', arg-desc CP#18
+  [38] = ICData target-name 'complete', arg-desc CP#18
+  [39] = Type dynamic
+  [40] = ArgDesc num-args 3, num-type-args 0, names []
+  [41] = ICData target-name 'completeError', arg-desc CP#40
+  [42] = EndClosureFunctionScope
+  [43] = Class dart.core::_Closure
+  [44] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
+  [45] = FieldOffset dart.core::_Closure::_function_type_arguments
+  [46] = FieldOffset dart.core::_Closure::_function
+  [47] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#21
+  [48] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#21
+  [49] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#21
+  [50] = TypeArgs [dynamic]
+  [51] = ArgDesc num-args 1, num-type-args 1, names []
+  [52] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#51
+  [53] = ICData get target-name 'future', arg-desc CP#21
+}
+Closure CP#15 {
+  EntryOptional        1, 3, 0
+  LoadConstant         r1, CP#6
+  LoadConstant         r2, CP#6
+  LoadConstant         r3, CP#6
+  Frame                7
+  CheckStack
+  Push                 r0
+  LoadFieldTOS         CP#16
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r5
+  PushConstant         CP#10
+  IfNeStrictNumTOS
+  Jump                 L1
+  Push                 r4
+  Push                 r4
+  StoreFieldTOS        CP#12
+Try #0 start:
+  AllocateContext      1
+  StoreLocal           r5
+  Push                 r5
+  Push                 r4
+  StoreFieldTOS        CP#0
+  PopLocal             r4
+  Push                 r4
+  PushConstant         CP#10
+  StoreFieldTOS        CP#1
+  AllocateContext      1
+  StoreLocal           r5
+  Push                 r5
+  Push                 r4
+  StoreFieldTOS        CP#0
+  PopLocal             r4
+  Push                 r4
+  PushConstant         CP#10
+  StoreFieldTOS        CP#1
+L6:
+  CheckStack
+  Push                 r4
+  LoadFieldTOS         CP#1
+  PushConstant         CP#17
+  InstanceCall1        2, CP#19
+  PushConstant         CP#20
+  IfNeStrictTOS
+  Jump                 L2
+  AllocateContext      1
+  StoreLocal           r5
+  Push                 r5
+  Push                 r4
+  StoreFieldTOS        CP#0
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#1
+  InstanceCall1        1, CP#22
+  PopLocal             r8
+  Push                 r4
+  Push                 r8
+  StoreFieldTOS        CP#1
+L5:
+  CheckStack
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r8
+  InstanceCall1        1, CP#23
+  PushConstant         CP#20
+  IfNeStrictTOS
+  Jump                 L3
+  AllocateContext      1
+  StoreLocal           r5
+  Push                 r5
+  Push                 r4
+  StoreFieldTOS        CP#0
+  PopLocal             r4
+  Push                 r4
+  Push                 r8
+  InstanceCall1        1, CP#24
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#1
+  StoreLocal           r9
+  StoreFieldTOS        CP#14
+  Push                 r9
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#1
+  Push                 r4
+  LoadFieldTOS         CP#1
+  InstanceCall1        2, CP#25
+  StoreLocal           r9
+  StoreFieldTOS        CP#13
+  Push                 r9
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  PushConstant         CP#26
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#11
+  PushConstant         CP#28
+  IndirectStaticCall   0, CP#27
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#8
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#9
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#29
+  PushConstant         CP#31
+  IndirectStaticCall   4, CP#30
+  PopLocal             r10
+  PushConstant         CP#6
+  ReturnTOS
+L11:
+  IfEqNull             r2
+  Jump                 L4
+  Push                 r2
+  Push                 r3
+  Throw                1
+L4:
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#14
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#13
+  Push                 r1
+  InstanceCall1        2, CP#32
+  InstanceCall1        2, CP#33
+  StoreLocal           r9
+  StoreFieldTOS        CP#1
+  Push                 r9
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  Jump                 L5
+L3:
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  Push                 r4
+  CloneContext
+  PopLocal             r4
+  Push                 r4
+  Push                 r4
+  LoadFieldTOS         CP#1
+  PushConstant         CP#26
+  InstanceCall1        2, CP#34
+  StoreLocal           r8
+  StoreFieldTOS        CP#1
+  Push                 r8
+  Drop1
+  Jump                 L6
+L2:
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  PushConstant         CP#10
+  PopLocal             r8
+L8:
+  CheckStack
+  Push                 r8
+  PushConstant         CP#17
+  InstanceCall1        2, CP#35
+  PushConstant         CP#20
+  IfNeStrictTOS
+  Jump                 L7
+  Push                 r4
+  Push                 r4
+  LoadFieldTOS         CP#1
+  Push                 r8
+  InstanceCall1        2, CP#36
+  StoreLocal           r9
+  StoreFieldTOS        CP#1
+  Push                 r9
+  Drop1
+  Push                 r8
+  PushConstant         CP#26
+  InstanceCall1        2, CP#37
+  StoreLocal           r8
+  Drop1
+  Jump                 L8
+L7:
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r8
+  StoreFieldTOS        CP#7
+  Push                 r8
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  Jump                 L9
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+L9:
+  Push                 r4
+  LoadFieldTOS         CP#5
+  Push                 r4
+  LoadFieldTOS         CP#7
+  InstanceCall1        2, CP#38
+  Drop1
+  PushConstant         CP#6
+  ReturnTOS
+  Jump                 L10
+Try #0 end:
+Try #0 handler:
+  Push                 r0
+  LoadFieldTOS         CP#16
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#12
+  PopLocal             r4
+  MoveSpecial          r6, exception
+  MoveSpecial          r7, stackTrace
+  Push                 r6
+  PopLocal             r8
+  Push                 r7
+  PopLocal             r9
+  Push                 r4
+  LoadFieldTOS         CP#5
+  Push                 r8
+  Push                 r9
+  InstanceCall1        3, CP#41
+  Drop1
+  Jump                 L10
+L10:
+  PushConstant         CP#6
+  ReturnTOS
+L1:
+  Push                 r4
+  LoadFieldTOS         CP#11
+  PopLocal             r4
+  Jump                 L11
+
+}
+]static method loops(core::List<core::int> list) → asy::Future<core::int> /* originally async */ {
+  final asy::Completer<core::int> :async_completer = asy::Completer::sync<core::int>();
+  asy::FutureOr<core::int> :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  dynamic :async_temporary_0;
+  dynamic :async_temporary_1;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L3:
+      {
+        core::int sum = 0;
+        for (core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1)) {
+          for (core::int j in list) {
+            :async_temporary_1 = sum;
+            :async_temporary_0 = i.{core::num::+}(j);
+            [yield] let dynamic #t3 = asy::_awaitHelper(self::foo(), :async_op_then, :async_op_error, :async_op) in null;
+            sum = :async_temporary_1.{core::num::+}(:async_temporary_0.{core::num::+}(:result));
+          }
+        }
+        for (core::int k = 0; k.{core::num::<}(10); k = k.{core::num::+}(1)) {
+          sum = sum.{core::num::+}(k);
+        }
+        :return_value = sum;
+        break #L3;
+      }
+      :async_completer.{asy::Completer::complete}(:return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  asy::Future::microtask<dynamic>(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                4
+  CheckStack
+  AllocateContext      3
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  Push                 FP[-7]
+  StoreFieldTOS        CP#1
+  Push                 r0
+  Push                 FP[-6]
+  StoreFieldTOS        CP#2
+  Push                 r0
+  Push                 FP[-5]
+  StoreFieldTOS        CP#3
+  AllocateContext      13
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  PushConstant         CP#4
+  PushConstant         CP#6
+  IndirectStaticCall   1, CP#5
+  StoreFieldTOS        CP#7
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#9
+  PushConstant         CP#8
+  PopLocal             r2
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#10
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#11
+  Push                 r0
+  PushConstant         CP#12
+  StoreFieldTOS        CP#1
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#2
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#13
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#14
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#15
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#16
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#17
+  Push                 r0
+  PushConstant         CP#8
+  StoreFieldTOS        CP#3
+  Push                 r0
+  Allocate             CP#52
+  StoreLocal           r3
+  Push                 r3
+  PushConstant         CP#8
+  StoreFieldTOS        CP#53
+  Push                 r3
+  PushConstant         CP#8
+  StoreFieldTOS        CP#54
+  Push                 r3
+  PushConstant         CP#18
+  StoreFieldTOS        CP#55
+  Push                 r3
+  Push                 r0
+  StoreFieldTOS        CP#19
+  StoreFieldTOS        CP#21
+  Push                 r0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#56
+  IndirectStaticCall   1, CP#35
+  StoreLocal           r2
+  Drop1
+  Push                 r0
+  Push                 r0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#57
+  IndirectStaticCall   1, CP#35
+  StoreLocal           r3
+  StoreFieldTOS        CP#10
+  Push                 r3
+  Drop1
+  Push                 r0
+  Push                 r0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#58
+  IndirectStaticCall   1, CP#35
+  StoreLocal           r3
+  StoreFieldTOS        CP#11
+  Push                 r3
+  Drop1
+  PushConstant         CP#59
+  Push                 r0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#61
+  IndirectStaticCall   2, CP#60
+  Drop1
+  Push                 r0
+  LoadFieldTOS         CP#7
+  InstanceCall1        1, CP#62
+  ReturnTOS
+  Push                 r0
+  LoadFieldTOS         CP#0
+  PopLocal             r0
+  PushConstant         CP#8
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ContextOffset parent
+  [1] = ContextOffset var [0]
+  [2] = ContextOffset var [1]
+  [3] = ContextOffset var [2]
+  [4] = TypeArgs [dart.core::int]
+  [5] = ArgDesc num-args 0, num-type-args 1, names []
+  [6] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#5
+  [7] = ContextOffset var [12]
+  [8] = Null
+  [9] = ContextOffset var [9]
+  [10] = ContextOffset var [6]
+  [11] = ContextOffset var [7]
+  [12] = Int 0
+  [13] = ContextOffset var [3]
+  [14] = ContextOffset var [4]
+  [15] = ContextOffset var [5]
+  [16] = ContextOffset var [10]
+  [17] = ContextOffset var [11]
+  [18] = ClosureFunction :async_op ([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding ;
+  [19] = FieldOffset dart.core::_Closure::_context
+  [20] = Int 1
+  [21] = ContextOffset var [8]
+  [22] = ArgDesc num-args 4, num-type-args 0, names []
+  [23] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
+  [24] = ArgDesc num-args 2, num-type-args 0, names []
+  [25] = ICData target-name '+', arg-desc CP#24
+  [26] = Type dynamic
+  [27] = Type dart.core::Error
+  [28] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#22
+  [29] = Bool true
+  [30] = Int 42
+  [31] = Int 2
+  [32] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
+  [33] = ICData target-name '+', arg-desc CP#24
+  [34] = String 'fin'
+  [35] = ArgDesc num-args 1, num-type-args 0, names []
+  [36] = StaticICData target 'dart.core::print', arg-desc CP#35
+  [37] = Int 3
+  [38] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
+  [39] = ICData target-name '+', arg-desc CP#24
+  [40] = StaticICData target 'dart.core::print', arg-desc CP#35
+  [41] = Int 4
+  [42] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
+  [43] = ICData target-name '+', arg-desc CP#24
+  [44] = StaticICData target 'dart.core::print', arg-desc CP#35
+  [45] = Int 5
+  [46] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
+  [47] = ICData target-name '+', arg-desc CP#24
+  [48] = ICData target-name 'complete', arg-desc CP#24
+  [49] = ArgDesc num-args 3, num-type-args 0, names []
+  [50] = ICData target-name 'completeError', arg-desc CP#49
+  [51] = EndClosureFunctionScope
+  [52] = Class dart.core::_Closure
+  [53] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
+  [54] = FieldOffset dart.core::_Closure::_function_type_arguments
+  [55] = FieldOffset dart.core::_Closure::_function
+  [56] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#35
+  [57] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#35
+  [58] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#35
+  [59] = TypeArgs [dynamic]
+  [60] = ArgDesc num-args 1, num-type-args 1, names []
+  [61] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#60
+  [62] = ICData get target-name 'future', arg-desc CP#35
+}
+Closure CP#18 {
+  EntryOptional        1, 3, 0
+  LoadConstant         r1, CP#8
+  LoadConstant         r2, CP#8
+  LoadConstant         r3, CP#8
+  Frame                10
+  CheckStack
+  Push                 r0
+  LoadFieldTOS         CP#19
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r5
+  PushConstant         CP#12
+  IfNeStrictNumTOS
+  Jump                 L1
+  Push                 r4
+  Push                 r4
+  StoreFieldTOS        CP#13
+Try #0 start:
+  AllocateContext      1
+  StoreLocal           r5
+  Push                 r5
+  Push                 r4
+  StoreFieldTOS        CP#0
+  PopLocal             r4
+  Push                 r4
+  PushConstant         CP#20
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#14
+Try #1 start:
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#15
+Try #2 start:
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r12
+  StoreFieldTOS        CP#3
+  Push                 r12
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PushConstant         CP#20
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#2
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#10
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#11
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#23
+  IndirectStaticCall   4, CP#22
+  PopLocal             r13
+  PushConstant         CP#8
+  ReturnTOS
+L13:
+  IfEqNull             r2
+  Jump                 L2
+  Push                 r2
+  Push                 r3
+  Throw                1
+L2:
+  Push                 r4
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#3
+  Push                 r1
+  InstanceCall1        2, CP#25
+  StoreLocal           r12
+  StoreFieldTOS        CP#1
+  Push                 r12
+  Drop1
+  Jump                 L3
+Try #2 end:
+Try #2 handler:
+  Push                 r0
+  LoadFieldTOS         CP#19
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#15
+  PopLocal             r4
+  MoveSpecial          r10, exception
+  MoveSpecial          r11, stackTrace
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r10
+  StoreFieldTOS        CP#16
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r11
+  StoreFieldTOS        CP#17
+  AllocateContext      1
+  StoreLocal           r5
+  Push                 r5
+  Push                 r4
+  StoreFieldTOS        CP#0
+  PopLocal             r4
+  Push                 r4
+  Push                 r10
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#1
+  PushConstant         CP#8
+  PushConstant         CP#8
+  PushConstant         CP#27
+  InstanceCall1        4, CP#28
+  PushConstant         CP#29
+  IfNeStrictTOS
+  Jump                 L4
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  PushConstant         CP#30
+  StoreLocal           r12
+  StoreFieldTOS        CP#9
+  Push                 r12
+  Drop1
+  Jump                 L5
+L4:
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#1
+  StoreLocal           r12
+  StoreFieldTOS        CP#3
+  Push                 r12
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  PushConstant         CP#31
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#2
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#2
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#10
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#11
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#32
+  IndirectStaticCall   4, CP#22
+  PopLocal             r13
+  PushConstant         CP#8
+  ReturnTOS
+L14:
+  IfEqNull             r2
+  Jump                 L6
+  Push                 r2
+  Push                 r3
+  Throw                1
+L6:
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#3
+  Push                 r1
+  InstanceCall1        2, CP#33
+  StoreLocal           r12
+  StoreFieldTOS        CP#1
+  Push                 r12
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#16
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#17
+  Throw                1
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  Jump                 L3
+L3:
+  Jump                 L7
+Try #1 end:
+Try #1 handler:
+  Push                 r0
+  LoadFieldTOS         CP#19
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#14
+  PopLocal             r4
+  MoveSpecial          r8, exception
+  MoveSpecial          r9, stackTrace
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r8
+  StoreFieldTOS        CP#16
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r9
+  StoreFieldTOS        CP#17
+  PushConstant         CP#34
+  PushConstant         CP#36
+  IndirectStaticCall   1, CP#35
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r10
+  StoreFieldTOS        CP#3
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PushConstant         CP#37
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#2
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#3
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#10
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#11
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#38
+  IndirectStaticCall   4, CP#22
+  PopLocal             r12
+  PushConstant         CP#8
+  ReturnTOS
+L15:
+  IfEqNull             r2
+  Jump                 L8
+  Push                 r2
+  Push                 r3
+  Throw                1
+L8:
+  Push                 r4
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#3
+  Push                 r1
+  InstanceCall1        2, CP#39
+  StoreLocal           r10
+  StoreFieldTOS        CP#1
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r10
+  StoreFieldTOS        CP#9
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  Jump                 L9
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#16
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#17
+  Throw                1
+L5:
+  Push                 r0
+  LoadFieldTOS         CP#19
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#14
+  PopLocal             r4
+  PushConstant         CP#34
+  PushConstant         CP#40
+  IndirectStaticCall   1, CP#35
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r10
+  StoreFieldTOS        CP#3
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PushConstant         CP#41
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#2
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#3
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#10
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#11
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#42
+  IndirectStaticCall   4, CP#22
+  PopLocal             r12
+  PushConstant         CP#8
+  ReturnTOS
+L16:
+  IfEqNull             r2
+  Jump                 L10
+  Push                 r2
+  Push                 r3
+  Throw                1
+L10:
+  Push                 r4
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#3
+  Push                 r1
+  InstanceCall1        2, CP#43
+  StoreLocal           r10
+  StoreFieldTOS        CP#1
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r10
+  StoreFieldTOS        CP#9
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  Jump                 L9
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  Jump                 L9
+L7:
+  Push                 r0
+  LoadFieldTOS         CP#19
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#14
+  PopLocal             r4
+  PushConstant         CP#34
+  PushConstant         CP#44
+  IndirectStaticCall   1, CP#35
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r10
+  StoreFieldTOS        CP#3
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PushConstant         CP#45
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#2
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#3
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#10
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#11
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#46
+  IndirectStaticCall   4, CP#22
+  PopLocal             r12
+  PushConstant         CP#8
+  ReturnTOS
+L17:
+  IfEqNull             r2
+  Jump                 L11
+  Push                 r2
+  Push                 r3
+  Throw                1
+L11:
+  Push                 r4
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#3
+  Push                 r1
+  InstanceCall1        2, CP#47
+  StoreLocal           r10
+  StoreFieldTOS        CP#1
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r10
+  StoreFieldTOS        CP#9
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  Jump                 L9
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+L9:
+  Push                 r4
+  LoadFieldTOS         CP#7
+  Push                 r4
+  LoadFieldTOS         CP#9
+  InstanceCall1        2, CP#48
+  Drop1
+  PushConstant         CP#8
+  ReturnTOS
+  Jump                 L12
+Try #0 end:
+Try #0 handler:
+  Push                 r0
+  LoadFieldTOS         CP#19
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#13
+  PopLocal             r4
+  MoveSpecial          r6, exception
+  MoveSpecial          r7, stackTrace
+  Push                 r6
+  PopLocal             r8
+  Push                 r7
+  PopLocal             r9
+  Push                 r4
+  LoadFieldTOS         CP#7
+  Push                 r8
+  Push                 r9
+  InstanceCall1        3, CP#50
+  Drop1
+  Jump                 L12
+L12:
+  PushConstant         CP#8
+  ReturnTOS
+L1:
+  Push                 r4
+  LoadFieldTOS         CP#2
+  PopLocal             r4
+  Push                 r5
+  PushConstant         CP#20
+  IfEqStrictNumTOS
+  Jump                 L13
+  Push                 r5
+  PushConstant         CP#31
+  IfEqStrictNumTOS
+  Jump                 L14
+  Push                 r5
+  PushConstant         CP#37
+  IfEqStrictNumTOS
+  Jump                 L15
+  Push                 r5
+  PushConstant         CP#41
+  IfEqStrictNumTOS
+  Jump                 L16
+  Jump                 L17
+
+}
+]static method tryCatchRethrow(asy::Future<core::int> a, asy::Future<core::int> b, asy::Future<core::int> c) → asy::Future<core::int> /* originally async */ {
+  final asy::Completer<core::int> :async_completer = asy::Completer::sync<core::int>();
+  asy::FutureOr<core::int> :return_value;
+  dynamic :async_stack_trace;
+  dynamic :async_op_then;
+  dynamic :async_op_error;
+  dynamic :await_jump_var = 0;
+  dynamic :await_ctx_var;
+  dynamic :saved_try_context_var0;
+  dynamic :saved_try_context_var1;
+  dynamic :saved_try_context_var2;
+  dynamic :exception0;
+  dynamic :stack_trace0;
+  dynamic :async_temporary_0;
+  function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+    try {
+      #L4:
+      {
+        core::int x = 1;
+        try
+          try {
+            :async_temporary_0 = x;
+            [yield] let dynamic #t4 = asy::_awaitHelper(a, :async_op_then, :async_op_error, :async_op) in null;
+            x = :async_temporary_0.{core::num::+}(:result);
+          }
+          on dynamic catch(final dynamic e) {
+            if(e is core::Error) {
+              :return_value = 42;
+              break #L4;
+            }
+            :async_temporary_0 = x;
+            [yield] let dynamic #t5 = asy::_awaitHelper(b, :async_op_then, :async_op_error, :async_op) in null;
+            x = :async_temporary_0.{core::num::+}(:result);
+            rethrow;
+          }
+        finally {
+          core::print("fin");
+          :async_temporary_0 = x;
+          [yield] let dynamic #t6 = asy::_awaitHelper(c, :async_op_then, :async_op_error, :async_op) in null;
+          x = :async_temporary_0.{core::num::+}(:result);
+          :return_value = x;
+          break #L4;
+        }
+      }
+      :async_completer.{asy::Completer::complete}(:return_value);
+      return;
+    }
+    on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+      :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+    }
+  :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+  :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+  :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+  asy::Future::microtask<dynamic>(:async_op);
+  return :async_completer.{asy::Completer::future};
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                4
+  CheckStack
+  AllocateContext      1
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  Push                 FP[-5]
+  StoreFieldTOS        CP#1
+  AllocateContext      1
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  PushConstant         CP#2
+  StoreFieldTOS        CP#1
+  Allocate             CP#36
+  StoreLocal           r3
+  Push                 r3
+  PushConstant         CP#9
+  StoreFieldTOS        CP#37
+  Push                 r3
+  PushConstant         CP#9
+  StoreFieldTOS        CP#38
+  Push                 r3
+  PushConstant         CP#3
+  StoreFieldTOS        CP#39
+  Push                 r3
+  Push                 r0
+  StoreFieldTOS        CP#4
+  PopLocal             r2
+  Push                 r2
+  ReturnTOS
+  Push                 r0
+  LoadFieldTOS         CP#0
+  PopLocal             r0
+  PushConstant         CP#9
+  ReturnTOS
+}
+ConstantPool {
+  [0] = ContextOffset parent
+  [1] = ContextOffset var [0]
+  [2] = Int 3
+  [3] = ClosureFunction nested () → dart.async::Future<dart.core::int> /* originally async */ ;
+  [4] = FieldOffset dart.core::_Closure::_context
+  [5] = TypeArgs [dart.core::int]
+  [6] = ArgDesc num-args 0, num-type-args 1, names []
+  [7] = StaticICData target 'dart.async::Completer::sync', arg-desc CP#6
+  [8] = ContextOffset var [8]
+  [9] = Null
+  [10] = ContextOffset var [7]
+  [11] = ContextOffset var [4]
+  [12] = ContextOffset var [5]
+  [13] = Int 0
+  [14] = ContextOffset var [1]
+  [15] = ContextOffset var [2]
+  [16] = ContextOffset var [3]
+  [17] = ClosureFunction :async_op ([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding ;
+  [18] = Int 4
+  [19] = Int 5
+  [20] = Int 1
+  [21] = ContextOffset var [6]
+  [22] = ArgDesc num-args 4, num-type-args 0, names []
+  [23] = StaticICData target 'dart.async::_awaitHelper', arg-desc CP#22
+  [24] = ArgDesc num-args 2, num-type-args 0, names []
+  [25] = ICData target-name '+', arg-desc CP#24
+  [26] = Type dynamic
+  [27] = String 'fin'
+  [28] = ArgDesc num-args 1, num-type-args 0, names []
+  [29] = StaticICData target 'dart.core::print', arg-desc CP#28
+  [30] = StaticICData target 'dart.core::print', arg-desc CP#28
+  [31] = StaticICData target 'dart.core::print', arg-desc CP#28
+  [32] = ICData target-name 'complete', arg-desc CP#24
+  [33] = ArgDesc num-args 3, num-type-args 0, names []
+  [34] = ICData target-name 'completeError', arg-desc CP#33
+  [35] = EndClosureFunctionScope
+  [36] = Class dart.core::_Closure
+  [37] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
+  [38] = FieldOffset dart.core::_Closure::_function_type_arguments
+  [39] = FieldOffset dart.core::_Closure::_function
+  [40] = StaticICData target 'dart.async::_asyncStackTraceHelper', arg-desc CP#28
+  [41] = StaticICData target 'dart.async::_asyncThenWrapperHelper', arg-desc CP#28
+  [42] = StaticICData target 'dart.async::_asyncErrorWrapperHelper', arg-desc CP#28
+  [43] = TypeArgs [dynamic]
+  [44] = ArgDesc num-args 1, num-type-args 1, names []
+  [45] = StaticICData target 'dart.async::Future::microtask', arg-desc CP#44
+  [46] = ICData get target-name 'future', arg-desc CP#28
+  [47] = EndClosureFunctionScope
+}
+Closure CP#17 {
+  EntryOptional        1, 3, 0
+  LoadConstant         r1, CP#9
+  LoadConstant         r2, CP#9
+  LoadConstant         r3, CP#9
+  Frame                8
+  CheckStack
+  Push                 r0
+  LoadFieldTOS         CP#4
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#1
+  StoreLocal           r5
+  PushConstant         CP#13
+  IfNeStrictNumTOS
+  Jump                 L1
+  Push                 r4
+  Push                 r4
+  StoreFieldTOS        CP#15
+Try #0 start:
+  AllocateContext      1
+  StoreLocal           r5
+  Push                 r5
+  Push                 r4
+  StoreFieldTOS        CP#0
+  PopLocal             r4
+  Push                 r4
+  PushConstant         CP#18
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#16
+Try #1 start:
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  PushConstant         CP#19
+  StoreLocal           r10
+  StoreFieldTOS        CP#1
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PushConstant         CP#20
+  StoreFieldTOS        CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  StoreFieldTOS        CP#14
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#11
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#12
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#23
+  IndirectStaticCall   4, CP#22
+  PopLocal             r11
+  PushConstant         CP#9
+  ReturnTOS
+L6:
+  Push                 r4
+  Push                 r1
+  StoreLocal           r10
+  StoreFieldTOS        CP#1
+  Push                 r10
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  Push                 r4
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#0
+  LoadFieldTOS         CP#1
+  Push                 r4
+  LoadFieldTOS         CP#1
+  InstanceCall1        2, CP#25
+  StoreLocal           r10
+  StoreFieldTOS        CP#10
+  Push                 r10
+  Drop1
+  Jump                 L2
+  Jump                 L3
+Try #1 end:
+Try #1 handler:
+  Push                 r0
+  LoadFieldTOS         CP#4
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#16
+  PopLocal             r4
+  MoveSpecial          r8, exception
+  MoveSpecial          r9, stackTrace
+  PushConstant         CP#27
+  PushConstant         CP#29
+  IndirectStaticCall   1, CP#28
+  Drop1
+  Push                 r8
+  Push                 r9
+  Throw                1
+L2:
+  Push                 r0
+  LoadFieldTOS         CP#4
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#16
+  PopLocal             r4
+  PushConstant         CP#27
+  PushConstant         CP#30
+  IndirectStaticCall   1, CP#28
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+  Jump                 L4
+L3:
+  Push                 r0
+  LoadFieldTOS         CP#4
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#16
+  PopLocal             r4
+  PushConstant         CP#27
+  PushConstant         CP#31
+  IndirectStaticCall   1, CP#28
+  Drop1
+  Push                 r4
+  LoadFieldTOS         CP#0
+  PopLocal             r4
+L4:
+  Push                 r4
+  LoadFieldTOS         CP#8
+  Push                 r4
+  LoadFieldTOS         CP#10
+  InstanceCall1        2, CP#32
+  Drop1
+  PushConstant         CP#9
+  ReturnTOS
+  Jump                 L5
+Try #0 end:
+Try #0 handler:
+  Push                 r0
+  LoadFieldTOS         CP#4
+  PopLocal             r4
+  Push                 r4
+  LoadFieldTOS         CP#15
+  PopLocal             r4
+  MoveSpecial          r6, exception
+  MoveSpecial          r7, stackTrace
+  Push                 r6
+  PopLocal             r8
+  Push                 r7
+  PopLocal             r9
+  Push                 r4
+  LoadFieldTOS         CP#8
+  Push                 r8
+  Push                 r9
+  InstanceCall1        3, CP#34
+  Drop1
+  Jump                 L5
+L5:
+  PushConstant         CP#9
+  ReturnTOS
+L1:
+  Push                 r4
+  LoadFieldTOS         CP#14
+  PopLocal             r4
+  Jump                 L6
+
+}
+
+Closure CP#3 {
+  Entry                4
+  CheckStack
+  Push                 FP[-5]
+  LoadFieldTOS         CP#4
+  PopLocal             r0
+  AllocateContext      9
+  StoreLocal           r1
+  Push                 r1
+  Push                 r0
+  StoreFieldTOS        CP#0
+  PopLocal             r0
+  Push                 r0
+  PushConstant         CP#5
+  PushConstant         CP#7
+  IndirectStaticCall   1, CP#6
+  StoreFieldTOS        CP#8
+  Push                 r0
+  PushConstant         CP#9
+  StoreFieldTOS        CP#10
+  PushConstant         CP#9
+  PopLocal             r2
+  Push                 r0
+  PushConstant         CP#9
+  StoreFieldTOS        CP#11
+  Push                 r0
+  PushConstant         CP#9
+  StoreFieldTOS        CP#12
+  Push                 r0
+  PushConstant         CP#13
+  StoreFieldTOS        CP#1
+  Push                 r0
+  PushConstant         CP#9
+  StoreFieldTOS        CP#14
+  Push                 r0
+  PushConstant         CP#9
+  StoreFieldTOS        CP#15
+  Push                 r0
+  PushConstant         CP#9
+  StoreFieldTOS        CP#16
+  Push                 r0
+  Allocate             CP#36
+  StoreLocal           r3
+  Push                 r3
+  PushConstant         CP#9
+  StoreFieldTOS        CP#37
+  Push                 r3
+  PushConstant         CP#9
+  StoreFieldTOS        CP#38
+  Push                 r3
+  PushConstant         CP#17
+  StoreFieldTOS        CP#39
+  Push                 r3
+  Push                 r0
+  StoreFieldTOS        CP#4
+  StoreFieldTOS        CP#21
+  Push                 r0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#40
+  IndirectStaticCall   1, CP#28
+  StoreLocal           r2
+  Drop1
+  Push                 r0
+  Push                 r0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#41
+  IndirectStaticCall   1, CP#28
+  StoreLocal           r3
+  StoreFieldTOS        CP#11
+  Push                 r3
+  Drop1
+  Push                 r0
+  Push                 r0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#42
+  IndirectStaticCall   1, CP#28
+  StoreLocal           r3
+  StoreFieldTOS        CP#12
+  Push                 r3
+  Drop1
+  PushConstant         CP#43
+  Push                 r0
+  LoadFieldTOS         CP#21
+  PushConstant         CP#45
+  IndirectStaticCall   2, CP#44
+  Drop1
+  Push                 r0
+  LoadFieldTOS         CP#8
+  InstanceCall1        1, CP#46
+  ReturnTOS
+  Push                 r0
+  LoadFieldTOS         CP#0
+  PopLocal             r0
+  PushConstant         CP#9
+  ReturnTOS
+
+}
+]static method closure(asy::Future<core::int> a) → dynamic {
+  core::int x = 3;
+  function nested() → asy::Future<core::int> /* originally async */ {
+    final asy::Completer<core::int> :async_completer = asy::Completer::sync<core::int>();
+    asy::FutureOr<core::int> :return_value;
+    dynamic :async_stack_trace;
+    dynamic :async_op_then;
+    dynamic :async_op_error;
+    dynamic :await_jump_var = 0;
+    dynamic :await_ctx_var;
+    dynamic :saved_try_context_var0;
+    dynamic :saved_try_context_var1;
+    function :async_op([dynamic :result, dynamic :exception, dynamic :stack_trace]) → dynamic yielding 
+      try {
+        #L5:
+        {
+          core::int y = 4;
+          try {
+            x = 5;
+            [yield] let dynamic #t7 = asy::_awaitHelper(a, :async_op_then, :async_op_error, :async_op) in null;
+            y = :result;
+            :return_value = x.{core::num::+}(y);
+            break #L5;
+          }
+          finally {
+            core::print("fin");
+          }
+        }
+        :async_completer.{asy::Completer::complete}(:return_value);
+        return;
+      }
+      on dynamic catch(dynamic :exception, dynamic :stack_trace) {
+        :async_completer.{asy::Completer::completeError}(:exception, :stack_trace);
+      }
+    :async_stack_trace = asy::_asyncStackTraceHelper(:async_op);
+    :async_op_then = asy::_asyncThenWrapperHelper(:async_op);
+    :async_op_error = asy::_asyncErrorWrapperHelper(:async_op);
+    asy::Future::microtask<dynamic>(:async_op);
+    return :async_completer.{asy::Completer::future};
+  }
+  return nested;
+}
+[@vm.bytecode=
+Bytecode {
+  Entry                0
+  CheckStack
+  PushConstant         CP#0
+  ReturnTOS
+}
+ConstantPool {
+  [0] = Null
+}
+]static method main() → dynamic {}