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 'dart:collection'; | 7 import 'dart:collection'; |
8 | 8 |
9 import '../common/names.dart' show | 9 import '../common/names.dart' show |
10 Identifiers, | 10 Identifiers, |
(...skipping 23 matching lines...) Expand all Loading... |
34 final Selector selector; | 34 final Selector selector; |
35 final ReceiverMask mask; | 35 final ReceiverMask mask; |
36 | 36 |
37 UniverseSelector(this.selector, this.mask); | 37 UniverseSelector(this.selector, this.mask); |
38 | 38 |
39 bool appliesUnnamed(Element element, ClassWorld world) { | 39 bool appliesUnnamed(Element element, ClassWorld world) { |
40 return selector.appliesUnnamed(element, world) && | 40 return selector.appliesUnnamed(element, world) && |
41 (mask == null || mask.canHit(element, selector, world)); | 41 (mask == null || mask.canHit(element, selector, world)); |
42 } | 42 } |
43 | 43 |
| 44 int get hashCode => selector.hashCode * 13 + mask.hashCode * 17; |
| 45 |
| 46 bool operator ==(other) { |
| 47 if (identical(this, other)) return true; |
| 48 if (other is! UniverseSelector) return false; |
| 49 return selector == other.selector && mask == other.mask; |
| 50 } |
| 51 |
44 String toString() => '$selector,$mask'; | 52 String toString() => '$selector,$mask'; |
45 } | 53 } |
46 | 54 |
47 /// A potential receiver for a dynamic call site. | 55 /// A potential receiver for a dynamic call site. |
48 abstract class ReceiverMask { | 56 abstract class ReceiverMask { |
49 /// Returns whether [element] is a potential target when being | 57 /// Returns whether [element] is a potential target when being |
50 /// invoked on this receiver mask. [selector] is used to ensure library | 58 /// invoked on this receiver mask. [selector] is used to ensure library |
51 /// privacy is taken into account. | 59 /// privacy is taken into account. |
52 bool canHit(Element element, Selector selector, ClassWorld classWorld); | 60 bool canHit(Element element, Selector selector, ClassWorld classWorld); |
53 } | 61 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 /// | 119 /// |
112 /// See [_directlyInstantiatedClasses]. | 120 /// See [_directlyInstantiatedClasses]. |
113 final Set<DartType> _instantiatedTypes = new Set<DartType>(); | 121 final Set<DartType> _instantiatedTypes = new Set<DartType>(); |
114 | 122 |
115 /// The set of all instantiated classes, either directly, as superclasses or | 123 /// The set of all instantiated classes, either directly, as superclasses or |
116 /// as supertypes. | 124 /// as supertypes. |
117 /// | 125 /// |
118 /// Invariant: Elements are declaration elements. | 126 /// Invariant: Elements are declaration elements. |
119 final Set<ClassElement> _allInstantiatedClasses = new Set<ClassElement>(); | 127 final Set<ClassElement> _allInstantiatedClasses = new Set<ClassElement>(); |
120 | 128 |
| 129 /// Classes implemented by directly instantiated classes. |
| 130 final Set<ClassElement> _implementedClasses = new Set<ClassElement>(); |
| 131 |
121 /// The set of all referenced static fields. | 132 /// The set of all referenced static fields. |
122 /// | 133 /// |
123 /// Invariant: Elements are declaration elements. | 134 /// Invariant: Elements are declaration elements. |
124 final Set<FieldElement> allReferencedStaticFields = new Set<FieldElement>(); | 135 final Set<FieldElement> allReferencedStaticFields = new Set<FieldElement>(); |
125 | 136 |
126 /** | 137 /** |
127 * Documentation wanted -- johnniwinther | 138 * Documentation wanted -- johnniwinther |
128 * | 139 * |
129 * Invariant: Elements are declaration elements. | 140 * Invariant: Elements are declaration elements. |
130 */ | 141 */ |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 } | 210 } |
200 | 211 |
201 /// All directly instantiated types, that is, the types of the directly | 212 /// All directly instantiated types, that is, the types of the directly |
202 /// instantiated classes. | 213 /// instantiated classes. |
203 /// | 214 /// |
204 /// See [directlyInstantiatedClasses]. | 215 /// See [directlyInstantiatedClasses]. |
205 // TODO(johnniwinther): Improve semantic precision. | 216 // TODO(johnniwinther): Improve semantic precision. |
206 Iterable<DartType> get instantiatedTypes => _instantiatedTypes; | 217 Iterable<DartType> get instantiatedTypes => _instantiatedTypes; |
207 | 218 |
208 /// Returns `true` if [cls] is considered to be instantiated, either directly, | 219 /// Returns `true` if [cls] is considered to be instantiated, either directly, |
209 /// through subclasses or through subtypes. The latter case only contains | 220 /// through subclasses. |
210 /// spurious information from instatiations through factory constructors and | |
211 /// mixins. | |
212 // TODO(johnniwinther): Improve semantic precision. | 221 // TODO(johnniwinther): Improve semantic precision. |
213 bool isInstantiated(ClassElement cls) { | 222 bool isInstantiated(ClassElement cls) { |
214 return _allInstantiatedClasses.contains(cls); | 223 return _allInstantiatedClasses.contains(cls.declaration); |
| 224 } |
| 225 |
| 226 /// Returns `true` if [cls] is considered to be implemented by an |
| 227 /// instantiated class, either directly, through subclasses or through |
| 228 /// subtypes. The latter case only contains spurious information from |
| 229 /// instantiations through factory constructors and mixins. |
| 230 // TODO(johnniwinther): Improve semantic precision. |
| 231 bool isImplemented(ClassElement cls) { |
| 232 return _implementedClasses.contains(cls.declaration); |
215 } | 233 } |
216 | 234 |
217 /// Register [type] as (directly) instantiated. | 235 /// Register [type] as (directly) instantiated. |
218 /// | 236 /// |
219 /// If [byMirrors] is `true`, the instantiation is through mirrors. | 237 /// If [byMirrors] is `true`, the instantiation is through mirrors. |
220 // TODO(johnniwinther): Fully enforce the separation between exact, through | 238 // TODO(johnniwinther): Fully enforce the separation between exact, through |
221 // subclass and through subtype instantiated types/classes. | 239 // subclass and through subtype instantiated types/classes. |
222 // TODO(johnniwinther): Support unknown type arguments for generic types. | 240 // TODO(johnniwinther): Support unknown type arguments for generic types. |
223 void registerTypeInstantiation(InterfaceType type, | 241 void registerTypeInstantiation(InterfaceType type, |
224 {bool byMirrors: false}) { | 242 {bool byMirrors: false, |
| 243 void onImplemented(ClassElement cls)}) { |
225 _instantiatedTypes.add(type); | 244 _instantiatedTypes.add(type); |
226 ClassElement cls = type.element; | 245 ClassElement cls = type.element; |
227 if (!cls.isAbstract | 246 if (!cls.isAbstract |
228 // We can't use the closed-world assumption with native abstract | 247 // We can't use the closed-world assumption with native abstract |
229 // classes; a native abstract class may have non-abstract subclasses | 248 // classes; a native abstract class may have non-abstract subclasses |
230 // not declared to the program. Instances of these classes are | 249 // not declared to the program. Instances of these classes are |
231 // indistinguishable from the abstract class. | 250 // indistinguishable from the abstract class. |
232 || cls.isNative | 251 || cls.isNative |
233 // Likewise, if this registration comes from the mirror system, | 252 // Likewise, if this registration comes from the mirror system, |
234 // all bets are off. | 253 // all bets are off. |
235 // TODO(herhut): Track classes required by mirrors seperately. | 254 // TODO(herhut): Track classes required by mirrors seperately. |
236 || byMirrors) { | 255 || byMirrors) { |
237 _directlyInstantiatedClasses.add(cls); | 256 _directlyInstantiatedClasses.add(cls); |
238 } | 257 } |
239 | 258 |
240 // TODO(johnniwinther): Replace this by separate more specific mappings. | 259 // TODO(johnniwinther): Replace this by separate more specific mappings that |
241 if (!_allInstantiatedClasses.add(cls)) return; | 260 // include the type arguments. |
242 cls.allSupertypes.forEach((InterfaceType supertype) { | 261 if (_implementedClasses.add(cls)) { |
243 _allInstantiatedClasses.add(supertype.element); | 262 onImplemented(cls); |
244 }); | 263 cls.allSupertypes.forEach((InterfaceType supertype) { |
| 264 if (_implementedClasses.add(supertype.element)) { |
| 265 onImplemented(supertype.element); |
| 266 } |
| 267 }); |
| 268 } |
| 269 while (cls != null) { |
| 270 if (!_allInstantiatedClasses.add(cls)) { |
| 271 return; |
| 272 } |
| 273 cls = cls.superclass; |
| 274 } |
245 } | 275 } |
246 | 276 |
247 bool _hasMatchingSelector(Map<Selector, ReceiverMaskSet> selectors, | 277 bool _hasMatchingSelector(Map<Selector, ReceiverMaskSet> selectors, |
248 Element member, | 278 Element member, |
249 World world) { | 279 World world) { |
250 if (selectors == null) return false; | 280 if (selectors == null) return false; |
251 for (Selector selector in selectors.keys) { | 281 for (Selector selector in selectors.keys) { |
252 if (selector.appliesUnnamed(member, world)) { | 282 if (selector.appliesUnnamed(member, world)) { |
253 ReceiverMaskSet masks = selectors[selector]; | 283 ReceiverMaskSet masks = selectors[selector]; |
254 if (masks.applies(member, selector, world)) { | 284 if (masks.applies(member, selector, world)) { |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
366 // TODO(ahe): Replace this method with something that is O(1), for example, | 396 // TODO(ahe): Replace this method with something that is O(1), for example, |
367 // by using a map. | 397 // by using a map. |
368 List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) { | 398 List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) { |
369 // Return new list to guard against concurrent modifications. | 399 // Return new list to guard against concurrent modifications. |
370 return new List<LocalFunctionElement>.from( | 400 return new List<LocalFunctionElement>.from( |
371 allClosures.where((LocalFunctionElement closure) { | 401 allClosures.where((LocalFunctionElement closure) { |
372 return closure.executableContext == element; | 402 return closure.executableContext == element; |
373 })); | 403 })); |
374 } | 404 } |
375 } | 405 } |
OLD | NEW |