OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
6 | 6 |
7 import '../closure.dart'; | 7 import '../closure.dart'; |
8 import '../common/tasks.dart'; | 8 import '../common/tasks.dart'; |
9 import '../elements/entities.dart'; | 9 import '../elements/entities.dart'; |
10 import '../kernel/element_map.dart'; | 10 import '../kernel/element_map.dart'; |
(...skipping 16 matching lines...) Expand all Loading... |
27 /// http://matt.might.net/articles/closure-conversion/. | 27 /// http://matt.might.net/articles/closure-conversion/. |
28 // TODO(efortuna): Change inheritance hierarchy so that the | 28 // TODO(efortuna): Change inheritance hierarchy so that the |
29 // ClosureConversionTask doesn't inherit from ClosureTask because it's just a | 29 // ClosureConversionTask doesn't inherit from ClosureTask because it's just a |
30 // glorified timer. | 30 // glorified timer. |
31 class KernelClosureConversionTask extends ClosureConversionTask<ir.Node> { | 31 class KernelClosureConversionTask extends ClosureConversionTask<ir.Node> { |
32 final KernelToElementMapForBuilding _elementMap; | 32 final KernelToElementMapForBuilding _elementMap; |
33 final GlobalLocalsMap _globalLocalsMap; | 33 final GlobalLocalsMap _globalLocalsMap; |
34 | 34 |
35 /// Map of the scoping information that corresponds to a particular entity. | 35 /// Map of the scoping information that corresponds to a particular entity. |
36 Map<Entity, ScopeInfo> _scopeMap = <Entity, ScopeInfo>{}; | 36 Map<Entity, ScopeInfo> _scopeMap = <Entity, ScopeInfo>{}; |
37 Map<ir.Node, ClosureScope> _scopesCapturedInClosureMap = | 37 Map<ir.Node, CapturedScope> _scopesCapturedInClosureMap = |
38 <ir.Node, ClosureScope>{}; | 38 <ir.Node, CapturedScope>{}; |
39 | 39 |
40 Map<Entity, ClosureRepresentationInfo> _closureRepresentationMap = | 40 Map<Entity, ClosureRepresentationInfo> _closureRepresentationMap = |
41 <Entity, ClosureRepresentationInfo>{}; | 41 <Entity, ClosureRepresentationInfo>{}; |
42 | 42 |
43 /// Should only be used at the very beginning to ensure we are looking at the | 43 /// Should only be used at the very beginning to ensure we are looking at the |
44 /// right kind of elements. | 44 /// right kind of elements. |
45 // TODO(efortuna): Remove this map once we have one kernel backend strategy. | 45 // TODO(efortuna): Remove this map once we have one kernel backend strategy. |
46 final JsToFrontendMap _kToJElementMap; | 46 final JsToFrontendMap _kToJElementMap; |
47 | 47 |
48 KernelClosureConversionTask(Measurer measurer, this._elementMap, | 48 KernelClosureConversionTask(Measurer measurer, this._elementMap, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 | 81 |
82 /// Inspect members and mark if those members capture any state that needs to | 82 /// Inspect members and mark if those members capture any state that needs to |
83 /// be marked as free variables. | 83 /// be marked as free variables. |
84 void _buildClosureModel( | 84 void _buildClosureModel( |
85 MemberEntity entity, | 85 MemberEntity entity, |
86 Map<ir.TreeNode, ScopeInfo> closuresToGenerate, | 86 Map<ir.TreeNode, ScopeInfo> closuresToGenerate, |
87 ClosedWorldRefiner closedWorldRefiner) { | 87 ClosedWorldRefiner closedWorldRefiner) { |
88 if (_scopeMap.keys.contains(entity)) return; | 88 if (_scopeMap.keys.contains(entity)) return; |
89 ir.Node node = _elementMap.getMemberNode(entity); | 89 ir.Node node = _elementMap.getMemberNode(entity); |
90 if (_scopesCapturedInClosureMap.keys.contains(node)) return; | 90 if (_scopesCapturedInClosureMap.keys.contains(node)) return; |
91 ClosureScopeBuilder translator = new ClosureScopeBuilder( | 91 CapturedScopeBuilder translator = new CapturedScopeBuilder( |
92 _scopesCapturedInClosureMap, | 92 _scopesCapturedInClosureMap, |
93 _scopeMap, | 93 _scopeMap, |
94 entity, | 94 entity, |
95 closuresToGenerate, | 95 closuresToGenerate, |
96 _globalLocalsMap.getLocalsMap(entity), | 96 _globalLocalsMap.getLocalsMap(entity), |
97 _elementMap); | 97 _elementMap); |
98 if (entity.isField) { | 98 if (entity.isField) { |
99 if (node is ir.Field && node.initializer != null) { | 99 if (node is ir.Field && node.initializer != null) { |
100 translator.translateLazyInitializer(node); | 100 translator.translateLazyInitializer(node); |
101 } | 101 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 ConstructorBodyEntity constructorBody = entity; | 146 ConstructorBodyEntity constructorBody = entity; |
147 entity = constructorBody.constructor; | 147 entity = constructorBody.constructor; |
148 } | 148 } |
149 | 149 |
150 return _scopeMap[entity] ?? getClosureRepresentationInfo(entity); | 150 return _scopeMap[entity] ?? getClosureRepresentationInfo(entity); |
151 } | 151 } |
152 | 152 |
153 // TODO(efortuna): Eventually scopesCapturedInClosureMap[node] should always | 153 // TODO(efortuna): Eventually scopesCapturedInClosureMap[node] should always |
154 // be non-null, and we should just test that with an assert. | 154 // be non-null, and we should just test that with an assert. |
155 @override | 155 @override |
156 ClosureScope getClosureScope(MemberEntity entity) => | 156 CapturedScope getCapturedScope(MemberEntity entity) => |
157 _scopesCapturedInClosureMap[_elementMap.getMemberNode(entity)] ?? | 157 _scopesCapturedInClosureMap[_elementMap.getMemberNode(entity)] ?? |
158 const ClosureScope(); | 158 const CapturedScope(); |
159 | 159 |
160 @override | 160 @override |
161 // TODO(efortuna): Eventually scopesCapturedInClosureMap[node] should always | 161 // TODO(efortuna): Eventually scopesCapturedInClosureMap[node] should always |
162 // be non-null, and we should just test that with an assert. | 162 // be non-null, and we should just test that with an assert. |
163 LoopClosureScope getLoopClosureScope(ir.Node loopNode) => | 163 CapturedLoopScope getCapturedLoopScope(ir.Node loopNode) => |
164 _scopesCapturedInClosureMap[loopNode] ?? const LoopClosureScope(); | 164 _scopesCapturedInClosureMap[loopNode] ?? const CapturedLoopScope(); |
165 | 165 |
166 @override | 166 @override |
167 // TODO(efortuna): Eventually closureRepresentationMap[node] should always be | 167 // TODO(efortuna): Eventually closureRepresentationMap[node] should always be |
168 // non-null, and we should just test that with an assert. | 168 // non-null, and we should just test that with an assert. |
169 ClosureRepresentationInfo getClosureRepresentationInfo(Entity entity) { | 169 ClosureRepresentationInfo getClosureRepresentationInfo(Entity entity) { |
170 return _closureRepresentationMap[entity] ?? | 170 return _closureRepresentationMap[entity] ?? |
171 const ClosureRepresentationInfo(); | 171 const ClosureRepresentationInfo(); |
172 } | 172 } |
173 } | 173 } |
174 | 174 |
(...skipping 30 matching lines...) Expand all Loading... |
205 String toString() { | 205 String toString() { |
206 StringBuffer sb = new StringBuffer(); | 206 StringBuffer sb = new StringBuffer(); |
207 sb.write('this=$thisLocal,'); | 207 sb.write('this=$thisLocal,'); |
208 sb.write('localsUsedInTryOrSync={${localsUsedInTryOrSync.join(', ')}}'); | 208 sb.write('localsUsedInTryOrSync={${localsUsedInTryOrSync.join(', ')}}'); |
209 return sb.toString(); | 209 return sb.toString(); |
210 } | 210 } |
211 | 211 |
212 bool isBoxed(Local variable) => boxedVariables.contains(variable); | 212 bool isBoxed(Local variable) => boxedVariables.contains(variable); |
213 } | 213 } |
214 | 214 |
215 class KernelClosureScope extends KernelScopeInfo implements ClosureScope { | 215 class KernelCapturedScope extends KernelScopeInfo implements CapturedScope { |
216 final Local context; | 216 final Local context; |
217 | 217 |
218 KernelClosureScope(Set<Local> boxedVariables, this.context, Local thisLocal) | 218 KernelCapturedScope(Set<Local> boxedVariables, this.context, Local thisLocal) |
219 : super.withBoxedVariables(boxedVariables, thisLocal); | 219 : super.withBoxedVariables(boxedVariables, thisLocal); |
220 | 220 |
221 bool get requiresContextBox => boxedVariables.isNotEmpty; | 221 bool get requiresContextBox => boxedVariables.isNotEmpty; |
222 } | 222 } |
223 | 223 |
224 class KernelLoopClosureScope extends KernelClosureScope | 224 class KernelCapturedLoopScope extends KernelCapturedScope |
225 implements LoopClosureScope { | 225 implements CapturedLoopScope { |
226 final List<Local> boxedLoopVariables; | 226 final List<Local> boxedLoopVariables; |
227 | 227 |
228 KernelLoopClosureScope(Set<Local> boxedVariables, this.boxedLoopVariables, | 228 KernelCapturedLoopScope(Set<Local> boxedVariables, this.boxedLoopVariables, |
229 Local context, Local thisLocal) | 229 Local context, Local thisLocal) |
230 : super(boxedVariables, context, thisLocal); | 230 : super(boxedVariables, context, thisLocal); |
231 | 231 |
232 bool get hasBoxedLoopVariables => boxedLoopVariables.isNotEmpty; | 232 bool get hasBoxedLoopVariables => boxedLoopVariables.isNotEmpty; |
233 } | 233 } |
234 | 234 |
235 // TODO(johnniwinther): Add unittest for the computed [ClosureClass]. | 235 // TODO(johnniwinther): Add unittest for the computed [ClosureClass]. |
236 class KernelClosureClass extends KernelScopeInfo | 236 class KernelClosureClass extends KernelScopeInfo |
237 implements ClosureRepresentationInfo, JClass { | 237 implements ClosureRepresentationInfo, JClass { |
238 // TODO(efortuna): Generate unique name for each closure class. | 238 // TODO(efortuna): Generate unique name for each closure class. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 // that (and the subsequent adjustment here) will follow soon. | 281 // that (and the subsequent adjustment here) will follow soon. |
282 bool get isClosure => false; | 282 bool get isClosure => false; |
283 | 283 |
284 bool get isAbstract => false; | 284 bool get isAbstract => false; |
285 | 285 |
286 // TODO(efortuna): Talk to Johnni. | 286 // TODO(efortuna): Talk to Johnni. |
287 JLibrary get library => null; | 287 JLibrary get library => null; |
288 | 288 |
289 String toString() => '${jsElementPrefix}class($name)'; | 289 String toString() => '${jsElementPrefix}class($name)'; |
290 } | 290 } |
OLD | NEW |