| Index: pkg/compiler/lib/src/js_backend/enqueuer.dart
 | 
| diff --git a/pkg/compiler/lib/src/js_backend/enqueuer.dart b/pkg/compiler/lib/src/js_backend/enqueuer.dart
 | 
| index a9736b81f1ceb5facc4a84c74f67b4725e68f36b..420dfab674328056091b8310b127457fcaf88d19 100644
 | 
| --- a/pkg/compiler/lib/src/js_backend/enqueuer.dart
 | 
| +++ b/pkg/compiler/lib/src/js_backend/enqueuer.dart
 | 
| @@ -58,16 +58,10 @@ class CodegenEnqueuer implements Enqueuer {
 | 
|    final CodegenWorldBuilderImpl _universe =
 | 
|        new CodegenWorldBuilderImpl(const TypeMaskStrategy());
 | 
|  
 | 
| -  static final TRACE_MIRROR_ENQUEUING =
 | 
| -      const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING");
 | 
| -
 | 
|    bool queueIsClosed = false;
 | 
|    EnqueueTask task;
 | 
|    native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask
 | 
|  
 | 
| -  bool hasEnqueuedReflectiveElements = false;
 | 
| -  bool hasEnqueuedReflectiveStaticFields = false;
 | 
| -
 | 
|    WorldImpactVisitor impactVisitor;
 | 
|  
 | 
|    CodegenEnqueuer(Compiler compiler, this.strategy)
 | 
| @@ -85,10 +79,6 @@ class CodegenEnqueuer implements Enqueuer {
 | 
|  
 | 
|    CompilerOptions get options => _compiler.options;
 | 
|  
 | 
| -  Registry get globalDependencies => _compiler.globalDependencies;
 | 
| -
 | 
| -  Registry get mirrorDependencies => _compiler.mirrorDependencies;
 | 
| -
 | 
|    ClosedWorld get _world => _compiler.closedWorld;
 | 
|  
 | 
|    bool get queueIsEmpty => queue.isEmpty;
 | 
| @@ -140,15 +130,24 @@ class CodegenEnqueuer implements Enqueuer {
 | 
|          .visitImpact(impactSource, worldImpact, impactVisitor, impactUse);
 | 
|    }
 | 
|  
 | 
| -  void registerInstantiatedType(InterfaceType type, {bool mirrorUsage: false}) {
 | 
| +  void registerInstantiatedType(InterfaceType type) {
 | 
| +    _registerInstantiatedType(type);
 | 
| +  }
 | 
| +
 | 
| +  void _registerInstantiatedType(InterfaceType type,
 | 
| +      {bool mirrorUsage: false, bool nativeUsage: false}) {
 | 
|      task.measure(() {
 | 
|        ClassElement cls = type.element;
 | 
|        bool isNative = backend.isNative(cls);
 | 
|        _universe.registerTypeInstantiation(type,
 | 
|            isNative: isNative,
 | 
|            byMirrors: mirrorUsage, onImplemented: (ClassElement cls) {
 | 
| -        backend.registerImplementedClass(cls, this, globalDependencies);
 | 
| +        backend.registerImplementedClass(cls, this);
 | 
|        });
 | 
| +      if (nativeUsage) {
 | 
| +        nativeEnqueuer.onInstantiatedType(type);
 | 
| +      }
 | 
| +      backend.registerInstantiatedType(type);
 | 
|        // TODO(johnniwinther): Share this reasoning with [Universe].
 | 
|        if (!cls.isAbstract || isNative || mirrorUsage) {
 | 
|          processInstantiatedClass(cls);
 | 
| @@ -274,7 +273,7 @@ class CodegenEnqueuer implements Enqueuer {
 | 
|          // We only tell the backend once that [superclass] was instantiated, so
 | 
|          // any additional dependencies must be treated as global
 | 
|          // dependencies.
 | 
| -        backend.registerInstantiatedClass(superclass, this, globalDependencies);
 | 
| +        backend.registerInstantiatedClass(superclass, this);
 | 
|        }
 | 
|  
 | 
|        ClassElement superclass = cls;
 | 
| @@ -293,165 +292,6 @@ class CodegenEnqueuer implements Enqueuer {
 | 
|      });
 | 
|    }
 | 
|  
 | 
| -  void logEnqueueReflectiveAction(action, [msg = ""]) {
 | 
| -    if (TRACE_MIRROR_ENQUEUING) {
 | 
| -      print("MIRROR_ENQUEUE (C): $action $msg");
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  /// Enqeue the constructor [ctor] if it is required for reflection.
 | 
| -  ///
 | 
| -  /// [enclosingWasIncluded] provides a hint whether the enclosing element was
 | 
| -  /// needed for reflection.
 | 
| -  void enqueueReflectiveConstructor(
 | 
| -      ConstructorElement ctor, bool enclosingWasIncluded) {
 | 
| -    if (shouldIncludeElementDueToMirrors(ctor,
 | 
| -        includedEnclosing: enclosingWasIncluded)) {
 | 
| -      logEnqueueReflectiveAction(ctor);
 | 
| -      ClassElement cls = ctor.declaration.enclosingClass;
 | 
| -      backend.registerInstantiatedType(cls.rawType, this, mirrorDependencies,
 | 
| -          mirrorUsage: true);
 | 
| -      registerStaticUse(new StaticUse.foreignUse(ctor.declaration));
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  /// Enqeue the member [element] if it is required for reflection.
 | 
| -  ///
 | 
| -  /// [enclosingWasIncluded] provides a hint whether the enclosing element was
 | 
| -  /// needed for reflection.
 | 
| -  void enqueueReflectiveMember(Element element, bool enclosingWasIncluded) {
 | 
| -    if (shouldIncludeElementDueToMirrors(element,
 | 
| -        includedEnclosing: enclosingWasIncluded)) {
 | 
| -      logEnqueueReflectiveAction(element);
 | 
| -      if (element.isTypedef) {
 | 
| -        // Do nothing.
 | 
| -      } else if (Elements.isStaticOrTopLevel(element)) {
 | 
| -        registerStaticUse(new StaticUse.foreignUse(element.declaration));
 | 
| -      } else if (element.isInstanceMember) {
 | 
| -        // We need to enqueue all members matching this one in subclasses, as
 | 
| -        // well.
 | 
| -        // TODO(herhut): Use TypedSelector.subtype for enqueueing
 | 
| -        DynamicUse dynamicUse =
 | 
| -            new DynamicUse(new Selector.fromElement(element), null);
 | 
| -        registerDynamicUse(dynamicUse);
 | 
| -        if (element.isField) {
 | 
| -          DynamicUse dynamicUse = new DynamicUse(
 | 
| -              new Selector.setter(
 | 
| -                  new Name(element.name, element.library, isSetter: true)),
 | 
| -              null);
 | 
| -          registerDynamicUse(dynamicUse);
 | 
| -        }
 | 
| -      }
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  /// Enqeue the member [element] if it is required for reflection.
 | 
| -  ///
 | 
| -  /// [enclosingWasIncluded] provides a hint whether the enclosing element was
 | 
| -  /// needed for reflection.
 | 
| -  void enqueueReflectiveElementsInClass(ClassElement cls,
 | 
| -      Iterable<ClassElement> recents, bool enclosingWasIncluded) {
 | 
| -    if (cls.library.isInternalLibrary || cls.isInjected) return;
 | 
| -    bool includeClass = shouldIncludeElementDueToMirrors(cls,
 | 
| -        includedEnclosing: enclosingWasIncluded);
 | 
| -    if (includeClass) {
 | 
| -      logEnqueueReflectiveAction(cls, "register");
 | 
| -      ClassElement decl = cls.declaration;
 | 
| -      backend.registerInstantiatedType(decl.rawType, this, mirrorDependencies,
 | 
| -          mirrorUsage: true);
 | 
| -    }
 | 
| -    // If the class is never instantiated, we know nothing of it can possibly
 | 
| -    // be reflected upon.
 | 
| -    // TODO(herhut): Add a warning if a mirrors annotation cannot hit.
 | 
| -    if (recents.contains(cls.declaration)) {
 | 
| -      logEnqueueReflectiveAction(cls, "members");
 | 
| -      cls.constructors.forEach((Element element) {
 | 
| -        enqueueReflectiveConstructor(element, includeClass);
 | 
| -      });
 | 
| -      cls.forEachClassMember((Member member) {
 | 
| -        enqueueReflectiveMember(member.element, includeClass);
 | 
| -      });
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  /// Enqeue special classes that might not be visible by normal means or that
 | 
| -  /// would not normally be enqueued:
 | 
| -  ///
 | 
| -  /// [Closure] is treated specially as it is the superclass of all closures.
 | 
| -  /// Although it is in an internal library, we mark it as reflectable. Note
 | 
| -  /// that none of its methods are reflectable, unless reflectable by
 | 
| -  /// inheritance.
 | 
| -  void enqueueReflectiveSpecialClasses() {
 | 
| -    Iterable<ClassElement> classes = backend.classesRequiredForReflection;
 | 
| -    for (ClassElement cls in classes) {
 | 
| -      if (backend.referencedFromMirrorSystem(cls)) {
 | 
| -        logEnqueueReflectiveAction(cls);
 | 
| -        backend.registerInstantiatedType(cls.rawType, this, mirrorDependencies,
 | 
| -            mirrorUsage: true);
 | 
| -      }
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  /// Enqeue all local members of the library [lib] if they are required for
 | 
| -  /// reflection.
 | 
| -  void enqueueReflectiveElementsInLibrary(
 | 
| -      LibraryElement lib, Iterable<ClassElement> recents) {
 | 
| -    bool includeLibrary =
 | 
| -        shouldIncludeElementDueToMirrors(lib, includedEnclosing: false);
 | 
| -    lib.forEachLocalMember((Element member) {
 | 
| -      if (member.isInjected) return;
 | 
| -      if (member.isClass) {
 | 
| -        enqueueReflectiveElementsInClass(member, recents, includeLibrary);
 | 
| -      } else {
 | 
| -        enqueueReflectiveMember(member, includeLibrary);
 | 
| -      }
 | 
| -    });
 | 
| -  }
 | 
| -
 | 
| -  /// Enqueue all elements that are matched by the mirrors used
 | 
| -  /// annotation or, in lack thereof, all elements.
 | 
| -  void enqueueReflectiveElements(Iterable<ClassElement> recents) {
 | 
| -    if (!hasEnqueuedReflectiveElements) {
 | 
| -      logEnqueueReflectiveAction("!START enqueueAll");
 | 
| -      // First round of enqueuing, visit everything that is visible to
 | 
| -      // also pick up static top levels, etc.
 | 
| -      // Also, during the first round, consider all classes that have been seen
 | 
| -      // as recently seen, as we do not know how many rounds of resolution might
 | 
| -      // have run before tree shaking is disabled and thus everything is
 | 
| -      // enqueued.
 | 
| -      recents = _processedClasses.toSet();
 | 
| -      reporter.log('Enqueuing everything');
 | 
| -      for (LibraryElement lib in _compiler.libraryLoader.libraries) {
 | 
| -        enqueueReflectiveElementsInLibrary(lib, recents);
 | 
| -      }
 | 
| -      enqueueReflectiveSpecialClasses();
 | 
| -      hasEnqueuedReflectiveElements = true;
 | 
| -      hasEnqueuedReflectiveStaticFields = true;
 | 
| -      logEnqueueReflectiveAction("!DONE enqueueAll");
 | 
| -    } else if (recents.isNotEmpty) {
 | 
| -      // Keep looking at new classes until fixpoint is reached.
 | 
| -      logEnqueueReflectiveAction("!START enqueueRecents");
 | 
| -      recents.forEach((ClassElement cls) {
 | 
| -        enqueueReflectiveElementsInClass(
 | 
| -            cls,
 | 
| -            recents,
 | 
| -            shouldIncludeElementDueToMirrors(cls.library,
 | 
| -                includedEnclosing: false));
 | 
| -      });
 | 
| -      logEnqueueReflectiveAction("!DONE enqueueRecents");
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
| -  /// Enqueue the static fields that have been marked as used by reflective
 | 
| -  /// usage through `MirrorsUsed`.
 | 
| -  void enqueueReflectiveStaticFields(Iterable<Element> elements) {
 | 
| -    if (hasEnqueuedReflectiveStaticFields) return;
 | 
| -    hasEnqueuedReflectiveStaticFields = true;
 | 
| -    for (Element element in elements) {
 | 
| -      enqueueReflectiveMember(element, true);
 | 
| -    }
 | 
| -  }
 | 
| -
 | 
|    void processSet(
 | 
|        Map<String, Set<Element>> map, String memberName, bool f(Element e)) {
 | 
|      Set<Element> members = map[memberName];
 | 
| @@ -517,7 +357,7 @@ class CodegenEnqueuer implements Enqueuer {
 | 
|      assert(invariant(element, element.isDeclaration,
 | 
|          message: "Element ${element} is not the declaration."));
 | 
|      _universe.registerStaticUse(staticUse);
 | 
| -    backend.registerStaticUse(element, forResolution: false);
 | 
| +    backend.registerStaticUse(this, element);
 | 
|      bool addElement = true;
 | 
|      switch (staticUse.kind) {
 | 
|        case StaticUseKind.STATIC_TEAR_OFF:
 | 
| @@ -553,7 +393,13 @@ class CodegenEnqueuer implements Enqueuer {
 | 
|      DartType type = typeUse.type;
 | 
|      switch (typeUse.kind) {
 | 
|        case TypeUseKind.INSTANTIATION:
 | 
| -        registerInstantiatedType(type);
 | 
| +        _registerInstantiatedType(type);
 | 
| +        break;
 | 
| +      case TypeUseKind.MIRROR_INSTANTIATION:
 | 
| +        _registerInstantiatedType(type, mirrorUsage: true);
 | 
| +        break;
 | 
| +      case TypeUseKind.NATIVE_INSTANTIATION:
 | 
| +        _registerInstantiatedType(type, nativeUsage: true);
 | 
|          break;
 | 
|        case TypeUseKind.IS_CHECK:
 | 
|        case TypeUseKind.AS_CAST:
 | 
| @@ -579,15 +425,13 @@ class CodegenEnqueuer implements Enqueuer {
 | 
|    }
 | 
|  
 | 
|    void registerCallMethodWithFreeTypeVariables(Element element) {
 | 
| -    backend.registerCallMethodWithFreeTypeVariables(
 | 
| -        element, this, globalDependencies);
 | 
| +    backend.registerCallMethodWithFreeTypeVariables(element, this);
 | 
|    }
 | 
|  
 | 
|    void registerClosurizedMember(TypedElement element) {
 | 
|      assert(element.isInstanceMember);
 | 
|      if (element.type.containsTypeVariables) {
 | 
| -      backend.registerClosureWithFreeTypeVariables(
 | 
| -          element, this, globalDependencies);
 | 
| +      backend.registerClosureWithFreeTypeVariables(element, this);
 | 
|      }
 | 
|      backend.registerBoundClosure(this);
 | 
|    }
 | 
| @@ -645,18 +489,6 @@ class CodegenEnqueuer implements Enqueuer {
 | 
|    bool isProcessed(Element member) =>
 | 
|        member.isAbstract || generatedCode.containsKey(member);
 | 
|  
 | 
| -  /**
 | 
| -   * Decides whether an element should be included to satisfy requirements
 | 
| -   * of the mirror system.
 | 
| -   *
 | 
| -   * For code generation, we rely on the precomputed set of elements that takes
 | 
| -   * subtyping constraints into account.
 | 
| -   */
 | 
| -  bool shouldIncludeElementDueToMirrors(Element element,
 | 
| -      {bool includedEnclosing}) {
 | 
| -    return backend.isAccessibleByReflection(element);
 | 
| -  }
 | 
| -
 | 
|    void registerNoSuchMethod(Element element) {
 | 
|      if (!enabledNoSuchMethod && backend.enabledNoSuchMethod) {
 | 
|        backend.enableNoSuchMethod(this);
 | 
| @@ -689,6 +521,9 @@ class CodegenEnqueuer implements Enqueuer {
 | 
|  
 | 
|    @override
 | 
|    Iterable<Entity> get processedEntities => generatedCode.keys;
 | 
| +
 | 
| +  @override
 | 
| +  Iterable<ClassElement> get processedClasses => _processedClasses;
 | 
|  }
 | 
|  
 | 
|  void removeFromSet(Map<String, Set<Element>> map, Element element) {
 | 
| 
 |