Index: pkg/compiler/lib/src/closure.dart |
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart |
index 93e7bb2c2b87e60d99bc6d8ac0dcad80f3a7c8c9..fbefe05b7dd83c3f74655b77bef969d9c1c558d7 100644 |
--- a/pkg/compiler/lib/src/closure.dart |
+++ b/pkg/compiler/lib/src/closure.dart |
@@ -272,6 +272,7 @@ class SynthesizedCallMethodElementX extends BaseFunctionElementX { |
ClosureClassElement enclosing) |
: expression = other, |
super(name, other.kind, other.modifiers, enclosing, false) { |
+ asyncMarker = other.asyncMarker; |
functionSignatureCache = other.functionSignature; |
} |
@@ -347,7 +348,13 @@ class ClosureClassMap { |
// contain any nested closure. |
final Map<Node, ClosureScope> capturingScopes = new Map<Node, ClosureScope>(); |
- final Set<Local> usedVariablesInTry = new Set<Local>(); |
+ /// Variables that are used in a try must be treated as boxed because the |
+ /// control flow can be non-linear. |
+ /// |
+ /// Also parameters to a `sync*` generator must be boxed, because of the way |
+ /// we rewrite sync* functions. See also comments in [useLocal]. |
+ /// TODO(johnniwinter): Add variables to this only if the variable is mutated. |
+ final Set<Local> variablesUsedInTryOrGenerator = new Set<Local>(); |
ClosureClassMap(this.closureElement, |
this.closureClassElement, |
@@ -427,6 +434,7 @@ class ClosureTranslator extends Visitor { |
int closureFieldCounter = 0; |
int boxedFieldCounter = 0; |
bool inTryStatement = false; |
+ |
final Map<Node, ClosureClassMap> closureMappingCache; |
// Map of captured variables. Initially they will map to `null`. If |
@@ -588,9 +596,13 @@ class ClosureTranslator extends Visitor { |
// Note that nested (named) functions are immutable. |
if (variable != closureData.thisLocal && |
variable != closureData.closureElement) { |
- // TODO(ngeoffray): only do this if the variable is mutated. |
- closureData.usedVariablesInTry.add(variable); |
+ closureData.variablesUsedInTryOrGenerator.add(variable); |
} |
+ } else if (variable is LocalParameterElement && |
+ variable.functionDeclaration.asyncMarker == AsyncMarker.SYNC_STAR) { |
+ // Parameters in a sync* function are shared between each Iterator created |
+ // by the Iterable returned by the function, therefore they must be boxed. |
+ closureData.variablesUsedInTryOrGenerator.add(variable); |
} |
} |