| 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.dart'; | 9 import '../common.dart'; |
| 10 import '../compiler.dart' show Compiler; | 10 import '../compiler.dart' show Compiler; |
| 11 import '../dart_types.dart'; | 11 import '../dart_types.dart'; |
| 12 import '../elements/elements.dart'; | 12 import '../elements/elements.dart'; |
| 13 import '../util/util.dart'; | 13 import '../util/util.dart'; |
| 14 import '../world.dart' show ClassWorld, ClosedWorld, OpenWorld; | 14 import '../world.dart' show World, ClosedWorld, OpenWorld; |
| 15 import 'selector.dart' show Selector; | 15 import 'selector.dart' show Selector; |
| 16 import 'use.dart' show DynamicUse, DynamicUseKind, StaticUse, StaticUseKind; | 16 import 'use.dart' show DynamicUse, DynamicUseKind, StaticUse, StaticUseKind; |
| 17 | 17 |
| 18 /// The known constraint on receiver for a dynamic call site. | 18 /// The known constraint on receiver for a dynamic call site. |
| 19 /// | 19 /// |
| 20 /// This can for instance be used to constrain this dynamic call to `foo` to | 20 /// This can for instance be used to constrain this dynamic call to `foo` to |
| 21 /// 'receivers of the exact instance `Bar`': | 21 /// 'receivers of the exact instance `Bar`': |
| 22 /// | 22 /// |
| 23 /// class Bar { | 23 /// class Bar { |
| 24 /// void foo() {} | 24 /// void foo() {} |
| 25 /// } | 25 /// } |
| 26 /// main() => new Bar().foo(); | 26 /// main() => new Bar().foo(); |
| 27 /// | 27 /// |
| 28 abstract class ReceiverConstraint { | 28 abstract class ReceiverConstraint { |
| 29 /// Returns whether [element] is a potential target when being | 29 /// Returns whether [element] is a potential target when being |
| 30 /// invoked on a receiver with this constraint. [selector] is used to ensure | 30 /// invoked on a receiver with this constraint. [selector] is used to ensure |
| 31 /// library privacy is taken into account. | 31 /// library privacy is taken into account. |
| 32 bool canHit(Element element, Selector selector, ClassWorld classWorld); | 32 bool canHit(Element element, Selector selector, World world); |
| 33 | 33 |
| 34 /// Returns whether this [TypeMask] applied to [selector] can hit a | 34 /// Returns whether this [TypeMask] applied to [selector] can hit a |
| 35 /// [noSuchMethod]. | 35 /// [noSuchMethod]. |
| 36 bool needsNoSuchMethodHandling(Selector selector, ClassWorld classWorld); | 36 bool needsNoSuchMethodHandling(Selector selector, World world); |
| 37 } | 37 } |
| 38 | 38 |
| 39 /// The combined constraints on receivers all the dynamic call sites of the same | 39 /// The combined constraints on receivers all the dynamic call sites of the same |
| 40 /// selector. | 40 /// selector. |
| 41 /// | 41 /// |
| 42 /// For instance for these calls | 42 /// For instance for these calls |
| 43 /// | 43 /// |
| 44 /// class A { | 44 /// class A { |
| 45 /// foo(a, b) {} | 45 /// foo(a, b) {} |
| 46 /// } | 46 /// } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 64 /// class A { | 64 /// class A { |
| 65 /// foo(a, b) {} | 65 /// foo(a, b) {} |
| 66 /// } | 66 /// } |
| 67 /// class B { | 67 /// class B { |
| 68 /// foo(a, b) {} | 68 /// foo(a, b) {} |
| 69 /// } | 69 /// } |
| 70 /// new A().foo(a, b); | 70 /// new A().foo(a, b); |
| 71 /// | 71 /// |
| 72 /// Ideally the selector constraints for calls `foo` with two positional | 72 /// Ideally the selector constraints for calls `foo` with two positional |
| 73 /// arguments apply to `A.foo` but `B.foo`. | 73 /// arguments apply to `A.foo` but `B.foo`. |
| 74 bool applies(Element element, Selector selector, ClassWorld world); | 74 bool applies(Element element, Selector selector, World world); |
| 75 | 75 |
| 76 /// Returns `true` if at least one of the receivers matching these constraints | 76 /// Returns `true` if at least one of the receivers matching these constraints |
| 77 /// in the closed [world] have no implementation matching [selector]. | 77 /// in the closed [world] have no implementation matching [selector]. |
| 78 /// | 78 /// |
| 79 /// For instance for this code snippet | 79 /// For instance for this code snippet |
| 80 /// | 80 /// |
| 81 /// class A {} | 81 /// class A {} |
| 82 /// class B { foo() {} } | 82 /// class B { foo() {} } |
| 83 /// m(b) => (b ? new A() : new B()).foo(); | 83 /// m(b) => (b ? new A() : new B()).foo(); |
| 84 /// | 84 /// |
| 85 /// the potential receiver `new A()` has no implementation of `foo` and thus | 85 /// the potential receiver `new A()` has no implementation of `foo` and thus |
| 86 /// needs to handle the call through its `noSuchMethod` handler. | 86 /// needs to handle the call through its `noSuchMethod` handler. |
| 87 bool needsNoSuchMethodHandling(Selector selector, ClassWorld world); | 87 bool needsNoSuchMethodHandling(Selector selector, World world); |
| 88 } | 88 } |
| 89 | 89 |
| 90 /// A mutable [SelectorConstraints] used in [Universe]. | 90 /// A mutable [SelectorConstraints] used in [Universe]. |
| 91 abstract class UniverseSelectorConstraints extends SelectorConstraints { | 91 abstract class UniverseSelectorConstraints extends SelectorConstraints { |
| 92 /// Adds [constraint] to these selector constraints. Return `true` if the set | 92 /// Adds [constraint] to these selector constraints. Return `true` if the set |
| 93 /// of potential receivers expanded due to the new constraint. | 93 /// of potential receivers expanded due to the new constraint. |
| 94 bool addReceiverConstraint(ReceiverConstraint constraint); | 94 bool addReceiverConstraint(ReceiverConstraint constraint); |
| 95 } | 95 } |
| 96 | 96 |
| 97 /// Strategy for computing the constraints on potential receivers of dynamic | 97 /// Strategy for computing the constraints on potential receivers of dynamic |
| 98 /// call sites. | 98 /// call sites. |
| 99 abstract class SelectorConstraintsStrategy { | 99 abstract class SelectorConstraintsStrategy { |
| 100 /// Create a [UniverseSelectorConstraints] to represent the global receiver | 100 /// Create a [UniverseSelectorConstraints] to represent the global receiver |
| 101 /// constraints for dynamic call sites with [selector]. | 101 /// constraints for dynamic call sites with [selector]. |
| 102 UniverseSelectorConstraints createSelectorConstraints(Selector selector); | 102 UniverseSelectorConstraints createSelectorConstraints(Selector selector); |
| 103 } | 103 } |
| 104 | 104 |
| 105 /// The [Universe] is an auxiliary class used in the process of computing the | 105 /// The [Universe] is an auxiliary class used in the process of computing the |
| 106 /// [ClassWorld]. The concepts here and in [ClassWorld] are very similar -- in | 106 /// [ClosedWorld]. The concepts here and in [ClosedWorld] are very similar -- in |
| 107 /// the same way that the "universe expands" you can think of this as a mutable | 107 /// the same way that the "universe expands" you can think of this as a mutable |
| 108 /// world that is expanding as we visit and discover parts of the program. | 108 /// world that is expanding as we visit and discover parts of the program. |
| 109 // TODO(sigmund): rename to "growing/expanding/mutable world"? | 109 // TODO(sigmund): rename to "growing/expanding/mutable world"? |
| 110 // TODO(johnniwinther): Move common implementation to a [UniverseBase] when | 110 // TODO(johnniwinther): Move common implementation to a [UniverseBase] when |
| 111 // universes and worlds have been unified. | 111 // universes and worlds have been unified. |
| 112 abstract class Universe { | 112 abstract class Universe { |
| 113 /// All directly instantiated classes, that is, classes with a generative | 113 /// All directly instantiated classes, that is, classes with a generative |
| 114 /// constructor that has been called directly and not only through a | 114 /// constructor that has been called directly and not only through a |
| 115 /// super-call. | 115 /// super-call. |
| 116 // TODO(johnniwinther): Improve semantic precision. | 116 // TODO(johnniwinther): Improve semantic precision. |
| 117 Iterable<ClassElement> get directlyInstantiatedClasses; | 117 Iterable<ClassElement> get directlyInstantiatedClasses; |
| 118 | 118 |
| 119 /// All types that are checked either through is, as or checked mode checks. | 119 /// All types that are checked either through is, as or checked mode checks. |
| 120 Iterable<DartType> get isChecks; | 120 Iterable<DartType> get isChecks; |
| 121 | 121 |
| 122 /// Registers that [type] is checked in this universe. The unaliased type is | 122 /// Registers that [type] is checked in this universe. The unaliased type is |
| 123 /// returned. | 123 /// returned. |
| 124 DartType registerIsCheck(DartType type, Compiler compiler); | 124 DartType registerIsCheck(DartType type, Compiler compiler); |
| 125 | 125 |
| 126 /// All directly instantiated types, that is, the types of the directly | 126 /// All directly instantiated types, that is, the types of the directly |
| 127 /// instantiated classes. | 127 /// instantiated classes. |
| 128 // TODO(johnniwinther): Improve semantic precision. | 128 // TODO(johnniwinther): Improve semantic precision. |
| 129 Iterable<DartType> get instantiatedTypes; | 129 Iterable<DartType> get instantiatedTypes; |
| 130 | 130 |
| 131 /// Returns `true` if [member] is invoked as a setter. | 131 /// Returns `true` if [member] is invoked as a setter. |
| 132 bool hasInvokedSetter(Element member, ClassWorld world); | 132 bool hasInvokedSetter(Element member, World world); |
| 133 } | 133 } |
| 134 | 134 |
| 135 abstract class ResolutionUniverse implements Universe { | 135 abstract class ResolutionUniverse implements Universe { |
| 136 /// Set of (live) local functions (closures) whose signatures reference type | 136 /// Set of (live) local functions (closures) whose signatures reference type |
| 137 /// variables. | 137 /// variables. |
| 138 /// | 138 /// |
| 139 /// A live function is one whose enclosing member function has been enqueued. | 139 /// A live function is one whose enclosing member function has been enqueued. |
| 140 Set<Element> get closuresWithFreeTypeVariables; | 140 Set<Element> get closuresWithFreeTypeVariables; |
| 141 | 141 |
| 142 /// Set of (live) `call` methods whose signatures reference type variables. | 142 /// Set of (live) `call` methods whose signatures reference type variables. |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 onImplemented(cls); | 292 onImplemented(cls); |
| 293 cls.allSupertypes.forEach((InterfaceType supertype) { | 293 cls.allSupertypes.forEach((InterfaceType supertype) { |
| 294 if (_implementedClasses.add(supertype.element)) { | 294 if (_implementedClasses.add(supertype.element)) { |
| 295 onImplemented(supertype.element); | 295 onImplemented(supertype.element); |
| 296 } | 296 } |
| 297 }); | 297 }); |
| 298 } | 298 } |
| 299 } | 299 } |
| 300 | 300 |
| 301 bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors, | 301 bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors, |
| 302 Element member, ClassWorld world) { | 302 Element member, OpenWorld world) { |
| 303 if (selectors == null) return false; | 303 if (selectors == null) return false; |
| 304 for (Selector selector in selectors.keys) { | 304 for (Selector selector in selectors.keys) { |
| 305 if (selector.appliesUnnamed(member, world.backend)) { | 305 if (selector.appliesUnnamed(member)) { |
| 306 SelectorConstraints masks = selectors[selector]; | 306 SelectorConstraints masks = selectors[selector]; |
| 307 if (masks.applies(member, selector, world)) { | 307 if (masks.applies(member, selector, world)) { |
| 308 return true; | 308 return true; |
| 309 } | 309 } |
| 310 } | 310 } |
| 311 } | 311 } |
| 312 return false; | 312 return false; |
| 313 } | 313 } |
| 314 | 314 |
| 315 bool hasInvocation(Element member, OpenWorld world) { | 315 bool hasInvocation(Element member, OpenWorld world) { |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 535 onImplemented(supertype.element); | 535 onImplemented(supertype.element); |
| 536 } | 536 } |
| 537 }); | 537 }); |
| 538 } | 538 } |
| 539 } | 539 } |
| 540 | 540 |
| 541 bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors, | 541 bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors, |
| 542 Element member, ClosedWorld world) { | 542 Element member, ClosedWorld world) { |
| 543 if (selectors == null) return false; | 543 if (selectors == null) return false; |
| 544 for (Selector selector in selectors.keys) { | 544 for (Selector selector in selectors.keys) { |
| 545 if (selector.appliesUnnamed(member, world.backend)) { | 545 if (selector.appliesUnnamed(member)) { |
| 546 SelectorConstraints masks = selectors[selector]; | 546 SelectorConstraints masks = selectors[selector]; |
| 547 if (masks.applies(member, selector, world)) { | 547 if (masks.applies(member, selector, world)) { |
| 548 return true; | 548 return true; |
| 549 } | 549 } |
| 550 } | 550 } |
| 551 } | 551 } |
| 552 return false; | 552 return false; |
| 553 } | 553 } |
| 554 | 554 |
| 555 bool hasInvocation(Element member, ClosedWorld world) { | 555 bool hasInvocation(Element member, ClosedWorld world) { |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 | 656 |
| 657 void forgetElement(Element element, Compiler compiler) { | 657 void forgetElement(Element element, Compiler compiler) { |
| 658 _directlyInstantiatedClasses.remove(element); | 658 _directlyInstantiatedClasses.remove(element); |
| 659 if (element is ClassElement) { | 659 if (element is ClassElement) { |
| 660 assert(invariant(element, element.thisType.isRaw, | 660 assert(invariant(element, element.thisType.isRaw, |
| 661 message: 'Generic classes not supported (${element.thisType}).')); | 661 message: 'Generic classes not supported (${element.thisType}).')); |
| 662 _instantiatedTypes..remove(element.rawType)..remove(element.thisType); | 662 _instantiatedTypes..remove(element.rawType)..remove(element.thisType); |
| 663 } | 663 } |
| 664 } | 664 } |
| 665 } | 665 } |
| OLD | NEW |