Chromium Code Reviews| Index: pkg/compiler/lib/src/universe/universe.dart |
| diff --git a/pkg/compiler/lib/src/universe/universe.dart b/pkg/compiler/lib/src/universe/universe.dart |
| index c5da864ad0b354b181a6146671a4b001ca840e45..525ebb4e88604d74f6f2b60173e15842bd2d31c9 100644 |
| --- a/pkg/compiler/lib/src/universe/universe.dart |
| +++ b/pkg/compiler/lib/src/universe/universe.dart |
| @@ -18,8 +18,8 @@ import '../diagnostics/spannable.dart' show |
| SpannableAssertionFailure; |
| import '../elements/elements.dart'; |
| import '../dart_types.dart'; |
| -import '../types/types.dart'; |
| import '../tree/tree.dart'; |
| +import '../types/types.dart'; |
| import '../util/util.dart'; |
| import '../world.dart' show |
| ClassWorld, |
| @@ -30,7 +30,7 @@ part 'side_effects.dart'; |
| class UniverseSelector { |
| final Selector selector; |
| - final TypeMask mask; |
| + final ReceiverMask mask; |
| UniverseSelector(this.selector, this.mask); |
| @@ -42,57 +42,56 @@ class UniverseSelector { |
| String toString() => '$selector,$mask'; |
| } |
| -abstract class TypeMaskSet { |
| - bool applies(Element element, Selector selector, ClassWorld world); |
| - Iterable<TypeMask> get masks; |
| +/// A potential receiver for a dynamic call site. |
| +abstract class ReceiverMask { |
| + /// Returns whether [element] is a potential target when being |
| + /// invoked on this type mask. [selector] is used to ensure library |
|
Siggi Cherem (dart-lang)
2015/09/01 02:12:59
type => receiver?
Johnni Winther
2015/09/01 08:15:51
Done.
|
| + /// privacy is taken into account. |
| + bool canHit(Element element, Selector selector, ClassWorld classWorld); |
| } |
| -/// An implementation of a [TypeMaskSet] that is only increasing, that is, once |
| -/// a mask is added it cannot be removed. |
| -class IncreasingTypeMaskSet extends TypeMaskSet { |
| - bool isAll = false; |
| - Set<TypeMask> _masks; |
| - |
| - bool applies(Element element, Selector selector, ClassWorld world) { |
| - if (isAll) return true; |
| - if (_masks == null) return false; |
| - for (TypeMask mask in _masks) { |
| - if (mask.canHit(element, selector, world)) return true; |
| - } |
| - return false; |
| - } |
| - |
| - bool add(TypeMask mask) { |
| - if (isAll) return false; |
| - if (mask == null) { |
| - isAll = true; |
| - _masks = null; |
| - return true; |
| - } |
| - if (_masks == null) { |
| - _masks = new Setlet<TypeMask>(); |
| - } |
| - return _masks.add(mask); |
| - } |
| - |
| - Iterable<TypeMask> get masks { |
| - if (isAll) return const [null]; |
| - if (_masks == null) return const []; |
| - return _masks; |
| - } |
| +/// A set of potential receivers for the dynamic call sites of the same |
| +/// selector. |
| +/// |
| +/// For instance for these calls |
| +/// |
| +/// new A().foo(a, b); |
| +/// new B().foo(0, 42); |
| +/// |
| +/// the receiver mask set for dynamic calls to 'foo' with to positional |
| +/// arguments will contain receiver masks abstracting `new A()` and `new B()`. |
| +abstract class ReceiverMaskSet { |
|
Siggi Cherem (dart-lang)
2015/09/01 02:12:59
let's keep the term for now, but I wonder if "mask
Johnni Winther
2015/09/01 08:15:51
Acknowledged.
|
| + /// Returns `true` if [selector] applies to any of the potential receivers |
| + /// in this set given the closed [world]. |
| + bool applies(Element element, Selector selector, ClassWorld world); |
| - String toString() { |
| - if (isAll) { |
| - return '<all>'; |
| - } else if (_masks != null) { |
| - return '$_masks'; |
| - } else { |
| - return '<none>'; |
| - } |
| - } |
| + /// Returns `true` if any potential receivers in this set given the closed |
| + /// [world] have no implementation matching [selector]. |
| + /// |
| + /// For instance for this code snippet |
| + /// |
| + /// class A {} |
| + /// class B { foo() {} } |
| + /// m(b) => (b ? new A() : new B()).foo(); |
| + /// |
| + /// the potential receiver `new A()` have no implementation of `foo` and thus |
| + /// needs to handle the call though its `noSuchMethod` handler. |
| + bool needsNoSuchMethodHandling(Selector selector, ClassWorld world); |
| } |
| +/// A mutable [ReceiverMaskSet] used in [Universe]. |
| +abstract class UniverseReceiverMaskSet extends ReceiverMaskSet { |
| + /// Adds [mask] to this set of potential receivers. Return `true` if the |
| + /// set expanded due to the new mask. |
| + bool addReceiverMask(ReceiverMask mask); |
|
Siggi Cherem (dart-lang)
2015/09/01 02:12:59
if this is the main API to add a possible receiver
Johnni Winther
2015/09/01 08:15:51
Acknowledged.
|
| +} |
| +/// Strategy for computing potential receivers of dynamic call sites. |
| +abstract class ReceiverMaskStrategy { |
| + /// Create a [UniverseReceiverMaskSet] to represent the potential receiver for |
| + /// a dynamic call site with [selector]. |
| + UniverseReceiverMaskSet createReceiverMaskSet(Selector selector); |
| +} |
| class Universe { |
| /// The set of all directly instantiated classes, that is, classes with a |
| @@ -131,12 +130,12 @@ class Universe { |
| new Set<FunctionElement>(); |
| final Set<FunctionElement> methodsNeedingSuperGetter = |
| new Set<FunctionElement>(); |
| - final Map<String, Map<Selector, TypeMaskSet>> _invokedNames = |
| - <String, Map<Selector, TypeMaskSet>>{}; |
| - final Map<String, Map<Selector, TypeMaskSet>> _invokedGetters = |
| - <String, Map<Selector, TypeMaskSet>>{}; |
| - final Map<String, Map<Selector, TypeMaskSet>> _invokedSetters = |
| - <String, Map<Selector, TypeMaskSet>>{}; |
| + final Map<String, Map<Selector, ReceiverMaskSet>> _invokedNames = |
| + <String, Map<Selector, ReceiverMaskSet>>{}; |
| + final Map<String, Map<Selector, ReceiverMaskSet>> _invokedGetters = |
| + <String, Map<Selector, ReceiverMaskSet>>{}; |
| + final Map<String, Map<Selector, ReceiverMaskSet>> _invokedSetters = |
| + <String, Map<Selector, ReceiverMaskSet>>{}; |
| /** |
| * Fields accessed. Currently only the codegen knows this |
| @@ -178,6 +177,10 @@ class Universe { |
| */ |
| final Set<Element> closurizedMembers = new Set<Element>(); |
| + final ReceiverMaskStrategy receiverMaskStrategy; |
| + |
| + Universe(this.receiverMaskStrategy); |
| + |
| /// All directly instantiated classes, that is, classes with a generative |
| /// constructor that has been called directly and not only through a |
| /// super-call. |
| @@ -239,13 +242,13 @@ class Universe { |
| }); |
| } |
| - bool _hasMatchingSelector(Map<Selector, TypeMaskSet> selectors, |
| + bool _hasMatchingSelector(Map<Selector, ReceiverMaskSet> selectors, |
| Element member, |
| World world) { |
| if (selectors == null) return false; |
| for (Selector selector in selectors.keys) { |
| if (selector.appliesUnnamed(member, world)) { |
| - TypeMaskSet masks = selectors[selector]; |
| + ReceiverMaskSet masks = selectors[selector]; |
| if (masks.applies(member, selector, world)) { |
| return true; |
| } |
| @@ -280,46 +283,47 @@ class Universe { |
| bool _registerNewSelector( |
| UniverseSelector universeSelector, |
| - Map<String, Map<Selector, TypeMaskSet>> selectorMap) { |
| + Map<String, Map<Selector, ReceiverMaskSet>> selectorMap) { |
| Selector selector = universeSelector.selector; |
| String name = selector.name; |
| - TypeMask mask = universeSelector.mask; |
| - Map<Selector, TypeMaskSet> selectors = selectorMap.putIfAbsent( |
| - name, () => new Maplet<Selector, TypeMaskSet>()); |
| - IncreasingTypeMaskSet masks = selectors.putIfAbsent( |
| - selector, () => new IncreasingTypeMaskSet()); |
| - return masks.add(mask); |
| + ReceiverMask mask = universeSelector.mask; |
| + Map<Selector, ReceiverMaskSet> selectors = selectorMap.putIfAbsent( |
| + name, () => new Maplet<Selector, ReceiverMaskSet>()); |
| + UniverseReceiverMaskSet masks = selectors.putIfAbsent( |
| + selector, () => receiverMaskStrategy.createReceiverMaskSet(selector)); |
| + return masks.addReceiverMask(mask); |
| } |
| - Map<Selector, TypeMaskSet> _asUnmodifiable(Map<Selector, TypeMaskSet> map) { |
| + Map<Selector, ReceiverMaskSet> _asUnmodifiable( |
| + Map<Selector, ReceiverMaskSet> map) { |
| if (map == null) return null; |
| return new UnmodifiableMapView(map); |
| } |
| - Map<Selector, TypeMaskSet> invocationsByName(String name) { |
| + Map<Selector, ReceiverMaskSet> invocationsByName(String name) { |
| return _asUnmodifiable(_invokedNames[name]); |
| } |
| - Map<Selector, TypeMaskSet> getterInvocationsByName(String name) { |
| + Map<Selector, ReceiverMaskSet> getterInvocationsByName(String name) { |
| return _asUnmodifiable(_invokedGetters[name]); |
| } |
| - Map<Selector, TypeMaskSet> setterInvocationsByName(String name) { |
| + Map<Selector, ReceiverMaskSet> setterInvocationsByName(String name) { |
| return _asUnmodifiable(_invokedSetters[name]); |
| } |
| void forEachInvokedName( |
| - f(String name, Map<Selector, TypeMaskSet> selectors)) { |
| + f(String name, Map<Selector, ReceiverMaskSet> selectors)) { |
| _invokedNames.forEach(f); |
| } |
| void forEachInvokedGetter( |
| - f(String name, Map<Selector, TypeMaskSet> selectors)) { |
| + f(String name, Map<Selector, ReceiverMaskSet> selectors)) { |
| _invokedGetters.forEach(f); |
| } |
| void forEachInvokedSetter( |
| - f(String name, Map<Selector, TypeMaskSet> selectors)) { |
| + f(String name, Map<Selector, ReceiverMaskSet> selectors)) { |
| _invokedSetters.forEach(f); |
| } |