| Index: sdk/lib/_internal/compiler/implementation/universe/selector_map.dart
|
| diff --git a/sdk/lib/_internal/compiler/implementation/universe/selector_map.dart b/sdk/lib/_internal/compiler/implementation/universe/selector_map.dart
|
| index cf98a10cddef9c81c9b98674de4d14e6b1f53a41..36b513999633480a771d6df9d6795a57b349efeb 100644
|
| --- a/sdk/lib/_internal/compiler/implementation/universe/selector_map.dart
|
| +++ b/sdk/lib/_internal/compiler/implementation/universe/selector_map.dart
|
| @@ -4,12 +4,13 @@
|
|
|
| part of universe;
|
|
|
| +// TODO(kasperl): It seems possible to rewrite this class to be more
|
| +// like the FunctionSet abstraction which is a lot simpler.
|
| class SelectorMap<T> extends PartialTypeTree {
|
|
|
| SelectorMap(Compiler compiler) : super(compiler);
|
|
|
| - SelectorMapNode<T> newSpecializedNode(ClassElement type)
|
| - => new SelectorMapNode<T>(type);
|
| + SelectorMapNode<T> newNode(ClassElement type) => new SelectorMapNode<T>(type);
|
|
|
| T operator [](Selector selector) {
|
| SelectorMapNode<T> node = findNode(selectorType(selector), false);
|
| @@ -23,32 +24,29 @@ class SelectorMap<T> extends PartialTypeTree {
|
| return null;
|
| }
|
|
|
| + // TODO(kasperl): Do we need to support removing selectors by
|
| + // passing null as the value?
|
| void operator []=(Selector selector, T value) {
|
| - SelectorMapNode<T> node = findNode(selectorType(selector), true);
|
| - Link<SelectorValue<T>> selectors = node.selectorsByName[selector.name];
|
| - if (selectors == null) {
|
| - // No existing selectors with the given name. Create a new
|
| - // linked list.
|
| - SelectorValue<T> head = new SelectorValue<T>(selector, value);
|
| - node.selectorsByName[selector.name] =
|
| - new Link<SelectorValue<T>>().prepend(head);
|
| - } else {
|
| - // Run through the linked list of selectors with the same name. If
|
| - // we find one that matches, we update the value in the mapping.
|
| - for (Link link = selectors; !link.isEmpty; link = link.tail) {
|
| - SelectorValue<T> existing = link.head;
|
| - // It is safe to ignore the type here, because all selector
|
| - // mappings that are stored in a single node have the same type.
|
| - if (existing.selector.equalsUntyped(selector)) {
|
| - existing.value = value;
|
| - return;
|
| - }
|
| + ClassElement type = selectorType(selector);
|
| + SelectorMapNode<T> node = findNode(type, true);
|
| + SourceString name = selector.name;
|
| + Link<SelectorValue<T>> selectors = node.selectorsByName.putIfAbsent(
|
| + name, () => const Link());
|
| + // Run through the linked list of selectors with the same name. If
|
| + // we find one that matches, we update the value in the mapping.
|
| + for (Link link = selectors; !link.isEmpty; link = link.tail) {
|
| + SelectorValue<T> existing = link.head;
|
| + // It is safe to ignore the type here, because all selector
|
| + // mappings that are stored in a single node have the same type.
|
| + if (existing.selector.equalsUntyped(selector)) {
|
| + existing.value = value;
|
| + return;
|
| }
|
| - // We could not find an existing mapping for the selector, so
|
| - // we add a new one to the existing linked list.
|
| - SelectorValue<T> head = new SelectorValue<T>(selector, value);
|
| - node.selectorsByName[selector.name] = selectors.prepend(head);
|
| }
|
| + // We could not find an existing mapping for the selector, so
|
| + // we add a new one to the existing linked list.
|
| + SelectorValue<T> head = new SelectorValue<T>(selector, value);
|
| + node.selectorsByName[name] = selectors.prepend(head);
|
| }
|
|
|
| // TODO(kasperl): Share code with the [] operator?
|
| @@ -72,13 +70,10 @@ class SelectorMap<T> extends PartialTypeTree {
|
| void visitMatching(Element member, bool visit(Selector selector, T value)) {
|
| assert(member.isMember());
|
| if (root == null) return;
|
| - // TODO(kasperl): For now, we use a different implementation for
|
| - // visiting if the tree contains interface subtypes.
|
| - if (containsInterfaceSubtypes) {
|
| - visitAllMatching(member, visit);
|
| - } else {
|
| - visitHierarchyMatching(member, visit);
|
| - }
|
| + // TODO(kasperl): Use visitHierachyMatching when possible. It is
|
| + // currently broken in subtle ways when it comes to finding typed
|
| + // selectors where we only know the interface of the receiver.
|
| + visitAllMatching(member, visit);
|
| }
|
|
|
| void visitAllMatching(Element member, bool visit(selector, value)) {
|
| @@ -116,12 +111,9 @@ class SelectorMap<T> extends PartialTypeTree {
|
| }
|
|
|
| class SelectorMapNode<T> extends PartialTypeTreeNode {
|
| -
|
| - final Map<SourceString, Link<SelectorValue<T>>> selectorsByName;
|
| -
|
| - SelectorMapNode(ClassElement type) : super(type),
|
| - selectorsByName = new Map<SourceString, Link<SelectorValue<T>>>();
|
| -
|
| + final Map<SourceString, Link<SelectorValue<T>>> selectorsByName =
|
| + new Map<SourceString, Link<SelectorValue<T>>>();
|
| + SelectorMapNode(ClassElement type) : super(type);
|
| }
|
|
|
| class SelectorValue<T> {
|
|
|