| 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 library dart2js.js_model.locals; | 5 library dart2js.js_model.locals; |
| 6 | 6 |
| 7 import 'package:kernel/ast.dart' as ir; | 7 import 'package:kernel/ast.dart' as ir; |
| 8 | 8 |
| 9 import '../closure.dart'; | 9 import '../closure.dart'; |
| 10 import '../common.dart'; | 10 import '../common.dart'; |
| 11 import '../elements/entities.dart'; | 11 import '../elements/entities.dart'; |
| 12 import '../elements/jumps.dart'; | 12 import '../elements/jumps.dart'; |
| 13 import '../elements/types.dart'; |
| 13 import '../kernel/element_map.dart'; | 14 import '../kernel/element_map.dart'; |
| 15 import '../kernel/indexed.dart'; |
| 14 | 16 |
| 15 class GlobalLocalsMap { | 17 class GlobalLocalsMap { |
| 16 Map<MemberEntity, KernelToLocalsMap> _localsMaps = | 18 Map<MemberEntity, KernelToLocalsMap> _localsMaps = |
| 17 <MemberEntity, KernelToLocalsMap>{}; | 19 <MemberEntity, KernelToLocalsMap>{}; |
| 18 | 20 |
| 19 /// Returns the [KernelToLocalsMap] for [member]. | 21 /// Returns the [KernelToLocalsMap] for [member]. |
| 20 KernelToLocalsMap getLocalsMap(MemberEntity member) { | 22 KernelToLocalsMap getLocalsMap(MemberEntity member) { |
| 21 return _localsMaps.putIfAbsent( | 23 return _localsMaps.putIfAbsent( |
| 22 member, () => new KernelToLocalsMapImpl(member)); | 24 member, () => new KernelToLocalsMapImpl(member)); |
| 23 } | 25 } |
| 24 | 26 |
| 25 /// Associates [localsMap] with [member]. | 27 /// Associates [localsMap] with [member]. |
| 26 /// | 28 /// |
| 27 /// Use this for sharing maps between members that share IR nodes. | 29 /// Use this for sharing maps between members that share IR nodes. |
| 28 void setLocalsMap(MemberEntity member, KernelToLocalsMap localsMap) { | 30 void setLocalsMap(MemberEntity member, KernelToLocalsMap localsMap) { |
| 29 assert(!_localsMaps.containsKey(member), | 31 assert(!_localsMaps.containsKey(member), |
| 30 "Locals map already created for $member."); | 32 "Locals map already created for $member."); |
| 31 _localsMaps[member] = localsMap; | 33 _localsMaps[member] = localsMap; |
| 32 } | 34 } |
| 33 } | 35 } |
| 34 | 36 |
| 35 class KernelToLocalsMapImpl implements KernelToLocalsMap { | 37 class KernelToLocalsMapImpl implements KernelToLocalsMap { |
| 36 final List<MemberEntity> _members = <MemberEntity>[]; | 38 final List<MemberEntity> _members = <MemberEntity>[]; |
| 39 final EntityDataMap<JLocal, LocalData> _locals = |
| 40 new EntityDataMap<JLocal, LocalData>(); |
| 37 Map<ir.VariableDeclaration, JLocal> _map = <ir.VariableDeclaration, JLocal>{}; | 41 Map<ir.VariableDeclaration, JLocal> _map = <ir.VariableDeclaration, JLocal>{}; |
| 38 Map<ir.TreeNode, JJumpTarget> _jumpTargetMap; | 42 Map<ir.TreeNode, JJumpTarget> _jumpTargetMap; |
| 39 Set<ir.BreakStatement> _breaksAsContinue; | 43 Set<ir.BreakStatement> _breaksAsContinue; |
| 40 List<ir.VariableDeclaration> _parameterList = <ir.VariableDeclaration>[]; | |
| 41 | 44 |
| 42 MemberEntity get currentMember => _members.last; | 45 MemberEntity get currentMember => _members.last; |
| 43 | 46 |
| 44 // TODO(johnniwinther): Compute this eagerly from the root of the member. | 47 // TODO(johnniwinther): Compute this eagerly from the root of the member. |
| 45 void _ensureJumpMap(ir.TreeNode node) { | 48 void _ensureJumpMap(ir.TreeNode node) { |
| 46 if (_jumpTargetMap == null) { | 49 if (_jumpTargetMap == null) { |
| 47 JumpVisitor visitor = new JumpVisitor(currentMember); | 50 JumpVisitor visitor = new JumpVisitor(currentMember); |
| 48 | 51 |
| 49 // Find the root node for the current member. | 52 // Find the root node for the current member. |
| 50 while (node is! ir.Member) { | 53 while (node is! ir.Member) { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 | 134 |
| 132 @override | 135 @override |
| 133 JumpTarget getJumpTargetForWhile(ir.WhileStatement node) { | 136 JumpTarget getJumpTargetForWhile(ir.WhileStatement node) { |
| 134 _ensureJumpMap(node); | 137 _ensureJumpMap(node); |
| 135 return _jumpTargetMap[node]; | 138 return _jumpTargetMap[node]; |
| 136 } | 139 } |
| 137 | 140 |
| 138 @override | 141 @override |
| 139 Local getLocalVariable(ir.VariableDeclaration node) { | 142 Local getLocalVariable(ir.VariableDeclaration node) { |
| 140 return _map.putIfAbsent(node, () { | 143 return _map.putIfAbsent(node, () { |
| 141 Local local; | 144 JLocal local = new JLocal(node.name, currentMember, |
| 142 if (node.parent is ir.FunctionNode) { | 145 isRegularParameter: node.parent is ir.FunctionNode); |
| 143 local = new JParameter(_parameterList.length, node.name, currentMember); | 146 _locals.register<JLocal, LocalData>(local, new LocalData(node)); |
| 144 _parameterList.add(node); | |
| 145 } else { | |
| 146 local = new JLocal(node.name, currentMember); | |
| 147 } | |
| 148 return local; | 147 return local; |
| 149 }); | 148 }); |
| 150 } | 149 } |
| 151 | 150 |
| 152 @override | 151 @override |
| 153 ir.FunctionNode getFunctionNodeForParameter(covariant JParameter parameter) { | 152 ir.FunctionNode getFunctionNodeForParameter(covariant JLocal parameter) { |
| 154 return _parameterList[parameter.parameterIndex].parent; | 153 return _locals.getData(parameter).functionNode; |
| 155 } | |
| 156 | |
| 157 ir.DartType getParameterType(covariant JParameter parameter) { | |
| 158 return _parameterList[parameter.parameterIndex].type; | |
| 159 } | 154 } |
| 160 | 155 |
| 161 @override | 156 @override |
| 157 DartType getLocalType(KernelToElementMap elementMap, covariant JLocal local) { |
| 158 return _locals.getData(local).getDartType(elementMap); |
| 159 } |
| 160 |
| 161 @override |
| 162 CapturedLoopScope getCapturedLoopScope( | 162 CapturedLoopScope getCapturedLoopScope( |
| 163 ClosureDataLookup closureLookup, ir.TreeNode node) { | 163 ClosureDataLookup closureLookup, ir.TreeNode node) { |
| 164 return closureLookup.getCapturedLoopScope(node); | 164 return closureLookup.getCapturedLoopScope(node); |
| 165 } | 165 } |
| 166 | 166 |
| 167 @override | 167 @override |
| 168 ClosureRepresentationInfo getClosureRepresentationInfo( | 168 ClosureRepresentationInfo getClosureRepresentationInfo( |
| 169 ClosureDataLookup closureLookup, ir.TreeNode node) { | 169 ClosureDataLookup closureLookup, ir.TreeNode node) { |
| 170 return closureLookup.getClosureInfo(node); | 170 return closureLookup.getClosureInfo(node); |
| 171 } | 171 } |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 sb.write(labelName); | 375 sb.write(labelName); |
| 376 sb.write(',isBreakTarget='); | 376 sb.write(',isBreakTarget='); |
| 377 sb.write(isBreakTarget); | 377 sb.write(isBreakTarget); |
| 378 sb.write(',isContinueTarget='); | 378 sb.write(',isContinueTarget='); |
| 379 sb.write(isContinueTarget); | 379 sb.write(isContinueTarget); |
| 380 sb.write(')'); | 380 sb.write(')'); |
| 381 return sb.toString(); | 381 return sb.toString(); |
| 382 } | 382 } |
| 383 } | 383 } |
| 384 | 384 |
| 385 class JLocal implements Local { | 385 class JLocal extends IndexedLocal { |
| 386 final String name; | 386 final String name; |
| 387 final MemberEntity memberContext; | 387 final MemberEntity memberContext; |
| 388 | 388 |
| 389 JLocal(this.name, this.memberContext); | 389 /// True if this local represents a local parameter. |
| 390 final bool isRegularParameter; |
| 390 | 391 |
| 391 /// True if this local represents a local parameter. | 392 JLocal(this.name, this.memberContext, {this.isRegularParameter: false}); |
| 392 bool get isRegularParameter => false; | |
| 393 | 393 |
| 394 @override | 394 @override |
| 395 Entity get executableContext => memberContext; | 395 Entity get executableContext => memberContext; |
| 396 | 396 |
| 397 String get _kind => 'local'; | 397 String get _kind => 'local'; |
| 398 | 398 |
| 399 String toString() { | 399 String toString() { |
| 400 StringBuffer sb = new StringBuffer(); | 400 StringBuffer sb = new StringBuffer(); |
| 401 sb.write('$_kind('); | 401 sb.write('$_kind('); |
| 402 if (memberContext.enclosingClass != null) { | 402 if (memberContext.enclosingClass != null) { |
| 403 sb.write(memberContext.enclosingClass.name); | 403 sb.write(memberContext.enclosingClass.name); |
| 404 sb.write('.'); | 404 sb.write('.'); |
| 405 } | 405 } |
| 406 sb.write(memberContext.name); | 406 sb.write(memberContext.name); |
| 407 sb.write('#'); | 407 sb.write('#'); |
| 408 sb.write(name); | 408 sb.write(name); |
| 409 sb.write(')'); | 409 sb.write(')'); |
| 410 return sb.toString(); | 410 return sb.toString(); |
| 411 } | 411 } |
| 412 } | 412 } |
| 413 | 413 |
| 414 class JParameter extends JLocal { | 414 class LocalData { |
| 415 final int parameterIndex; | 415 final ir.VariableDeclaration node; |
| 416 | 416 |
| 417 JParameter(this.parameterIndex, String name, MemberEntity memberContext) | 417 DartType _type; |
| 418 : super(name, memberContext); | |
| 419 | 418 |
| 420 bool get isRegularParameter => true; | 419 LocalData(this.node); |
| 421 | 420 |
| 422 String get _kind => 'parameter'; | 421 DartType getDartType(KernelToElementMap elementMap) { |
| 422 return _type ??= elementMap.getDartType(node.type); |
| 423 } |
| 424 |
| 425 ir.FunctionNode get functionNode => node.parent; |
| 423 } | 426 } |
| OLD | NEW |