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

Unified Diff: pkg/compiler/lib/src/js_backend/enqueuer.dart

Issue 2314703002: Split World usage into open, inference, and closed world. (Closed)
Patch Set: Updated cf. comments Created 4 years, 3 months 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
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 d95c529c0948a3b43cd3d2183e4a7d0558e63894..b7710eb6f8415c5d8b396639d125e6243c757a8e 100644
--- a/pkg/compiler/lib/src/js_backend/enqueuer.dart
+++ b/pkg/compiler/lib/src/js_backend/enqueuer.dart
@@ -6,9 +6,10 @@ library dart2js.js.enqueue;
import 'dart:collection' show Queue;
+import '../common/backend_api.dart' show Backend;
import '../common/codegen.dart' show CodegenWorkItem;
+import '../common/registry.dart' show Registry;
import '../common/names.dart' show Identifiers;
-import '../common/resolution.dart' show Resolution;
import '../common/work.dart' show WorkItem;
import '../common.dart';
import '../compiler.dart' show Compiler;
@@ -30,6 +31,7 @@ import '../elements/elements.dart'
import '../enqueue.dart';
import '../js/js.dart' as js;
import '../native/native.dart' as native;
+import '../options.dart';
import '../types/types.dart' show TypeMaskStrategy;
import '../universe/selector.dart' show Selector;
import '../universe/universe.dart';
@@ -38,11 +40,13 @@ import '../universe/use.dart'
import '../universe/world_impact.dart'
show ImpactUseCase, WorldImpact, WorldImpactVisitor;
import '../util/util.dart' show Setlet;
+import '../world.dart';
/// [Enqueuer] which is specific to code generation.
class CodegenEnqueuer implements Enqueuer {
final String name;
- final Compiler compiler; // TODO(ahe): Remove this dependency.
+ @deprecated
+ final Compiler _compiler; // TODO(ahe): Remove this dependency.
final EnqueuerStrategy strategy;
final Map<String, Set<Element>> instanceMembersByName =
new Map<String, Set<Element>>();
@@ -69,25 +73,28 @@ class CodegenEnqueuer implements Enqueuer {
newlyEnqueuedElements = compiler.cacheStrategy.newSet(),
newlySeenSelectors = compiler.cacheStrategy.newSet(),
this.name = 'codegen enqueuer',
- this.compiler = compiler {
+ this._compiler = compiler {
impactVisitor = new _EnqueuerImpactVisitor(this);
}
- // TODO(johnniwinther): Move this to [ResolutionEnqueuer].
- Resolution get resolution => compiler.resolution;
+ Backend get backend => _compiler.backend;
+
+ CompilerOptions get options => _compiler.options;
+
+ Registry get globalDependencies => _compiler.globalDependencies;
+
+ Registry get mirrorDependencies => _compiler.mirrorDependencies;
+
+ ClassWorld get _world => _compiler.closedWorld;
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;
-
- bool isClassProcessed(ClassElement cls) => _processedClasses.contains(cls);
+ QueueFilter get filter => _compiler.enqueuerFilter;
- Iterable<ClassElement> get processedClasses => _processedClasses;
+ DiagnosticReporter get reporter => _compiler.reporter;
/**
* Documentation wanted -- johnniwinther
@@ -96,30 +103,48 @@ class CodegenEnqueuer implements Enqueuer {
*/
void addToWorkList(Element element) {
assert(invariant(element, element.isDeclaration));
- if (internalAddToWorkList(element) && compiler.options.dumpInfo) {
+ // Don't generate code for foreign elements.
+ if (backend.isForeign(element)) return;
+
+ // Codegen inlines field initializers. It only needs to generate
+ // code for checked setters.
+ if (element.isField && element.isInstanceMember) {
+ if (!options.enableTypeAssertions || element.enclosingElement.isClosure) {
+ return;
+ }
+ }
+
+ if (options.hasIncrementalSupport && !isProcessed(element)) {
+ newlyEnqueuedElements.add(element);
+ }
+
+ if (queueIsClosed) {
+ throw new SpannableAssertionFailure(
+ element, "Codegen work list is closed. Trying to add $element");
+ }
+ queue.add(new CodegenWorkItem(_compiler, element));
+ if (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);
+ _compiler.dumpInfoTask
+ .registerDependency(_compiler.currentElement, element);
}
}
/// Apply the [worldImpact] of processing [element] to this enqueuer.
void applyImpact(Element element, WorldImpact worldImpact) {
- compiler.impactStrategy
+ _compiler.impactStrategy
.visitImpact(element, worldImpact, impactVisitor, impactUse);
}
void registerInstantiatedType(InterfaceType type, {bool mirrorUsage: false}) {
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, compiler.globalDependencies);
+ backend.registerImplementedClass(cls, this, globalDependencies);
});
// TODO(johnniwinther): Share this reasoning with [Universe].
if (!cls.isAbstract || isNative || mirrorUsage) {
@@ -150,14 +175,12 @@ class CodegenEnqueuer implements 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.world.registerUsedElement(member);
- if (universe.hasInvokedGetter(member, compiler.world) ||
- universe.hasInvocation(member, compiler.world)) {
+ if (backend.isNative(cls)) {
+ if (universe.hasInvokedGetter(member, _world) ||
+ universe.hasInvocation(member, _world)) {
addToWorkList(member);
return;
- }
- if (universe.hasInvokedSetter(member, compiler.world)) {
+ } else if (universe.hasInvokedSetter(member, _world)) {
addToWorkList(member);
return;
}
@@ -172,7 +195,6 @@ class CodegenEnqueuer implements Enqueuer {
}
} else if (member.isFunction) {
FunctionElement function = member;
- function.computeType(resolution);
if (function.name == Identifiers.noSuchMethod_) {
registerNoSuchMethod(function);
}
@@ -181,7 +203,7 @@ class CodegenEnqueuer implements 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.world)) {
+ if (universe.hasInvokedGetter(function, _world)) {
registerClosurizedMember(function);
addToWorkList(function);
return;
@@ -191,27 +213,25 @@ class CodegenEnqueuer implements Enqueuer {
instanceFunctionsByName
.putIfAbsent(memberName, () => new Set<Element>())
.add(member);
- if (universe.hasInvocation(function, compiler.world)) {
+ if (universe.hasInvocation(function, _world)) {
addToWorkList(function);
return;
}
} else if (member.isGetter) {
FunctionElement getter = member;
- getter.computeType(resolution);
- if (universe.hasInvokedGetter(getter, compiler.world)) {
+ if (universe.hasInvokedGetter(getter, _world)) {
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.world)) {
+ if (universe.hasInvocation(getter, _world)) {
addToWorkList(getter);
return;
}
} else if (member.isSetter) {
FunctionElement setter = member;
- setter.computeType(resolution);
- if (universe.hasInvokedSetter(setter, compiler.world)) {
+ if (universe.hasInvokedSetter(setter, _world)) {
addToWorkList(setter);
return;
}
@@ -229,35 +249,25 @@ class CodegenEnqueuer implements Enqueuer {
void processInstantiatedClass(ClassElement cls) {
task.measure(() {
if (_processedClasses.contains(cls)) return;
- // The class must be resolved to compute the set of all
- // supertypes.
- cls.ensureResolved(resolution);
void processClass(ClassElement superclass) {
if (_processedClasses.contains(superclass)) return;
// TODO(johnniwinther): Re-insert this invariant when unittests don't
// fail. There is already a similar invariant on the members.
- /*if (!isResolutionQueue) {
- assert(invariant(superclass,
+ /*assert(invariant(superclass,
superclass.isClosure ||
- compiler.enqueuer.resolution.isClassProcessed(superclass),
+ _compiler.enqueuer.resolution.isClassProcessed(superclass),
message: "Class $superclass has not been "
"processed in resolution."));
- }*/
+ */
_processedClasses.add(superclass);
recentClasses.add(superclass);
- superclass.ensureResolved(resolution);
superclass.implementation.forEachMember(processInstantiatedClassMember);
- if (isResolutionQueue &&
- !compiler.serialization.isDeserialized(superclass)) {
- compiler.resolver.checkClass(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, compiler.globalDependencies);
+ backend.registerInstantiatedClass(superclass, this, globalDependencies);
}
ClassElement superclass = cls;
@@ -278,7 +288,7 @@ class CodegenEnqueuer implements Enqueuer {
void logEnqueueReflectiveAction(action, [msg = ""]) {
if (TRACE_MIRROR_ENQUEUING) {
- print("MIRROR_ENQUEUE (${isResolutionQueue ? "R" : "C"}): $action $msg");
+ print("MIRROR_ENQUEUE (C): $action $msg");
}
}
@@ -292,8 +302,7 @@ class CodegenEnqueuer implements Enqueuer {
includedEnclosing: enclosingWasIncluded)) {
logEnqueueReflectiveAction(ctor);
ClassElement cls = ctor.declaration.enclosingClass;
- compiler.backend.registerInstantiatedType(
- cls.rawType, this, compiler.mirrorDependencies,
+ backend.registerInstantiatedType(cls.rawType, this, mirrorDependencies,
mirrorUsage: true);
registerStaticUse(new StaticUse.foreignUse(ctor.declaration));
}
@@ -308,9 +317,7 @@ class CodegenEnqueuer implements Enqueuer {
includedEnclosing: enclosingWasIncluded)) {
logEnqueueReflectiveAction(element);
if (element.isTypedef) {
- TypedefElement typedef = element;
- typedef.ensureResolved(resolution);
- compiler.world.allTypedefs.add(element);
+ // Do nothing.
} else if (Elements.isStaticOrTopLevel(element)) {
registerStaticUse(new StaticUse.foreignUse(element.declaration));
} else if (element.isInstanceMember) {
@@ -343,9 +350,7 @@ class CodegenEnqueuer implements Enqueuer {
if (includeClass) {
logEnqueueReflectiveAction(cls, "register");
ClassElement decl = cls.declaration;
- decl.ensureResolved(resolution);
- compiler.backend.registerInstantiatedType(
- decl.rawType, this, compiler.mirrorDependencies,
+ backend.registerInstantiatedType(decl.rawType, this, mirrorDependencies,
mirrorUsage: true);
}
// If the class is never instantiated, we know nothing of it can possibly
@@ -370,14 +375,11 @@ class CodegenEnqueuer implements Enqueuer {
/// that none of its methods are reflectable, unless reflectable by
/// inheritance.
void enqueueReflectiveSpecialClasses() {
- Iterable<ClassElement> classes =
- compiler.backend.classesRequiredForReflection;
+ Iterable<ClassElement> classes = backend.classesRequiredForReflection;
for (ClassElement cls in classes) {
- if (compiler.backend.referencedFromMirrorSystem(cls)) {
+ if (backend.referencedFromMirrorSystem(cls)) {
logEnqueueReflectiveAction(cls);
- cls.ensureResolved(resolution);
- compiler.backend.registerInstantiatedType(
- cls.rawType, this, compiler.mirrorDependencies,
+ backend.registerInstantiatedType(cls.rawType, this, mirrorDependencies,
mirrorUsage: true);
}
}
@@ -412,7 +414,7 @@ class CodegenEnqueuer implements Enqueuer {
// enqueued.
recents = _processedClasses.toSet();
reporter.log('Enqueuing everything');
- for (LibraryElement lib in compiler.libraryLoader.libraries) {
+ for (LibraryElement lib in _compiler.libraryLoader.libraries) {
enqueueReflectiveElementsInLibrary(lib, recents);
}
enqueueReflectiveSpecialClasses();
@@ -474,7 +476,7 @@ class CodegenEnqueuer implements Enqueuer {
Selector selector = dynamicUse.selector;
String methodName = selector.name;
processInstanceMembers(methodName, (Element member) {
- if (dynamicUse.appliesUnnamed(member, compiler.world)) {
+ if (dynamicUse.appliesUnnamed(member, _world)) {
if (member.isFunction && selector.isGetter) {
registerClosurizedMember(member);
}
@@ -485,7 +487,7 @@ class CodegenEnqueuer implements Enqueuer {
});
if (selector.isGetter) {
processInstanceFunctions(methodName, (Element member) {
- if (dynamicUse.appliesUnnamed(member, compiler.world)) {
+ if (dynamicUse.appliesUnnamed(member, _world)) {
registerClosurizedMember(member);
return true;
}
@@ -508,11 +510,11 @@ class CodegenEnqueuer implements Enqueuer {
assert(invariant(element, element.isDeclaration,
message: "Element ${element} is not the declaration."));
universe.registerStaticUse(staticUse);
- compiler.backend.registerStaticUse(element, this);
+ backend.registerStaticUse(element, this);
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:
@@ -546,7 +548,7 @@ class CodegenEnqueuer implements Enqueuer {
_registerIsCheck(type);
break;
case TypeUseKind.CHECKED_MODE_CHECK:
- if (compiler.options.enableTypeAssertions) {
+ if (options.enableTypeAssertions) {
_registerIsCheck(type);
}
break;
@@ -556,7 +558,7 @@ class CodegenEnqueuer implements Enqueuer {
}
void _registerIsCheck(DartType type) {
- type = universe.registerIsCheck(type, compiler);
+ type = universe.registerIsCheck(type, _compiler);
// 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.
@@ -564,18 +566,18 @@ class CodegenEnqueuer implements Enqueuer {
}
void registerCallMethodWithFreeTypeVariables(Element element) {
- compiler.backend.registerCallMethodWithFreeTypeVariables(
- element, this, compiler.globalDependencies);
+ backend.registerCallMethodWithFreeTypeVariables(
+ element, this, globalDependencies);
universe.callMethodsWithFreeTypeVariables.add(element);
}
void registerClosurizedMember(TypedElement element) {
assert(element.isInstanceMember);
- if (element.computeType(resolution).containsTypeVariables) {
- compiler.backend.registerClosureWithFreeTypeVariables(
- element, this, compiler.globalDependencies);
+ if (element.type.containsTypeVariables) {
+ backend.registerClosureWithFreeTypeVariables(
+ element, this, globalDependencies);
}
- compiler.backend.registerBoundClosure(this);
+ backend.registerBoundClosure(this);
universe.closurizedMembers.add(element);
}
@@ -598,7 +600,7 @@ class CodegenEnqueuer implements Enqueuer {
/// 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);
+ return backend.onQueueEmpty(this, recentClasses);
}
void logSummary(log(message)) {
@@ -609,7 +611,7 @@ class CodegenEnqueuer implements Enqueuer {
String toString() => 'Enqueuer($name)';
void _forgetElement(Element element) {
- universe.forgetElement(element, compiler);
+ universe.forgetElement(element, _compiler);
_processedClasses.remove(element);
instanceMembersByName[element.name]?.remove(element);
instanceFunctionsByName[element.name]?.remove(element);
@@ -641,42 +643,12 @@ class CodegenEnqueuer implements Enqueuer {
*/
bool shouldIncludeElementDueToMirrors(Element element,
{bool includedEnclosing}) {
- return compiler.backend.isAccessibleByReflection(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) {
- // Don't generate code for foreign elements.
- if (compiler.backend.isForeign(element)) return false;
-
- // Codegen inlines field initializers. It only needs to generate
- // code for checked setters.
- if (element.isField && element.isInstanceMember) {
- if (!compiler.options.enableTypeAssertions ||
- element.enclosingElement.isClosure) {
- return false;
- }
- }
-
- if (compiler.options.hasIncrementalSupport && !isProcessed(element)) {
- newlyEnqueuedElements.add(element);
- }
-
- if (queueIsClosed) {
- throw new SpannableAssertionFailure(
- element, "Codegen work list is closed. Trying to add $element");
- }
- queue.add(new CodegenWorkItem(compiler, element));
- return true;
+ return backend.isAccessibleByReflection(element);
}
void registerNoSuchMethod(Element element) {
- if (!enabledNoSuchMethod && compiler.backend.enabledNoSuchMethod) {
- compiler.backend.enableNoSuchMethod(this);
+ if (!enabledNoSuchMethod && backend.enabledNoSuchMethod) {
+ backend.enableNoSuchMethod(this);
enabledNoSuchMethod = true;
}
}
@@ -698,7 +670,7 @@ class CodegenEnqueuer implements Enqueuer {
}
void handleUnseenSelector(DynamicUse dynamicUse) {
- if (compiler.options.hasIncrementalSupport) {
+ if (options.hasIncrementalSupport) {
newlySeenSelectors.add(dynamicUse);
}
_handleUnseenSelector(dynamicUse);
« no previous file with comments | « pkg/compiler/lib/src/js_backend/backend.dart ('k') | pkg/compiler/lib/src/js_backend/field_naming_mixin.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698