Chromium Code Reviews| Index: dart/sdk/lib/_internal/compiler/implementation/enqueue.dart |
| diff --git a/dart/sdk/lib/_internal/compiler/implementation/enqueue.dart b/dart/sdk/lib/_internal/compiler/implementation/enqueue.dart |
| index 1278cd0627fcbf7a39a63994e254360737f4b5c9..6ffab718eb65a03192044a8447484d8891fcce4a 100644 |
| --- a/dart/sdk/lib/_internal/compiler/implementation/enqueue.dart |
| +++ b/dart/sdk/lib/_internal/compiler/implementation/enqueue.dart |
| @@ -29,9 +29,15 @@ abstract class Enqueuer { |
| final String name; |
| final Compiler compiler; // TODO(ahe): Remove this dependency. |
| final Function itemCompilationContextCreator; |
| - final Map<String, Link<Element>> instanceMembersByName; |
| - final Set<ClassElement> seenClasses; |
| - final Universe universe; |
| + final Map<String, Link<Element>> instanceMembersByName |
| + = new Map<String, Link<Element>>(); |
| + final Set<ClassElement> seenClasses = new Set<ClassElement>(); |
| + final Universe universe = new Universe(); |
| + |
| + /// A reverse map from name to *all* elements with that name, not |
| + /// just instance members of instantiated classes. |
| + final Map<String, Link<Element>> allElementsByName |
| + = new Map<String, Link<Element>>(); |
|
ngeoffray
2013/05/08 12:34:06
I think this should be in the world. It will be th
ahe
2013/05/08 21:47:53
I'm really opposed to the class World. I'll move
|
| bool queueIsClosed = false; |
| EnqueueTask task; |
| @@ -39,10 +45,7 @@ abstract class Enqueuer { |
| Enqueuer(this.name, this.compiler, |
| ItemCompilationContext itemCompilationContextCreator()) |
| - : this.itemCompilationContextCreator = itemCompilationContextCreator, |
| - instanceMembersByName = new Map<String, Link<Element>>(), |
| - universe = new Universe(), |
| - seenClasses = new Set<ClassElement>(); |
| + : this.itemCompilationContextCreator = itemCompilationContextCreator; |
| /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
| bool get isResolutionQueue => false; |
| @@ -272,6 +275,104 @@ abstract class Enqueuer { |
| }); |
| } |
| + /// Called when [:const Symbol(name):] is seen. |
| + void registerConstSymbol(String name, TreeElements elements) { |
| + // If dart:mirrors is loaded, a const symbol may be used to call a |
| + // static/top-level method or accessor, instantiate a class, call |
| + // an instance method or accessor with the given name. |
| + if (compiler.mirrorSystemClass == null) return; |
| + |
| + ensureAllElementsByName(); |
| + |
| + for (var link = allElementsByName[name]; |
| + link != null && !link.isEmpty; |
| + link = link.tail) { |
| + Element element = link.head; |
| + if (Elements.isUnresolved(element)) { |
|
ngeoffray
2013/05/08 12:34:06
Could you just avoid adding them? Also, because yo
ahe
2013/05/08 21:47:53
This is defensive programming. Whenever you look
|
| + // Ignore. |
| + } else if (element.isConstructor()) { |
| + ClassElement cls = element.declaration.getEnclosingClass(); |
| + registerInstantiatedType(cls.rawType, elements); |
| + registerStaticUse(element.declaration); |
| + } else if (element.impliesType()) { |
| + // Don't enqueue classes, typedefs, and type variables. |
| + } else if (Elements.isStaticOrTopLevel(element)) { |
| + registerStaticUse(element.declaration); |
| + } else if (element.isInstanceMember()) { |
| + if (element.isFunction()) { |
| + int arity = |
| + element.asFunctionElement().requiredParameterCount(compiler); |
| + Selector selector = |
| + new Selector.call(element.name, element.getLibrary(), arity); |
| + registerInvocation(element.name, selector); |
| + } else if (element.isSetter()) { |
| + Selector selector = |
| + new Selector.setter(element.name, element.getLibrary()); |
| + registerInvokedSetter(element.name, selector); |
| + } else if (element.isGetter()) { |
| + Selector selector = |
| + new Selector.getter(element.name, element.getLibrary()); |
| + registerInvokedGetter(element.name, selector); |
| + } else if (element.isField()) { |
| + Selector selector = |
| + new Selector.setter(element.name, element.getLibrary()); |
| + registerInvokedSetter(element.name, selector); |
| + selector = |
| + new Selector.getter(element.name, element.getLibrary()); |
| + registerInvokedGetter(element.name, selector); |
| + } |
| + } |
| + } |
| + } |
| + |
| + void ensureAllElementsByName() { |
| + if (!allElementsByName.isEmpty) return; |
| + |
| + void addMemberByName(Element element) { |
| + element = element.declaration; |
| + String name = element.name.slowToString(); |
| + Link<Element> members = const Link<Element>(); |
| + if (element.isLibrary()) { |
| + LibraryElementX library = element; |
| + Uri uri = library.canonicalUri; |
| + if (uri.scheme != 'dart' && !uri.path.startsWith('_')) { |
|
Johnni Winther
2013/05/08 08:22:08
What are you trying to compute in this block?
ahe
2013/05/08 08:57:43
Top-level members. However, some of the special c
|
| + members = library.localMembers; |
| + // TODO(ahe): Is this right? Is this necessary? |
| + name = library.getLibraryOrScriptName(); |
| + } |
| + } else if (element.isClass() && !element.isMixinApplication) { |
|
ngeoffray
2013/05/08 12:34:06
What could go wrong with a mixin application?
ahe
2013/05/08 21:47:53
Not sure. Added a TODO.
|
| + ClassElementX cls = element; |
| + cls.ensureResolved(compiler); |
| + members = cls.localMembers; |
| + for (var link = cls.computeTypeParameters(compiler); |
| + !link.isEmpty; |
| + link = link.tail) { |
| + addMemberByName(link.head.element); |
|
ngeoffray
2013/05/08 12:34:06
Why do you want to add type parameters? Potential
ahe
2013/05/08 21:47:53
Yes. testNames in mirrors_test.dart will test tha
|
| + } |
| + } else if (element.isConstructor()) { |
| + SourceString source = Elements.deconstructConstructorName( |
| + element.name, element.getEnclosingClass()); |
| + if (source == null) { |
| + // source is null for unnamed constructors. |
| + name = ''; |
| + } else { |
| + name = source.slowToString(); |
| + } |
| + } |
| + allElementsByName[name] = allElementsByName.putIfAbsent( |
| + name, () => const Link<Element>()).prepend(element); |
| + for (var link = members; !link.isEmpty; link = link.tail) { |
| + addMemberByName(link.head); |
| + } |
| + } |
| + |
| + compiler.libraries.values.forEach(addMemberByName); |
| + } |
| + |
| + /// Called when [:new Symbol(...):] is seen. |
| + void registerNewSymbol(TreeElements elements) { |
| + } |
| + |
| processInstanceMembers(SourceString n, bool f(Element e)) { |
| String memberName = n.slowToString(); |
| Link<Element> members = instanceMembersByName[memberName]; |