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]; |