| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 compiler.src.inferrer.type_graph_nodes; | 5 library compiler.src.inferrer.type_graph_nodes; |
| 6 | 6 |
| 7 import 'dart:collection' show IterableBase; | 7 import 'dart:collection' show IterableBase; |
| 8 | 8 |
| 9 import '../common.dart'; | 9 import '../common.dart'; |
| 10 import '../common/names.dart' show Identifiers; | 10 import '../common/names.dart' show Identifiers; |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 int other = assignments[replacement]; | 303 int other = assignments[replacement]; |
| 304 if (other != null) existing += other; | 304 if (other != null) existing += other; |
| 305 assignments[replacement] = existing; | 305 assignments[replacement] = existing; |
| 306 assignments.remove(old); | 306 assignments.remove(old); |
| 307 } | 307 } |
| 308 } | 308 } |
| 309 | 309 |
| 310 Iterator<TypeInformation> get iterator => assignments.keys.iterator; | 310 Iterator<TypeInformation> get iterator => assignments.keys.iterator; |
| 311 Iterable<TypeInformation> where(Function f) => assignments.keys.where(f); | 311 Iterable<TypeInformation> where(Function f) => assignments.keys.where(f); |
| 312 | 312 |
| 313 bool contains(TypeInformation info) => assignments.containsKey(info); | 313 bool contains(Object info) => assignments.containsKey(info); |
| 314 | 314 |
| 315 String toString() => assignments.keys.toList().toString(); | 315 String toString() => assignments.keys.toList().toString(); |
| 316 } | 316 } |
| 317 | 317 |
| 318 /** | 318 /** |
| 319 * A node representing a resolved element of the program. The kind of | 319 * A node representing a resolved element of the program. The kind of |
| 320 * elements that need an [ElementTypeInformation] are: | 320 * elements that need an [ElementTypeInformation] are: |
| 321 * | 321 * |
| 322 * - Functions (including getters and setters) | 322 * - Functions (including getters and setters) |
| 323 * - Constructors (factory or generative) | 323 * - Constructors (factory or generative) |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 * The global information is summarized in [cleanup], after which [_callers] | 401 * The global information is summarized in [cleanup], after which [_callers] |
| 402 * is set to `null`. | 402 * is set to `null`. |
| 403 */ | 403 */ |
| 404 Map<Element, Setlet<Spannable>> _callers; | 404 Map<Element, Setlet<Spannable>> _callers; |
| 405 | 405 |
| 406 MemberTypeInformation._internal(Element element) | 406 MemberTypeInformation._internal(Element element) |
| 407 : super._internal(null, element); | 407 : super._internal(null, element); |
| 408 | 408 |
| 409 void addCall(Element caller, Spannable node) { | 409 void addCall(Element caller, Spannable node) { |
| 410 assert(node is ast.Node || node is Element); | 410 assert(node is ast.Node || node is Element); |
| 411 _callers ??= <Element, Setlet>{}; | 411 _callers ??= <Element, Setlet<Spannable>>{}; |
| 412 _callers.putIfAbsent(caller, () => new Setlet()).add(node); | 412 _callers.putIfAbsent(caller, () => new Setlet()).add(node); |
| 413 } | 413 } |
| 414 | 414 |
| 415 void removeCall(Element caller, node) { | 415 void removeCall(Element caller, node) { |
| 416 if (_callers == null) return; | 416 if (_callers == null) return; |
| 417 Setlet calls = _callers[caller]; | 417 Setlet calls = _callers[caller]; |
| 418 if (calls == null) return; | 418 if (calls == null) return; |
| 419 calls.remove(node); | 419 calls.remove(node); |
| 420 if (calls.isEmpty) { | 420 if (calls.isEmpty) { |
| 421 _callers.remove(caller); | 421 _callers.remove(caller); |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 830 for (MemberElement element in targets) { | 830 for (MemberElement element in targets) { |
| 831 MemberTypeInformation callee = inferrer.types.getInferredTypeOf(element); | 831 MemberTypeInformation callee = inferrer.types.getInferredTypeOf(element); |
| 832 callee.addCall(caller, call); | 832 callee.addCall(caller, call); |
| 833 callee.addUser(this); | 833 callee.addUser(this); |
| 834 inferrer.updateParameterAssignments( | 834 inferrer.updateParameterAssignments( |
| 835 this, element, arguments, selector, typeMask, | 835 this, element, arguments, selector, typeMask, |
| 836 remove: false, addToQueue: false); | 836 remove: false, addToQueue: false); |
| 837 } | 837 } |
| 838 } | 838 } |
| 839 | 839 |
| 840 Iterable<Element> get callees => | 840 Iterable<Element> get callees => targets.map((_e) { |
| 841 targets.map((MemberElement e) => e.implementation); | 841 MemberElement e = _e; |
| 842 return e.implementation; |
| 843 }); |
| 842 | 844 |
| 843 TypeMask computeTypedSelector(InferrerEngine inferrer) { | 845 TypeMask computeTypedSelector(InferrerEngine inferrer) { |
| 844 TypeMask receiverType = receiver.type; | 846 TypeMask receiverType = receiver.type; |
| 845 | 847 |
| 846 if (mask != receiverType) { | 848 if (mask != receiverType) { |
| 847 return receiverType == inferrer.commonMasks.dynamicType | 849 return receiverType == inferrer.commonMasks.dynamicType |
| 848 ? null | 850 ? null |
| 849 : receiverType; | 851 : receiverType; |
| 850 } else { | 852 } else { |
| 851 return mask; | 853 return mask; |
| 852 } | 854 } |
| 853 } | 855 } |
| 854 | 856 |
| 855 bool targetsIncludeComplexNoSuchMethod(InferrerEngine inferrer) { | 857 bool targetsIncludeComplexNoSuchMethod(InferrerEngine inferrer) { |
| 856 return targets.any((MemberElement e) { | 858 return targets.any((_e) { |
| 859 MemberElement e = _e; |
| 857 return e is MethodElement && | 860 return e is MethodElement && |
| 858 e.isInstanceMember && | 861 e.isInstanceMember && |
| 859 e.name == Identifiers.noSuchMethod_ && | 862 e.name == Identifiers.noSuchMethod_ && |
| 860 inferrer.backend.noSuchMethodRegistry.isComplex(e); | 863 inferrer.backend.noSuchMethodRegistry.isComplex(e); |
| 861 }); | 864 }); |
| 862 } | 865 } |
| 863 | 866 |
| 864 /** | 867 /** |
| 865 * We optimize certain operations on the [int] class because we know more | 868 * We optimize certain operations on the [int] class because we know more |
| 866 * about their return type than the actual Dart code. For example, we know int | 869 * about their return type than the actual Dart code. For example, we know int |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1015 callee.removeCall(caller, call); | 1018 callee.removeCall(caller, call); |
| 1016 callee.removeUser(this); | 1019 callee.removeUser(this); |
| 1017 inferrer.updateParameterAssignments( | 1020 inferrer.updateParameterAssignments( |
| 1018 this, element, arguments, selector, typeMask, | 1021 this, element, arguments, selector, typeMask, |
| 1019 remove: true, addToQueue: true); | 1022 remove: true, addToQueue: true); |
| 1020 }); | 1023 }); |
| 1021 } | 1024 } |
| 1022 | 1025 |
| 1023 // Walk over the found targets, and compute the joined union type mask | 1026 // Walk over the found targets, and compute the joined union type mask |
| 1024 // for all these targets. | 1027 // for all these targets. |
| 1025 TypeMask result = | 1028 TypeMask result = inferrer.types.joinTypeMasks(targets.map((_element) { |
| 1026 inferrer.types.joinTypeMasks(targets.map((MemberElement element) { | 1029 MemberElement element = _element; |
| 1027 // If [canReachAll] is true, then we are iterating over all | 1030 // If [canReachAll] is true, then we are iterating over all |
| 1028 // targets that satisfy the untyped selector. We skip the return | 1031 // targets that satisfy the untyped selector. We skip the return |
| 1029 // type of the targets that can only be reached through | 1032 // type of the targets that can only be reached through |
| 1030 // `Invocation.delegate`. Note that the `noSuchMethod` targets | 1033 // `Invocation.delegate`. Note that the `noSuchMethod` targets |
| 1031 // are included in [typedTargets]. | 1034 // are included in [typedTargets]. |
| 1032 if (canReachAll && !typedTargets.contains(element)) { | 1035 if (canReachAll && !typedTargets.contains(element)) { |
| 1033 return const TypeMask.nonNullEmpty(); | 1036 return const TypeMask.nonNullEmpty(); |
| 1034 } | 1037 } |
| 1035 if (inferrer.returnsListElementType(selector, typeMask)) { | 1038 if (inferrer.returnsListElementType(selector, typeMask)) { |
| 1036 ContainerTypeMask containerTypeMask = receiver.type; | 1039 ContainerTypeMask containerTypeMask = receiver.type; |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1111 } | 1114 } |
| 1112 | 1115 |
| 1113 String toString() => 'Call site $call on ${receiver.type} $type'; | 1116 String toString() => 'Call site $call on ${receiver.type} $type'; |
| 1114 | 1117 |
| 1115 accept(TypeInformationVisitor visitor) { | 1118 accept(TypeInformationVisitor visitor) { |
| 1116 return visitor.visitDynamicCallSiteTypeInformation(this); | 1119 return visitor.visitDynamicCallSiteTypeInformation(this); |
| 1117 } | 1120 } |
| 1118 | 1121 |
| 1119 bool hasStableType(InferrerEngine inferrer) { | 1122 bool hasStableType(InferrerEngine inferrer) { |
| 1120 return receiver.isStable && | 1123 return receiver.isStable && |
| 1121 targets.every((MemberElement element) => | 1124 targets.every((_element) { |
| 1122 inferrer.types.getInferredTypeOf(element).isStable) && | 1125 MemberElement element = _element; |
| 1126 return inferrer.types.getInferredTypeOf(element).isStable; |
| 1127 }) && |
| 1123 (arguments == null || arguments.every((info) => info.isStable)) && | 1128 (arguments == null || arguments.every((info) => info.isStable)) && |
| 1124 super.hasStableType(inferrer); | 1129 super.hasStableType(inferrer); |
| 1125 } | 1130 } |
| 1126 } | 1131 } |
| 1127 | 1132 |
| 1128 class ClosureCallSiteTypeInformation extends CallSiteTypeInformation { | 1133 class ClosureCallSiteTypeInformation extends CallSiteTypeInformation { |
| 1129 final TypeInformation closure; | 1134 final TypeInformation closure; |
| 1130 | 1135 |
| 1131 ClosureCallSiteTypeInformation( | 1136 ClosureCallSiteTypeInformation( |
| 1132 MemberTypeInformation context, | 1137 MemberTypeInformation context, |
| (...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1758 // TODO(ngeoffray): Narrow to bound. | 1763 // TODO(ngeoffray): Narrow to bound. |
| 1759 return type; | 1764 return type; |
| 1760 } else { | 1765 } else { |
| 1761 ResolutionInterfaceType interfaceType = annotation; | 1766 ResolutionInterfaceType interfaceType = annotation; |
| 1762 otherType = new TypeMask.nonNullSubtype(interfaceType.element, closedWorld); | 1767 otherType = new TypeMask.nonNullSubtype(interfaceType.element, closedWorld); |
| 1763 } | 1768 } |
| 1764 if (isNullable) otherType = otherType.nullable(); | 1769 if (isNullable) otherType = otherType.nullable(); |
| 1765 if (type == null) return otherType; | 1770 if (type == null) return otherType; |
| 1766 return type.intersection(otherType, closedWorld); | 1771 return type.intersection(otherType, closedWorld); |
| 1767 } | 1772 } |
| OLD | NEW |