| Index: pkg/compiler/lib/src/closure.dart
|
| diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
|
| index 44fcc597ac039edf58f5376b60500ac5a9568348..5bdd71b6038b2462da84182c986a4cf119f19a6c 100644
|
| --- a/pkg/compiler/lib/src/closure.dart
|
| +++ b/pkg/compiler/lib/src/closure.dart
|
| @@ -84,13 +84,13 @@ class ScopeInfo {
|
| /// Also parameters to a `sync*` generator must be boxed, because of the way
|
| /// we rewrite sync* functions. See also comments in
|
| /// [ClosureClassMap.useLocal].
|
| - bool variableIsUsedInTryOrSync(Local variable) => false;
|
| + bool localIsUsedInTryOrSync(Local variable) => false;
|
|
|
| /// Loop through each variable that has been defined in this scope, modified
|
| /// anywhere (this scope or another scope) and used in another scope. Because
|
| /// it is used in another scope, these variables need to be "boxed", creating
|
| /// a thin wrapper around accesses to these variables so that accesses get
|
| - /// the correct updated value. The variables in variablesUsedInTryOrSync may
|
| + /// the correct updated value. The variables in localsUsedInTryOrSync may
|
| /// be included in this set.
|
| ///
|
| /// In the case of loops, this is the set of iteration variables (or any
|
| @@ -100,9 +100,6 @@ class ScopeInfo {
|
|
|
| /// True if [variable] has been mutated and is also used in another scope.
|
| bool isBoxed(Local variable) => false;
|
| -
|
| - /// True if this scope declares any variables that need to be boxed.
|
| - bool get hasBoxedVariables => false;
|
| }
|
|
|
| /// Class representing the usage of a scope that has been captured in the
|
| @@ -141,6 +138,27 @@ class ClosureScope extends ScopeInfo {
|
| /// each iteration, by boxing the iteration variable[s].
|
| class LoopClosureScope extends ClosureScope {
|
| const LoopClosureScope();
|
| +
|
| + /// True if this loop scope declares in the first part of the loop
|
| + /// `for (<here>;...;...)` any variables that need to be boxed.
|
| + bool get hasBoxedLoopVariables => false;
|
| +
|
| + /// The set of iteration variables (or variables declared in the for loop
|
| + /// expression (`for (<here>; ... ; ...)`) that need to be boxed to snapshot
|
| + /// their value. These variables are also included in the set of
|
| + /// `forEachBoxedVariable` method. The distinction between these two sets is
|
| + /// in this example:
|
| + ///
|
| + /// run(f) => f();
|
| + /// var a;
|
| + /// for (int i = 0; i < 3; i++) {
|
| + /// var b = 3;
|
| + /// a = () => b = i;
|
| + /// }
|
| + ///
|
| + /// `i` would be a part of the boxedLoopVariables AND boxedVariables, but b
|
| + /// would only be a part of boxedVariables.
|
| + List<Local> get boxedLoopVariables => const <Local>[];
|
| }
|
|
|
| /// Class that describes the actual mechanics of how the converted, rewritten
|
| @@ -647,18 +665,10 @@ class ClosureScopeImpl implements ClosureScope, LoopClosureScope {
|
| bool get requiresContextBox => capturedVariables.keys.isNotEmpty;
|
|
|
| void forEachBoxedVariable(f(Local local, FieldEntity field)) {
|
| - if (capturedVariables.isNotEmpty) {
|
| - capturedVariables.forEach(f);
|
| - } else {
|
| - for (Local l in boxedLoopVariables) {
|
| - // The boxes for loop variables are constructed on-demand per-iteration
|
| - // in the locals handler.
|
| - f(l, null);
|
| - }
|
| - }
|
| + capturedVariables.forEach(f);
|
| }
|
|
|
| - bool get hasBoxedVariables => !capturedVariables.isEmpty;
|
| + bool get hasBoxedLoopVariables => boxedLoopVariables.isNotEmpty;
|
|
|
| bool isBoxed(Local variable) {
|
| return capturedVariables.containsKey(variable);
|
| @@ -670,8 +680,8 @@ class ClosureScopeImpl implements ClosureScope, LoopClosureScope {
|
| }
|
|
|
| // Should not be called. Added to make the new interface happy.
|
| - bool variableIsUsedInTryOrSync(Local variable) =>
|
| - throw new UnsupportedError("ClosureScopeImpl.variableIsUsedInTryOrSync");
|
| + bool localIsUsedInTryOrSync(Local variable) =>
|
| + throw new UnsupportedError("ClosureScopeImpl.localIsUsedInTryOrSync");
|
|
|
| // Should not be called. Added to make the new interface happy.
|
| Local get thisLocal =>
|
| @@ -741,14 +751,11 @@ class ClosureClassMap implements ClosureRepresentationInfo {
|
| /// Also parameters to a `sync*` generator must be boxed, because of the way
|
| /// we rewrite sync* functions. See also comments in [useLocal].
|
| // TODO(johnniwinther): Add variables to this only if the variable is mutated.
|
| - final Set<Local> variablesUsedInTryOrSync = new Set<Local>();
|
| + final Set<Local> localsUsedInTryOrSync = new Set<Local>();
|
|
|
| ClosureClassMap(this.closureEntity, this.closureClassEntity, this.callMethod,
|
| this.thisLocal);
|
|
|
| - bool get hasBoxedVariables =>
|
| - throw new UnsupportedError("ClosureClassMap.hasBoxedVariables");
|
| -
|
| List<Local> get createdFieldEntities {
|
| List<Local> fields = <Local>[];
|
| if (closureClassEntity == null) return const <Local>[];
|
| @@ -775,8 +782,8 @@ class ClosureClassMap implements ClosureRepresentationInfo {
|
|
|
| FieldEntity get thisFieldEntity => freeVariableMap[thisLocal];
|
|
|
| - bool variableIsUsedInTryOrSync(Local variable) =>
|
| - variablesUsedInTryOrSync.contains(variable);
|
| + bool localIsUsedInTryOrSync(Local variable) =>
|
| + localsUsedInTryOrSync.contains(variable);
|
|
|
| Local getLocalVariableForClosureField(ClosureFieldElement field) {
|
| return field.local;
|
| @@ -1025,13 +1032,13 @@ class ClosureTranslator extends Visitor {
|
| if (variable != closureData.thisLocal &&
|
| variable != closureData.closureEntity &&
|
| variable is! TypeVariableLocal) {
|
| - closureData.variablesUsedInTryOrSync.add(variable);
|
| + closureData.localsUsedInTryOrSync.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.variablesUsedInTryOrSync.add(variable);
|
| + closureData.localsUsedInTryOrSync.add(variable);
|
| }
|
| }
|
|
|
|
|