| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 universe; | 5 library universe; |
| 6 | 6 |
| 7 import '../elements/elements.dart'; | 7 import '../elements/elements.dart'; |
| 8 import '../dart2jslib.dart'; | 8 import '../dart2jslib.dart'; |
| 9 import '../dart_types.dart'; | 9 import '../dart_types.dart'; |
| 10 import '../types/types.dart'; | 10 import '../types/types.dart'; |
| 11 import '../tree/tree.dart'; | 11 import '../tree/tree.dart'; |
| 12 import '../util/util.dart'; | 12 import '../util/util.dart'; |
| 13 | 13 |
| 14 part 'function_set.dart'; | 14 part 'function_set.dart'; |
| 15 part 'side_effects.dart'; | 15 part 'side_effects.dart'; |
| 16 | 16 |
| 17 class UniverseSelector { | |
| 18 final Selector selector; | |
| 19 final TypeMask mask; | |
| 20 | |
| 21 UniverseSelector(this.selector, this.mask); | |
| 22 | |
| 23 bool appliesUnnamed(Element element, ClassWorld world) { | |
| 24 return selector.appliesUnnamed(element, world) && | |
| 25 (mask == null || mask.canHit(element, selector, world)); | |
| 26 } | |
| 27 | |
| 28 String toString() => '$selector,$mask'; | |
| 29 } | |
| 30 | |
| 31 abstract class TypeMaskSet { | |
| 32 bool applies(Element element, Selector selector, ClassWorld world); | |
| 33 Iterable<TypeMask> get masks; | |
| 34 } | |
| 35 | |
| 36 /// An implementation of a [TypeMaskSet] that is only increasing, that is, once | |
| 37 /// a mask is added it cannot be removed. | |
| 38 class IncreasingTypeMaskSet extends TypeMaskSet { | |
| 39 bool isAll = false; | |
| 40 Set<TypeMask> _masks; | |
| 41 | |
| 42 bool applies(Element element, Selector selector, ClassWorld world) { | |
| 43 if (isAll) return true; | |
| 44 if (_masks == null) return false; | |
| 45 for (TypeMask mask in _masks) { | |
| 46 if (mask.canHit(element, selector, world)) return true; | |
| 47 } | |
| 48 return false; | |
| 49 } | |
| 50 | |
| 51 bool add(TypeMask mask) { | |
| 52 if (isAll) return false; | |
| 53 if (mask == null) { | |
| 54 isAll = true; | |
| 55 _masks = null; | |
| 56 return true; | |
| 57 } | |
| 58 if (_masks == null) { | |
| 59 _masks = new Setlet<TypeMask>(); | |
| 60 } | |
| 61 return _masks.add(mask); | |
| 62 } | |
| 63 | |
| 64 Iterable<TypeMask> get masks { | |
| 65 if (isAll) return const [null]; | |
| 66 if (_masks == null) return const []; | |
| 67 return _masks; | |
| 68 } | |
| 69 | |
| 70 String toString() { | |
| 71 if (isAll) { | |
| 72 return '<all>'; | |
| 73 } else if (_masks != null) { | |
| 74 return '$_masks'; | |
| 75 } else { | |
| 76 return '<none>'; | |
| 77 } | |
| 78 } | |
| 79 } | |
| 80 | |
| 81 | |
| 82 | |
| 83 class Universe { | 17 class Universe { |
| 84 /// The set of all directly instantiated classes, that is, classes with a | 18 /// The set of all directly instantiated classes, that is, classes with a |
| 85 /// generative constructor that has been called directly and not only through | 19 /// generative constructor that has been called directly and not only through |
| 86 /// a super-call. | 20 /// a super-call. |
| 87 /// | 21 /// |
| 88 /// Invariant: Elements are declaration elements. | 22 /// Invariant: Elements are declaration elements. |
| 89 // TODO(johnniwinther): [_directlyInstantiatedClasses] and | 23 // TODO(johnniwinther): [_directlyInstantiatedClasses] and |
| 90 // [_instantiatedTypes] sets should be merged. | 24 // [_instantiatedTypes] sets should be merged. |
| 91 final Set<ClassElement> _directlyInstantiatedClasses = | 25 final Set<ClassElement> _directlyInstantiatedClasses = |
| 92 new Set<ClassElement>(); | 26 new Set<ClassElement>(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 110 | 44 |
| 111 /** | 45 /** |
| 112 * Documentation wanted -- johnniwinther | 46 * Documentation wanted -- johnniwinther |
| 113 * | 47 * |
| 114 * Invariant: Elements are declaration elements. | 48 * Invariant: Elements are declaration elements. |
| 115 */ | 49 */ |
| 116 final Set<FunctionElement> staticFunctionsNeedingGetter = | 50 final Set<FunctionElement> staticFunctionsNeedingGetter = |
| 117 new Set<FunctionElement>(); | 51 new Set<FunctionElement>(); |
| 118 final Set<FunctionElement> methodsNeedingSuperGetter = | 52 final Set<FunctionElement> methodsNeedingSuperGetter = |
| 119 new Set<FunctionElement>(); | 53 new Set<FunctionElement>(); |
| 120 final Map<String, Map<Selector, TypeMaskSet>> _invokedNames = | 54 final Map<String, Set<Selector>> invokedNames = |
| 121 <String, Map<Selector, TypeMaskSet>>{}; | 55 new Map<String, Set<Selector>>(); |
| 122 final Map<String, Map<Selector, TypeMaskSet>> _invokedGetters = | 56 final Map<String, Set<Selector>> invokedGetters = |
| 123 <String, Map<Selector, TypeMaskSet>>{}; | 57 new Map<String, Set<Selector>>(); |
| 124 final Map<String, Map<Selector, TypeMaskSet>> _invokedSetters = | 58 final Map<String, Set<Selector>> invokedSetters = |
| 125 <String, Map<Selector, TypeMaskSet>>{}; | 59 new Map<String, Set<Selector>>(); |
| 126 | 60 |
| 127 /** | 61 /** |
| 128 * Fields accessed. Currently only the codegen knows this | 62 * Fields accessed. Currently only the codegen knows this |
| 129 * information. The resolver is too conservative when seeing a | 63 * information. The resolver is too conservative when seeing a |
| 130 * getter and only registers an invoked getter. | 64 * getter and only registers an invoked getter. |
| 131 */ | 65 */ |
| 132 final Set<Element> fieldGetters = new Set<Element>(); | 66 final Set<Element> fieldGetters = new Set<Element>(); |
| 133 | 67 |
| 134 /** | 68 /** |
| 135 * Fields set. See comment in [fieldGetters]. | 69 * Fields set. See comment in [fieldGetters]. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 _directlyInstantiatedClasses.add(cls); | 152 _directlyInstantiatedClasses.add(cls); |
| 219 } | 153 } |
| 220 | 154 |
| 221 // TODO(johnniwinther): Replace this by separate more specific mappings. | 155 // TODO(johnniwinther): Replace this by separate more specific mappings. |
| 222 if (!_allInstantiatedClasses.add(cls)) return; | 156 if (!_allInstantiatedClasses.add(cls)) return; |
| 223 cls.allSupertypes.forEach((InterfaceType supertype) { | 157 cls.allSupertypes.forEach((InterfaceType supertype) { |
| 224 _allInstantiatedClasses.add(supertype.element); | 158 _allInstantiatedClasses.add(supertype.element); |
| 225 }); | 159 }); |
| 226 } | 160 } |
| 227 | 161 |
| 228 bool _hasMatchingSelector(Map<Selector, TypeMaskSet> selectors, | 162 bool hasMatchingSelector(Set<Selector> selectors, |
| 229 Element member, | 163 Element member, |
| 230 World world) { | 164 World world) { |
| 231 if (selectors == null) return false; | 165 if (selectors == null) return false; |
| 232 for (Selector selector in selectors.keys) { | 166 for (Selector selector in selectors) { |
| 233 if (selector.appliesUnnamed(member, world)) { | 167 if (selector.appliesUnnamed(member, world)) return true; |
| 234 TypeMaskSet masks = selectors[selector]; | |
| 235 if (masks.applies(member, selector, world)) { | |
| 236 return true; | |
| 237 } | |
| 238 } | |
| 239 } | 168 } |
| 240 return false; | 169 return false; |
| 241 } | 170 } |
| 242 | 171 |
| 243 bool hasInvocation(Element member, World world) { | 172 bool hasInvocation(Element member, World world) { |
| 244 return _hasMatchingSelector(_invokedNames[member.name], member, world); | 173 return hasMatchingSelector(invokedNames[member.name], member, world); |
| 245 } | 174 } |
| 246 | 175 |
| 247 bool hasInvokedGetter(Element member, World world) { | 176 bool hasInvokedGetter(Element member, World world) { |
| 248 return _hasMatchingSelector(_invokedGetters[member.name], member, world); | 177 return hasMatchingSelector(invokedGetters[member.name], member, world); |
| 249 } | 178 } |
| 250 | 179 |
| 251 bool hasInvokedSetter(Element member, World world) { | 180 bool hasInvokedSetter(Element member, World world) { |
| 252 return _hasMatchingSelector(_invokedSetters[member.name], member, world); | 181 return hasMatchingSelector(invokedSetters[member.name], member, world); |
| 253 } | |
| 254 | |
| 255 bool registerInvocation(UniverseSelector selector) { | |
| 256 return _registerNewSelector(selector, _invokedNames); | |
| 257 } | |
| 258 | |
| 259 bool registerInvokedGetter(UniverseSelector selector) { | |
| 260 return _registerNewSelector(selector, _invokedGetters); | |
| 261 } | |
| 262 | |
| 263 bool registerInvokedSetter(UniverseSelector selector) { | |
| 264 return _registerNewSelector(selector, _invokedSetters); | |
| 265 } | |
| 266 | |
| 267 bool _registerNewSelector( | |
| 268 UniverseSelector universeSelector, | |
| 269 Map<String, Map<Selector, TypeMaskSet>> selectorMap) { | |
| 270 Selector selector = universeSelector.selector; | |
| 271 String name = selector.name; | |
| 272 TypeMask mask = universeSelector.mask; | |
| 273 Map<Selector, TypeMaskSet> selectors = selectorMap.putIfAbsent( | |
| 274 name, () => new Maplet<Selector, TypeMaskSet>()); | |
| 275 IncreasingTypeMaskSet masks = selectors.putIfAbsent( | |
| 276 selector, () => new IncreasingTypeMaskSet()); | |
| 277 return masks.add(mask); | |
| 278 } | |
| 279 | |
| 280 Map<Selector, TypeMaskSet> invocationsByName(String name) { | |
| 281 return _invokedNames[name]; | |
| 282 } | |
| 283 | |
| 284 void forEachInvokedName( | |
| 285 f(String name, Map<Selector, TypeMaskSet> selectors)) { | |
| 286 _invokedNames.forEach(f); | |
| 287 } | |
| 288 | |
| 289 void forEachInvokedGetter( | |
| 290 f(String name, Map<Selector, TypeMaskSet> selectors)) { | |
| 291 _invokedGetters.forEach(f); | |
| 292 } | |
| 293 | |
| 294 void forEachInvokedSetter( | |
| 295 f(String name, Map<Selector, TypeMaskSet> selectors)) { | |
| 296 _invokedSetters.forEach(f); | |
| 297 } | 182 } |
| 298 | 183 |
| 299 DartType registerIsCheck(DartType type, Compiler compiler) { | 184 DartType registerIsCheck(DartType type, Compiler compiler) { |
| 300 type = type.unalias(compiler); | 185 type = type.unalias(compiler); |
| 301 // Even in checked mode, type annotations for return type and argument | 186 // Even in checked mode, type annotations for return type and argument |
| 302 // types do not imply type checks, so there should never be a check | 187 // types do not imply type checks, so there should never be a check |
| 303 // against the type variable of a typedef. | 188 // against the type variable of a typedef. |
| 304 isChecks.add(type); | 189 isChecks.add(type); |
| 305 return type; | 190 return type; |
| 306 } | 191 } |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 676 Name name, | 561 Name name, |
| 677 CallStructure callStructure) { | 562 CallStructure callStructure) { |
| 678 // TODO(johnniwinther): Maybe use equality instead of implicit hashing. | 563 // TODO(johnniwinther): Maybe use equality instead of implicit hashing. |
| 679 int hashCode = computeHashCode(kind, name, callStructure); | 564 int hashCode = computeHashCode(kind, name, callStructure); |
| 680 List<Selector> list = canonicalizedValues.putIfAbsent(hashCode, | 565 List<Selector> list = canonicalizedValues.putIfAbsent(hashCode, |
| 681 () => <Selector>[]); | 566 () => <Selector>[]); |
| 682 for (int i = 0; i < list.length; i++) { | 567 for (int i = 0; i < list.length; i++) { |
| 683 Selector existing = list[i]; | 568 Selector existing = list[i]; |
| 684 if (existing.match(kind, name, callStructure)) { | 569 if (existing.match(kind, name, callStructure)) { |
| 685 assert(existing.hashCode == hashCode); | 570 assert(existing.hashCode == hashCode); |
| 571 assert(existing.mask == null); |
| 686 return existing; | 572 return existing; |
| 687 } | 573 } |
| 688 } | 574 } |
| 689 Selector result = new Selector.internal( | 575 Selector result = new Selector.internal( |
| 690 kind, name, callStructure, hashCode); | 576 kind, name, callStructure, hashCode); |
| 691 list.add(result); | 577 list.add(result); |
| 692 return result; | 578 return result; |
| 693 } | 579 } |
| 694 | 580 |
| 695 factory Selector.fromElement(Element element) { | 581 factory Selector.fromElement(Element element) { |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 800 | 686 |
| 801 bool get isIndex => kind == SelectorKind.INDEX && argumentCount == 1; | 687 bool get isIndex => kind == SelectorKind.INDEX && argumentCount == 1; |
| 802 bool get isIndexSet => kind == SelectorKind.INDEX && argumentCount == 2; | 688 bool get isIndexSet => kind == SelectorKind.INDEX && argumentCount == 2; |
| 803 | 689 |
| 804 bool get isOperator => kind == SelectorKind.OPERATOR; | 690 bool get isOperator => kind == SelectorKind.OPERATOR; |
| 805 bool get isUnaryOperator => isOperator && argumentCount == 0; | 691 bool get isUnaryOperator => isOperator && argumentCount == 0; |
| 806 | 692 |
| 807 /** Check whether this is a call to 'assert'. */ | 693 /** Check whether this is a call to 'assert'. */ |
| 808 bool get isAssert => isCall && identical(name, "assert"); | 694 bool get isAssert => isCall && identical(name, "assert"); |
| 809 | 695 |
| 696 bool get hasExactMask => false; |
| 697 TypeMask get mask => null; |
| 698 Selector get asUntyped => this; |
| 699 |
| 810 /** | 700 /** |
| 811 * The member name for invocation mirrors created from this selector. | 701 * The member name for invocation mirrors created from this selector. |
| 812 */ | 702 */ |
| 813 String get invocationMirrorMemberName => | 703 String get invocationMirrorMemberName => |
| 814 isSetter ? '$name=' : name; | 704 isSetter ? '$name=' : name; |
| 815 | 705 |
| 816 int get invocationMirrorKind { | 706 int get invocationMirrorKind { |
| 817 const int METHOD = 0; | 707 const int METHOD = 0; |
| 818 const int GETTER = 1; | 708 const int GETTER = 1; |
| 819 const int SETTER = 2; | 709 const int SETTER = 2; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 879 static int computeHashCode(SelectorKind kind, | 769 static int computeHashCode(SelectorKind kind, |
| 880 Name name, | 770 Name name, |
| 881 CallStructure callStructure) { | 771 CallStructure callStructure) { |
| 882 // Add bits from name and kind. | 772 // Add bits from name and kind. |
| 883 int hash = Hashing.mixHashCodeBits(name.hashCode, kind.hashCode); | 773 int hash = Hashing.mixHashCodeBits(name.hashCode, kind.hashCode); |
| 884 // Add bits from the call structure. | 774 // Add bits from the call structure. |
| 885 return Hashing.mixHashCodeBits(hash, callStructure.hashCode); | 775 return Hashing.mixHashCodeBits(hash, callStructure.hashCode); |
| 886 } | 776 } |
| 887 | 777 |
| 888 String toString() { | 778 String toString() { |
| 889 return 'Selector($kind, $name, ${callStructure.structureToString()})'; | 779 String type = ''; |
| 780 if (mask != null) type = ', mask=$mask'; |
| 781 return 'Selector($kind, $name, ${callStructure.structureToString()}$type)'; |
| 782 } |
| 783 |
| 784 Selector extendIfReachesAll(Compiler compiler) { |
| 785 return new TypedSelector( |
| 786 compiler.typesTask.dynamicType, this, compiler.world); |
| 890 } | 787 } |
| 891 | 788 |
| 892 Selector toCallSelector() => new Selector.callClosureFrom(this); | 789 Selector toCallSelector() => new Selector.callClosureFrom(this); |
| 893 } | 790 } |
| 791 |
| 792 class TypedSelector extends Selector { |
| 793 final Selector asUntyped; |
| 794 final TypeMask mask; |
| 795 |
| 796 TypedSelector.internal(this.mask, Selector selector, int hashCode) |
| 797 : asUntyped = selector, |
| 798 super.internal(selector.kind, |
| 799 selector.memberName, |
| 800 selector.callStructure, |
| 801 hashCode) { |
| 802 assert(mask != null); |
| 803 assert(asUntyped.mask == null); |
| 804 } |
| 805 |
| 806 |
| 807 factory TypedSelector(TypeMask mask, Selector selector, World world) { |
| 808 if (!world.hasClosedWorldAssumption) { |
| 809 // TODO(johnniwinther): Improve use of TypedSelector in an open world. |
| 810 bool isNullable = mask.isNullable; |
| 811 mask = world.compiler.typesTask.dynamicType; |
| 812 if (isNullable) { |
| 813 mask = mask.nullable(); |
| 814 } |
| 815 } |
| 816 // TODO(johnniwinther): Allow more TypeSelector kinds during resoluton. |
| 817 assert(world.isClosed || mask.isExact); |
| 818 if (selector.mask == mask) return selector; |
| 819 Selector untyped = selector.asUntyped; |
| 820 Map<TypeMask, TypedSelector> map = world.canonicalizedValues |
| 821 .putIfAbsent(untyped, () => new Map<TypeMask, TypedSelector>()); |
| 822 TypedSelector result = map[mask]; |
| 823 if (result == null) { |
| 824 int hashCode = Hashing.mixHashCodeBits(untyped.hashCode, mask.hashCode); |
| 825 result = map[mask] = new TypedSelector.internal(mask, untyped, hashCode); |
| 826 } |
| 827 return result; |
| 828 } |
| 829 |
| 830 factory TypedSelector.exact( |
| 831 ClassElement base, Selector selector, World world) |
| 832 => new TypedSelector(new TypeMask.exact(base, world), selector, |
| 833 world); |
| 834 |
| 835 factory TypedSelector.subclass( |
| 836 ClassElement base, Selector selector, World world) |
| 837 => new TypedSelector(new TypeMask.subclass(base, world), |
| 838 selector, world); |
| 839 |
| 840 factory TypedSelector.subtype( |
| 841 ClassElement base, Selector selector, World world) |
| 842 => new TypedSelector(new TypeMask.subtype(base, world), |
| 843 selector, world); |
| 844 |
| 845 bool appliesUnnamed(Element element, World world) { |
| 846 assert(sameNameHack(element, world)); |
| 847 if (!mask.canHit(element, this, world)) return false; |
| 848 return appliesUntyped(element, world); |
| 849 } |
| 850 |
| 851 Selector extendIfReachesAll(Compiler compiler) { |
| 852 bool canReachAll = compiler.enabledInvokeOn |
| 853 && mask.needsNoSuchMethodHandling(this, compiler.world); |
| 854 return canReachAll |
| 855 ? new TypedSelector( |
| 856 compiler.typesTask.dynamicType, this, compiler.world) |
| 857 : this; |
| 858 } |
| 859 } |
| OLD | NEW |