Chromium Code Reviews| 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..6fec7f86b98019ce6af2aae5c850db127dcb12ef 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,9 @@ 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 +171,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 +191,15 @@ class ResolutionEnqueuer extends Enqueuer { |
| _universe.registerTypeInstantiation(type, |
| isNative: isNative, |
| byMirrors: mirrorUsage, onImplemented: (ClassElement cls) { |
|
Harry Terkelsen
2016/11/11 21:24:27
dartfmt?
Johnni Winther
2016/11/14 09:08:36
Done.
|
| - 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 +323,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 +342,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 +407,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 +420,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 +448,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 +482,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 +547,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 +592,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; |
| } |