| 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 24 matching lines...) Expand all Loading... |
| 35 final Selector selector; | 35 final Selector selector; |
| 36 final ReceiverConstraint mask; | 36 final ReceiverConstraint mask; |
| 37 | 37 |
| 38 UniverseSelector(this.selector, this.mask); | 38 UniverseSelector(this.selector, this.mask); |
| 39 | 39 |
| 40 bool appliesUnnamed(Element element, ClassWorld world) { | 40 bool appliesUnnamed(Element element, ClassWorld world) { |
| 41 return selector.appliesUnnamed(element, world) && | 41 return selector.appliesUnnamed(element, world) && |
| 42 (mask == null || mask.canHit(element, selector, world)); | 42 (mask == null || mask.canHit(element, selector, world)); |
| 43 } | 43 } |
| 44 | 44 |
| 45 int get hashCode => selector.hashCode * 13 + mask.hashCode * 17; | |
| 46 | |
| 47 bool operator ==(other) { | |
| 48 if (identical(this, other)) return true; | |
| 49 if (other is! UniverseSelector) return false; | |
| 50 return selector == other.selector && mask == other.mask; | |
| 51 } | |
| 52 | |
| 53 String toString() => '$selector,$mask'; | 45 String toString() => '$selector,$mask'; |
| 54 } | 46 } |
| 55 | 47 |
| 56 /// The known constraint on receiver for a dynamic call site. | 48 /// The known constraint on receiver for a dynamic call site. |
| 57 /// | 49 /// |
| 58 /// This can for instance be used to constrain this dynamic call to `foo` to | 50 /// This can for instance be used to constrain this dynamic call to `foo` to |
| 59 /// 'receivers of the exact instance `Bar`': | 51 /// 'receivers of the exact instance `Bar`': |
| 60 /// | 52 /// |
| 61 /// class Bar { | 53 /// class Bar { |
| 62 /// void foo() {} | 54 /// void foo() {} |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 152 /// | 144 /// |
| 153 /// See [_directlyInstantiatedClasses]. | 145 /// See [_directlyInstantiatedClasses]. |
| 154 final Set<DartType> _instantiatedTypes = new Set<DartType>(); | 146 final Set<DartType> _instantiatedTypes = new Set<DartType>(); |
| 155 | 147 |
| 156 /// The set of all instantiated classes, either directly, as superclasses or | 148 /// The set of all instantiated classes, either directly, as superclasses or |
| 157 /// as supertypes. | 149 /// as supertypes. |
| 158 /// | 150 /// |
| 159 /// Invariant: Elements are declaration elements. | 151 /// Invariant: Elements are declaration elements. |
| 160 final Set<ClassElement> _allInstantiatedClasses = new Set<ClassElement>(); | 152 final Set<ClassElement> _allInstantiatedClasses = new Set<ClassElement>(); |
| 161 | 153 |
| 162 /// Classes implemented by directly instantiated classes. | |
| 163 final Set<ClassElement> _implementedClasses = new Set<ClassElement>(); | |
| 164 | |
| 165 /// The set of all referenced static fields. | 154 /// The set of all referenced static fields. |
| 166 /// | 155 /// |
| 167 /// Invariant: Elements are declaration elements. | 156 /// Invariant: Elements are declaration elements. |
| 168 final Set<FieldElement> allReferencedStaticFields = new Set<FieldElement>(); | 157 final Set<FieldElement> allReferencedStaticFields = new Set<FieldElement>(); |
| 169 | 158 |
| 170 /** | 159 /** |
| 171 * Documentation wanted -- johnniwinther | 160 * Documentation wanted -- johnniwinther |
| 172 * | 161 * |
| 173 * Invariant: Elements are declaration elements. | 162 * Invariant: Elements are declaration elements. |
| 174 */ | 163 */ |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 } | 232 } |
| 244 | 233 |
| 245 /// All directly instantiated types, that is, the types of the directly | 234 /// All directly instantiated types, that is, the types of the directly |
| 246 /// instantiated classes. | 235 /// instantiated classes. |
| 247 /// | 236 /// |
| 248 /// See [directlyInstantiatedClasses]. | 237 /// See [directlyInstantiatedClasses]. |
| 249 // TODO(johnniwinther): Improve semantic precision. | 238 // TODO(johnniwinther): Improve semantic precision. |
| 250 Iterable<DartType> get instantiatedTypes => _instantiatedTypes; | 239 Iterable<DartType> get instantiatedTypes => _instantiatedTypes; |
| 251 | 240 |
| 252 /// Returns `true` if [cls] is considered to be instantiated, either directly, | 241 /// Returns `true` if [cls] is considered to be instantiated, either directly, |
| 253 /// through subclasses. | 242 /// through subclasses or through subtypes. The latter case only contains |
| 243 /// spurious information from instatiations through factory constructors and |
| 244 /// mixins. |
| 254 // TODO(johnniwinther): Improve semantic precision. | 245 // TODO(johnniwinther): Improve semantic precision. |
| 255 bool isInstantiated(ClassElement cls) { | 246 bool isInstantiated(ClassElement cls) { |
| 256 return _allInstantiatedClasses.contains(cls.declaration); | 247 return _allInstantiatedClasses.contains(cls); |
| 257 } | |
| 258 | |
| 259 /// Returns `true` if [cls] is considered to be implemented by an | |
| 260 /// instantiated class, either directly, through subclasses or through | |
| 261 /// subtypes. The latter case only contains spurious information from | |
| 262 /// instantiations through factory constructors and mixins. | |
| 263 // TODO(johnniwinther): Improve semantic precision. | |
| 264 bool isImplemented(ClassElement cls) { | |
| 265 return _implementedClasses.contains(cls.declaration); | |
| 266 } | 248 } |
| 267 | 249 |
| 268 /// Register [type] as (directly) instantiated. | 250 /// Register [type] as (directly) instantiated. |
| 269 /// | 251 /// |
| 270 /// If [byMirrors] is `true`, the instantiation is through mirrors. | 252 /// If [byMirrors] is `true`, the instantiation is through mirrors. |
| 271 // TODO(johnniwinther): Fully enforce the separation between exact, through | 253 // TODO(johnniwinther): Fully enforce the separation between exact, through |
| 272 // subclass and through subtype instantiated types/classes. | 254 // subclass and through subtype instantiated types/classes. |
| 273 // TODO(johnniwinther): Support unknown type arguments for generic types. | 255 // TODO(johnniwinther): Support unknown type arguments for generic types. |
| 274 void registerTypeInstantiation(InterfaceType type, | 256 void registerTypeInstantiation(InterfaceType type, |
| 275 {bool byMirrors: false, | 257 {bool byMirrors: false}) { |
| 276 void onImplemented(ClassElement cls)}) { | |
| 277 _instantiatedTypes.add(type); | 258 _instantiatedTypes.add(type); |
| 278 ClassElement cls = type.element; | 259 ClassElement cls = type.element; |
| 279 if (!cls.isAbstract | 260 if (!cls.isAbstract |
| 280 // We can't use the closed-world assumption with native abstract | 261 // We can't use the closed-world assumption with native abstract |
| 281 // classes; a native abstract class may have non-abstract subclasses | 262 // classes; a native abstract class may have non-abstract subclasses |
| 282 // not declared to the program. Instances of these classes are | 263 // not declared to the program. Instances of these classes are |
| 283 // indistinguishable from the abstract class. | 264 // indistinguishable from the abstract class. |
| 284 || cls.isNative | 265 || cls.isNative |
| 285 // Likewise, if this registration comes from the mirror system, | 266 // Likewise, if this registration comes from the mirror system, |
| 286 // all bets are off. | 267 // all bets are off. |
| 287 // TODO(herhut): Track classes required by mirrors seperately. | 268 // TODO(herhut): Track classes required by mirrors seperately. |
| 288 || byMirrors) { | 269 || byMirrors) { |
| 289 _directlyInstantiatedClasses.add(cls); | 270 _directlyInstantiatedClasses.add(cls); |
| 290 } | 271 } |
| 291 | 272 |
| 292 // TODO(johnniwinther): Replace this by separate more specific mappings that | 273 // TODO(johnniwinther): Replace this by separate more specific mappings. |
| 293 // include the type arguments. | 274 if (!_allInstantiatedClasses.add(cls)) return; |
| 294 if (_implementedClasses.add(cls)) { | 275 cls.allSupertypes.forEach((InterfaceType supertype) { |
| 295 onImplemented(cls); | 276 _allInstantiatedClasses.add(supertype.element); |
| 296 cls.allSupertypes.forEach((InterfaceType supertype) { | 277 }); |
| 297 if (_implementedClasses.add(supertype.element)) { | |
| 298 onImplemented(supertype.element); | |
| 299 } | |
| 300 }); | |
| 301 } | |
| 302 while (cls != null) { | |
| 303 if (!_allInstantiatedClasses.add(cls)) { | |
| 304 return; | |
| 305 } | |
| 306 cls = cls.superclass; | |
| 307 } | |
| 308 } | 278 } |
| 309 | 279 |
| 310 bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors, | 280 bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors, |
| 311 Element member, | 281 Element member, |
| 312 World world) { | 282 World world) { |
| 313 if (selectors == null) return false; | 283 if (selectors == null) return false; |
| 314 for (Selector selector in selectors.keys) { | 284 for (Selector selector in selectors.keys) { |
| 315 if (selector.appliesUnnamed(member, world)) { | 285 if (selector.appliesUnnamed(member, world)) { |
| 316 SelectorConstraints masks = selectors[selector]; | 286 SelectorConstraints masks = selectors[selector]; |
| 317 if (masks.applies(member, selector, world)) { | 287 if (masks.applies(member, selector, world)) { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 // TODO(ahe): Replace this method with something that is O(1), for example, | 399 // TODO(ahe): Replace this method with something that is O(1), for example, |
| 430 // by using a map. | 400 // by using a map. |
| 431 List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) { | 401 List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) { |
| 432 // Return new list to guard against concurrent modifications. | 402 // Return new list to guard against concurrent modifications. |
| 433 return new List<LocalFunctionElement>.from( | 403 return new List<LocalFunctionElement>.from( |
| 434 allClosures.where((LocalFunctionElement closure) { | 404 allClosures.where((LocalFunctionElement closure) { |
| 435 return closure.executableContext == element; | 405 return closure.executableContext == element; |
| 436 })); | 406 })); |
| 437 } | 407 } |
| 438 } | 408 } |
| OLD | NEW |