| 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 15 matching lines...) Expand all Loading... |
| 26 World; | 26 World; |
| 27 | 27 |
| 28 import 'call_structure.dart'; | 28 import 'call_structure.dart'; |
| 29 import 'selector.dart' show | 29 import 'selector.dart' show |
| 30 Selector; | 30 Selector; |
| 31 import 'function_set.dart'; | 31 import 'function_set.dart'; |
| 32 import 'side_effects.dart'; | 32 import 'side_effects.dart'; |
| 33 | 33 |
| 34 class UniverseSelector { | 34 class UniverseSelector { |
| 35 final Selector selector; | 35 final Selector selector; |
| 36 final ReceiverMask 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 String toString() => '$selector,$mask'; | 45 String toString() => '$selector,$mask'; |
| 46 } | 46 } |
| 47 | 47 |
| 48 /// A potential receiver for a dynamic call site. | 48 /// The known constraint on receiver for a dynamic call site. |
| 49 abstract class ReceiverMask { | 49 /// |
| 50 /// This can for instance be used to constrain this dynamic call to `foo` to |
| 51 /// 'receivers of the exact instance `Bar`': |
| 52 /// |
| 53 /// class Bar { |
| 54 /// void foo() {} |
| 55 /// } |
| 56 /// main() => new Bar().foo(); |
| 57 /// |
| 58 abstract class ReceiverConstraint { |
| 50 /// Returns whether [element] is a potential target when being | 59 /// Returns whether [element] is a potential target when being |
| 51 /// invoked on this receiver mask. [selector] is used to ensure library | 60 /// invoked on a receiver with this constraint. [selector] is used to ensure |
| 52 /// privacy is taken into account. | 61 /// library privacy is taken into account. |
| 53 bool canHit(Element element, Selector selector, ClassWorld classWorld); | 62 bool canHit(Element element, Selector selector, ClassWorld classWorld); |
| 54 } | 63 } |
| 55 | 64 |
| 56 /// A set of potential receivers for the dynamic call sites of the same | 65 /// The combined constraints on receivers all the dynamic call sites of the same |
| 57 /// selector. | 66 /// selector. |
| 58 /// | 67 /// |
| 59 /// For instance for these calls | 68 /// For instance for these calls |
| 60 /// | 69 /// |
| 70 /// class A { |
| 71 /// foo(a, b) {} |
| 72 /// } |
| 73 /// class B { |
| 74 /// foo(a, b) {} |
| 75 /// } |
| 76 /// class C { |
| 77 /// foo(a, b) {} |
| 78 /// } |
| 61 /// new A().foo(a, b); | 79 /// new A().foo(a, b); |
| 62 /// new B().foo(0, 42); | 80 /// new B().foo(0, 42); |
| 63 /// | 81 /// |
| 64 /// the receiver mask set for dynamic calls to 'foo' with to positional | 82 /// the selector constaints for dynamic calls to 'foo' with two positional |
| 65 /// arguments will contain receiver masks abstracting `new A()` and `new B()`. | 83 /// arguments could be 'receiver of exact instance `A` or `B`'. |
| 66 abstract class ReceiverMaskSet { | 84 abstract class SelectorConstraints { |
| 67 /// Returns `true` if [selector] applies to any of the potential receivers | 85 /// Returns `true` if [selector] applies to [element] under these constraints |
| 68 /// in this set given the closed [world]. | 86 /// given the closed [world]. |
| 87 /// |
| 88 /// Consider for instance in this world: |
| 89 /// |
| 90 /// class A { |
| 91 /// foo(a, b) {} |
| 92 /// } |
| 93 /// class B { |
| 94 /// foo(a, b) {} |
| 95 /// } |
| 96 /// new A().foo(a, b); |
| 97 /// |
| 98 /// Ideally the selector constraints for calls `foo` with two positional |
| 99 /// arguments apply to `A.foo` but `B.foo`. |
| 69 bool applies(Element element, Selector selector, ClassWorld world); | 100 bool applies(Element element, Selector selector, ClassWorld world); |
| 70 | 101 |
| 71 /// Returns `true` if any potential receivers in this set given the closed | 102 /// Returns `true` if at least one of the receivers matching these constraints |
| 72 /// [world] have no implementation matching [selector]. | 103 /// in the closed [world] have no implementation matching [selector]. |
| 73 /// | 104 /// |
| 74 /// For instance for this code snippet | 105 /// For instance for this code snippet |
| 75 /// | 106 /// |
| 76 /// class A {} | 107 /// class A {} |
| 77 /// class B { foo() {} } | 108 /// class B { foo() {} } |
| 78 /// m(b) => (b ? new A() : new B()).foo(); | 109 /// m(b) => (b ? new A() : new B()).foo(); |
| 79 /// | 110 /// |
| 80 /// the potential receiver `new A()` have no implementation of `foo` and thus | 111 /// the potential receiver `new A()` has no implementation of `foo` and thus |
| 81 /// needs to handle the call though its `noSuchMethod` handler. | 112 /// needs to handle the call through its `noSuchMethod` handler. |
| 82 bool needsNoSuchMethodHandling(Selector selector, ClassWorld world); | 113 bool needsNoSuchMethodHandling(Selector selector, ClassWorld world); |
| 83 } | 114 } |
| 84 | 115 |
| 85 /// A mutable [ReceiverMaskSet] used in [Universe]. | 116 /// A mutable [SelectorConstraints] used in [Universe]. |
| 86 abstract class UniverseReceiverMaskSet extends ReceiverMaskSet { | 117 abstract class UniverseSelectorConstraints extends SelectorConstraints { |
| 87 /// Adds [mask] to this set of potential receivers. Return `true` if the | 118 /// Adds [constraint] to these selector constraints. Return `true` if the set |
| 88 /// set expanded due to the new mask. | 119 /// of potential receivers expanded due to the new constraint. |
| 89 bool addReceiverMask(ReceiverMask mask); | 120 bool addReceiverConstraint(ReceiverConstraint constraint); |
| 90 } | 121 } |
| 91 | 122 |
| 92 /// Strategy for computing potential receivers of dynamic call sites. | 123 /// Strategy for computing the constraints on potential receivers of dynamic |
| 93 abstract class ReceiverMaskStrategy { | 124 /// call sites. |
| 94 /// Create a [UniverseReceiverMaskSet] to represent the potential receiver for | 125 abstract class SelectorConstraintsStrategy { |
| 95 /// a dynamic call site with [selector]. | 126 /// Create a [UniverseSelectorConstraints] to represent the global receiver |
| 96 UniverseReceiverMaskSet createReceiverMaskSet(Selector selector); | 127 /// constraints for dynamic call sites with [selector]. |
| 128 UniverseSelectorConstraints createSelectorConstraints(Selector selector); |
| 97 } | 129 } |
| 98 | 130 |
| 99 class Universe { | 131 class Universe { |
| 100 /// The set of all directly instantiated classes, that is, classes with a | 132 /// The set of all directly instantiated classes, that is, classes with a |
| 101 /// generative constructor that has been called directly and not only through | 133 /// generative constructor that has been called directly and not only through |
| 102 /// a super-call. | 134 /// a super-call. |
| 103 /// | 135 /// |
| 104 /// Invariant: Elements are declaration elements. | 136 /// Invariant: Elements are declaration elements. |
| 105 // TODO(johnniwinther): [_directlyInstantiatedClasses] and | 137 // TODO(johnniwinther): [_directlyInstantiatedClasses] and |
| 106 // [_instantiatedTypes] sets should be merged. | 138 // [_instantiatedTypes] sets should be merged. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 126 | 158 |
| 127 /** | 159 /** |
| 128 * Documentation wanted -- johnniwinther | 160 * Documentation wanted -- johnniwinther |
| 129 * | 161 * |
| 130 * Invariant: Elements are declaration elements. | 162 * Invariant: Elements are declaration elements. |
| 131 */ | 163 */ |
| 132 final Set<FunctionElement> staticFunctionsNeedingGetter = | 164 final Set<FunctionElement> staticFunctionsNeedingGetter = |
| 133 new Set<FunctionElement>(); | 165 new Set<FunctionElement>(); |
| 134 final Set<FunctionElement> methodsNeedingSuperGetter = | 166 final Set<FunctionElement> methodsNeedingSuperGetter = |
| 135 new Set<FunctionElement>(); | 167 new Set<FunctionElement>(); |
| 136 final Map<String, Map<Selector, ReceiverMaskSet>> _invokedNames = | 168 final Map<String, Map<Selector, SelectorConstraints>> _invokedNames = |
| 137 <String, Map<Selector, ReceiverMaskSet>>{}; | 169 <String, Map<Selector, SelectorConstraints>>{}; |
| 138 final Map<String, Map<Selector, ReceiverMaskSet>> _invokedGetters = | 170 final Map<String, Map<Selector, SelectorConstraints>> _invokedGetters = |
| 139 <String, Map<Selector, ReceiverMaskSet>>{}; | 171 <String, Map<Selector, SelectorConstraints>>{}; |
| 140 final Map<String, Map<Selector, ReceiverMaskSet>> _invokedSetters = | 172 final Map<String, Map<Selector, SelectorConstraints>> _invokedSetters = |
| 141 <String, Map<Selector, ReceiverMaskSet>>{}; | 173 <String, Map<Selector, SelectorConstraints>>{}; |
| 142 | 174 |
| 143 /** | 175 /** |
| 144 * Fields accessed. Currently only the codegen knows this | 176 * Fields accessed. Currently only the codegen knows this |
| 145 * information. The resolver is too conservative when seeing a | 177 * information. The resolver is too conservative when seeing a |
| 146 * getter and only registers an invoked getter. | 178 * getter and only registers an invoked getter. |
| 147 */ | 179 */ |
| 148 final Set<Element> fieldGetters = new Set<Element>(); | 180 final Set<Element> fieldGetters = new Set<Element>(); |
| 149 | 181 |
| 150 /** | 182 /** |
| 151 * Fields set. See comment in [fieldGetters]. | 183 * Fields set. See comment in [fieldGetters]. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 173 * to find all live closure instances. | 205 * to find all live closure instances. |
| 174 */ | 206 */ |
| 175 final Set<LocalFunctionElement> allClosures = new Set<LocalFunctionElement>(); | 207 final Set<LocalFunctionElement> allClosures = new Set<LocalFunctionElement>(); |
| 176 | 208 |
| 177 /** | 209 /** |
| 178 * Set of methods in instantiated classes that are potentially | 210 * Set of methods in instantiated classes that are potentially |
| 179 * closurized. | 211 * closurized. |
| 180 */ | 212 */ |
| 181 final Set<Element> closurizedMembers = new Set<Element>(); | 213 final Set<Element> closurizedMembers = new Set<Element>(); |
| 182 | 214 |
| 183 final ReceiverMaskStrategy receiverMaskStrategy; | 215 final SelectorConstraintsStrategy selectorConstraintsStrategy; |
| 184 | 216 |
| 185 Universe(this.receiverMaskStrategy); | 217 Universe(this.selectorConstraintsStrategy); |
| 186 | 218 |
| 187 /// All directly instantiated classes, that is, classes with a generative | 219 /// All directly instantiated classes, that is, classes with a generative |
| 188 /// constructor that has been called directly and not only through a | 220 /// constructor that has been called directly and not only through a |
| 189 /// super-call. | 221 /// super-call. |
| 190 // TODO(johnniwinther): Improve semantic precision. | 222 // TODO(johnniwinther): Improve semantic precision. |
| 191 Iterable<ClassElement> get directlyInstantiatedClasses { | 223 Iterable<ClassElement> get directlyInstantiatedClasses { |
| 192 return _directlyInstantiatedClasses; | 224 return _directlyInstantiatedClasses; |
| 193 } | 225 } |
| 194 | 226 |
| 195 /// All instantiated classes, either directly, as superclasses or as | 227 /// All instantiated classes, either directly, as superclasses or as |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 _directlyInstantiatedClasses.add(cls); | 270 _directlyInstantiatedClasses.add(cls); |
| 239 } | 271 } |
| 240 | 272 |
| 241 // TODO(johnniwinther): Replace this by separate more specific mappings. | 273 // TODO(johnniwinther): Replace this by separate more specific mappings. |
| 242 if (!_allInstantiatedClasses.add(cls)) return; | 274 if (!_allInstantiatedClasses.add(cls)) return; |
| 243 cls.allSupertypes.forEach((InterfaceType supertype) { | 275 cls.allSupertypes.forEach((InterfaceType supertype) { |
| 244 _allInstantiatedClasses.add(supertype.element); | 276 _allInstantiatedClasses.add(supertype.element); |
| 245 }); | 277 }); |
| 246 } | 278 } |
| 247 | 279 |
| 248 bool _hasMatchingSelector(Map<Selector, ReceiverMaskSet> selectors, | 280 bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors, |
| 249 Element member, | 281 Element member, |
| 250 World world) { | 282 World world) { |
| 251 if (selectors == null) return false; | 283 if (selectors == null) return false; |
| 252 for (Selector selector in selectors.keys) { | 284 for (Selector selector in selectors.keys) { |
| 253 if (selector.appliesUnnamed(member, world)) { | 285 if (selector.appliesUnnamed(member, world)) { |
| 254 ReceiverMaskSet masks = selectors[selector]; | 286 SelectorConstraints masks = selectors[selector]; |
| 255 if (masks.applies(member, selector, world)) { | 287 if (masks.applies(member, selector, world)) { |
| 256 return true; | 288 return true; |
| 257 } | 289 } |
| 258 } | 290 } |
| 259 } | 291 } |
| 260 return false; | 292 return false; |
| 261 } | 293 } |
| 262 | 294 |
| 263 bool hasInvocation(Element member, World world) { | 295 bool hasInvocation(Element member, World world) { |
| 264 return _hasMatchingSelector(_invokedNames[member.name], member, world); | 296 return _hasMatchingSelector(_invokedNames[member.name], member, world); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 279 bool registerInvokedGetter(UniverseSelector selector) { | 311 bool registerInvokedGetter(UniverseSelector selector) { |
| 280 return _registerNewSelector(selector, _invokedGetters); | 312 return _registerNewSelector(selector, _invokedGetters); |
| 281 } | 313 } |
| 282 | 314 |
| 283 bool registerInvokedSetter(UniverseSelector selector) { | 315 bool registerInvokedSetter(UniverseSelector selector) { |
| 284 return _registerNewSelector(selector, _invokedSetters); | 316 return _registerNewSelector(selector, _invokedSetters); |
| 285 } | 317 } |
| 286 | 318 |
| 287 bool _registerNewSelector( | 319 bool _registerNewSelector( |
| 288 UniverseSelector universeSelector, | 320 UniverseSelector universeSelector, |
| 289 Map<String, Map<Selector, ReceiverMaskSet>> selectorMap) { | 321 Map<String, Map<Selector, SelectorConstraints>> selectorMap) { |
| 290 Selector selector = universeSelector.selector; | 322 Selector selector = universeSelector.selector; |
| 291 String name = selector.name; | 323 String name = selector.name; |
| 292 ReceiverMask mask = universeSelector.mask; | 324 ReceiverConstraint mask = universeSelector.mask; |
| 293 Map<Selector, ReceiverMaskSet> selectors = selectorMap.putIfAbsent( | 325 Map<Selector, SelectorConstraints> selectors = selectorMap.putIfAbsent( |
| 294 name, () => new Maplet<Selector, ReceiverMaskSet>()); | 326 name, () => new Maplet<Selector, SelectorConstraints>()); |
| 295 UniverseReceiverMaskSet masks = selectors.putIfAbsent( | 327 UniverseSelectorConstraints constraints = selectors.putIfAbsent( |
| 296 selector, () => receiverMaskStrategy.createReceiverMaskSet(selector)); | 328 selector, () => selectorConstraintsStrategy.createSelectorConstraints(se
lector)); |
| 297 return masks.addReceiverMask(mask); | 329 return constraints.addReceiverConstraint(mask); |
| 298 } | 330 } |
| 299 | 331 |
| 300 Map<Selector, ReceiverMaskSet> _asUnmodifiable( | 332 Map<Selector, SelectorConstraints> _asUnmodifiable( |
| 301 Map<Selector, ReceiverMaskSet> map) { | 333 Map<Selector, SelectorConstraints> map) { |
| 302 if (map == null) return null; | 334 if (map == null) return null; |
| 303 return new UnmodifiableMapView(map); | 335 return new UnmodifiableMapView(map); |
| 304 } | 336 } |
| 305 | 337 |
| 306 Map<Selector, ReceiverMaskSet> invocationsByName(String name) { | 338 Map<Selector, SelectorConstraints> invocationsByName(String name) { |
| 307 return _asUnmodifiable(_invokedNames[name]); | 339 return _asUnmodifiable(_invokedNames[name]); |
| 308 } | 340 } |
| 309 | 341 |
| 310 Map<Selector, ReceiverMaskSet> getterInvocationsByName(String name) { | 342 Map<Selector, SelectorConstraints> getterInvocationsByName(String name) { |
| 311 return _asUnmodifiable(_invokedGetters[name]); | 343 return _asUnmodifiable(_invokedGetters[name]); |
| 312 } | 344 } |
| 313 | 345 |
| 314 Map<Selector, ReceiverMaskSet> setterInvocationsByName(String name) { | 346 Map<Selector, SelectorConstraints> setterInvocationsByName(String name) { |
| 315 return _asUnmodifiable(_invokedSetters[name]); | 347 return _asUnmodifiable(_invokedSetters[name]); |
| 316 } | 348 } |
| 317 | 349 |
| 318 void forEachInvokedName( | 350 void forEachInvokedName( |
| 319 f(String name, Map<Selector, ReceiverMaskSet> selectors)) { | 351 f(String name, Map<Selector, SelectorConstraints> selectors)) { |
| 320 _invokedNames.forEach(f); | 352 _invokedNames.forEach(f); |
| 321 } | 353 } |
| 322 | 354 |
| 323 void forEachInvokedGetter( | 355 void forEachInvokedGetter( |
| 324 f(String name, Map<Selector, ReceiverMaskSet> selectors)) { | 356 f(String name, Map<Selector, SelectorConstraints> selectors)) { |
| 325 _invokedGetters.forEach(f); | 357 _invokedGetters.forEach(f); |
| 326 } | 358 } |
| 327 | 359 |
| 328 void forEachInvokedSetter( | 360 void forEachInvokedSetter( |
| 329 f(String name, Map<Selector, ReceiverMaskSet> selectors)) { | 361 f(String name, Map<Selector, SelectorConstraints> selectors)) { |
| 330 _invokedSetters.forEach(f); | 362 _invokedSetters.forEach(f); |
| 331 } | 363 } |
| 332 | 364 |
| 333 DartType registerIsCheck(DartType type, Compiler compiler) { | 365 DartType registerIsCheck(DartType type, Compiler compiler) { |
| 334 type = type.unalias(compiler); | 366 type = type.unalias(compiler); |
| 335 // Even in checked mode, type annotations for return type and argument | 367 // Even in checked mode, type annotations for return type and argument |
| 336 // types do not imply type checks, so there should never be a check | 368 // types do not imply type checks, so there should never be a check |
| 337 // against the type variable of a typedef. | 369 // against the type variable of a typedef. |
| 338 isChecks.add(type); | 370 isChecks.add(type); |
| 339 return type; | 371 return type; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 367 // 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, |
| 368 // by using a map. | 400 // by using a map. |
| 369 List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) { | 401 List<LocalFunctionElement> slowDirectlyNestedClosures(Element element) { |
| 370 // Return new list to guard against concurrent modifications. | 402 // Return new list to guard against concurrent modifications. |
| 371 return new List<LocalFunctionElement>.from( | 403 return new List<LocalFunctionElement>.from( |
| 372 allClosures.where((LocalFunctionElement closure) { | 404 allClosures.where((LocalFunctionElement closure) { |
| 373 return closure.executableContext == element; | 405 return closure.executableContext == element; |
| 374 })); | 406 })); |
| 375 } | 407 } |
| 376 } | 408 } |
| OLD | NEW |