Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(206)

Side by Side Diff: pkg/compiler/lib/src/closure.dart

Issue 2961253005: Added for-loop variable tracking and regular closures/initializers captured variable tracking. (Closed)
Patch Set: . Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'common/names.dart' show Identifiers; 5 import 'common/names.dart' show Identifiers;
6 import 'common/resolution.dart' show ParsingContext, Resolution; 6 import 'common/resolution.dart' show ParsingContext, Resolution;
7 import 'common/tasks.dart' show CompilerTask, Measurer; 7 import 'common/tasks.dart' show CompilerTask, Measurer;
8 import 'common.dart'; 8 import 'common.dart';
9 import 'compiler.dart' show Compiler; 9 import 'compiler.dart' show Compiler;
10 import 'constants/expressions.dart'; 10 import 'constants/expressions.dart';
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 /// the correct updated value. The variables in variablesUsedInTryOrSync may 93 /// the correct updated value. The variables in variablesUsedInTryOrSync may
94 /// be included in this set. 94 /// be included in this set.
95 /// 95 ///
96 /// In the case of loops, this is the set of iteration variables (or any 96 /// In the case of loops, this is the set of iteration variables (or any
97 /// variables declared in the for loop expression (`for (...here...)`) that 97 /// variables declared in the for loop expression (`for (...here...)`) that
98 /// need to be boxed to snapshot their value. 98 /// need to be boxed to snapshot their value.
99 void forEachBoxedVariable(f(Local local, FieldEntity field)) {} 99 void forEachBoxedVariable(f(Local local, FieldEntity field)) {}
100 100
101 /// True if [variable] has been mutated and is also used in another scope. 101 /// True if [variable] has been mutated and is also used in another scope.
102 bool isBoxed(Local variable) => false; 102 bool isBoxed(Local variable) => false;
103
104 /// True if this scope declares any variables that need to be boxed.
105 bool get hasBoxedVariables => false;
106 } 103 }
107 104
108 /// Class representing the usage of a scope that has been captured in the 105 /// Class representing the usage of a scope that has been captured in the
109 /// context of a closure. 106 /// context of a closure.
110 class ClosureScope extends ScopeInfo { 107 class ClosureScope extends ScopeInfo {
111 const ClosureScope(); 108 const ClosureScope();
112 109
113 /// If true, this closure accesses a variable that was defined in an outside 110 /// If true, this closure accesses a variable that was defined in an outside
114 /// scope and this variable gets modified at some point (sometimes we say that 111 /// scope and this variable gets modified at some point (sometimes we say that
115 /// variable has been "captured"). In this situation, access to this variable 112 /// variable has been "captured"). In this situation, access to this variable
(...skipping 18 matching lines...) Expand all
134 /// var lst = []; 131 /// var lst = [];
135 /// for (int i = 0; i < 5; i++) lst.add(()=>i); 132 /// for (int i = 0; i < 5; i++) lst.add(()=>i);
136 /// var result = list.map((f) => f()).toList(); 133 /// var result = list.map((f) => f()).toList();
137 /// 134 ///
138 /// `result` will be [0, 1, 2, 3, 4], whereas were this JS code 135 /// `result` will be [0, 1, 2, 3, 4], whereas were this JS code
139 /// the result would be [5, 5, 5, 5, 5]. Because of this difference we need to 136 /// the result would be [5, 5, 5, 5, 5]. Because of this difference we need to
140 /// create a closure for these sorts of loops to capture the variable's value at 137 /// create a closure for these sorts of loops to capture the variable's value at
141 /// each iteration, by boxing the iteration variable[s]. 138 /// each iteration, by boxing the iteration variable[s].
142 class LoopClosureScope extends ClosureScope { 139 class LoopClosureScope extends ClosureScope {
143 const LoopClosureScope(); 140 const LoopClosureScope();
141
142 /// True if this loop scope declares in the first part of the loop
143 /// `for (<here>;...;...)` any variables that need to be boxed.
144 bool get hasBoxedLoopVariables => false;
145
146 /// The set of iteration variables (or variables declared in the for loop
147 /// expression (`for (<here>; ... ; ...)`) that need to be boxed to snapshot
148 /// their value. These variables are also included in the set of
149 /// `forEachBoxedVariable` method. The distinction between these two sets is
150 /// in this example:
151 ///
152 /// run(f) => f();
153 /// var a;
154 /// for (int i = 0; i < 3; i++) {
155 /// var b = 3;
156 /// a = () => b = i;
157 /// }
158 ///
159 /// `i` would be a part of the boxedLoopVariables AND boxedVariables, but b
160 /// would only be a part of boxedVariables.
161 List<Local> get boxedLoopVariables => const <Local>[];
144 } 162 }
145 163
146 /// Class that describes the actual mechanics of how the converted, rewritten 164 /// Class that describes the actual mechanics of how the converted, rewritten
147 /// closure is implemented. For example, for the following closure (named foo 165 /// closure is implemented. For example, for the following closure (named foo
148 /// for convenience): 166 /// for convenience):
149 /// 167 ///
150 /// var foo = (x) => y + x; 168 /// var foo = (x) => y + x;
151 /// 169 ///
152 /// We would produce the following class to control access to these variables in 170 /// We would produce the following class to control access to these variables in
153 /// the following way (modulo naming of variables, assuming that y is modified 171 /// the following way (modulo naming of variables, assuming that y is modified
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 // Otherwise contains the empty List. 658 // Otherwise contains the empty List.
641 List<Local> boxedLoopVariables = const <Local>[]; 659 List<Local> boxedLoopVariables = const <Local>[];
642 660
643 ClosureScopeImpl(this.boxElement, this.capturedVariables); 661 ClosureScopeImpl(this.boxElement, this.capturedVariables);
644 662
645 Local get context => boxElement; 663 Local get context => boxElement;
646 664
647 bool get requiresContextBox => capturedVariables.keys.isNotEmpty; 665 bool get requiresContextBox => capturedVariables.keys.isNotEmpty;
648 666
649 void forEachBoxedVariable(f(Local local, FieldEntity field)) { 667 void forEachBoxedVariable(f(Local local, FieldEntity field)) {
650 if (capturedVariables.isNotEmpty) { 668 capturedVariables.forEach(f);
651 capturedVariables.forEach(f);
652 } else {
653 for (Local l in boxedLoopVariables) {
654 // The boxes for loop variables are constructed on-demand per-iteration
655 // in the locals handler.
656 f(l, null);
657 }
658 }
659 } 669 }
660 670
661 bool get hasBoxedVariables => !capturedVariables.isEmpty; 671 bool get hasBoxedLoopVariables => boxedLoopVariables.isNotEmpty;
662 672
663 bool isBoxed(Local variable) { 673 bool isBoxed(Local variable) {
664 return capturedVariables.containsKey(variable); 674 return capturedVariables.containsKey(variable);
665 } 675 }
666 676
667 void forEachCapturedVariable( 677 void forEachCapturedVariable(
668 f(LocalVariableElement variable, BoxFieldElement boxField)) { 678 f(LocalVariableElement variable, BoxFieldElement boxField)) {
669 capturedVariables.forEach(f); 679 capturedVariables.forEach(f);
670 } 680 }
671 681
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 /// control flow can be non-linear. 749 /// control flow can be non-linear.
740 /// 750 ///
741 /// Also parameters to a `sync*` generator must be boxed, because of the way 751 /// Also parameters to a `sync*` generator must be boxed, because of the way
742 /// we rewrite sync* functions. See also comments in [useLocal]. 752 /// we rewrite sync* functions. See also comments in [useLocal].
743 // TODO(johnniwinther): Add variables to this only if the variable is mutated. 753 // TODO(johnniwinther): Add variables to this only if the variable is mutated.
744 final Set<Local> variablesUsedInTryOrSync = new Set<Local>(); 754 final Set<Local> variablesUsedInTryOrSync = new Set<Local>();
745 755
746 ClosureClassMap(this.closureEntity, this.closureClassEntity, this.callMethod, 756 ClosureClassMap(this.closureEntity, this.closureClassEntity, this.callMethod,
747 this.thisLocal); 757 this.thisLocal);
748 758
749 bool get hasBoxedVariables =>
750 throw new UnsupportedError("ClosureClassMap.hasBoxedVariables");
751
752 List<Local> get createdFieldEntities { 759 List<Local> get createdFieldEntities {
753 List<Local> fields = <Local>[]; 760 List<Local> fields = <Local>[];
754 if (closureClassEntity == null) return const <Local>[]; 761 if (closureClassEntity == null) return const <Local>[];
755 closureClassEntity.closureFields.forEach((field) { 762 closureClassEntity.closureFields.forEach((field) {
756 fields.add(field.local); 763 fields.add(field.local);
757 }); 764 });
758 return fields; 765 return fields;
759 } 766 }
760 767
761 void addFreeVariable(Local element) { 768 void addFreeVariable(Local element) {
(...skipping 763 matching lines...) Expand 10 before | Expand all | Expand 10 after
1525 /// 1532 ///
1526 /// Move the below classes to a JS model eventually. 1533 /// Move the below classes to a JS model eventually.
1527 /// 1534 ///
1528 abstract class JSEntity implements MemberEntity { 1535 abstract class JSEntity implements MemberEntity {
1529 Local get declaredEntity; 1536 Local get declaredEntity;
1530 } 1537 }
1531 1538
1532 abstract class PrivatelyNamedJSEntity implements JSEntity { 1539 abstract class PrivatelyNamedJSEntity implements JSEntity {
1533 Entity get rootOfScope; 1540 Entity get rootOfScope;
1534 } 1541 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_model/closure.dart » ('j') | pkg/compiler/lib/src/js_model/closure.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698