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