| 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) {
|
|
|