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

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

Issue 2975323002: Renamed some scoping classes to make their usage clearer. (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
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_model/closure.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 // one for local functions. 46 // one for local functions.
47 ScopeInfo getScopeInfo(covariant Entity member); 47 ScopeInfo getScopeInfo(covariant Entity member);
48 48
49 /// This returns the same information as ScopeInfo, but can be called in 49 /// This returns the same information as ScopeInfo, but can be called in
50 /// situations when you are sure you are dealing with a closure specifically. 50 /// situations when you are sure you are dealing with a closure specifically.
51 ClosureRepresentationInfo getClosureRepresentationInfo( 51 ClosureRepresentationInfo getClosureRepresentationInfo(
52 covariant Entity member); 52 covariant Entity member);
53 53
54 /// Look up information about a loop, in case any variables it declares need 54 /// Look up information about a loop, in case any variables it declares need
55 /// to be boxed/snapshotted. 55 /// to be boxed/snapshotted.
56 LoopClosureScope getLoopClosureScope(T loopNode); 56 CapturedLoopScope getCapturedLoopScope(T loopNode);
57 57
58 /// Accessor to the information about closures that the SSA builder will use. 58 /// Accessor to the information about scopes that closures capture. Used by
59 ClosureScope getClosureScope(MemberEntity entity); 59 /// the SSA builder.
60 CapturedScope getCapturedScope(MemberEntity entity);
60 } 61 }
61 62
62 /// Class that represents one level of scoping information, whether this scope 63 /// Class that represents one level of scoping information, whether this scope
63 /// is a closure or not. This is specifically used to store information 64 /// is a closure or not. This is specifically used to store information
64 /// about the usage of variables in try or sync blocks, because they need to be 65 /// about the usage of variables in try or sync blocks, because they need to be
65 /// boxed. 66 /// boxed.
66 /// 67 ///
67 /// Variables that are used in a try must be treated as boxed because the 68 /// Variables that are used in a try must be treated as boxed because the
68 /// control flow can be non-linear. Also parameters to a `sync*` generator must 69 /// control flow can be non-linear. Also parameters to a `sync*` generator must
69 /// be boxed, because of the way we rewrite sync* functions. See also comments 70 /// be boxed, because of the way we rewrite sync* functions. See also comments
(...skipping 28 matching lines...) Expand all
98 /// variables declared in the for loop expression (`for (...here...)`) that 99 /// variables declared in the for loop expression (`for (...here...)`) that
99 /// need to be boxed to snapshot their value. 100 /// need to be boxed to snapshot their value.
100 void forEachBoxedVariable(f(Local local, FieldEntity field)) {} 101 void forEachBoxedVariable(f(Local local, FieldEntity field)) {}
101 102
102 /// True if [variable] has been mutated and is also used in another scope. 103 /// True if [variable] has been mutated and is also used in another scope.
103 bool isBoxed(Local variable) => false; 104 bool isBoxed(Local variable) => false;
104 } 105 }
105 106
106 /// Class representing the usage of a scope that has been captured in the 107 /// Class representing the usage of a scope that has been captured in the
107 /// context of a closure. 108 /// context of a closure.
108 class ClosureScope extends ScopeInfo { 109 class CapturedScope extends ScopeInfo {
109 const ClosureScope(); 110 const CapturedScope();
110 111
111 /// If true, this closure accesses a variable that was defined in an outside 112 /// If true, this closure accesses a variable that was defined in an outside
112 /// scope and this variable gets modified at some point (sometimes we say that 113 /// scope and this variable gets modified at some point (sometimes we say that
113 /// variable has been "captured"). In this situation, access to this variable 114 /// variable has been "captured"). In this situation, access to this variable
114 /// is controlled via a wrapper (box) so that updates to this variable 115 /// is controlled via a wrapper (box) so that updates to this variable
115 /// are done in a way that is in line with Dart's closure rules. 116 /// are done in a way that is in line with Dart's closure rules.
116 bool get requiresContextBox => false; 117 bool get requiresContextBox => false;
117 118
118 /// Accessor to the local environment in which a particular closure node is 119 /// Accessor to the local environment in which a particular closure node is
119 /// executed. This will encapsulate the value of any variables that have been 120 /// executed. This will encapsulate the value of any variables that have been
(...skipping 10 matching lines...) Expand all
130 /// following loop: 131 /// following loop:
131 /// 132 ///
132 /// var lst = []; 133 /// var lst = [];
133 /// for (int i = 0; i < 5; i++) lst.add(()=>i); 134 /// for (int i = 0; i < 5; i++) lst.add(()=>i);
134 /// var result = list.map((f) => f()).toList(); 135 /// var result = list.map((f) => f()).toList();
135 /// 136 ///
136 /// `result` will be [0, 1, 2, 3, 4], whereas were this JS code 137 /// `result` will be [0, 1, 2, 3, 4], whereas were this JS code
137 /// the result would be [5, 5, 5, 5, 5]. Because of this difference we need to 138 /// the result would be [5, 5, 5, 5, 5]. Because of this difference we need to
138 /// create a closure for these sorts of loops to capture the variable's value at 139 /// create a closure for these sorts of loops to capture the variable's value at
139 /// each iteration, by boxing the iteration variable[s]. 140 /// each iteration, by boxing the iteration variable[s].
140 class LoopClosureScope extends ClosureScope { 141 class CapturedLoopScope extends CapturedScope {
141 const LoopClosureScope(); 142 const CapturedLoopScope();
142 143
143 /// True if this loop scope declares in the first part of the loop 144 /// True if this loop scope declares in the first part of the loop
144 /// `for (<here>;...;...)` any variables that need to be boxed. 145 /// `for (<here>;...;...)` any variables that need to be boxed.
145 bool get hasBoxedLoopVariables => false; 146 bool get hasBoxedLoopVariables => false;
146 147
147 /// The set of iteration variables (or variables declared in the for loop 148 /// The set of iteration variables (or variables declared in the for loop
148 /// expression (`for (<here>; ... ; ...)`) that need to be boxed to snapshot 149 /// expression (`for (<here>; ... ; ...)`) that need to be boxed to snapshot
149 /// their value. These variables are also included in the set of 150 /// their value. These variables are also included in the set of
150 /// `forEachBoxedVariable` method. The distinction between these two sets is 151 /// `forEachBoxedVariable` method. The distinction between these two sets is
151 /// in this example: 152 /// in this example:
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 /// variables do not require boxing). 245 /// variables do not require boxing).
245 bool isVariableBoxed(Local variable) => false; 246 bool isVariableBoxed(Local variable) => false;
246 247
247 // TODO(efortuna): Remove this method. The old system was using 248 // TODO(efortuna): Remove this method. The old system was using
248 // ClosureClassMaps for situations other than closure class maps, and that's 249 // ClosureClassMaps for situations other than closure class maps, and that's
249 // just confusing. 250 // just confusing.
250 bool get isClosure => false; 251 bool get isClosure => false;
251 } 252 }
252 253
253 class ClosureTask extends ClosureConversionTask<Node> { 254 class ClosureTask extends ClosureConversionTask<Node> {
254 Map<Node, ClosureScopeImpl> _closureInfoMap = <Node, ClosureScopeImpl>{}; 255 Map<Node, CapturedScopeImpl> _closureInfoMap = <Node, CapturedScopeImpl>{};
255 Map<Element, ClosureClassMap> _closureMappingCache = 256 Map<Element, ClosureClassMap> _closureMappingCache =
256 <Element, ClosureClassMap>{}; 257 <Element, ClosureClassMap>{};
257 Compiler compiler; 258 Compiler compiler;
258 ClosureTask(Compiler compiler) 259 ClosureTask(Compiler compiler)
259 : compiler = compiler, 260 : compiler = compiler,
260 super(compiler.measurer); 261 super(compiler.measurer);
261 262
262 String get name => "Closure Simplifier"; 263 String get name => "Closure Simplifier";
263 264
264 DiagnosticReporter get reporter => compiler.reporter; 265 DiagnosticReporter get reporter => compiler.reporter;
265 266
266 void convertClosures(Iterable<MemberEntity> processedEntities, 267 void convertClosures(Iterable<MemberEntity> processedEntities,
267 ClosedWorldRefiner closedWorldRefiner) { 268 ClosedWorldRefiner closedWorldRefiner) {
268 createClosureClasses(closedWorldRefiner); 269 createClosureClasses(closedWorldRefiner);
269 } 270 }
270 271
271 ClosureScope _getClosureScope(Node node) { 272 CapturedScope _getCapturedScope(Node node) {
272 var value = _closureInfoMap[node]; 273 var value = _closureInfoMap[node];
273 return value == null ? const ClosureScope() : value; 274 return value == null ? const CapturedScope() : value;
274 } 275 }
275 276
276 ClosureScope getClosureScope(covariant MemberElement member) { 277 CapturedScope getCapturedScope(covariant MemberElement member) {
277 ResolvedAst resolvedAst = member.resolvedAst; 278 ResolvedAst resolvedAst = member.resolvedAst;
278 if (resolvedAst.kind != ResolvedAstKind.PARSED) return const ClosureScope(); 279 if (resolvedAst.kind != ResolvedAstKind.PARSED)
279 return _getClosureScope(resolvedAst.node); 280 return const CapturedScope();
281 return _getCapturedScope(resolvedAst.node);
280 } 282 }
281 283
282 ScopeInfo getScopeInfo(Element member) { 284 ScopeInfo getScopeInfo(Element member) {
283 return getClosureToClassMapping(member); 285 return getClosureToClassMapping(member);
284 } 286 }
285 287
286 ClosureRepresentationInfo getClosureRepresentationInfo(Element member) { 288 ClosureRepresentationInfo getClosureRepresentationInfo(Element member) {
287 return getClosureToClassMapping(member); 289 return getClosureToClassMapping(member);
288 } 290 }
289 291
290 LoopClosureScope getLoopClosureScope(Node loopNode) { 292 CapturedLoopScope getCapturedLoopScope(Node loopNode) {
291 var value = _closureInfoMap[loopNode]; 293 var value = _closureInfoMap[loopNode];
292 return value == null ? const LoopClosureScope() : value; 294 return value == null ? const CapturedLoopScope() : value;
293 } 295 }
294 296
295 /// Returns the [ClosureClassMap] computed for [resolvedAst]. 297 /// Returns the [ClosureClassMap] computed for [resolvedAst].
296 ClosureClassMap getClosureToClassMapping(Element element) { 298 ClosureClassMap getClosureToClassMapping(Element element) {
297 return measure(() { 299 return measure(() {
298 if (element.isGenerativeConstructorBody) { 300 if (element.isGenerativeConstructorBody) {
299 ConstructorBodyElement constructorBody = element; 301 ConstructorBodyElement constructorBody = element;
300 element = constructorBody.constructor; 302 element = constructorBody.constructor;
301 } 303 }
302 ClosureClassMap closureClassMap = _closureMappingCache[element]; 304 ClosureClassMap closureClassMap = _closureMappingCache[element];
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 expression.compilationUnit.script.resourceUri); 650 expression.compilationUnit.script.resourceUri);
649 } 651 }
650 652
651 accept(ElementVisitor visitor, arg) { 653 accept(ElementVisitor visitor, arg) {
652 return visitor.visitMethodElement(this, arg); 654 return visitor.visitMethodElement(this, arg);
653 } 655 }
654 } 656 }
655 657
656 // The box-element for a scope, and the captured variables that need to be 658 // The box-element for a scope, and the captured variables that need to be
657 // stored in the box. 659 // stored in the box.
658 class ClosureScopeImpl implements ClosureScope, LoopClosureScope { 660 class CapturedScopeImpl implements CapturedScope, CapturedLoopScope {
659 final BoxLocal boxElement; 661 final BoxLocal boxElement;
660 final Map<Local, BoxFieldElement> capturedVariables; 662 final Map<Local, BoxFieldElement> capturedVariables;
661 663
662 // If the scope is attached to a [For] contains the variables that are 664 // If the scope is attached to a [For] contains the variables that are
663 // declared in the initializer of the [For] and that need to be boxed. 665 // declared in the initializer of the [For] and that need to be boxed.
664 // Otherwise contains the empty List. 666 // Otherwise contains the empty List.
665 List<Local> boxedLoopVariables = const <Local>[]; 667 List<Local> boxedLoopVariables = const <Local>[];
666 668
667 ClosureScopeImpl(this.boxElement, this.capturedVariables); 669 CapturedScopeImpl(this.boxElement, this.capturedVariables);
668 670
669 Local get context => boxElement; 671 Local get context => boxElement;
670 672
671 bool get requiresContextBox => capturedVariables.keys.isNotEmpty; 673 bool get requiresContextBox => capturedVariables.keys.isNotEmpty;
672 674
673 void forEachBoxedVariable(f(Local local, FieldEntity field)) { 675 void forEachBoxedVariable(f(Local local, FieldEntity field)) {
674 capturedVariables.forEach(f); 676 capturedVariables.forEach(f);
675 } 677 }
676 678
677 bool get hasBoxedLoopVariables => boxedLoopVariables.isNotEmpty; 679 bool get hasBoxedLoopVariables => boxedLoopVariables.isNotEmpty;
678 680
679 bool isBoxed(Local variable) { 681 bool isBoxed(Local variable) {
680 return capturedVariables.containsKey(variable); 682 return capturedVariables.containsKey(variable);
681 } 683 }
682 684
683 void forEachCapturedVariable( 685 void forEachCapturedVariable(
684 f(LocalVariableElement variable, BoxFieldElement boxField)) { 686 f(LocalVariableElement variable, BoxFieldElement boxField)) {
685 capturedVariables.forEach(f); 687 capturedVariables.forEach(f);
686 } 688 }
687 689
688 // Should not be called. Added to make the new interface happy. 690 // Should not be called. Added to make the new interface happy.
689 bool localIsUsedInTryOrSync(Local variable) => 691 bool localIsUsedInTryOrSync(Local variable) =>
690 throw new UnsupportedError("ClosureScopeImpl.localIsUsedInTryOrSync"); 692 throw new UnsupportedError("CapturedScopeImpl.localIsUsedInTryOrSync");
691 693
692 // Should not be called. Added to make the new interface happy. 694 // Should not be called. Added to make the new interface happy.
693 Local get thisLocal => 695 Local get thisLocal =>
694 throw new UnsupportedError("ClosureScopeImpl.thisLocal"); 696 throw new UnsupportedError("CapturedScopeImpl.thisLocal");
695 697
696 String toString() { 698 String toString() {
697 String separator = ''; 699 String separator = '';
698 StringBuffer sb = new StringBuffer(); 700 StringBuffer sb = new StringBuffer();
699 sb.write('ClosureScopeImpl('); 701 sb.write('CapturedScopeImpl(');
700 if (boxElement != null) { 702 if (boxElement != null) {
701 sb.write('box=$boxElement'); 703 sb.write('box=$boxElement');
702 separator = ','; 704 separator = ',';
703 } 705 }
704 if (boxedLoopVariables.isNotEmpty) { 706 if (boxedLoopVariables.isNotEmpty) {
705 sb.write(separator); 707 sb.write(separator);
706 sb.write('boxedLoopVariables=${boxedLoopVariables}'); 708 sb.write('boxedLoopVariables=${boxedLoopVariables}');
707 separator = ','; 709 separator = ',';
708 } 710 }
709 if (capturedVariables.isNotEmpty) { 711 if (capturedVariables.isNotEmpty) {
(...skipping 23 matching lines...) Expand all
733 final MethodElement callMethod; 735 final MethodElement callMethod;
734 736
735 /// The [thisLocal] makes handling 'this' easier by treating it like any 737 /// The [thisLocal] makes handling 'this' easier by treating it like any
736 /// other argument. It is only set for instance-members. 738 /// other argument. It is only set for instance-members.
737 final ThisLocal thisLocal; 739 final ThisLocal thisLocal;
738 740
739 /// Maps free locals, arguments, function elements, and box locals to 741 /// Maps free locals, arguments, function elements, and box locals to
740 /// their locations. 742 /// their locations.
741 final Map<Local, FieldEntity> freeVariableMap = new Map<Local, FieldEntity>(); 743 final Map<Local, FieldEntity> freeVariableMap = new Map<Local, FieldEntity>();
742 744
743 /// Maps [Loop] and [FunctionExpression] nodes to their [ClosureScopeImpl] whi ch 745 /// Maps [Loop] and [FunctionExpression] nodes to their [CapturedScopeImpl] wh ich
744 /// contains their box and the captured variables that are stored in the box. 746 /// contains their box and the captured variables that are stored in the box.
745 /// This map will be empty if the method/closure of this [ClosureData] does 747 /// This map will be empty if the method/closure of this [ClosureData] does
746 /// not contain any nested closure. 748 /// not contain any nested closure.
747 final Map<Node, ClosureScopeImpl> capturingScopes = 749 final Map<Node, CapturedScopeImpl> capturingScopes =
748 new Map<Node, ClosureScopeImpl>(); 750 new Map<Node, CapturedScopeImpl>();
749 751
750 /// Set of [variable]s referenced in this scope that are used inside a 752 /// Set of [variable]s referenced in this scope that are used inside a
751 /// `try` block or a `sync*` generator (this is important to know because 753 /// `try` block or a `sync*` generator (this is important to know because
752 /// boxing/redirection needs to happen for those local variables). 754 /// boxing/redirection needs to happen for those local variables).
753 /// 755 ///
754 /// Variables that are used in a try must be treated as boxed because the 756 /// Variables that are used in a try must be treated as boxed because the
755 /// control flow can be non-linear. 757 /// control flow can be non-linear.
756 /// 758 ///
757 /// Also parameters to a `sync*` generator must be boxed, because of the way 759 /// Also parameters to a `sync*` generator must be boxed, because of the way
758 /// we rewrite sync* functions. See also comments in [useLocal]. 760 /// we rewrite sync* functions. See also comments in [useLocal].
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
809 return true; 811 return true;
810 } 812 }
811 return capturingScopesBox(variable); 813 return capturingScopesBox(variable);
812 } 814 }
813 815
814 void forEachCapturedVariable(void f(Local variable, FieldEntity field)) { 816 void forEachCapturedVariable(void f(Local variable, FieldEntity field)) {
815 freeVariableMap.forEach((variable, copy) { 817 freeVariableMap.forEach((variable, copy) {
816 if (variable is BoxLocal) return; 818 if (variable is BoxLocal) return;
817 f(variable, copy); 819 f(variable, copy);
818 }); 820 });
819 capturingScopes.values.forEach((ClosureScopeImpl scope) { 821 capturingScopes.values.forEach((CapturedScopeImpl scope) {
820 scope.forEachCapturedVariable(f); 822 scope.forEachCapturedVariable(f);
821 }); 823 });
822 } 824 }
823 825
824 void forEachBoxedVariable( 826 void forEachBoxedVariable(
825 void f(LocalVariableElement local, BoxFieldElement field)) { 827 void f(LocalVariableElement local, BoxFieldElement field)) {
826 freeVariableMap.forEach((variable, copy) { 828 freeVariableMap.forEach((variable, copy) {
827 if (!isVariableBoxed(variable)) return; 829 if (!isVariableBoxed(variable)) return;
828 f(variable, copy); 830 f(variable, copy);
829 }); 831 });
830 capturingScopes.values.forEach((ClosureScopeImpl scope) { 832 capturingScopes.values.forEach((CapturedScopeImpl scope) {
831 scope.forEachCapturedVariable(f); 833 scope.forEachCapturedVariable(f);
832 }); 834 });
833 } 835 }
834 836
835 bool isBoxed(Local local) { 837 bool isBoxed(Local local) {
836 bool variableIsBoxed = false; 838 bool variableIsBoxed = false;
837 forEachBoxedVariable((LocalVariableElement element, BoxFieldElement field) { 839 forEachBoxedVariable((LocalVariableElement element, BoxFieldElement field) {
838 if (element == local) variableIsBoxed = true; 840 if (element == local) variableIsBoxed = true;
839 }); 841 });
840 return variableIsBoxed; 842 return variableIsBoxed;
841 } 843 }
842 } 844 }
843 845
844 class ClosureTranslator extends Visitor { 846 class ClosureTranslator extends Visitor {
845 final Compiler compiler; 847 final Compiler compiler;
846 final ClosedWorldRefiner closedWorldRefiner; 848 final ClosedWorldRefiner closedWorldRefiner;
847 final TreeElements elements; 849 final TreeElements elements;
848 int closureFieldCounter = 0; 850 int closureFieldCounter = 0;
849 int boxedFieldCounter = 0; 851 int boxedFieldCounter = 0;
850 bool inTryStatement = false; 852 bool inTryStatement = false;
851 853
852 final Map<Element, ClosureClassMap> closureMappingCache; 854 final Map<Element, ClosureClassMap> closureMappingCache;
853 final Map<Node, ClosureScopeImpl> closureInfo; 855 final Map<Node, CapturedScopeImpl> closureInfo;
854 856
855 // Map of captured variables. Initially they will map to `null`. If 857 // Map of captured variables. Initially they will map to `null`. If
856 // a variable needs to be boxed then the scope declaring the variable 858 // a variable needs to be boxed then the scope declaring the variable
857 // will update this to mapping to the capturing [BoxFieldElement]. 859 // will update this to mapping to the capturing [BoxFieldElement].
858 Map<Local, BoxFieldElement> _capturedVariableMapping = 860 Map<Local, BoxFieldElement> _capturedVariableMapping =
859 new Map<Local, BoxFieldElement>(); 861 new Map<Local, BoxFieldElement>();
860 862
861 // List of encountered closures. 863 // List of encountered closures.
862 List<LocalFunctionElement> closures = <LocalFunctionElement>[]; 864 List<LocalFunctionElement> closures = <LocalFunctionElement>[];
863 865
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after
1254 } 1256 }
1255 } 1257 }
1256 1258
1257 for (LocalVariableElement variable in scopeVariables) { 1259 for (LocalVariableElement variable in scopeVariables) {
1258 // No need to box non-assignable elements. 1260 // No need to box non-assignable elements.
1259 if (!variable.isAssignable) continue; 1261 if (!variable.isAssignable) continue;
1260 if (!mutatedVariables.contains(variable)) continue; 1262 if (!mutatedVariables.contains(variable)) continue;
1261 boxCapturedVariable(variable); 1263 boxCapturedVariable(variable);
1262 } 1264 }
1263 if (!scopeMapping.isEmpty) { 1265 if (!scopeMapping.isEmpty) {
1264 ClosureScopeImpl scope = new ClosureScopeImpl(box, scopeMapping); 1266 CapturedScopeImpl scope = new CapturedScopeImpl(box, scopeMapping);
1265 closureData.capturingScopes[node] = scope; 1267 closureData.capturingScopes[node] = scope;
1266 assert(closureInfo[node] == null); 1268 assert(closureInfo[node] == null);
1267 closureInfo[node] = scope; 1269 closureInfo[node] = scope;
1268 } 1270 }
1269 } 1271 }
1270 1272
1271 void inNewScope(Node node, Function action) { 1273 void inNewScope(Node node, Function action) {
1272 List<LocalVariableElement> oldScopeVariables = scopeVariables; 1274 List<LocalVariableElement> oldScopeVariables = scopeVariables;
1273 scopeVariables = <LocalVariableElement>[]; 1275 scopeVariables = <LocalVariableElement>[];
1274 action(); 1276 action();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1319 link = link.tail) { 1321 link = link.tail) {
1320 Node definition = link.head; 1322 Node definition = link.head;
1321 LocalVariableElement element = elements[definition]; 1323 LocalVariableElement element = elements[definition];
1322 // Non-mutated variables should not be boxed. The mutatedVariables set 1324 // Non-mutated variables should not be boxed. The mutatedVariables set
1323 // gets cleared when 'inNewScope' returns, so check it here. 1325 // gets cleared when 'inNewScope' returns, so check it here.
1324 if (isCapturedVariable(element) && mutatedVariables.contains(element)) { 1326 if (isCapturedVariable(element) && mutatedVariables.contains(element)) {
1325 boxedLoopVariables.add(element); 1327 boxedLoopVariables.add(element);
1326 } 1328 }
1327 } 1329 }
1328 }); 1330 });
1329 ClosureScopeImpl scopeData = closureData.capturingScopes[node]; 1331 CapturedScopeImpl scopeData = closureData.capturingScopes[node];
1330 if (scopeData == null) return; 1332 if (scopeData == null) return;
1331 scopeData.boxedLoopVariables = boxedLoopVariables; 1333 scopeData.boxedLoopVariables = boxedLoopVariables;
1332 } 1334 }
1333 1335
1334 /** Returns a non-unique name for the given closure element. */ 1336 /** Returns a non-unique name for the given closure element. */
1335 String computeClosureName(Element element) { 1337 String computeClosureName(Element element) {
1336 Link<String> parts = const Link<String>(); 1338 Link<String> parts = const Link<String>();
1337 String ownName = element.name; 1339 String ownName = element.name;
1338 if (ownName == null || ownName == "") { 1340 if (ownName == null || ownName == "") {
1339 parts = parts.prepend("closure"); 1341 parts = parts.prepend("closure");
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
1539 /// 1541 ///
1540 /// Move the below classes to a JS model eventually. 1542 /// Move the below classes to a JS model eventually.
1541 /// 1543 ///
1542 abstract class JSEntity implements MemberEntity { 1544 abstract class JSEntity implements MemberEntity {
1543 Local get declaredEntity; 1545 Local get declaredEntity;
1544 } 1546 }
1545 1547
1546 abstract class PrivatelyNamedJSEntity implements JSEntity { 1548 abstract class PrivatelyNamedJSEntity implements JSEntity {
1547 Entity get rootOfScope; 1549 Entity get rootOfScope;
1548 } 1550 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_model/closure.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698