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