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 13 matching lines...) Expand all Loading... |
24 /// For a general explanation of how closure conversion works at a high level, | 24 /// For a general explanation of how closure conversion works at a high level, |
25 /// check out: | 25 /// check out: |
26 /// http://siek.blogspot.com/2012/07/essence-of-closure-conversion.html or | 26 /// http://siek.blogspot.com/2012/07/essence-of-closure-conversion.html or |
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 Map<ir.Node, ClosureScope> _closureScopeMap = <ir.Node, ClosureScope>{}; | 34 |
| 35 /// Map of the scoping information that corresponds to a particular entity. |
| 36 Map<Entity, ScopeInfo> _scopeMap = <Entity, ScopeInfo>{}; |
| 37 Map<ir.Node, ClosureScope> _scopesCapturedInClosureMap = |
| 38 <ir.Node, ClosureScope>{}; |
35 | 39 |
36 Map<Entity, ClosureRepresentationInfo> _closureRepresentationMap = | 40 Map<Entity, ClosureRepresentationInfo> _closureRepresentationMap = |
37 <Entity, ClosureRepresentationInfo>{}; | 41 <Entity, ClosureRepresentationInfo>{}; |
38 | 42 |
39 /// 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 |
40 /// right kind of elements. | 44 /// right kind of elements. |
41 // 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. |
42 final JsToFrontendMap _kToJElementMap; | 46 final JsToFrontendMap _kToJElementMap; |
43 | 47 |
44 KernelClosureConversionTask(Measurer measurer, this._elementMap, | 48 KernelClosureConversionTask(Measurer measurer, this._elementMap, |
(...skipping 29 matching lines...) Expand all Loading... |
74 node, closuresToGenerate[node], closedWorldRefiner); | 78 node, closuresToGenerate[node], closedWorldRefiner); |
75 } | 79 } |
76 } | 80 } |
77 | 81 |
78 /// 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 |
79 /// be marked as free variables. | 83 /// be marked as free variables. |
80 void _buildClosureModel( | 84 void _buildClosureModel( |
81 MemberEntity entity, | 85 MemberEntity entity, |
82 Map<ir.TreeNode, ScopeInfo> closuresToGenerate, | 86 Map<ir.TreeNode, ScopeInfo> closuresToGenerate, |
83 ClosedWorldRefiner closedWorldRefiner) { | 87 ClosedWorldRefiner closedWorldRefiner) { |
| 88 if (_scopeMap.keys.contains(entity)) return; |
84 ir.Node node = _elementMap.getMemberNode(entity); | 89 ir.Node node = _elementMap.getMemberNode(entity); |
85 if (_closureScopeMap.keys.contains(node)) return; | 90 if (_scopesCapturedInClosureMap.keys.contains(node)) return; |
86 ClosureScopeBuilder translator = new ClosureScopeBuilder(_closureScopeMap, | 91 ClosureScopeBuilder translator = new ClosureScopeBuilder( |
87 closuresToGenerate, _globalLocalsMap.getLocalsMap(entity), _elementMap); | 92 _scopesCapturedInClosureMap, |
| 93 _scopeMap, |
| 94 entity, |
| 95 closuresToGenerate, |
| 96 _globalLocalsMap.getLocalsMap(entity), |
| 97 _elementMap); |
88 if (entity.isField) { | 98 if (entity.isField) { |
89 if (node is ir.Field && node.initializer != null) { | 99 if (node is ir.Field && node.initializer != null) { |
90 translator.translateLazyInitializer(node); | 100 translator.translateLazyInitializer(node); |
91 } | 101 } |
92 } else { | 102 } else { |
93 assert(node is ir.Procedure || node is ir.Constructor); | 103 assert(node is ir.Procedure || node is ir.Constructor); |
94 translator.translateConstructorOrProcedure(node); | 104 translator.translateConstructorOrProcedure(node); |
95 } | 105 } |
96 } | 106 } |
97 | 107 |
(...skipping 24 matching lines...) Expand all Loading... |
122 | 132 |
123 _closureRepresentationMap[entity] = closureClass; | 133 _closureRepresentationMap[entity] = closureClass; |
124 | 134 |
125 // Register that a new class has been created. | 135 // Register that a new class has been created. |
126 closedWorldRefiner.registerClosureClass( | 136 closedWorldRefiner.registerClosureClass( |
127 closureClass, node is ir.Member && node.isInstanceMember); | 137 closureClass, node is ir.Member && node.isInstanceMember); |
128 } | 138 } |
129 | 139 |
130 @override | 140 @override |
131 ScopeInfo getScopeInfo(Entity entity) { | 141 ScopeInfo getScopeInfo(Entity entity) { |
132 return getClosureRepresentationInfo(entity); | |
133 } | |
134 | |
135 // TODO(efortuna): Eventually closureScopeMap[node] should always be non-null, | |
136 // and we should just test that with an assert. | |
137 ClosureScope _getClosureScope(ir.Node node) => | |
138 _closureScopeMap[node] ?? const ClosureScope(); | |
139 | |
140 @override | |
141 ClosureScope getClosureScope(MemberEntity entity) { | |
142 return _getClosureScope(_elementMap.getMemberNode(entity)); | |
143 } | |
144 | |
145 @override | |
146 // TODO(efortuna): Eventually closureScopeMap[node] should always be non-null, | |
147 // and we should just test that with an assert. | |
148 LoopClosureScope getLoopClosureScope(ir.Node loopNode) => | |
149 _closureScopeMap[loopNode] ?? const LoopClosureScope(); | |
150 | |
151 @override | |
152 // TODO(efortuna): Eventually closureRepresentationMap[node] should always be | |
153 // non-null, and we should just test that with an assert. | |
154 ClosureRepresentationInfo getClosureRepresentationInfo(Entity entity) { | |
155 // TODO(johnniwinther): Remove this check when constructor bodies a created | 142 // TODO(johnniwinther): Remove this check when constructor bodies a created |
156 // eagerly with the J-model; a constructor body should have it's own | 143 // eagerly with the J-model; a constructor body should have it's own |
157 // [ClosureRepresentationInfo]. | 144 // [ClosureRepresentationInfo]. |
158 if (entity is ConstructorBodyEntity) { | 145 if (entity is ConstructorBodyEntity) { |
159 ConstructorBodyEntity constructorBody = entity; | 146 ConstructorBodyEntity constructorBody = entity; |
160 entity = constructorBody.constructor; | 147 entity = constructorBody.constructor; |
161 } | 148 } |
| 149 |
| 150 return _scopeMap[entity] ?? getClosureRepresentationInfo(entity); |
| 151 } |
| 152 |
| 153 // TODO(efortuna): Eventually scopesCapturedInClosureMap[node] should always |
| 154 // be non-null, and we should just test that with an assert. |
| 155 @override |
| 156 ClosureScope getClosureScope(MemberEntity entity) => |
| 157 _scopesCapturedInClosureMap[_elementMap.getMemberNode(entity)] ?? |
| 158 const ClosureScope(); |
| 159 |
| 160 @override |
| 161 // TODO(efortuna): Eventually scopesCapturedInClosureMap[node] should always |
| 162 // be non-null, and we should just test that with an assert. |
| 163 LoopClosureScope getLoopClosureScope(ir.Node loopNode) => |
| 164 _scopesCapturedInClosureMap[loopNode] ?? const LoopClosureScope(); |
| 165 |
| 166 @override |
| 167 // TODO(efortuna): Eventually closureRepresentationMap[node] should always be |
| 168 // non-null, and we should just test that with an assert. |
| 169 ClosureRepresentationInfo getClosureRepresentationInfo(Entity entity) { |
162 return _closureRepresentationMap[entity] ?? | 170 return _closureRepresentationMap[entity] ?? |
163 const ClosureRepresentationInfo(); | 171 const ClosureRepresentationInfo(); |
164 } | 172 } |
165 } | 173 } |
166 | 174 |
167 class KernelScopeInfo extends ScopeInfo { | 175 class KernelScopeInfo extends ScopeInfo { |
168 final Set<Local> localsUsedInTryOrSync; | 176 final Set<Local> localsUsedInTryOrSync; |
169 final Local thisLocal; | 177 final Local thisLocal; |
170 final Set<Local> boxedVariables; | 178 final Set<Local> boxedVariables; |
171 | 179 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 // that (and the subsequent adjustment here) will follow soon. | 281 // that (and the subsequent adjustment here) will follow soon. |
274 bool get isClosure => false; | 282 bool get isClosure => false; |
275 | 283 |
276 bool get isAbstract => false; | 284 bool get isAbstract => false; |
277 | 285 |
278 // TODO(efortuna): Talk to Johnni. | 286 // TODO(efortuna): Talk to Johnni. |
279 JLibrary get library => null; | 287 JLibrary get library => null; |
280 | 288 |
281 String toString() => '${jsElementPrefix}class($name)'; | 289 String toString() => '${jsElementPrefix}class($name)'; |
282 } | 290 } |
OLD | NEW |