[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 {}