Index: pkg/compiler/lib/src/enqueue.dart |
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart |
index 6fec7f86b98019ce6af2aae5c850db127dcb12ef..369c3ef6d22395bd5d90ecd1ff65ff603d8df96d 100644 |
--- a/pkg/compiler/lib/src/enqueue.dart |
+++ b/pkg/compiler/lib/src/enqueue.dart |
@@ -6,13 +6,17 @@ library dart2js.enqueue; |
import 'dart:collection' show Queue; |
+import 'cache_strategy.dart'; |
+import 'common/backend_api.dart' show Backend; |
import 'common/names.dart' show Identifiers; |
-import 'common/resolution.dart' show Resolution; |
-import 'common/resolution.dart' show ResolutionWorkItem; |
+import 'common/resolution.dart' show Resolution, ResolutionWorkItem; |
+import 'common/registry.dart' show Registry; |
import 'common/tasks.dart' show CompilerTask; |
import 'common/work.dart' show WorkItem; |
import 'common.dart'; |
-import 'compiler.dart' show Compiler; |
+import 'compiler.dart' show Compiler, GlobalDependencyRegistry; |
+import 'core_types.dart' show CommonElements; |
+import 'options.dart'; |
import 'dart_types.dart' show DartType, InterfaceType; |
import 'elements/elements.dart' |
show |
@@ -32,44 +36,49 @@ import 'universe/world_builder.dart'; |
import 'universe/use.dart' |
show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; |
import 'universe/world_impact.dart' |
- show ImpactUseCase, WorldImpact, WorldImpactVisitor; |
+ show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor; |
import 'util/util.dart' show Setlet; |
+import 'world.dart' show OpenWorld; |
class EnqueueTask extends CompilerTask { |
- final ResolutionEnqueuer resolution; |
- final Enqueuer codegen; |
+ ResolutionEnqueuer _resolution; |
+ Enqueuer _codegen; |
final Compiler compiler; |
String get name => 'Enqueue'; |
EnqueueTask(Compiler compiler) |
- : compiler = compiler, |
- resolution = new ResolutionEnqueuer( |
- compiler, |
- compiler.options.analyzeOnly && compiler.options.analyzeMain |
- ? const EnqueuerStrategy() |
- : const TreeShakingEnqueuerStrategy()), |
- codegen = compiler.backend.createCodegenEnqueuer(compiler), |
+ : this.compiler = compiler, |
super(compiler.measurer) { |
- codegen.task = this; |
- resolution.task = this; |
- |
- codegen.nativeEnqueuer = compiler.backend.nativeCodegenEnqueuer(codegen); |
- resolution.nativeEnqueuer = |
- compiler.backend.nativeResolutionEnqueuer(resolution); |
- } |
+ _resolution = new ResolutionEnqueuer( |
+ this, |
+ compiler.options, |
+ compiler.resolution, |
+ compiler.enqueuerFilter, |
+ compiler.options.analyzeOnly && compiler.options.analyzeMain |
+ ? const EnqueuerStrategy() |
+ : const TreeShakingEnqueuerStrategy(), |
+ compiler.globalDependencies, |
+ compiler.backend, |
+ compiler.coreClasses, |
+ compiler.cacheStrategy); |
+ _codegen = compiler.backend.createCodegenEnqueuer(this, compiler); |
+ } |
+ |
+ ResolutionEnqueuer get resolution => _resolution; |
+ Enqueuer get codegen => _codegen; |
void forgetElement(Element element) { |
- resolution.forgetElement(element); |
- codegen.forgetElement(element); |
+ resolution.forgetElement(element, compiler); |
+ codegen.forgetElement(element, compiler); |
} |
} |
abstract class Enqueuer { |
- EnqueueTask task; |
+ CompilerTask get task; |
WorldBuilder get universe; |
- native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask |
- void forgetElement(Element element); |
+ native.NativeEnqueuer get nativeEnqueuer; |
+ void forgetElement(Element element, Compiler compiler); |
void processInstantiatedClassMembers(ClassElement cls); |
void processInstantiatedClassMember(ClassElement cls, Element member); |
void handleUnseenSelectorInternal(DynamicUse dynamicUse); |
@@ -102,7 +111,8 @@ abstract class Enqueuer { |
/// 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}); |
+ void applyImpact(ImpactStrategy impactStrategy, WorldImpact worldImpact, |
+ {Element impactSource}); |
bool checkNoEnqueuedInvokedInstanceMethods(); |
void logSummary(log(message)); |
@@ -116,8 +126,16 @@ abstract class Enqueuer { |
/// [Enqueuer] which is specific to resolution. |
class ResolutionEnqueuer extends Enqueuer { |
+ final CompilerTask task; |
final String name; |
- final Compiler compiler; // TODO(ahe): Remove this dependency. |
+ final Resolution resolution; |
+ final QueueFilter filter; |
+ final CompilerOptions options; |
+ final Backend backend; |
+ final GlobalDependencyRegistry globalDependencies; |
+ final CommonElements commonElements; |
+ final native.NativeEnqueuer nativeEnqueuer; |
+ |
final EnqueuerStrategy strategy; |
final Map<String, Set<Element>> instanceMembersByName = |
new Map<String, Set<Element>>(); |
@@ -125,32 +143,43 @@ class ResolutionEnqueuer extends Enqueuer { |
new Map<String, Set<Element>>(); |
final Set<ClassElement> _processedClasses = new Set<ClassElement>(); |
Set<ClassElement> recentClasses = new Setlet<ClassElement>(); |
- final ResolutionWorldBuilderImpl _universe = |
- new ResolutionWorldBuilderImpl(const TypeMaskStrategy()); |
- |
+ final ResolutionWorldBuilderImpl _universe; |
bool queueIsClosed = false; |
WorldImpactVisitor impactVisitor; |
- ResolutionEnqueuer(Compiler compiler, this.strategy) |
+ ImpactStrategy impactStrategy; |
+ |
+ ResolutionEnqueuer( |
+ this.task, |
+ this.options, |
+ this.resolution, |
+ this.filter, |
+ this.strategy, |
+ this.globalDependencies, |
+ Backend backend, |
+ CommonElements commonElements, |
+ CacheStrategy cacheStrategy) |
: this.name = 'resolution enqueuer', |
- this.compiler = compiler, |
+ this.backend = backend, |
+ this.commonElements = commonElements, |
+ this.nativeEnqueuer = backend.nativeResolutionEnqueuer(), |
processedElements = new Set<AstElement>(), |
queue = new Queue<ResolutionWorkItem>(), |
- deferredQueue = new Queue<_DeferredAction>() { |
+ deferredQueue = new Queue<_DeferredAction>(), |
+ _universe = new ResolutionWorldBuilderImpl( |
+ backend, commonElements, cacheStrategy, const TypeMaskStrategy()) { |
impactVisitor = new _EnqueuerImpactVisitor(this); |
} |
- Resolution get resolution => compiler.resolution; |
- |
ResolutionWorldBuilder get universe => _universe; |
- bool get queueIsEmpty => queue.isEmpty; |
+ OpenWorld get openWorld => universe.openWorld; |
- QueueFilter get filter => compiler.enqueuerFilter; |
+ bool get queueIsEmpty => queue.isEmpty; |
- DiagnosticReporter get reporter => compiler.reporter; |
+ DiagnosticReporter get reporter => resolution.reporter; |
bool isClassProcessed(ClassElement cls) => _processedClasses.contains(cls); |
@@ -163,21 +192,17 @@ class ResolutionEnqueuer extends Enqueuer { |
*/ |
void addToWorkList(Element element) { |
assert(invariant(element, element.isDeclaration)); |
- if (internalAddToWorkList(element) && compiler.options.dumpInfo) { |
- // TODO(sigmund): add other missing dependencies (internals, selectors |
- // enqueued after allocations), also enable only for the codegen enqueuer. |
- compiler.dumpInfoTask |
- .registerDependency(compiler.currentElement, element); |
- } |
+ internalAddToWorkList(element); |
} |
- void registerInstantiatedType(InterfaceType type) { |
- _registerInstantiatedType(type, globalDependency: true); |
+ void applyImpact(ImpactStrategy impactStrategy, WorldImpact worldImpact, |
+ {Element impactSource}) { |
+ impactStrategy.visitImpact( |
+ impactSource, worldImpact, impactVisitor, impactUse); |
} |
- void applyImpact(WorldImpact worldImpact, {Element impactSource}) { |
- compiler.impactStrategy |
- .visitImpact(impactSource, worldImpact, impactVisitor, impactUse); |
+ void registerInstantiatedType(InterfaceType type) { |
+ _registerInstantiatedType(type, globalDependency: true); |
} |
void _registerInstantiatedType(InterfaceType type, |
@@ -187,19 +212,19 @@ class ResolutionEnqueuer extends Enqueuer { |
task.measure(() { |
ClassElement cls = type.element; |
cls.ensureResolved(resolution); |
- bool isNative = compiler.backend.isNative(cls); |
+ bool isNative = backend.isNative(cls); |
_universe.registerTypeInstantiation(type, |
isNative: isNative, |
byMirrors: mirrorUsage, onImplemented: (ClassElement cls) { |
- compiler.backend.registerImplementedClass(cls, this); |
+ backend.registerImplementedClass(cls, this); |
}); |
if (globalDependency && !mirrorUsage) { |
- compiler.globalDependencies.registerDependency(type.element); |
+ globalDependencies.registerDependency(type.element); |
} |
if (nativeUsage) { |
nativeEnqueuer.onInstantiatedType(type); |
} |
- compiler.backend.registerInstantiatedType(type); |
+ backend.registerInstantiatedType(type); |
// TODO(johnniwinther): Share this reasoning with [Universe]. |
if (!cls.isAbstract || isNative || mirrorUsage) { |
processInstantiatedClass(cls); |
@@ -229,14 +254,14 @@ class ResolutionEnqueuer extends Enqueuer { |
// its metadata parsed and analyzed. |
// Note: this assumes that there are no non-native fields on native |
// classes, which may not be the case when a native class is subclassed. |
- if (compiler.backend.isNative(cls)) { |
- compiler.openWorld.registerUsedElement(member); |
- if (_universe.hasInvokedGetter(member, compiler.openWorld) || |
- _universe.hasInvocation(member, compiler.openWorld)) { |
+ if (backend.isNative(cls)) { |
+ openWorld.registerUsedElement(member); |
+ if (_universe.hasInvokedGetter(member, openWorld) || |
+ _universe.hasInvocation(member, openWorld)) { |
addToWorkList(member); |
return; |
} |
- if (_universe.hasInvokedSetter(member, compiler.openWorld)) { |
+ if (_universe.hasInvokedSetter(member, openWorld)) { |
addToWorkList(member); |
return; |
} |
@@ -260,7 +285,7 @@ class ResolutionEnqueuer extends Enqueuer { |
} |
// If there is a property access with the same name as a method we |
// need to emit the method. |
- if (_universe.hasInvokedGetter(function, compiler.openWorld)) { |
+ if (_universe.hasInvokedGetter(function, openWorld)) { |
registerClosurizedMember(function); |
addToWorkList(function); |
return; |
@@ -270,27 +295,27 @@ class ResolutionEnqueuer extends Enqueuer { |
instanceFunctionsByName |
.putIfAbsent(memberName, () => new Set<Element>()) |
.add(member); |
- if (_universe.hasInvocation(function, compiler.openWorld)) { |
+ if (_universe.hasInvocation(function, openWorld)) { |
addToWorkList(function); |
return; |
} |
} else if (member.isGetter) { |
FunctionElement getter = member; |
getter.computeType(resolution); |
- if (_universe.hasInvokedGetter(getter, compiler.openWorld)) { |
+ if (_universe.hasInvokedGetter(getter, openWorld)) { |
addToWorkList(getter); |
return; |
} |
// We don't know what selectors the returned closure accepts. If |
// the set contains any selector we have to assume that it matches. |
- if (_universe.hasInvocation(getter, compiler.openWorld)) { |
+ if (_universe.hasInvocation(getter, openWorld)) { |
addToWorkList(getter); |
return; |
} |
} else if (member.isSetter) { |
FunctionElement setter = member; |
setter.computeType(resolution); |
- if (_universe.hasInvokedSetter(setter, compiler.openWorld)) { |
+ if (_universe.hasInvokedSetter(setter, openWorld)) { |
addToWorkList(setter); |
return; |
} |
@@ -317,13 +342,11 @@ class ResolutionEnqueuer extends Enqueuer { |
recentClasses.add(superclass); |
superclass.ensureResolved(resolution); |
superclass.implementation.forEachMember(processInstantiatedClassMember); |
- if (!compiler.serialization.isDeserialized(superclass)) { |
- compiler.resolver.checkClass(superclass); |
- } |
+ resolution.ensureClassMembers(superclass); |
// 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); |
+ backend.registerInstantiatedClass(superclass, this); |
} |
ClassElement superclass = cls; |
@@ -373,7 +396,7 @@ class ResolutionEnqueuer extends Enqueuer { |
Selector selector = dynamicUse.selector; |
String methodName = selector.name; |
processInstanceMembers(methodName, (Element member) { |
- if (dynamicUse.appliesUnnamed(member, compiler.openWorld)) { |
+ if (dynamicUse.appliesUnnamed(member, openWorld)) { |
if (member.isFunction && selector.isGetter) { |
registerClosurizedMember(member); |
} |
@@ -384,7 +407,7 @@ class ResolutionEnqueuer extends Enqueuer { |
}); |
if (selector.isGetter) { |
processInstanceFunctions(methodName, (Element member) { |
- if (dynamicUse.appliesUnnamed(member, compiler.openWorld)) { |
+ if (dynamicUse.appliesUnnamed(member, openWorld)) { |
registerClosurizedMember(member); |
return true; |
} |
@@ -407,11 +430,11 @@ class ResolutionEnqueuer extends Enqueuer { |
assert(invariant(element, element.isDeclaration, |
message: "Element ${element} is not the declaration.")); |
_universe.registerStaticUse(staticUse); |
- compiler.backend.registerStaticUse(this, element); |
+ backend.registerStaticUse(this, element); |
bool addElement = true; |
switch (staticUse.kind) { |
case StaticUseKind.STATIC_TEAR_OFF: |
- compiler.backend.registerGetOfStaticFunction(this); |
+ backend.registerGetOfStaticFunction(this); |
break; |
case StaticUseKind.FIELD_GET: |
case StaticUseKind.FIELD_SET: |
@@ -464,7 +487,7 @@ class ResolutionEnqueuer extends Enqueuer { |
_registerIsCheck(type); |
break; |
case TypeUseKind.CHECKED_MODE_CHECK: |
- if (compiler.options.enableTypeAssertions) { |
+ if (options.enableTypeAssertions) { |
_registerIsCheck(type); |
} |
break; |
@@ -474,7 +497,7 @@ class ResolutionEnqueuer extends Enqueuer { |
} |
void _registerIsCheck(DartType type) { |
- type = _universe.registerIsCheck(type, compiler); |
+ type = _universe.registerIsCheck(type, resolution); |
// Even in checked mode, type annotations for return type and argument |
// types do not imply type checks, so there should never be a check |
// against the type variable of a typedef. |
@@ -482,17 +505,17 @@ class ResolutionEnqueuer extends Enqueuer { |
} |
void registerCallMethodWithFreeTypeVariables(Element element) { |
- compiler.backend.registerCallMethodWithFreeTypeVariables(element, this); |
+ 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); |
+ backend.registerClosureWithFreeTypeVariables(element, this); |
_universe.closuresWithFreeTypeVariables.add(element); |
} |
- compiler.backend.registerBoundClosure(this); |
+ backend.registerBoundClosure(this); |
_universe.closurizedMembers.add(element); |
} |
@@ -543,7 +566,7 @@ class ResolutionEnqueuer extends Enqueuer { |
/// Registers [element] as processed by the resolution enqueuer. |
void registerProcessedElement(AstElement element) { |
processedElements.add(element); |
- compiler.backend.onElementResolved(element); |
+ backend.onElementResolved(element); |
} |
/** |
@@ -562,16 +585,16 @@ class ResolutionEnqueuer extends Enqueuer { |
element, "Resolution work list is closed. Trying to add $element."); |
} |
- compiler.openWorld.registerUsedElement(element); |
+ openWorld.registerUsedElement(element); |
- ResolutionWorkItem workItem = compiler.resolution.createWorkItem(element); |
+ ResolutionWorkItem workItem = resolution.createWorkItem(element); |
queue.add(workItem); |
// Enable isolate support if we start using something from the isolate |
// library, or timers for the async library. We exclude constant fields, |
// which are ending here because their initializing expression is compiled. |
LibraryElement library = element.library; |
- if (!compiler.hasIsolateSupport && (!element.isField || !element.isConst)) { |
+ if (!universe.hasIsolateSupport && (!element.isField || !element.isConst)) { |
String uri = library.canonicalUri.toString(); |
if (uri == 'dart:isolate') { |
enableIsolateSupport(); |
@@ -590,23 +613,23 @@ class ResolutionEnqueuer extends Enqueuer { |
// We have to enable runtime type before hitting the codegen, so |
// that constructors know whether they need to generate code for |
// runtime type. |
- compiler.enabledRuntimeType = true; |
+ _universe.hasRuntimeTypeSupport = true; |
// TODO(ahe): Record precise dependency here. |
- compiler.backend.registerRuntimeType(this); |
- } else if (compiler.commonElements.isFunctionApplyMethod(element)) { |
- compiler.enabledFunctionApply = true; |
+ backend.registerRuntimeType(this); |
+ } else if (commonElements.isFunctionApplyMethod(element)) { |
+ _universe.hasFunctionApplySupport = true; |
} |
return true; |
} |
void registerNoSuchMethod(Element element) { |
- compiler.backend.registerNoSuchMethod(element); |
+ backend.registerNoSuchMethod(element); |
} |
void enableIsolateSupport() { |
- compiler.hasIsolateSupport = true; |
- compiler.backend.enableIsolateSupport(this); |
+ _universe.hasIsolateSupport = true; |
+ backend.enableIsolateSupport(this); |
} |
/** |
@@ -636,7 +659,7 @@ class ResolutionEnqueuer extends Enqueuer { |
bool onQueueEmpty(Iterable<ClassElement> recentClasses) { |
_emptyDeferredQueue(); |
- return compiler.backend.onQueueEmpty(this, recentClasses); |
+ return backend.onQueueEmpty(this, recentClasses); |
} |
void emptyDeferredQueueForTesting() => _emptyDeferredQueue(); |
@@ -648,7 +671,7 @@ class ResolutionEnqueuer extends Enqueuer { |
} |
} |
- void forgetElement(Element element) { |
+ void forgetElement(Element element, Compiler compiler) { |
_universe.forgetElement(element, compiler); |
_processedClasses.remove(element); |
instanceMembersByName[element.name]?.remove(element); |