Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(461)

Unified Diff: pkg/compiler/lib/src/enqueue.dart

Issue 2531303002: Decouple WorkItem from Compiler (Closed)
Patch Set: Updated cf. comments. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/compiler/lib/src/deferred_load.dart ('k') | pkg/compiler/lib/src/js_backend/backend.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/enqueue.dart
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 6c7de3fbbe2961ada4e97ad40f7847b95f20f24e..9277ee41052496707f857e3dfe7c8690946d2b17 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -54,9 +54,8 @@ class EnqueueTask extends CompilerTask {
this,
compiler.options,
compiler.resolution,
- compiler.enqueuerFilter,
compiler.options.analyzeOnly && compiler.options.analyzeMain
- ? const EnqueuerStrategy()
+ ? const DirectEnqueuerStrategy()
: const TreeShakingEnqueuerStrategy(),
compiler.globalDependencies,
compiler.backend,
@@ -75,16 +74,24 @@ class EnqueueTask extends CompilerTask {
}
abstract class Enqueuer {
- CompilerTask get task;
WorldBuilder get universe;
native.NativeEnqueuer get nativeEnqueuer;
void forgetElement(Element element, Compiler compiler);
- 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);
+
+ // TODO(johnniwinther): Initialize [_impactStrategy] to `null`.
+ ImpactStrategy _impactStrategy = const ImpactStrategy();
+
+ ImpactStrategy get impactStrategy => _impactStrategy;
+
+ void open(ImpactStrategy impactStrategy) {
+ _impactStrategy = impactStrategy;
+ }
+
+ void close() {
+ // TODO(johnniwinther): Set [_impactStrategy] to `null` and [queueIsClosed]
+ // to `false` here.
+ _impactStrategy = const ImpactStrategy();
+ }
/// Returns [:true:] if this enqueuer is the resolution enqueuer.
bool get isResolutionQueue;
@@ -95,23 +102,12 @@ abstract class Enqueuer {
ImpactUseCase get impactUse;
- /**
- * Documentation wanted -- johnniwinther
- *
- * Invariant: [element] must be a declaration element.
- */
- void addToWorkList(Element element);
-
- void enableIsolateSupport();
-
- void registerInstantiatedType(InterfaceType type);
void forEach(void f(WorkItem work));
- /// Apply the [worldImpact] to this enqueuer. If the [impactSource] is provided
- /// the impact strategy will remove it from the element impact cache, if it is
- /// no longer needed.
- void applyImpact(ImpactStrategy impactStrategy, WorldImpact worldImpact,
- {Element impactSource});
+ /// Apply the [worldImpact] to this enqueuer. If the [impactSource] is
+ /// provided the impact strategy will remove it from the element impact cache,
+ /// if it is no longer needed.
+ void applyImpact(WorldImpact worldImpact, {Element impactSource});
bool checkNoEnqueuedInvokedInstanceMethods();
void logSummary(log(message));
@@ -123,12 +119,23 @@ abstract class Enqueuer {
Iterable<ClassElement> get processedClasses;
}
+abstract class EnqueuerImpl extends Enqueuer {
+ CompilerTask get task;
+ void processInstantiatedClassMembers(ClassElement cls);
+ void processInstantiatedClassMember(ClassElement cls, Element member);
+ void registerStaticUse(StaticUse staticUse);
+ void registerStaticUseInternal(StaticUse staticUse);
+ void registerTypeUse(TypeUse typeUse);
+ void registerTypeUseInternal(TypeUse typeUse);
+ void registerDynamicUse(DynamicUse dynamicUse);
+ void handleUnseenSelectorInternal(DynamicUse dynamicUse);
+}
+
/// [Enqueuer] which is specific to resolution.
-class ResolutionEnqueuer extends Enqueuer {
+class ResolutionEnqueuer extends EnqueuerImpl {
final CompilerTask task;
final String name;
final Resolution resolution;
- final QueueFilter filter;
final CompilerOptions options;
final Backend backend;
final GlobalDependencyRegistry globalDependencies;
@@ -148,13 +155,10 @@ class ResolutionEnqueuer extends Enqueuer {
WorldImpactVisitor impactVisitor;
- ImpactStrategy impactStrategy;
-
ResolutionEnqueuer(
this.task,
this.options,
this.resolution,
- this.filter,
this.strategy,
this.globalDependencies,
Backend backend,
@@ -169,7 +173,7 @@ class ResolutionEnqueuer extends Enqueuer {
deferredQueue = new Queue<_DeferredAction>(),
_universe = new ResolutionWorldBuilderImpl(
backend, commonElements, cacheStrategy, const TypeMaskStrategy()) {
- impactVisitor = new _EnqueuerImpactVisitor(this);
+ impactVisitor = new EnqueuerImplImpactVisitor(this);
}
ResolutionWorldBuilder get universe => _universe;
@@ -194,8 +198,8 @@ class ResolutionEnqueuer extends Enqueuer {
internalAddToWorkList(element);
}
- void applyImpact(ImpactStrategy impactStrategy, WorldImpact worldImpact,
- {Element impactSource}) {
+ void applyImpact(WorldImpact worldImpact, {Element impactSource}) {
+ if (worldImpact.isEmpty) return;
impactStrategy.visitImpact(
impactSource, worldImpact, impactVisitor, impactUse);
}
@@ -219,7 +223,7 @@ class ResolutionEnqueuer extends Enqueuer {
isNative: isNative,
byMirrors: mirrorUsage,
isRedirection: isRedirection, onImplemented: (ClassElement cls) {
- backend.registerImplementedClass(cls, this);
+ applyImpact(backend.registerImplementedClass(cls, forResolution: true));
});
if (globalDependency && !mirrorUsage) {
globalDependencies.registerDependency(type.element);
@@ -236,7 +240,7 @@ class ResolutionEnqueuer extends Enqueuer {
}
bool checkNoEnqueuedInvokedInstanceMethods() {
- return filter.checkNoEnqueuedInvokedInstanceMethods(this);
+ return strategy.checkEnqueuerConsistency(this);
}
void processInstantiatedClassMembers(ClassElement cls) {
@@ -284,7 +288,7 @@ class ResolutionEnqueuer extends Enqueuer {
registerNoSuchMethod(function);
}
if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) {
- registerCallMethodWithFreeTypeVariables(function);
+ _registerCallMethodWithFreeTypeVariables(function);
}
// If there is a property access with the same name as a method we
// need to emit the method.
@@ -349,7 +353,8 @@ class ResolutionEnqueuer extends 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);
+ applyImpact(
+ backend.registerInstantiatedClass(superclass, forResolution: true));
}
ClassElement superclass = cls;
@@ -433,11 +438,11 @@ class ResolutionEnqueuer extends Enqueuer {
assert(invariant(element, element.isDeclaration,
message: "Element ${element} is not the declaration."));
_universe.registerStaticUse(staticUse);
- backend.registerStaticUse(this, element);
+ applyImpact(backend.registerStaticUse(element, forResolution: true));
bool addElement = true;
switch (staticUse.kind) {
case StaticUseKind.STATIC_TEAR_OFF:
- backend.registerGetOfStaticFunction(this);
+ applyImpact(backend.registerGetOfStaticFunction());
break;
case StaticUseKind.FIELD_GET:
case StaticUseKind.FIELD_SET:
@@ -455,6 +460,7 @@ class ResolutionEnqueuer extends Enqueuer {
case StaticUseKind.SUPER_FIELD_SET:
case StaticUseKind.SUPER_TEAR_OFF:
case StaticUseKind.GENERAL:
+ case StaticUseKind.DIRECT_USE:
break;
case StaticUseKind.CONSTRUCTOR_INVOKE:
case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
@@ -477,7 +483,11 @@ class ResolutionEnqueuer extends Enqueuer {
}
}
- void _registerTypeUse(TypeUse typeUse) {
+ void registerTypeUse(TypeUse typeUse) {
+ strategy.processTypeUse(this, typeUse);
+ }
+
+ void registerTypeUseInternal(TypeUse typeUse) {
DartType type = typeUse.type;
switch (typeUse.kind) {
case TypeUseKind.INSTANTIATION:
@@ -514,18 +524,20 @@ class ResolutionEnqueuer extends Enqueuer {
assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef);
}
- void registerCallMethodWithFreeTypeVariables(Element element) {
- backend.registerCallMethodWithFreeTypeVariables(element, this);
+ void _registerCallMethodWithFreeTypeVariables(Element element) {
+ applyImpact(backend.registerCallMethodWithFreeTypeVariables(element,
+ forResolution: true));
_universe.callMethodsWithFreeTypeVariables.add(element);
}
void registerClosurizedMember(TypedElement element) {
assert(element.isInstanceMember);
if (element.computeType(resolution).containsTypeVariables) {
- backend.registerClosureWithFreeTypeVariables(element, this);
+ applyImpact(backend.registerClosureWithFreeTypeVariables(element,
+ forResolution: true));
_universe.closuresWithFreeTypeVariables.add(element);
}
- backend.registerBoundClosure(this);
+ applyImpact(backend.registerBoundClosure());
_universe.closurizedMembers.add(element);
}
@@ -533,7 +545,11 @@ class ResolutionEnqueuer extends Enqueuer {
do {
while (queue.isNotEmpty) {
// TODO(johnniwinther): Find an optimal process order.
- filter.processWorkItem(f, queue.removeLast());
+ WorkItem work = queue.removeLast();
+ if (!isProcessed(work.element)) {
+ strategy.processWorkItem(f, work);
+ registerProcessedElement(work.element);
+ }
}
List recents = recentClasses.toList(growable: false);
recentClasses.clear();
@@ -625,7 +641,7 @@ class ResolutionEnqueuer extends Enqueuer {
// runtime type.
_universe.hasRuntimeTypeSupport = true;
// TODO(ahe): Record precise dependency here.
- backend.registerRuntimeType(this);
+ applyImpact(backend.registerRuntimeType());
} else if (commonElements.isFunctionApplyMethod(element)) {
_universe.hasFunctionApplySupport = true;
}
@@ -639,7 +655,7 @@ class ResolutionEnqueuer extends Enqueuer {
void enableIsolateSupport() {
_universe.hasIsolateSupport = true;
- backend.enableIsolateSupport(this);
+ applyImpact(backend.enableIsolateSupport(forResolution: true));
}
/**
@@ -690,11 +706,32 @@ class ResolutionEnqueuer extends Enqueuer {
}
}
-/// Parameterizes filtering of which work items are enqueued.
-class QueueFilter {
- bool checkNoEnqueuedInvokedInstanceMethods(Enqueuer enqueuer) {
+void removeFromSet(Map<String, Set<Element>> map, Element element) {
+ Set<Element> set = map[element.name];
+ if (set == null) return;
+ set.remove(element);
+}
+
+/// Strategy used by the enqueuer to populate the world.
+class EnqueuerStrategy {
+ const EnqueuerStrategy();
+
+ /// Process a class instantiated in live code.
+ void processInstantiatedClass(EnqueuerImpl enqueuer, ClassElement cls) {}
+
+ /// Process a static use of and element in live code.
+ void processStaticUse(EnqueuerImpl enqueuer, StaticUse staticUse) {}
+
+ /// Process a type use in live code.
+ void processTypeUse(EnqueuerImpl enqueuer, TypeUse typeUse) {}
+
+ /// Process a dynamic use for a call site in live code.
+ void processDynamicUse(EnqueuerImpl enqueuer, DynamicUse dynamicUse) {}
+
+ /// Check enqueuer consistency after the queue has been closed.
+ bool checkEnqueuerConsistency(EnqueuerImpl enqueuer) {
enqueuer.task.measure(() {
- // Run through the classes and see if we need to compile methods.
+ // Run through the classes and see if we need to enqueue more methods.
for (ClassElement classElement
in enqueuer.universe.directlyInstantiatedClasses) {
for (ClassElement currentClass = classElement;
@@ -707,55 +744,51 @@ class QueueFilter {
return true;
}
+ /// Process [work] using [f].
void processWorkItem(void f(WorkItem work), WorkItem work) {
f(work);
}
}
-void removeFromSet(Map<String, Set<Element>> map, Element element) {
- Set<Element> set = map[element.name];
- if (set == null) return;
- set.remove(element);
-}
-
-/// Strategy used by the enqueuer to populate the world.
-// TODO(johnniwinther): Merge this interface with [QueueFilter].
-class EnqueuerStrategy {
- const EnqueuerStrategy();
-
- /// Process a class instantiated in live code.
- void processInstantiatedClass(Enqueuer enqueuer, ClassElement cls) {}
-
- /// Process a static use of and element in live code.
- void processStaticUse(Enqueuer enqueuer, StaticUse staticUse) {}
-
- /// Process a dynamic use for a call site in live code.
- void processDynamicUse(Enqueuer enqueuer, DynamicUse dynamicUse) {}
+/// Strategy that only enqueues directly used elements.
+class DirectEnqueuerStrategy extends EnqueuerStrategy {
+ const DirectEnqueuerStrategy();
+ void processStaticUse(EnqueuerImpl enqueuer, StaticUse staticUse) {
+ if (staticUse.kind == StaticUseKind.DIRECT_USE) {
+ enqueuer.registerStaticUseInternal(staticUse);
+ }
+ }
}
-class TreeShakingEnqueuerStrategy implements EnqueuerStrategy {
+/// Strategy used for tree-shaking.
+class TreeShakingEnqueuerStrategy extends EnqueuerStrategy {
const TreeShakingEnqueuerStrategy();
@override
- void processInstantiatedClass(Enqueuer enqueuer, ClassElement cls) {
+ void processInstantiatedClass(EnqueuerImpl enqueuer, ClassElement cls) {
cls.implementation.forEachMember(enqueuer.processInstantiatedClassMember);
}
@override
- void processStaticUse(Enqueuer enqueuer, StaticUse staticUse) {
+ void processStaticUse(EnqueuerImpl enqueuer, StaticUse staticUse) {
enqueuer.registerStaticUseInternal(staticUse);
}
@override
- void processDynamicUse(Enqueuer enqueuer, DynamicUse dynamicUse) {
+ void processTypeUse(EnqueuerImpl enqueuer, TypeUse typeUse) {
+ enqueuer.registerTypeUseInternal(typeUse);
+ }
+
+ @override
+ void processDynamicUse(EnqueuerImpl enqueuer, DynamicUse dynamicUse) {
enqueuer.handleUnseenSelectorInternal(dynamicUse);
}
}
-class _EnqueuerImpactVisitor implements WorldImpactVisitor {
- final ResolutionEnqueuer enqueuer;
+class EnqueuerImplImpactVisitor implements WorldImpactVisitor {
+ final EnqueuerImpl enqueuer;
- _EnqueuerImpactVisitor(this.enqueuer);
+ EnqueuerImplImpactVisitor(this.enqueuer);
@override
void visitDynamicUse(DynamicUse dynamicUse) {
@@ -769,7 +802,7 @@ class _EnqueuerImpactVisitor implements WorldImpactVisitor {
@override
void visitTypeUse(TypeUse typeUse) {
- enqueuer._registerTypeUse(typeUse);
+ enqueuer.registerTypeUse(typeUse);
}
}
« no previous file with comments | « pkg/compiler/lib/src/deferred_load.dart ('k') | pkg/compiler/lib/src/js_backend/backend.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698