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

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

Issue 2494093002: Refactor enqueuers (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/js_backend/type_variable_handler.dart ('k') | pkg/compiler/lib/src/ssa/builder.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/native/enqueue.dart
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index 7c3f125ac0852cb220e35cd2ff53f416b2dd3400..44d3be38efe79babbd177b20d6c70f5f8b9f2a6c 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -21,18 +21,25 @@ import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter;
import '../tokens/token.dart' show BeginGroupToken, Token;
import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN;
import '../tree/tree.dart';
+import '../universe/use.dart' show StaticUse, TypeUse;
+import '../universe/world_impact.dart' show WorldImpactBuilder;
import 'behavior.dart';
/**
* This could be an abstract class but we use it as a stub for the dart_backend.
*/
class NativeEnqueuer {
+ /// Called when a [type] has been instantiated natively.
+ void onInstantiatedType(InterfaceType type) {}
+
/// Initial entry point to native enqueuer.
- void processNativeClasses(Iterable<LibraryElement> libraries) {}
+ void processNativeClasses(
+ WorldImpactBuilder impactBuilder, Iterable<LibraryElement> libraries) {}
/// Registers the [nativeBehavior]. Adds the liveness of its instantiated
/// types to the world.
- void registerNativeBehavior(NativeBehavior nativeBehavior, cause) {}
+ void registerNativeBehavior(
+ WorldImpactBuilder impactBuilder, NativeBehavior nativeBehavior, cause) {}
// TODO(johnniwinther): Move [handleFieldAnnotations] and
// [handleMethodAnnotations] to [JavaScriptBackend] or [NativeData].
@@ -86,12 +93,6 @@ abstract class NativeEnqueuerBase implements NativeEnqueuer {
*/
final Set matchedTypeConstraints = new Set();
- /// Pending actions. Classes in [pendingClasses] have action thunks in
- /// [queue] to register the class.
- final queue = new Queue();
- bool flushing = false;
-
- final Enqueuer world;
final Compiler compiler;
final bool enableLiveTypeAnalysis;
@@ -100,7 +101,7 @@ abstract class NativeEnqueuerBase implements NativeEnqueuer {
ClassElement _annotationJsNameClass;
/// Subclasses of [NativeEnqueuerBase] are constructed by the backend.
- NativeEnqueuerBase(this.world, Compiler compiler, this.enableLiveTypeAnalysis)
+ NativeEnqueuerBase(Compiler compiler, this.enableLiveTypeAnalysis)
: this.compiler = compiler,
processedLibraries = compiler.cacheStrategy.newSet();
@@ -111,7 +112,14 @@ abstract class NativeEnqueuerBase implements NativeEnqueuer {
DiagnosticReporter get reporter => compiler.reporter;
CoreTypes get coreTypes => compiler.coreTypes;
- void processNativeClasses(Iterable<LibraryElement> libraries) {
+ void onInstantiatedType(InterfaceType type) {
+ if (unusedClasses.remove(type.element)) {
+ registeredClasses.add(type.element);
+ }
+ }
+
+ void processNativeClasses(
+ WorldImpactBuilder impactBuilder, Iterable<LibraryElement> libraries) {
if (compiler.options.hasIncrementalSupport) {
// Since [Set.add] returns bool if an element was added, this restricts
// [libraries] to ones that haven't already been processed. This saves
@@ -124,8 +132,7 @@ abstract class NativeEnqueuerBase implements NativeEnqueuer {
}
processSubclassesOfNativeClasses(libraries);
if (!enableLiveTypeAnalysis) {
- nativeClasses.forEach((c) => enqueueClass(c, 'forced'));
- flushQueue();
+ _registerTypeUses(impactBuilder, nativeClasses, 'forced');
}
}
@@ -333,40 +340,19 @@ abstract class NativeEnqueuerBase implements NativeEnqueuer {
return name;
}
- enqueueClass(ClassElement classElement, cause) {
- assert(unusedClasses.contains(classElement));
- unusedClasses.remove(classElement);
- pendingClasses.add(classElement);
- queue.add(() {
- processClass(classElement, cause);
- });
- }
-
- void flushQueue() {
- if (flushing) return;
- flushing = true;
- while (!queue.isEmpty) {
- (queue.removeFirst())();
- }
- flushing = false;
- }
-
- processClass(ClassElement classElement, cause) {
- // TODO(ahe): Fix this assertion to work in incremental compilation.
- assert(compiler.options.hasIncrementalSupport ||
- !registeredClasses.contains(classElement));
-
- bool firstTime = registeredClasses.isEmpty;
- pendingClasses.remove(classElement);
- registeredClasses.add(classElement);
-
- // TODO(ahe): Is this really a global dependency?
- classElement.ensureResolved(resolution);
- compiler.backend.registerInstantiatedType(
- classElement.rawType, world, compiler.globalDependencies);
-
- if (firstTime) {
- queue.add(onFirstNativeClass);
+ /// Register [classes] as natively instantiated in [impactBuilder].
+ void _registerTypeUses(
+ WorldImpactBuilder impactBuilder, Set<ClassElement> classes, cause) {
+ for (ClassElement cls in classes) {
+ if (!unusedClasses.contains(cls)) {
+ // No need to add [classElement] to [impactBuilder]: it has already been
+ // instantiated and we don't track origins of native instantiations
+ // precisely.
+ continue;
+ }
+ cls.ensureResolved(resolution);
+ impactBuilder
+ .registerTypeUse(new TypeUse.nativeInstantiation(cls.rawType));
}
}
@@ -449,43 +435,45 @@ abstract class NativeEnqueuerBase implements NativeEnqueuer {
});
}
- void registerNativeBehavior(NativeBehavior nativeBehavior, cause) {
- processNativeBehavior(nativeBehavior, cause);
- flushQueue();
+ void registerNativeBehavior(
+ WorldImpactBuilder impactBuilder, NativeBehavior nativeBehavior, cause) {
+ _processNativeBehavior(impactBuilder, nativeBehavior, cause);
}
- processNativeBehavior(NativeBehavior behavior, cause) {
- // TODO(ahe): Is this really a global dependency?
- Registry registry = compiler.globalDependencies;
- bool allUsedBefore = unusedClasses.isEmpty;
+ void _processNativeBehavior(
+ WorldImpactBuilder impactBuilder, NativeBehavior behavior, cause) {
+ void registerInstantiation(InterfaceType type) {
+ impactBuilder.registerTypeUse(new TypeUse.nativeInstantiation(type));
+ }
+
+ int unusedBefore = unusedClasses.length;
+ Set<ClassElement> matchingClasses = new Set<ClassElement>();
for (var type in behavior.typesInstantiated) {
if (matchedTypeConstraints.contains(type)) continue;
matchedTypeConstraints.add(type);
if (type is SpecialType) {
if (type == SpecialType.JsObject) {
- backend.registerInstantiatedType(
- compiler.coreTypes.objectType, world, registry);
+ registerInstantiation(compiler.coreTypes.objectType);
}
continue;
}
if (type is InterfaceType) {
if (type == coreTypes.intType) {
- backend.registerInstantiatedType(type, world, registry);
+ registerInstantiation(type);
} else if (type == coreTypes.doubleType) {
- backend.registerInstantiatedType(type, world, registry);
+ registerInstantiation(type);
} else if (type == coreTypes.numType) {
- backend.registerInstantiatedType(
- coreTypes.doubleType, world, registry);
- backend.registerInstantiatedType(coreTypes.intType, world, registry);
+ registerInstantiation(coreTypes.doubleType);
+ registerInstantiation(coreTypes.intType);
} else if (type == coreTypes.stringType) {
- backend.registerInstantiatedType(type, world, registry);
+ registerInstantiation(type);
} else if (type == coreTypes.nullType) {
- backend.registerInstantiatedType(type, world, registry);
+ registerInstantiation(type);
} else if (type == coreTypes.boolType) {
- backend.registerInstantiatedType(type, world, registry);
+ registerInstantiation(type);
} else if (compiler.types.isSubtype(
type, backend.backendClasses.listImplementation.rawType)) {
- backend.registerInstantiatedType(type, world, registry);
+ registerInstantiation(type);
}
// TODO(johnniwinther): Improve spec string precision to handle type
// arguments and implements relations that preserve generics. Currently
@@ -494,60 +482,66 @@ abstract class NativeEnqueuerBase implements NativeEnqueuer {
// any native subclasses of generic classes.
// TODO(johnniwinther,sra): Find and replace uses of `List` with the
// actual implementation classes such as `JSArray` et al.
- enqueueUnusedClassesMatching((ClassElement nativeClass) {
+ matchingClasses
+ .addAll(_findUnusedClassesMatching((ClassElement nativeClass) {
InterfaceType nativeType = nativeClass.thisType;
InterfaceType specType = type.element.thisType;
return compiler.types.isSubtype(nativeType, specType);
- }, cause, 'subtypeof($type)');
+ }));
} else if (type.isDynamic) {
- enqueueUnusedClassesMatching((_) => true, cause, 'subtypeof($type)');
+ matchingClasses.addAll(unusedClasses);
} else {
assert(type is VoidType);
}
}
+ if (matchingClasses.isNotEmpty && registeredClasses.isEmpty) {
+ matchingClasses.addAll(_onFirstNativeClass(impactBuilder));
+ }
+ _registerTypeUses(impactBuilder, matchingClasses, cause);
// Give an info so that library developers can compile with -v to find why
// all the native classes are included.
- if (unusedClasses.isEmpty && !allUsedBefore) {
+ if (unusedBefore == matchingClasses.length) {
reporter.log('All native types marked as used due to $cause.');
}
}
- enqueueUnusedClassesMatching(bool predicate(classElement), cause,
- [String reason]) {
- Iterable matches = unusedClasses.where(predicate);
- matches.toList().forEach((c) => enqueueClass(c, cause));
+ Iterable<ClassElement> _findUnusedClassesMatching(
+ bool predicate(classElement)) {
+ return unusedClasses.where(predicate);
}
- onFirstNativeClass() {
- staticUse(name) {
- backend.enqueue(
- world, helpers.findHelper(name), compiler.globalDependencies);
+ Iterable<ClassElement> _onFirstNativeClass(WorldImpactBuilder impactBuilder) {
+ void staticUse(name) {
+ Element element = helpers.findHelper(name);
+ impactBuilder.registerStaticUse(new StaticUse.foreignUse(element));
+ backend.registerBackendUse(element);
+ compiler.globalDependencies.registerDependency(element);
}
staticUse('defineProperty');
staticUse('toStringForNativeObject');
staticUse('hashCodeForNativeObject');
staticUse('convertDartClosureToJS');
- addNativeExceptions();
+ return _findNativeExceptions();
}
- addNativeExceptions() {
- enqueueUnusedClassesMatching((classElement) {
+ Iterable<ClassElement> _findNativeExceptions() {
+ return _findUnusedClassesMatching((classElement) {
// TODO(sra): Annotate exception classes in dart:html.
String name = classElement.name;
if (name.contains('Exception')) return true;
if (name.contains('Error')) return true;
return false;
- }, 'native exception');
+ });
}
}
class NativeResolutionEnqueuer extends NativeEnqueuerBase {
Map<String, ClassElement> tagOwner = new Map<String, ClassElement>();
- NativeResolutionEnqueuer(Enqueuer world, Compiler compiler)
- : super(world, compiler, compiler.options.enableNativeLiveTypeAnalysis);
+ NativeResolutionEnqueuer(Compiler compiler)
+ : super(compiler, compiler.options.enableNativeLiveTypeAnalysis);
void processNativeClass(ClassElement classElement) {
super.processNativeClass(classElement);
@@ -623,37 +617,46 @@ class NativeCodegenEnqueuer extends NativeEnqueuerBase {
final Set<ClassElement> doneAddSubtypes = new Set<ClassElement>();
- NativeCodegenEnqueuer(Enqueuer world, Compiler compiler, this.emitter)
- : super(world, compiler, compiler.options.enableNativeLiveTypeAnalysis);
+ NativeCodegenEnqueuer(Compiler compiler, this.emitter)
+ : super(compiler, compiler.options.enableNativeLiveTypeAnalysis);
- void processNativeClasses(Iterable<LibraryElement> libraries) {
- super.processNativeClasses(libraries);
+ void processNativeClasses(
+ WorldImpactBuilder impactBuilder, Iterable<LibraryElement> libraries) {
+ super.processNativeClasses(impactBuilder, libraries);
// HACK HACK - add all the resolved classes.
NativeEnqueuerBase enqueuer = compiler.enqueuer.resolution.nativeEnqueuer;
+ Set<ClassElement> matchingClasses = new Set<ClassElement>();
for (final classElement in enqueuer.registeredClasses) {
if (unusedClasses.contains(classElement)) {
- enqueueClass(classElement, 'was resolved');
+ matchingClasses.add(classElement);
}
}
- flushQueue();
+ if (matchingClasses.isNotEmpty && registeredClasses.isEmpty) {
+ matchingClasses.addAll(_onFirstNativeClass(impactBuilder));
+ }
+ _registerTypeUses(impactBuilder, matchingClasses, 'was resolved');
}
- processClass(ClassElement classElement, cause) {
- super.processClass(classElement, cause);
- // Add the information that this class is a subtype of its supertypes. The
- // code emitter and the ssa builder use that information.
- addSubtypes(classElement, emitter.nativeEmitter);
+ void _registerTypeUses(
+ WorldImpactBuilder impactBuilder, Set<ClassElement> classes, cause) {
+ super._registerTypeUses(impactBuilder, classes, cause);
+
+ for (ClassElement classElement in classes) {
+ // Add the information that this class is a subtype of its supertypes. The
+ // code emitter and the ssa builder use that information.
+ _addSubtypes(classElement, emitter.nativeEmitter);
+ }
}
- void addSubtypes(ClassElement cls, NativeEmitter emitter) {
+ void _addSubtypes(ClassElement cls, NativeEmitter emitter) {
if (!backend.isNative(cls)) return;
if (doneAddSubtypes.contains(cls)) return;
doneAddSubtypes.add(cls);
// Walk the superclass chain since classes on the superclass chain might not
// be instantiated (abstract or simply unused).
- addSubtypes(cls.superclass, emitter);
+ _addSubtypes(cls.superclass, emitter);
for (DartType type in cls.allSupertypes) {
List<Element> subtypes =
« no previous file with comments | « pkg/compiler/lib/src/js_backend/type_variable_handler.dart ('k') | pkg/compiler/lib/src/ssa/builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698