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