| 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 |