Index: pkg/compiler/lib/src/enqueue.dart |
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart |
index 1af9b3fc7c39e29361daeaeb829379352742e796..56c6a6c28f3712efb0c29f986d48fd6335feb720 100644 |
--- a/pkg/compiler/lib/src/enqueue.dart |
+++ b/pkg/compiler/lib/src/enqueue.dart |
@@ -6,7 +6,6 @@ library dart2js.enqueue; |
import 'dart:collection' show Queue; |
-import 'common/codegen.dart' show CodegenWorkItem; |
import 'common/names.dart' show Identifiers; |
import 'common/resolution.dart' show Resolution; |
import 'common/resolution.dart' show ResolutionWorkItem; |
@@ -23,14 +22,13 @@ import 'elements/elements.dart' |
ConstructorElement, |
Element, |
Elements, |
+ Entity, |
FunctionElement, |
LibraryElement, |
Member, |
- MemberElement, |
Name, |
TypedElement, |
TypedefElement; |
-import 'js/js.dart' as js; |
import 'native/native.dart' as native; |
import 'types/types.dart' show TypeMaskStrategy; |
import 'universe/selector.dart' show Selector; |
@@ -45,7 +43,7 @@ typedef ItemCompilationContext ItemCompilationContextCreator(); |
class EnqueueTask extends CompilerTask { |
final ResolutionEnqueuer resolution; |
- final CodegenEnqueuer codegen; |
+ final Enqueuer codegen; |
final Compiler compiler; |
String get name => 'Enqueue'; |
@@ -75,6 +73,58 @@ class EnqueueTask extends CompilerTask { |
} |
abstract class Enqueuer { |
+ EnqueueTask task; |
+ Universe get universe; |
+ native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask |
+ void forgetElement(Element element); |
+ void processInstantiatedClassMembers(ClassElement cls); |
+ void processInstantiatedClassMember(ClassElement cls, Element member); |
+ void handleUnseenSelectorInternal(DynamicUse dynamicUse); |
+ void registerStaticUse(StaticUse staticUse); |
+ void registerStaticUseInternal(StaticUse staticUse); |
+ void registerDynamicUse(DynamicUse dynamicUse); |
+ void registerTypeUse(TypeUse typeUse); |
+ |
+ /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
+ bool get isResolutionQueue; |
+ |
+ bool queueIsClosed; |
+ |
+ bool get queueIsEmpty; |
+ |
+ ImpactUseCase get impactUse; |
+ |
+ /** |
+ * Documentation wanted -- johnniwinther |
+ * |
+ * Invariant: [element] must be a declaration element. |
+ */ |
+ void addToWorkList(Element element); |
+ |
+ 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 forEach(void f(WorkItem work)); |
+ void applyImpact(Element element, WorldImpact worldImpact); |
+ bool checkNoEnqueuedInvokedInstanceMethods(); |
+ void logSummary(log(message)); |
+ |
+ /// Returns [:true:] if [member] has been processed by this enqueuer. |
+ bool isProcessed(Element member); |
+ |
+ Iterable<Entity> get processedEntities; |
+} |
+ |
+/// [Enqueuer] which is specific to resolution. |
+class ResolutionEnqueuer extends Enqueuer { |
final String name; |
final Compiler compiler; // TODO(ahe): Remove this dependency. |
final EnqueuerStrategy strategy; |
@@ -91,41 +141,35 @@ abstract class Enqueuer { |
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; |
- Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator, |
- this.strategy) { |
+ ResolutionEnqueuer( |
+ Compiler compiler, this.itemCompilationContextCreator, this.strategy) |
+ : this.name = 'resolution enqueuer', |
+ this.compiler = compiler, |
+ processedElements = new Set<AstElement>(), |
+ queue = new Queue<ResolutionWorkItem>(), |
+ deferredQueue = new Queue<_DeferredAction>() { |
impactVisitor = new _EnqueuerImpactVisitor(this); |
} |
// TODO(johnniwinther): Move this to [ResolutionEnqueuer]. |
Resolution get resolution => compiler.resolution; |
- Queue<WorkItem> get queue; |
bool get queueIsEmpty => queue.isEmpty; |
- /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
- bool get isResolutionQueue => false; |
- |
QueueFilter get filter => compiler.enqueuerFilter; |
DiagnosticReporter get reporter => compiler.reporter; |
- /// Returns [:true:] if [member] has been processed by this enqueuer. |
- bool isProcessed(Element member); |
- |
bool isClassProcessed(ClassElement cls) => _processedClasses.contains(cls); |
Iterable<ClassElement> get processedClasses => _processedClasses; |
- ImpactUseCase get impactUse; |
- |
/** |
* Documentation wanted -- johnniwinther |
* |
@@ -141,13 +185,6 @@ abstract class Enqueuer { |
} |
} |
- /** |
- * Adds [element] to the work list if it has not already been processed. |
- * |
- * Returns [true] if the element was actually added to the queue. |
- */ |
- bool internalAddToWorkList(Element element); |
- |
/// Apply the [worldImpact] of processing [element] to this enqueuer. |
void applyImpact(Element element, WorldImpact worldImpact) { |
compiler.impactStrategy |
@@ -268,10 +305,6 @@ abstract class Enqueuer { |
.add(member); |
} |
- void registerNoSuchMethod(Element noSuchMethod); |
- |
- void enableIsolateSupport() {} |
- |
void processInstantiatedClass(ClassElement cls) { |
task.measure(() { |
if (_processedClasses.contains(cls)) return; |
@@ -322,16 +355,6 @@ abstract class Enqueuer { |
}); |
} |
- /** |
- * Decides whether an element should be included to satisfy requirements |
- * of the mirror system. [includedEnclosing] provides a hint whether the |
- * enclosing element was included. |
- * |
- * The actual implementation depends on the current compiler phase. |
- */ |
- bool shouldIncludeElementDueToMirrors(Element element, |
- {bool includedEnclosing}); |
- |
void logEnqueueReflectiveAction(action, [msg = ""]) { |
if (TRACE_MIRROR_ENQUEUING) { |
print("MIRROR_ENQUEUE (${isResolutionQueue ? "R" : "C"}): $action $msg"); |
@@ -647,39 +670,18 @@ abstract class Enqueuer { |
} while (queue.isNotEmpty || recentClasses.isNotEmpty); |
} |
- /// [onQueueEmpty] is called whenever the queue is drained. [recentClasses] |
- /// contains the set of all classes seen for the first time since |
- /// [onQueueEmpty] was called last. A return value of [true] indicates that |
- /// the [recentClasses] have been processed and may be cleared. If [false] is |
- /// returned, [onQueueEmpty] will be called once the queue is empty again (or |
- /// still empty) and [recentClasses] will be a superset of the current value. |
- bool onQueueEmpty(Iterable<ClassElement> recentClasses) { |
- return compiler.backend.onQueueEmpty(this, recentClasses); |
- } |
- |
void logSummary(log(message)) { |
- _logSpecificSummary(log); |
+ log('Resolved ${processedElements.length} elements.'); |
nativeEnqueuer.logSummary(log); |
} |
- /// Log summary specific to the concrete enqueuer. |
- void _logSpecificSummary(log(message)); |
- |
String toString() => 'Enqueuer($name)'; |
- void forgetElement(Element element) { |
- universe.forgetElement(element, compiler); |
- _processedClasses.remove(element); |
- instanceMembersByName[element.name]?.remove(element); |
- instanceFunctionsByName[element.name]?.remove(element); |
- } |
-} |
- |
-/// [Enqueuer] which is specific to resolution. |
-class ResolutionEnqueuer extends Enqueuer { |
/// All declaration elements that have been processed by the resolver. |
final Set<AstElement> processedElements; |
+ Iterable<Entity> get processedEntities => processedElements; |
+ |
final Queue<ResolutionWorkItem> queue; |
/// Queue of deferred resolution actions to execute when the resolution queue |
@@ -691,16 +693,6 @@ class ResolutionEnqueuer extends Enqueuer { |
ImpactUseCase get impactUse => IMPACT_USE; |
- ResolutionEnqueuer( |
- Compiler compiler, |
- ItemCompilationContext itemCompilationContextCreator(), |
- EnqueuerStrategy strategy) |
- : super('resolution enqueuer', compiler, itemCompilationContextCreator, |
- strategy), |
- processedElements = new Set<AstElement>(), |
- queue = new Queue<ResolutionWorkItem>(), |
- deferredQueue = new Queue<_DeferredAction>(); |
- |
bool get isResolutionQueue => true; |
bool isProcessed(Element member) => processedElements.contains(member); |
@@ -730,6 +722,11 @@ class ResolutionEnqueuer extends Enqueuer { |
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. |
+ */ |
bool internalAddToWorkList(Element element) { |
if (element.isMalformed) return false; |
@@ -807,9 +804,16 @@ class ResolutionEnqueuer extends Enqueuer { |
deferredQueue.add(new _DeferredAction(element, action)); |
} |
+ /// [onQueueEmpty] is called whenever the queue is drained. [recentClasses] |
+ /// contains the set of all classes seen for the first time since |
+ /// [onQueueEmpty] was called last. A return value of [true] indicates that |
+ /// the [recentClasses] have been processed and may be cleared. If [false] is |
+ /// returned, [onQueueEmpty] will be called once the queue is empty again (or |
+ /// still empty) and [recentClasses] will be a superset of the current value. |
bool onQueueEmpty(Iterable<ClassElement> recentClasses) { |
_emptyDeferredQueue(); |
- return super.onQueueEmpty(recentClasses); |
+ |
+ return compiler.backend.onQueueEmpty(this, recentClasses); |
} |
void emptyDeferredQueueForTesting() => _emptyDeferredQueue(); |
@@ -821,23 +825,15 @@ class ResolutionEnqueuer extends Enqueuer { |
} |
} |
- void _logSpecificSummary(log(message)) { |
- log('Resolved ${processedElements.length} elements.'); |
- } |
- |
void forgetElement(Element element) { |
- super.forgetElement(element); |
+ universe.forgetElement(element, compiler); |
+ _processedClasses.remove(element); |
+ instanceMembersByName[element.name]?.remove(element); |
+ instanceFunctionsByName[element.name]?.remove(element); |
processedElements.remove(element); |
} |
} |
-/// [Enqueuer] which is specific to code generation. |
-abstract class CodegenEnqueuer implements Enqueuer { |
- Map<Element, js.Expression> get generatedCode; |
- |
- Set<Element> get newlyEnqueuedElements; |
-} |
- |
/// Parameterizes filtering of which work items are enqueued. |
class QueueFilter { |
bool checkNoEnqueuedInvokedInstanceMethods(Enqueuer enqueuer) { |