| 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 |
| 17 class Universe { | 83 class Universe { |
| 18 /// The set of all directly instantiated classes, that is, classes with a | 84 /// The set of all directly instantiated classes, that is, classes with a |
| 19 /// generative constructor that has been called directly and not only through | 85 /// generative constructor that has been called directly and not only through |
| 20 /// a super-call. | 86 /// a super-call. |
| 21 /// | 87 /// |
| 22 /// Invariant: Elements are declaration elements. | 88 /// Invariant: Elements are declaration elements. |
| 23 // TODO(johnniwinther): [_directlyInstantiatedClasses] and | 89 // TODO(johnniwinther): [_directlyInstantiatedClasses] and |
| 24 // [_instantiatedTypes] sets should be merged. | 90 // [_instantiatedTypes] sets should be merged. |
| 25 final Set<ClassElement> _directlyInstantiatedClasses = | 91 final Set<ClassElement> _directlyInstantiatedClasses = |
| 26 new Set<ClassElement>(); | 92 new Set<ClassElement>(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 44 | 110 |
| 45 /** | 111 /** |
| 46 * Documentation wanted -- johnniwinther | 112 * Documentation wanted -- johnniwinther |
| 47 * | 113 * |
| 48 * Invariant: Elements are declaration elements. | 114 * Invariant: Elements are declaration elements. |
| 49 */ | 115 */ |
| 50 final Set<FunctionElement> staticFunctionsNeedingGetter = | 116 final Set<FunctionElement> staticFunctionsNeedingGetter = |
| 51 new Set<FunctionElement>(); | 117 new Set<FunctionElement>(); |
| 52 final Set<FunctionElement> methodsNeedingSuperGetter = | 118 final Set<FunctionElement> methodsNeedingSuperGetter = |
| 53 new Set<FunctionElement>(); | 119 new Set<FunctionElement>(); |
| 54 final Map<String, Set<Selector>> invokedNames = | 120 final Map<String, Map<Selector, TypeMaskSet>> _invokedNames = |
| 55 new Map<String, Set<Selector>>(); | 121 <String, Map<Selector, TypeMaskSet>>{}; |
| 56 final Map<String, Set<Selector>> invokedGetters = | 122 final Map<String, Map<Selector, TypeMaskSet>> _invokedGetters = |
| 57 new Map<String, Set<Selector>>(); | 123 <String, Map<Selector, TypeMaskSet>>{}; |
| 58 final Map<String, Set<Selector>> invokedSetters = | 124 final Map<String, Map<Selector, TypeMaskSet>> _invokedSetters = |
| 59 new Map<String, Set<Selector>>(); | 125 <String, Map<Selector, TypeMaskSet>>{}; |
| 60 | 126 |
| 61 /** | 127 /** |
| 62 * Fields accessed. Currently only the codegen knows this | 128 * Fields accessed. Currently only the codegen knows this |
| 63 * information. The resolver is too conservative when seeing a | 129 * information. The resolver is too conservative when seeing a |
| 64 * getter and only registers an invoked getter. | 130 * getter and only registers an invoked getter. |
| 65 */ | 131 */ |
| 66 final Set<Element> fieldGetters = new Set<Element>(); | 132 final Set<Element> fieldGetters = new Set<Element>(); |
| 67 | 133 |
| 68 /** | 134 /** |
| 69 * Fields set. See comment in [fieldGetters]. | 135 * Fields set. See comment in [fieldGetters]. |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 _directlyInstantiatedClasses.add(cls); | 218 _directlyInstantiatedClasses.add(cls); |
| 153 } | 219 } |
| 154 | 220 |
| 155 // TODO(johnniwinther): Replace this by separate more specific mappings. | 221 // TODO(johnniwinther): Replace this by separate more specific mappings. |
| 156 if (!_allInstantiatedClasses.add(cls)) return; | 222 if (!_allInstantiatedClasses.add(cls)) return; |
| 157 cls.allSupertypes.forEach((InterfaceType supertype) { | 223 cls.allSupertypes.forEach((InterfaceType supertype) { |
| 158 _allInstantiatedClasses.add(supertype.element); | 224 _allInstantiatedClasses.add(supertype.element); |
| 159 }); | 225 }); |
| 160 } | 226 } |
| 161 | 227 |
| 162 bool hasMatchingSelector(Set<Selector> selectors, | 228 bool _hasMatchingSelector(Map<Selector, TypeMaskSet> selectors, |
| 163 Element member, | 229 Element member, |
| 164 World world) { | 230 World world) { |
| 165 if (selectors == null) return false; | 231 if (selectors == null) return false; |
| 166 for (Selector selector in selectors) { | 232 for (Selector selector in selectors.keys) { |
| 167 if (selector.appliesUnnamed(member, world)) return true; | 233 if (selector.appliesUnnamed(member, world)) { |
| 234 TypeMaskSet masks = selectors[selector]; |
| 235 if (masks.applies(member, selector, world)) { |
| 236 return true; |
| 237 } |
| 238 } |
| 168 } | 239 } |
| 169 return false; | 240 return false; |
| 170 } | 241 } |
| 171 | 242 |
| 172 bool hasInvocation(Element member, World world) { | 243 bool hasInvocation(Element member, World world) { |
| 173 return hasMatchingSelector(invokedNames[member.name], member, world); | 244 return _hasMatchingSelector(_invokedNames[member.name], member, world); |
| 174 } | 245 } |
| 175 | 246 |
| 176 bool hasInvokedGetter(Element member, World world) { | 247 bool hasInvokedGetter(Element member, World world) { |
| 177 return hasMatchingSelector(invokedGetters[member.name], member, world); | 248 return _hasMatchingSelector(_invokedGetters[member.name], member, world); |
| 178 } | 249 } |
| 179 | 250 |
| 180 bool hasInvokedSetter(Element member, World world) { | 251 bool hasInvokedSetter(Element member, World world) { |
| 181 return hasMatchingSelector(invokedSetters[member.name], member, world); | 252 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); |
| 182 } | 297 } |
| 183 | 298 |
| 184 DartType registerIsCheck(DartType type, Compiler compiler) { | 299 DartType registerIsCheck(DartType type, Compiler compiler) { |
| 185 type = type.unalias(compiler); | 300 type = type.unalias(compiler); |
| 186 // Even in checked mode, type annotations for return type and argument | 301 // Even in checked mode, type annotations for return type and argument |
| 187 // types do not imply type checks, so there should never be a check | 302 // types do not imply type checks, so there should never be a check |
| 188 // against the type variable of a typedef. | 303 // against the type variable of a typedef. |
| 189 isChecks.add(type); | 304 isChecks.add(type); |
| 190 return type; | 305 return type; |
| 191 } | 306 } |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 561 Name name, | 676 Name name, |
| 562 CallStructure callStructure) { | 677 CallStructure callStructure) { |
| 563 // TODO(johnniwinther): Maybe use equality instead of implicit hashing. | 678 // TODO(johnniwinther): Maybe use equality instead of implicit hashing. |
| 564 int hashCode = computeHashCode(kind, name, callStructure); | 679 int hashCode = computeHashCode(kind, name, callStructure); |
| 565 List<Selector> list = canonicalizedValues.putIfAbsent(hashCode, | 680 List<Selector> list = canonicalizedValues.putIfAbsent(hashCode, |
| 566 () => <Selector>[]); | 681 () => <Selector>[]); |
| 567 for (int i = 0; i < list.length; i++) { | 682 for (int i = 0; i < list.length; i++) { |
| 568 Selector existing = list[i]; | 683 Selector existing = list[i]; |
| 569 if (existing.match(kind, name, callStructure)) { | 684 if (existing.match(kind, name, callStructure)) { |
| 570 assert(existing.hashCode == hashCode); | 685 assert(existing.hashCode == hashCode); |
| 571 assert(existing.mask == null); | |
| 572 return existing; | 686 return existing; |
| 573 } | 687 } |
| 574 } | 688 } |
| 575 Selector result = new Selector.internal( | 689 Selector result = new Selector.internal( |
| 576 kind, name, callStructure, hashCode); | 690 kind, name, callStructure, hashCode); |
| 577 list.add(result); | 691 list.add(result); |
| 578 return result; | 692 return result; |
| 579 } | 693 } |
| 580 | 694 |
| 581 factory Selector.fromElement(Element element) { | 695 factory Selector.fromElement(Element element) { |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 | 800 |
| 687 bool get isIndex => kind == SelectorKind.INDEX && argumentCount == 1; | 801 bool get isIndex => kind == SelectorKind.INDEX && argumentCount == 1; |
| 688 bool get isIndexSet => kind == SelectorKind.INDEX && argumentCount == 2; | 802 bool get isIndexSet => kind == SelectorKind.INDEX && argumentCount == 2; |
| 689 | 803 |
| 690 bool get isOperator => kind == SelectorKind.OPERATOR; | 804 bool get isOperator => kind == SelectorKind.OPERATOR; |
| 691 bool get isUnaryOperator => isOperator && argumentCount == 0; | 805 bool get isUnaryOperator => isOperator && argumentCount == 0; |
| 692 | 806 |
| 693 /** Check whether this is a call to 'assert'. */ | 807 /** Check whether this is a call to 'assert'. */ |
| 694 bool get isAssert => isCall && identical(name, "assert"); | 808 bool get isAssert => isCall && identical(name, "assert"); |
| 695 | 809 |
| 696 bool get hasExactMask => false; | |
| 697 TypeMask get mask => null; | |
| 698 Selector get asUntyped => this; | |
| 699 | |
| 700 /** | 810 /** |
| 701 * The member name for invocation mirrors created from this selector. | 811 * The member name for invocation mirrors created from this selector. |
| 702 */ | 812 */ |
| 703 String get invocationMirrorMemberName => | 813 String get invocationMirrorMemberName => |
| 704 isSetter ? '$name=' : name; | 814 isSetter ? '$name=' : name; |
| 705 | 815 |
| 706 int get invocationMirrorKind { | 816 int get invocationMirrorKind { |
| 707 const int METHOD = 0; | 817 const int METHOD = 0; |
| 708 const int GETTER = 1; | 818 const int GETTER = 1; |
| 709 const int SETTER = 2; | 819 const int SETTER = 2; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 769 static int computeHashCode(SelectorKind kind, | 879 static int computeHashCode(SelectorKind kind, |
| 770 Name name, | 880 Name name, |
| 771 CallStructure callStructure) { | 881 CallStructure callStructure) { |
| 772 // Add bits from name and kind. | 882 // Add bits from name and kind. |
| 773 int hash = Hashing.mixHashCodeBits(name.hashCode, kind.hashCode); | 883 int hash = Hashing.mixHashCodeBits(name.hashCode, kind.hashCode); |
| 774 // Add bits from the call structure. | 884 // Add bits from the call structure. |
| 775 return Hashing.mixHashCodeBits(hash, callStructure.hashCode); | 885 return Hashing.mixHashCodeBits(hash, callStructure.hashCode); |
| 776 } | 886 } |
| 777 | 887 |
| 778 String toString() { | 888 String toString() { |
| 779 String type = ''; | 889 return 'Selector($kind, $name, ${callStructure.structureToString()})'; |
| 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); | |
| 787 } | 890 } |
| 788 | 891 |
| 789 Selector toCallSelector() => new Selector.callClosureFrom(this); | 892 Selector toCallSelector() => new Selector.callClosureFrom(this); |
| 790 } | 893 } |
| 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 |