OLD | NEW |
---|---|
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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
45 // one for local functions. | 45 // one for local functions. |
46 ScopeInfo getScopeInfo(covariant Entity member); | 46 ScopeInfo getScopeInfo(covariant Entity member); |
47 | 47 |
48 /// This returns the same information as ScopeInfo, but can be called in | 48 /// This returns the same information as ScopeInfo, but can be called in |
49 /// situations when you are sure you are dealing with a closure specifically. | 49 /// situations when you are sure you are dealing with a closure specifically. |
50 ClosureRepresentationInfo getClosureRepresentationInfo( | 50 ClosureRepresentationInfo getClosureRepresentationInfo( |
51 covariant Entity member); | 51 covariant Entity member); |
52 | 52 |
53 /// Look up information about a loop, in case any variables it declares need | 53 /// Look up information about a loop, in case any variables it declares need |
54 /// to be boxed/snapshotted. | 54 /// to be boxed/snapshotted. |
55 LoopClosureRepresentationInfo getClosureRepresentationInfoForLoop(T loopNode); | 55 ClosureBase getClosureRepresentationInfoForLoop(T loopNode); |
56 | 56 |
57 /// Accessor to the information about closures that the SSA builder will use. | 57 /// Accessor to the information about closures that the SSA builder will use. |
58 ClosureAnalysisInfo getClosureAnalysisInfo(T node); | 58 ClosureBase getClosureBase(T node); |
59 } | 59 } |
60 | 60 |
61 /// Class that represents one level of scoping information, whether this scope | 61 /// Class that represents one level of scoping information, whether this scope |
62 /// is a closure or not. This is specifically used to store information | 62 /// is a closure or not. This is specifically used to store information |
63 /// about the usage of variables in try or sync blocks, because they need to be | 63 /// about the usage of variables in try or sync blocks, because they need to be |
64 /// boxed. | 64 /// boxed. |
65 /// | 65 /// |
66 /// Variables that are used in a try must be treated as boxed because the | 66 /// Variables that are used in a try must be treated as boxed because the |
67 /// control flow can be non-linear. Also parameters to a `sync*` generator must | 67 /// control flow can be non-linear. Also parameters to a `sync*` generator must |
68 /// be boxed, because of the way we rewrite sync* functions. See also comments | 68 /// be boxed, because of the way we rewrite sync* functions. See also comments |
69 /// in [ClosureClassMap.useLocal]. | 69 /// in [ClosureClassMap.useLocal]. |
70 class ScopeInfo { | 70 class ScopeInfo { |
71 const ScopeInfo(); | 71 const ScopeInfo(); |
72 | 72 |
73 /// Convenience reference pointer to the element representing `this`. | |
74 /// If this scope is not in an instance member, it will be null. | |
75 Local get thisLocal => null; | |
76 | |
73 /// Returns true if this [variable] is used inside a `try` block or a `sync*` | 77 /// Returns true if this [variable] is used inside a `try` block or a `sync*` |
74 /// generator (this is important to know because boxing/redirection needs to | 78 /// generator (this is important to know because boxing/redirection needs to |
75 /// happen for those local variables). | 79 /// happen for those local variables). |
76 /// | 80 /// |
77 /// Variables that are used in a try must be treated as boxed because the | 81 /// Variables that are used in a try must be treated as boxed because the |
78 /// control flow can be non-linear. | 82 /// control flow can be non-linear. |
79 /// | 83 /// |
80 /// Also parameters to a `sync*` generator must be boxed, because of the way | 84 /// Also parameters to a `sync*` generator must be boxed, because of the way |
81 /// we rewrite sync* functions. See also comments in | 85 /// we rewrite sync* functions. See also comments in |
82 /// [ClosureClassMap.useLocal]. | 86 /// [ClosureClassMap.useLocal]. |
83 bool variableIsUsedInTryOrSync(Local variable) => false; | 87 bool variableIsUsedInTryOrSync(Local variable) => false; |
84 | 88 |
85 /// Convenience reference pointer to the element representing `this`. | 89 /// Loop through each variabe that has been defined in this scope, modified |
Johnni Winther
2017/06/26 08:31:39
`variabe` -> `variable`
Emily Fortuna
2017/06/26 21:57:19
Done.
| |
86 /// If this scope is not in an instance member, it will be null. | 90 /// anywhere (this scope or another scope) and used in another scope . Because |
Johnni Winther
2017/06/26 08:31:39
`scope .` -> `scope.`
Start a new paragraph at`Be
Emily Fortuna
2017/06/26 21:57:20
Done.
| |
87 Local get thisLocal => null; | 91 /// it is used in another scope, these variables need to be "boxed", creating |
92 /// a thin wrapper around accesses to these variables so that accesses get | |
93 /// the correct updated value. The variables in variablesUsedInTryOrSync may | |
94 /// be included in this set. | |
95 /// | |
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 | |
98 /// need to be boxed to snapshot their value. | |
99 void forEachBoxedVariable(f(Local local, FieldEntity field)) {} | |
100 | |
101 /// True if [variable] has been mutated and is also used in another scope. | |
102 bool isBoxed(Local variable) => false; | |
103 | |
104 /// True if this loop declares any variables that need to be boxed. | |
Johnni Winther
2017/06/26 08:31:39
`this loop` -> `this scope`
Emily Fortuna
2017/06/26 21:57:20
thank you!
| |
105 bool get hasBoxedVariables => false; | |
88 } | 106 } |
89 | 107 |
90 /// Class that provides a black-box interface to information gleaned from | 108 /// Class that provides a basic interface for closures. Actual Dart closures |
91 /// analyzing a closure's characteristics, most commonly used to influence how | 109 /// will use this class (see [ClosureRepresentationInfo]) as well as loops. |
92 /// code should be generated in SSA builder stage. | 110 class ClosureBase extends ScopeInfo { |
93 class ClosureAnalysisInfo { | 111 const ClosureBase(); |
94 const ClosureAnalysisInfo(); | |
95 | 112 |
96 /// If true, this closure accesses a variable that was defined in an outside | 113 /// If true, this closure accesses a variable that was defined in an outside |
97 /// scope and this variable gets modified at some point (sometimes we say that | 114 /// scope and this variable gets modified at some point (sometimes we say that |
98 /// variable has been "captured"). In this situation, access to this variable | 115 /// variable has been "captured"). In this situation, access to this variable |
99 /// is controlled via a wrapper (box) so that updates to this variable | 116 /// is controlled via a wrapper (box) so that updates to this variable |
100 /// are done in a way that is in line with Dart's closure rules. | 117 /// are done in a way that is in line with Dart's closure rules. |
101 bool get requiresContextBox => false; | 118 bool get requiresContextBox => false; |
102 | 119 |
103 /// Accessor to the local environment in which a particular closure node is | 120 /// Accessor to the local environment in which a particular closure node is |
104 /// executed. This will encapsulate the value of any variables that have been | 121 /// executed. This will encapsulate the value of any variables that have been |
105 /// scoped into this context from outside. This is an accessor to the | 122 /// scoped into this context from outside. This is an accessor to the |
106 /// contextBox that [requiresContextBox] is testing is required. | 123 /// contextBox that [requiresContextBox] is testing is required. |
107 Local get context => null; | 124 Local get context => null; |
108 | |
109 /// True if the specified variable has been mutated inside the scope of this | |
110 /// closure. | |
111 bool isCaptured(Local variable) => false; | |
112 | |
113 /// Loop through every variable that has been captured in this closure. This | |
114 /// consists of all the free variables (variables captured *just* in this | |
115 /// closure) and all variables captured in nested scopes that we may be | |
116 /// capturing as well. | |
117 void forEachCapturedVariable(f(Local from, FieldEntity to)) {} | |
118 } | |
119 | |
120 /// Class that describes the actual mechanics of how a loop is | |
121 /// converted/rewritten without closures. Unlike JS, the value of a declared | |
122 /// loop iteration variable in any closure is captured/snapshotted inside at | |
123 /// each iteration point, as if we created a new local variable for that value | |
124 /// inside the loop. For example, for the following loop: | |
125 /// | |
126 /// var lst = []; | |
127 /// for (int i = 0; i < 5; i++) lst.add(()=>i); | |
128 /// var result = list.map((f) => f()).toList(); | |
129 /// | |
130 /// `result` will be [0, 1, 2, 3, 4], whereas were this JS code | |
131 /// the result would be [5, 5, 5, 5, 5]. Because of this difference we need to | |
132 /// create a closure for these sorts of loops to capture the variable's value at | |
133 /// each iteration, by boxing the iteration variable[s]. | |
134 class LoopClosureRepresentationInfo extends ClosureAnalysisInfo { | |
135 const LoopClosureRepresentationInfo(); | |
136 | |
137 /// True if this loop declares any variables that need to be boxed. | |
138 bool get hasBoxedVariables => false; | |
139 | |
140 /// The set of iteration variables (or variables declared in the for loop | |
141 /// expression (`for (...here...)`) that need to be boxed to snapshot their | |
142 /// value. | |
143 List<Local> get boxedVariables => const <Local>[]; | |
144 } | 125 } |
145 | 126 |
146 /// Class that describes the actual mechanics of how the converted, rewritten | 127 /// Class that describes the actual mechanics of how the converted, rewritten |
147 /// closure is implemented. For example, for the following closure (named foo | 128 /// closure is implemented. For example, for the following closure (named foo |
148 /// for convenience): | 129 /// for convenience): |
149 /// | 130 /// |
150 /// var foo = (x) => y + x; | 131 /// var foo = (x) => y + x; |
151 /// | 132 /// |
152 /// We would produce the following class to control access to these variables in | 133 /// 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 | 134 /// the following way (modulo naming of variables, assuming that y is modified |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
202 /// Loop through every variable that has been captured in this closure. This | 183 /// Loop through every variable that has been captured in this closure. This |
203 /// consists of all the free variables (variables captured *just* in this | 184 /// consists of all the free variables (variables captured *just* in this |
204 /// closure) and all variables captured in nested scopes that we may be | 185 /// closure) and all variables captured in nested scopes that we may be |
205 /// capturing as well. These nested scopes hold "boxes" to hold the executable | 186 /// capturing as well. These nested scopes hold "boxes" to hold the executable |
206 /// context for that scope. | 187 /// context for that scope. |
207 void forEachCapturedVariable(f(Local from, FieldEntity to)) {} | 188 void forEachCapturedVariable(f(Local from, FieldEntity to)) {} |
208 | 189 |
209 /// Loop through each variable that has been boxed in this closure class. Only | 190 /// Loop through each variable that has been boxed in this closure class. Only |
210 /// captured variables that are mutated need to be "boxed" (which basically | 191 /// captured variables that are mutated need to be "boxed" (which basically |
211 /// puts a thin layer between updates and reads to this variable to ensure | 192 /// puts a thin layer between updates and reads to this variable to ensure |
212 /// that every place that accesses it gets the correct updated value). | 193 /// that every place that accesses it gets the correct updated value). This |
194 /// includes looping over variables that were boxed from other scopes, not | |
195 /// strictly variables defined in this closure, unlike the behavior in | |
196 /// the superclass ScopeInfo. | |
197 @override | |
213 void forEachBoxedVariable(f(Local local, FieldEntity field)) {} | 198 void forEachBoxedVariable(f(Local local, FieldEntity field)) {} |
214 | 199 |
215 /// Loop through each free variable in this closure. Free variables are the | 200 /// Loop through each free variable in this closure. Free variables are the |
216 /// variables that have been captured *just* in this closure, not in nested | 201 /// variables that have been captured *just* in this closure, not in nested |
217 /// scopes. | 202 /// scopes. |
218 void forEachFreeVariable(f(Local variable, FieldEntity field)) {} | 203 void forEachFreeVariable(f(Local variable, FieldEntity field)) {} |
219 | 204 |
220 /// Return true if [variable] has been captured and mutated (all other | 205 /// Return true if [variable] has been captured and mutated (all other |
221 /// variables do not require boxing). | 206 /// variables do not require boxing). |
222 bool isVariableBoxed(Local variable) => false; | 207 bool isVariableBoxed(Local variable) => false; |
(...skipping 15 matching lines...) Expand all Loading... | |
238 | 223 |
239 String get name => "Closure Simplifier"; | 224 String get name => "Closure Simplifier"; |
240 | 225 |
241 DiagnosticReporter get reporter => compiler.reporter; | 226 DiagnosticReporter get reporter => compiler.reporter; |
242 | 227 |
243 void convertClosures(Iterable<MemberEntity> processedEntities, | 228 void convertClosures(Iterable<MemberEntity> processedEntities, |
244 ClosedWorldRefiner closedWorldRefiner) { | 229 ClosedWorldRefiner closedWorldRefiner) { |
245 createClosureClasses(closedWorldRefiner); | 230 createClosureClasses(closedWorldRefiner); |
246 } | 231 } |
247 | 232 |
248 ClosureAnalysisInfo getClosureAnalysisInfo(Node node) { | 233 ClosureBase getClosureBase(Node node) { |
249 var value = _closureInfoMap[node]; | 234 var value = _closureInfoMap[node]; |
250 return value == null ? const ClosureAnalysisInfo() : value; | 235 return value == null ? const ClosureBase() : value; |
251 } | 236 } |
252 | 237 |
253 ScopeInfo getScopeInfo(Element member) { | 238 ScopeInfo getScopeInfo(Element member) { |
254 return getClosureToClassMapping(member); | 239 return getClosureToClassMapping(member); |
255 } | 240 } |
256 | 241 |
257 ClosureRepresentationInfo getClosureRepresentationInfo(Element member) { | 242 ClosureRepresentationInfo getClosureRepresentationInfo(Element member) { |
258 return getClosureToClassMapping(member); | 243 return getClosureToClassMapping(member); |
259 } | 244 } |
260 | 245 |
261 LoopClosureRepresentationInfo getClosureRepresentationInfoForLoop( | 246 ClosureBase getClosureRepresentationInfoForLoop(Node loopNode) { |
262 Node loopNode) { | |
263 var value = _closureInfoMap[loopNode]; | 247 var value = _closureInfoMap[loopNode]; |
264 return value == null ? const LoopClosureRepresentationInfo() : value; | 248 return value == null ? const ClosureBase() : value; |
265 } | 249 } |
266 | 250 |
267 /// Returns the [ClosureClassMap] computed for [resolvedAst]. | 251 /// Returns the [ClosureClassMap] computed for [resolvedAst]. |
268 ClosureClassMap getClosureToClassMapping(Element element) { | 252 ClosureClassMap getClosureToClassMapping(Element element) { |
269 return measure(() { | 253 return measure(() { |
270 if (element.isGenerativeConstructorBody) { | 254 if (element.isGenerativeConstructorBody) { |
271 ConstructorBodyElement constructorBody = element; | 255 ConstructorBodyElement constructorBody = element; |
272 element = constructorBody.constructor; | 256 element = constructorBody.constructor; |
273 } | 257 } |
274 ClosureClassMap closureClassMap = _closureMappingCache[element]; | 258 ClosureClassMap closureClassMap = _closureMappingCache[element]; |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
622 expression.compilationUnit.script.resourceUri); | 606 expression.compilationUnit.script.resourceUri); |
623 } | 607 } |
624 | 608 |
625 accept(ElementVisitor visitor, arg) { | 609 accept(ElementVisitor visitor, arg) { |
626 return visitor.visitMethodElement(this, arg); | 610 return visitor.visitMethodElement(this, arg); |
627 } | 611 } |
628 } | 612 } |
629 | 613 |
630 // The box-element for a scope, and the captured variables that need to be | 614 // The box-element for a scope, and the captured variables that need to be |
631 // stored in the box. | 615 // stored in the box. |
632 class ClosureScope | 616 class ClosureScope implements ClosureBase { |
Siggi Cherem (dart-lang)
2017/06/26 16:54:42
mmm... I sort of like the idea of swapping the two
| |
633 implements ClosureAnalysisInfo, LoopClosureRepresentationInfo { | |
634 final BoxLocal boxElement; | 617 final BoxLocal boxElement; |
635 final Map<Local, BoxFieldElement> capturedVariables; | 618 final Map<Local, BoxFieldElement> capturedVariables; |
636 | 619 |
637 // If the scope is attached to a [For] contains the variables that are | 620 // If the scope is attached to a [For] contains the variables that are |
638 // declared in the initializer of the [For] and that need to be boxed. | 621 // declared in the initializer of the [For] and that need to be boxed. |
639 // Otherwise contains the empty List. | 622 // Otherwise contains the empty List. |
640 List<Local> boxedLoopVariables = const <Local>[]; | 623 List<Local> boxedLoopVariables = const <Local>[]; |
641 | 624 |
642 ClosureScope(this.boxElement, this.capturedVariables); | 625 ClosureScope(this.boxElement, this.capturedVariables); |
643 | 626 |
644 Local get context => boxElement; | 627 Local get context => boxElement; |
645 | 628 |
646 bool get requiresContextBox => capturedVariables.keys.isNotEmpty; | 629 bool get requiresContextBox => capturedVariables.keys.isNotEmpty; |
647 | 630 |
648 List<Local> get boxedVariables => boxedLoopVariables; | 631 void forEachBoxedVariable(f(Local local, FieldEntity field)) { |
632 if (capturedVariables.isNotEmpty) { | |
633 capturedVariables.forEach(f); | |
Johnni Winther
2017/06/26 08:31:39
assert(boxedLoopVariables.isEmpty)
| |
634 } else { | |
635 for (Local l in boxedLoopVariables) { | |
636 // The boxes for loop variables are constructed on-demand per-iteration | |
637 // in the locals handler. | |
638 f(l, null); | |
639 } | |
640 } | |
641 } | |
649 | 642 |
650 bool get hasBoxedVariables => !boxedLoopVariables.isEmpty; | 643 Map<Local, BoxFieldElement> get boxedVariables { |
Johnni Winther
2017/06/26 08:31:39
When is this used?
Emily Fortuna
2017/06/26 21:57:20
oops. that was holdover from a previous edit. Remo
| |
644 Map<Local, BoxFieldElement> temp = <Local, BoxFieldElement>{}; | |
645 boxedLoopVariables.forEach((Local l) { | |
646 temp[l] = null; | |
647 }); | |
648 return capturedVariables.isNotEmpty ? capturedVariables : temp; | |
649 } | |
651 | 650 |
652 bool isCaptured(Local variable) { | 651 bool get hasBoxedVariables => !capturedVariables.isEmpty; |
652 | |
653 bool isBoxed(Local variable) { | |
653 return capturedVariables.containsKey(variable); | 654 return capturedVariables.containsKey(variable); |
654 } | 655 } |
655 | 656 |
656 void forEachCapturedVariable( | 657 void forEachCapturedVariable( |
657 f(LocalVariableElement variable, BoxFieldElement boxField)) { | 658 f(LocalVariableElement variable, BoxFieldElement boxField)) { |
658 capturedVariables.forEach(f); | 659 capturedVariables.forEach(f); |
659 } | 660 } |
660 | 661 |
662 // Should not be called. Added to make the new interface happy. | |
663 bool variableIsUsedInTryOrSync(Local variable) => | |
664 throw new UnsupportedError("ClosureScope.variableIsUsedInTryOrSync"); | |
665 | |
666 // Should not be called. Added to make the new interface happy. | |
667 Local get thisLocal => throw new UnsupportedError("ClosureScope.thisLocal"); | |
668 | |
661 String toString() { | 669 String toString() { |
662 String separator = ''; | 670 String separator = ''; |
663 StringBuffer sb = new StringBuffer(); | 671 StringBuffer sb = new StringBuffer(); |
664 sb.write('ClosureScope('); | 672 sb.write('ClosureScope('); |
665 if (boxElement != null) { | 673 if (boxElement != null) { |
666 sb.write('box=$boxElement'); | 674 sb.write('box=$boxElement'); |
667 separator = ','; | 675 separator = ','; |
668 } | 676 } |
669 if (boxedLoopVariables.isNotEmpty) { | 677 if (boxedLoopVariables.isNotEmpty) { |
670 sb.write(separator); | 678 sb.write(separator); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
719 /// control flow can be non-linear. | 727 /// control flow can be non-linear. |
720 /// | 728 /// |
721 /// Also parameters to a `sync*` generator must be boxed, because of the way | 729 /// Also parameters to a `sync*` generator must be boxed, because of the way |
722 /// we rewrite sync* functions. See also comments in [useLocal]. | 730 /// we rewrite sync* functions. See also comments in [useLocal]. |
723 // TODO(johnniwinther): Add variables to this only if the variable is mutated. | 731 // TODO(johnniwinther): Add variables to this only if the variable is mutated. |
724 final Set<Local> variablesUsedInTryOrSync = new Set<Local>(); | 732 final Set<Local> variablesUsedInTryOrSync = new Set<Local>(); |
725 | 733 |
726 ClosureClassMap(this.closureEntity, this.closureClassEntity, this.callMethod, | 734 ClosureClassMap(this.closureEntity, this.closureClassEntity, this.callMethod, |
727 this.thisLocal); | 735 this.thisLocal); |
728 | 736 |
737 bool get hasBoxedVariables => | |
738 throw new UnsupportedError("ClosureClassMap.hasBoxedVariables"); | |
739 | |
729 List<Local> get createdFieldEntities { | 740 List<Local> get createdFieldEntities { |
730 List<Local> fields = <Local>[]; | 741 List<Local> fields = <Local>[]; |
731 if (closureClassEntity == null) return const <Local>[]; | 742 if (closureClassEntity == null) return const <Local>[]; |
732 closureClassEntity.closureFields.forEach((field) { | 743 closureClassEntity.closureFields.forEach((field) { |
733 fields.add(field.local); | 744 fields.add(field.local); |
734 }); | 745 }); |
735 return fields; | 746 return fields; |
736 } | 747 } |
737 | 748 |
738 void addFreeVariable(Local element) { | 749 void addFreeVariable(Local element) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
788 void forEachBoxedVariable( | 799 void forEachBoxedVariable( |
789 void f(LocalVariableElement local, BoxFieldElement field)) { | 800 void f(LocalVariableElement local, BoxFieldElement field)) { |
790 freeVariableMap.forEach((variable, copy) { | 801 freeVariableMap.forEach((variable, copy) { |
791 if (!isVariableBoxed(variable)) return; | 802 if (!isVariableBoxed(variable)) return; |
792 f(variable, copy); | 803 f(variable, copy); |
793 }); | 804 }); |
794 capturingScopes.values.forEach((ClosureScope scope) { | 805 capturingScopes.values.forEach((ClosureScope scope) { |
795 scope.forEachCapturedVariable(f); | 806 scope.forEachCapturedVariable(f); |
796 }); | 807 }); |
797 } | 808 } |
809 | |
810 bool isBoxed(Local local) { | |
811 bool variableIsBoxed = false; | |
812 forEachBoxedVariable((LocalVariableElement element, BoxFieldElement field) { | |
813 if (element == local) variableIsBoxed = true; | |
814 }); | |
815 return variableIsBoxed; | |
816 } | |
798 } | 817 } |
799 | 818 |
800 class ClosureTranslator extends Visitor { | 819 class ClosureTranslator extends Visitor { |
801 final Compiler compiler; | 820 final Compiler compiler; |
802 final ClosedWorldRefiner closedWorldRefiner; | 821 final ClosedWorldRefiner closedWorldRefiner; |
803 final TreeElements elements; | 822 final TreeElements elements; |
804 int closureFieldCounter = 0; | 823 int closureFieldCounter = 0; |
805 int boxedFieldCounter = 0; | 824 int boxedFieldCounter = 0; |
806 bool inTryStatement = false; | 825 bool inTryStatement = false; |
807 | 826 |
(...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1493 /// | 1512 /// |
1494 /// Move the below classes to a JS model eventually. | 1513 /// Move the below classes to a JS model eventually. |
1495 /// | 1514 /// |
1496 abstract class JSEntity implements MemberEntity { | 1515 abstract class JSEntity implements MemberEntity { |
1497 Local get declaredEntity; | 1516 Local get declaredEntity; |
1498 } | 1517 } |
1499 | 1518 |
1500 abstract class PrivatelyNamedJSEntity implements JSEntity { | 1519 abstract class PrivatelyNamedJSEntity implements JSEntity { |
1501 Entity get rootOfScope; | 1520 Entity get rootOfScope; |
1502 } | 1521 } |
OLD | NEW |