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 8af776327ee76c2076205e910b6ce06ba9ed8eb6..0ae3cb6906c4ce5657afd8e76bf10b0f1c9472a9 100644 |
--- a/pkg/compiler/lib/src/universe/universe.dart |
+++ b/pkg/compiler/lib/src/universe/universe.dart |
@@ -14,72 +14,6 @@ import '../util/util.dart'; |
part 'function_set.dart'; |
part 'side_effects.dart'; |
-class UniverseSelector { |
- final Selector selector; |
- final TypeMask mask; |
- |
- UniverseSelector(this.selector, this.mask); |
- |
- bool appliesUnnamed(Element element, ClassWorld world) { |
- return selector.appliesUnnamed(element, world) && |
- (mask == null || mask.canHit(element, selector, world)); |
- } |
- |
- String toString() => '$selector,$mask'; |
-} |
- |
-abstract class TypeMaskSet { |
- bool applies(Element element, Selector selector, ClassWorld world); |
- Iterable<TypeMask> get masks; |
-} |
- |
-/// 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; |
- } |
- |
- String toString() { |
- if (isAll) { |
- return '<all>'; |
- } else if (_masks != null) { |
- return '$_masks'; |
- } else { |
- return '<none>'; |
- } |
- } |
-} |
- |
- |
- |
class Universe { |
/// The set of all directly instantiated classes, that is, classes with a |
/// generative constructor that has been called directly and not only through |
@@ -117,12 +51,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, Set<Selector>> invokedNames = |
+ new Map<String, Set<Selector>>(); |
+ final Map<String, Set<Selector>> invokedGetters = |
+ new Map<String, Set<Selector>>(); |
+ final Map<String, Set<Selector>> invokedSetters = |
+ new Map<String, Set<Selector>>(); |
/** |
* Fields accessed. Currently only the codegen knows this |
@@ -225,75 +159,26 @@ class Universe { |
}); |
} |
- bool _hasMatchingSelector(Map<Selector, TypeMaskSet> selectors, |
- Element member, |
- World world) { |
+ bool hasMatchingSelector(Set<Selector> 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]; |
- if (masks.applies(member, selector, world)) { |
- return true; |
- } |
- } |
+ for (Selector selector in selectors) { |
+ if (selector.appliesUnnamed(member, world)) return true; |
} |
return false; |
} |
bool hasInvocation(Element member, World world) { |
- return _hasMatchingSelector(_invokedNames[member.name], member, world); |
+ return hasMatchingSelector(invokedNames[member.name], member, world); |
} |
bool hasInvokedGetter(Element member, World world) { |
- return _hasMatchingSelector(_invokedGetters[member.name], member, world); |
+ return hasMatchingSelector(invokedGetters[member.name], member, world); |
} |
bool hasInvokedSetter(Element member, World world) { |
- return _hasMatchingSelector(_invokedSetters[member.name], member, world); |
- } |
- |
- bool registerInvocation(UniverseSelector selector) { |
- return _registerNewSelector(selector, _invokedNames); |
- } |
- |
- bool registerInvokedGetter(UniverseSelector selector) { |
- return _registerNewSelector(selector, _invokedGetters); |
- } |
- |
- bool registerInvokedSetter(UniverseSelector selector) { |
- return _registerNewSelector(selector, _invokedSetters); |
- } |
- |
- bool _registerNewSelector( |
- UniverseSelector universeSelector, |
- Map<String, Map<Selector, TypeMaskSet>> 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); |
- } |
- |
- Map<Selector, TypeMaskSet> invocationsByName(String name) { |
- return _invokedNames[name]; |
- } |
- |
- void forEachInvokedName( |
- f(String name, Map<Selector, TypeMaskSet> selectors)) { |
- _invokedNames.forEach(f); |
- } |
- |
- void forEachInvokedGetter( |
- f(String name, Map<Selector, TypeMaskSet> selectors)) { |
- _invokedGetters.forEach(f); |
- } |
- |
- void forEachInvokedSetter( |
- f(String name, Map<Selector, TypeMaskSet> selectors)) { |
- _invokedSetters.forEach(f); |
+ return hasMatchingSelector(invokedSetters[member.name], member, world); |
} |
DartType registerIsCheck(DartType type, Compiler compiler) { |
@@ -683,6 +568,7 @@ class Selector { |
Selector existing = list[i]; |
if (existing.match(kind, name, callStructure)) { |
assert(existing.hashCode == hashCode); |
+ assert(existing.mask == null); |
return existing; |
} |
} |
@@ -807,6 +693,10 @@ class Selector { |
/** Check whether this is a call to 'assert'. */ |
bool get isAssert => isCall && identical(name, "assert"); |
+ bool get hasExactMask => false; |
+ TypeMask get mask => null; |
+ Selector get asUntyped => this; |
+ |
/** |
* The member name for invocation mirrors created from this selector. |
*/ |
@@ -886,8 +776,84 @@ class Selector { |
} |
String toString() { |
- return 'Selector($kind, $name, ${callStructure.structureToString()})'; |
+ String type = ''; |
+ if (mask != null) type = ', mask=$mask'; |
+ return 'Selector($kind, $name, ${callStructure.structureToString()}$type)'; |
+ } |
+ |
+ Selector extendIfReachesAll(Compiler compiler) { |
+ return new TypedSelector( |
+ compiler.typesTask.dynamicType, this, compiler.world); |
} |
Selector toCallSelector() => new Selector.callClosureFrom(this); |
} |
+ |
+class TypedSelector extends Selector { |
+ final Selector asUntyped; |
+ final TypeMask mask; |
+ |
+ TypedSelector.internal(this.mask, Selector selector, int hashCode) |
+ : asUntyped = selector, |
+ super.internal(selector.kind, |
+ selector.memberName, |
+ selector.callStructure, |
+ hashCode) { |
+ assert(mask != null); |
+ assert(asUntyped.mask == null); |
+ } |
+ |
+ |
+ factory TypedSelector(TypeMask mask, Selector selector, World world) { |
+ if (!world.hasClosedWorldAssumption) { |
+ // TODO(johnniwinther): Improve use of TypedSelector in an open world. |
+ bool isNullable = mask.isNullable; |
+ mask = world.compiler.typesTask.dynamicType; |
+ if (isNullable) { |
+ mask = mask.nullable(); |
+ } |
+ } |
+ // TODO(johnniwinther): Allow more TypeSelector kinds during resoluton. |
+ assert(world.isClosed || mask.isExact); |
+ if (selector.mask == mask) return selector; |
+ Selector untyped = selector.asUntyped; |
+ Map<TypeMask, TypedSelector> map = world.canonicalizedValues |
+ .putIfAbsent(untyped, () => new Map<TypeMask, TypedSelector>()); |
+ TypedSelector result = map[mask]; |
+ if (result == null) { |
+ int hashCode = Hashing.mixHashCodeBits(untyped.hashCode, mask.hashCode); |
+ result = map[mask] = new TypedSelector.internal(mask, untyped, hashCode); |
+ } |
+ return result; |
+ } |
+ |
+ factory TypedSelector.exact( |
+ ClassElement base, Selector selector, World world) |
+ => new TypedSelector(new TypeMask.exact(base, world), selector, |
+ world); |
+ |
+ factory TypedSelector.subclass( |
+ ClassElement base, Selector selector, World world) |
+ => new TypedSelector(new TypeMask.subclass(base, world), |
+ selector, world); |
+ |
+ factory TypedSelector.subtype( |
+ ClassElement base, Selector selector, World world) |
+ => new TypedSelector(new TypeMask.subtype(base, world), |
+ selector, world); |
+ |
+ bool appliesUnnamed(Element element, World world) { |
+ assert(sameNameHack(element, world)); |
+ if (!mask.canHit(element, this, world)) return false; |
+ return appliesUntyped(element, world); |
+ } |
+ |
+ Selector extendIfReachesAll(Compiler compiler) { |
+ bool canReachAll = compiler.enabledInvokeOn |
+ && mask.needsNoSuchMethodHandling(this, compiler.world); |
+ return canReachAll |
+ ? new TypedSelector( |
+ compiler.typesTask.dynamicType, this, compiler.world) |
+ : this; |
+ } |
+} |