| Index: pkg/compiler/lib/src/enqueue.dart
|
| diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
|
| index b254e0d75b57c89d186b5c1b291c05430546dc88..660e2e866dedf682cf5e6a9e716f54cdcfdb7bc3 100644
|
| --- a/pkg/compiler/lib/src/enqueue.dart
|
| +++ b/pkg/compiler/lib/src/enqueue.dart
|
| @@ -19,16 +19,12 @@ import 'elements/elements.dart'
|
| AnalyzableElement,
|
| AstElement,
|
| ClassElement,
|
| - ConstructorElement,
|
| Element,
|
| - Elements,
|
| Entity,
|
| FunctionElement,
|
| LibraryElement,
|
| - Member,
|
| - Name,
|
| - TypedElement,
|
| - TypedefElement;
|
| + LocalFunctionElement,
|
| + TypedElement;
|
| import 'native/native.dart' as native;
|
| import 'types/types.dart' show TypeMaskStrategy;
|
| import 'universe/selector.dart' show Selector;
|
| @@ -100,15 +96,7 @@ abstract class Enqueuer {
|
|
|
| void enableIsolateSupport();
|
|
|
| - /// Enqueue the static fields that have been marked as used by reflective
|
| - /// usage through `MirrorsUsed`.
|
| - void enqueueReflectiveStaticFields(Iterable<Element> elements);
|
| -
|
| - /// Enqueue all elements that are matched by the mirrors used
|
| - /// annotation or, in lack thereof, all elements.
|
| - void enqueueReflectiveElements(Iterable<ClassElement> recents);
|
| -
|
| - void registerInstantiatedType(InterfaceType type, {bool mirrorUsage: false});
|
| + void registerInstantiatedType(InterfaceType type);
|
| void forEach(void f(WorkItem work));
|
|
|
| /// Apply the [worldImpact] to this enqueuer. If the [impactSource] is provided
|
| @@ -122,6 +110,8 @@ abstract class Enqueuer {
|
| bool isProcessed(Element member);
|
|
|
| Iterable<Entity> get processedEntities;
|
| +
|
| + Iterable<ClassElement> get processedClasses;
|
| }
|
|
|
| /// [Enqueuer] which is specific to resolution.
|
| @@ -138,14 +128,8 @@ class ResolutionEnqueuer extends Enqueuer {
|
| final ResolutionWorldBuilderImpl _universe =
|
| new ResolutionWorldBuilderImpl(const TypeMaskStrategy());
|
|
|
| - static final TRACE_MIRROR_ENQUEUING =
|
| - const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING");
|
| -
|
| bool queueIsClosed = false;
|
|
|
| - bool hasEnqueuedReflectiveElements = false;
|
| - bool hasEnqueuedReflectiveStaticFields = false;
|
| -
|
| WorldImpactVisitor impactVisitor;
|
|
|
| ResolutionEnqueuer(Compiler compiler, this.strategy)
|
| @@ -186,12 +170,19 @@ class ResolutionEnqueuer extends Enqueuer {
|
| }
|
| }
|
|
|
| + void registerInstantiatedType(InterfaceType type) {
|
| + _registerInstantiatedType(type, globalDependency: true);
|
| + }
|
| +
|
| void applyImpact(WorldImpact worldImpact, {Element impactSource}) {
|
| compiler.impactStrategy
|
| .visitImpact(impactSource, worldImpact, impactVisitor, impactUse);
|
| }
|
|
|
| - void registerInstantiatedType(InterfaceType type, {bool mirrorUsage: false}) {
|
| + void _registerInstantiatedType(InterfaceType type,
|
| + {bool mirrorUsage: false,
|
| + bool nativeUsage: false,
|
| + bool globalDependency: false}) {
|
| task.measure(() {
|
| ClassElement cls = type.element;
|
| cls.ensureResolved(resolution);
|
| @@ -199,9 +190,15 @@ class ResolutionEnqueuer extends Enqueuer {
|
| _universe.registerTypeInstantiation(type,
|
| isNative: isNative,
|
| byMirrors: mirrorUsage, onImplemented: (ClassElement cls) {
|
| - compiler.backend
|
| - .registerImplementedClass(cls, this, compiler.globalDependencies);
|
| + compiler.backend.registerImplementedClass(cls, this);
|
| });
|
| + if (globalDependency && !mirrorUsage) {
|
| + compiler.globalDependencies.registerDependency(type.element);
|
| + }
|
| + if (nativeUsage) {
|
| + nativeEnqueuer.onInstantiatedType(type);
|
| + }
|
| + compiler.backend.registerInstantiatedType(type);
|
| // TODO(johnniwinther): Share this reasoning with [Universe].
|
| if (!cls.isAbstract || isNative || mirrorUsage) {
|
| processInstantiatedClass(cls);
|
| @@ -325,8 +322,7 @@ class ResolutionEnqueuer extends Enqueuer {
|
| // We only tell the backend once that [superclass] was instantiated, so
|
| // any additional dependencies must be treated as global
|
| // dependencies.
|
| - compiler.backend.registerInstantiatedClass(
|
| - superclass, this, compiler.globalDependencies);
|
| + compiler.backend.registerInstantiatedClass(superclass, this);
|
| }
|
|
|
| ClassElement superclass = cls;
|
| @@ -345,172 +341,6 @@ class ResolutionEnqueuer extends Enqueuer {
|
| });
|
| }
|
|
|
| - void logEnqueueReflectiveAction(action, [msg = ""]) {
|
| - if (TRACE_MIRROR_ENQUEUING) {
|
| - print("MIRROR_ENQUEUE (R): $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;
|
| - compiler.backend.registerInstantiatedType(
|
| - cls.rawType, this, compiler.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) {
|
| - TypedefElement typedef = element;
|
| - typedef.ensureResolved(resolution);
|
| - } 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;
|
| - decl.ensureResolved(resolution);
|
| - compiler.backend.registerInstantiatedType(
|
| - decl.rawType, this, compiler.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 =
|
| - compiler.backend.classesRequiredForReflection;
|
| - for (ClassElement cls in classes) {
|
| - if (compiler.backend.referencedFromMirrorSystem(cls)) {
|
| - logEnqueueReflectiveAction(cls);
|
| - cls.ensureResolved(resolution);
|
| - compiler.backend.registerInstantiatedType(
|
| - cls.rawType, this, compiler.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];
|
| @@ -576,7 +406,7 @@ class ResolutionEnqueuer extends Enqueuer {
|
| assert(invariant(element, element.isDeclaration,
|
| message: "Element ${element} is not the declaration."));
|
| _universe.registerStaticUse(staticUse);
|
| - compiler.backend.registerStaticUse(element, forResolution: true);
|
| + compiler.backend.registerStaticUse(this, element);
|
| bool addElement = true;
|
| switch (staticUse.kind) {
|
| case StaticUseKind.STATIC_TEAR_OFF:
|
| @@ -589,6 +419,10 @@ class ResolutionEnqueuer extends Enqueuer {
|
| // [FIELD_SET] contains [BoxFieldElement]s which we cannot enqueue.
|
| // Also [CLOSURE] contains [LocalFunctionElement] which we cannot
|
| // enqueue.
|
| + LocalFunctionElement closure = staticUse.element;
|
| + if (closure.type.containsTypeVariables) {
|
| + universe.closuresWithFreeTypeVariables.add(closure);
|
| + }
|
| addElement = false;
|
| break;
|
| case StaticUseKind.SUPER_FIELD_SET:
|
| @@ -613,7 +447,15 @@ class ResolutionEnqueuer extends Enqueuer {
|
| DartType type = typeUse.type;
|
| switch (typeUse.kind) {
|
| case TypeUseKind.INSTANTIATION:
|
| - registerInstantiatedType(type);
|
| + _registerInstantiatedType(type, globalDependency: false);
|
| + break;
|
| + case TypeUseKind.MIRROR_INSTANTIATION:
|
| + _registerInstantiatedType(type,
|
| + mirrorUsage: true, globalDependency: false);
|
| + break;
|
| + case TypeUseKind.NATIVE_INSTANTIATION:
|
| + _registerInstantiatedType(type,
|
| + nativeUsage: true, globalDependency: true);
|
| break;
|
| case TypeUseKind.IS_CHECK:
|
| case TypeUseKind.AS_CAST:
|
| @@ -639,16 +481,14 @@ class ResolutionEnqueuer extends Enqueuer {
|
| }
|
|
|
| void registerCallMethodWithFreeTypeVariables(Element element) {
|
| - compiler.backend.registerCallMethodWithFreeTypeVariables(
|
| - element, this, compiler.globalDependencies);
|
| + compiler.backend.registerCallMethodWithFreeTypeVariables(element, this);
|
| _universe.callMethodsWithFreeTypeVariables.add(element);
|
| }
|
|
|
| void registerClosurizedMember(TypedElement element) {
|
| assert(element.isInstanceMember);
|
| if (element.computeType(resolution).containsTypeVariables) {
|
| - compiler.backend.registerClosureWithFreeTypeVariables(
|
| - element, this, compiler.globalDependencies);
|
| + compiler.backend.registerClosureWithFreeTypeVariables(element, this);
|
| _universe.closuresWithFreeTypeVariables.add(element);
|
| }
|
| compiler.backend.registerBoundClosure(this);
|
| @@ -706,20 +546,6 @@ class ResolutionEnqueuer extends Enqueuer {
|
| }
|
|
|
| /**
|
| - * Decides whether an element should be included to satisfy requirements
|
| - * of the mirror system.
|
| - *
|
| - * During resolution, we have to resort to matching elements against the
|
| - * [MirrorsUsed] pattern, as we do not have a complete picture of the world,
|
| - * yet.
|
| - */
|
| - bool shouldIncludeElementDueToMirrors(Element element,
|
| - {bool includedEnclosing}) {
|
| - return includedEnclosing ||
|
| - compiler.backend.requiredByMirrorSystem(element);
|
| - }
|
| -
|
| - /**
|
| * Adds [element] to the work list if it has not already been processed.
|
| *
|
| * Returns [true] if the element was actually added to the queue.
|
| @@ -765,7 +591,7 @@ class ResolutionEnqueuer extends Enqueuer {
|
| // runtime type.
|
| compiler.enabledRuntimeType = true;
|
| // TODO(ahe): Record precise dependency here.
|
| - compiler.backend.registerRuntimeType(this, compiler.globalDependencies);
|
| + compiler.backend.registerRuntimeType(this);
|
| } else if (compiler.commonElements.isFunctionApplyMethod(element)) {
|
| compiler.enabledFunctionApply = true;
|
| }
|
|
|