| 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.dart'; | 8 import '../common.dart'; |
| 9 import '../constants/constant_system.dart'; | 9 import '../constants/constant_system.dart'; |
| 10 import '../elements/entities.dart'; | 10 import '../elements/entities.dart'; |
| 11 import '../elements/types.dart'; | 11 import '../elements/types.dart'; |
| 12 import '../kernel/element_map.dart'; | 12 import '../kernel/element_map.dart'; |
| 13 import '../options.dart'; | 13 import '../options.dart'; |
| 14 import '../types/constants.dart'; | 14 import '../types/constants.dart'; |
| 15 import '../types/types.dart'; |
| 16 import '../universe/selector.dart'; |
| 17 import '../universe/side_effects.dart'; |
| 15 import '../world.dart'; | 18 import '../world.dart'; |
| 16 import 'inferrer_engine.dart'; | 19 import 'inferrer_engine.dart'; |
| 17 import 'locals_handler.dart'; | 20 import 'locals_handler.dart'; |
| 18 import 'type_graph_nodes.dart'; | 21 import 'type_graph_nodes.dart'; |
| 19 import 'type_system.dart'; | 22 import 'type_system.dart'; |
| 20 | 23 |
| 21 /// [KernelTypeGraphBuilder] constructs a type-inference graph for a particular | 24 /// [KernelTypeGraphBuilder] constructs a type-inference graph for a particular |
| 22 /// element. | 25 /// element. |
| 23 /// | 26 /// |
| 24 /// Calling [run] will start the work of visiting the body of the code to | 27 /// Calling [run] will start the work of visiting the body of the code to |
| 25 /// construct a set of inference-nodes that abstractly represent what the code | 28 /// construct a set of inference-nodes that abstractly represent what the code |
| 26 /// is doing. | 29 /// is doing. |
| 27 class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> { | 30 class KernelTypeGraphBuilder extends ir.Visitor<TypeInformation> { |
| 28 final CompilerOptions _options; | 31 final CompilerOptions _options; |
| 29 final ClosedWorld _closedWorld; | 32 final ClosedWorld _closedWorld; |
| 30 final ClosureDataLookup<ir.Node> _closureDataLookup; | 33 final ClosureDataLookup<ir.Node> _closureDataLookup; |
| 31 final InferrerEngine<ir.Node> _inferrer; | 34 final InferrerEngine<ir.Node> _inferrer; |
| 32 final TypeSystem<ir.Node> _types; | 35 final TypeSystem<ir.Node> _types; |
| 33 final MemberEntity _analyzedMember; | 36 final MemberEntity _analyzedMember; |
| 34 final ir.Node _analyzedNode; | 37 final ir.Node _analyzedNode; |
| 35 final KernelToElementMapForBuilding _elementMap; | 38 final KernelToElementMapForBuilding _elementMap; |
| 36 final KernelToLocalsMap _localsMap; | 39 final KernelToLocalsMap _localsMap; |
| 37 LocalsHandler _locals; | 40 LocalsHandler _locals; |
| 41 final GlobalTypeInferenceElementData<ir.Node> _memberData; |
| 42 SideEffects _sideEffects = new SideEffects.empty(); |
| 38 | 43 |
| 39 TypeInformation _returnType; | 44 TypeInformation _returnType; |
| 40 | 45 |
| 41 KernelTypeGraphBuilder( | 46 KernelTypeGraphBuilder( |
| 42 this._options, | 47 this._options, |
| 43 this._closedWorld, | 48 this._closedWorld, |
| 44 this._closureDataLookup, | 49 this._closureDataLookup, |
| 45 this._inferrer, | 50 this._inferrer, |
| 46 this._analyzedMember, | 51 this._analyzedMember, |
| 47 this._analyzedNode, | 52 this._analyzedNode, |
| 48 this._elementMap, | 53 this._elementMap, |
| 49 this._localsMap, | 54 this._localsMap, |
| 50 [this._locals]) | 55 [this._locals]) |
| 51 : this._types = _inferrer.types { | 56 : this._types = _inferrer.types, |
| 57 this._memberData = _inferrer.dataOfMember(_analyzedMember) { |
| 52 if (_locals != null) return; | 58 if (_locals != null) return; |
| 53 | 59 |
| 54 FieldInitializationScope<ir.Node> fieldScope = | 60 FieldInitializationScope<ir.Node> fieldScope = |
| 55 _analyzedNode is ir.Constructor | 61 _analyzedNode is ir.Constructor |
| 56 ? new FieldInitializationScope(_types) | 62 ? new FieldInitializationScope(_types) |
| 57 : null; | 63 : null; |
| 58 _locals = new LocalsHandler( | 64 _locals = new LocalsHandler( |
| 59 _inferrer, _types, _options, _analyzedNode, fieldScope); | 65 _inferrer, _types, _options, _analyzedNode, fieldScope); |
| 60 } | 66 } |
| 61 | 67 |
| 68 int _loopLevel = 0; |
| 69 |
| 70 bool get inLoop => _loopLevel > 0; |
| 71 |
| 62 TypeInformation run() { | 72 TypeInformation run() { |
| 63 if (_analyzedMember.isField) { | 73 if (_analyzedMember.isField) { |
| 64 if (_analyzedNode == null || _analyzedNode is ir.NullLiteral) { | 74 if (_analyzedNode == null || _analyzedNode is ir.NullLiteral) { |
| 65 // Eagerly bailout, because computing the closure data only | 75 // Eagerly bailout, because computing the closure data only |
| 66 // works for functions and field assignments. | 76 // works for functions and field assignments. |
| 67 return _types.nullType; | 77 return _types.nullType; |
| 68 } | 78 } |
| 69 } | 79 } |
| 70 | 80 |
| 71 // Update the locals that are boxed in [locals]. These locals will | 81 // Update the locals that are boxed in [locals]. These locals will |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 } | 257 } |
| 248 | 258 |
| 249 @override | 259 @override |
| 250 TypeInformation visitVariableSet(ir.VariableSet node) { | 260 TypeInformation visitVariableSet(ir.VariableSet node) { |
| 251 Local local = _localsMap.getLocalVariable(node.variable); | 261 Local local = _localsMap.getLocalVariable(node.variable); |
| 252 DartType type = _localsMap.getLocalType(_elementMap, local); | 262 DartType type = _localsMap.getLocalType(_elementMap, local); |
| 253 TypeInformation rhsType = visit(node.value); | 263 TypeInformation rhsType = visit(node.value); |
| 254 _locals.update(local, rhsType, node, type); | 264 _locals.update(local, rhsType, node, type); |
| 255 return rhsType; | 265 return rhsType; |
| 256 } | 266 } |
| 267 |
| 268 ArgumentsTypes analyzeArguments(ir.Arguments arguments) { |
| 269 List<TypeInformation> positional = <TypeInformation>[]; |
| 270 Map<String, TypeInformation> named; |
| 271 for (ir.Expression argument in arguments.positional) { |
| 272 positional.add(argument.accept(this)); |
| 273 } |
| 274 for (ir.NamedExpression argument in arguments.named) { |
| 275 named ??= <String, TypeInformation>{}; |
| 276 named[argument.name] = argument.value.accept(this); |
| 277 } |
| 278 |
| 279 /// TODO(johnniwinther): Track `isThisExposed`. |
| 280 return new ArgumentsTypes(positional, named); |
| 281 } |
| 282 |
| 283 @override |
| 284 TypeInformation visitMethodInvocation(ir.MethodInvocation node) { |
| 285 TypeInformation receiverType = visit(node.receiver); |
| 286 Selector selector = _elementMap.getSelector(node); |
| 287 TypeMask mask = _memberData.typeOfSend(node); |
| 288 |
| 289 ArgumentsTypes arguments = analyzeArguments(node.arguments); |
| 290 if (selector.name == '==' || selector.name == '!=') { |
| 291 if (_types.isNull(receiverType)) { |
| 292 // TODO(johnniwinther): Add null check. |
| 293 return _types.boolType; |
| 294 } else if (_types.isNull(arguments.positional[0])) { |
| 295 // TODO(johnniwinther): Add null check. |
| 296 return _types.boolType; |
| 297 } |
| 298 } |
| 299 return handleDynamicInvoke( |
| 300 CallType.access, node, selector, mask, receiverType, arguments); |
| 301 } |
| 302 |
| 303 TypeInformation handleDynamicInvoke( |
| 304 CallType callType, |
| 305 ir.Node node, |
| 306 Selector selector, |
| 307 TypeMask mask, |
| 308 TypeInformation receiverType, |
| 309 ArgumentsTypes arguments) { |
| 310 assert(receiverType != null); |
| 311 if (_types.selectorNeedsUpdate(receiverType, mask)) { |
| 312 mask = receiverType == _types.dynamicType |
| 313 ? null |
| 314 : _types.newTypedSelector(receiverType, mask); |
| 315 _inferrer.updateSelectorInMember( |
| 316 _analyzedMember, callType, node, selector, mask); |
| 317 } |
| 318 |
| 319 // TODO(johnniwinther): Refine receiver on non-captured locals. |
| 320 |
| 321 return _inferrer.registerCalledSelector(callType, node, selector, mask, |
| 322 receiverType, _analyzedMember, arguments, _sideEffects, |
| 323 inLoop: inLoop, isConditional: false); |
| 324 } |
| 257 } | 325 } |
| OLD | NEW |