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

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

Issue 693183006: Revert "Move dart2js from sdk/lib/_internal/compiler to pkg/compiler" (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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/elements/visitor.dart ('k') | pkg/compiler/lib/src/filenames.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
deleted file mode 100644
index a00c365e2d766fdf465c8ef3533ce6bba95218ff..0000000000000000000000000000000000000000
--- a/pkg/compiler/lib/src/enqueue.dart
+++ /dev/null
@@ -1,905 +0,0 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of dart2js;
-
-typedef ItemCompilationContext ItemCompilationContextCreator();
-
-class EnqueueTask extends CompilerTask {
- final ResolutionEnqueuer resolution;
- final CodegenEnqueuer codegen;
-
- String get name => 'Enqueue';
-
- EnqueueTask(Compiler compiler)
- : resolution = new ResolutionEnqueuer(
- compiler, compiler.backend.createItemCompilationContext),
- codegen = new CodegenEnqueuer(
- compiler, compiler.backend.createItemCompilationContext),
- super(compiler) {
- codegen.task = this;
- resolution.task = this;
-
- codegen.nativeEnqueuer = compiler.backend.nativeCodegenEnqueuer(codegen);
- resolution.nativeEnqueuer =
- compiler.backend.nativeResolutionEnqueuer(resolution);
- }
-
- void forgetElement(Element element) {
- resolution.forgetElement(element);
- codegen.forgetElement(element);
- }
-}
-
-abstract class Enqueuer {
- final String name;
- final Compiler compiler; // TODO(ahe): Remove this dependency.
- final ItemCompilationContextCreator itemCompilationContextCreator;
- final Map<String, Set<Element>> instanceMembersByName
- = new Map<String, Set<Element>>();
- final Map<String, Set<Element>> instanceFunctionsByName
- = new Map<String, Set<Element>>();
- final Set<ClassElement> _processedClasses = new Set<ClassElement>();
- Set<ClassElement> recentClasses = new Setlet<ClassElement>();
- final Universe universe = new Universe();
-
- static final TRACE_MIRROR_ENQUEUING =
- const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING");
-
- bool queueIsClosed = false;
- EnqueueTask task;
- native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask
-
- bool hasEnqueuedReflectiveElements = false;
- bool hasEnqueuedReflectiveStaticFields = false;
-
- Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator);
-
- 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;
-
- /// Returns [:true:] if [member] has been processed by this enqueuer.
- bool isProcessed(Element member);
-
- /**
- * Documentation wanted -- johnniwinther
- *
- * Invariant: [element] must be a declaration element.
- */
- void addToWorkList(Element element) {
- assert(invariant(element, element.isDeclaration));
- internalAddToWorkList(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);
-
- void registerInstantiatedType(InterfaceType type, Registry registry,
- {bool mirrorUsage: false}) {
- task.measure(() {
- ClassElement cls = type.element;
- registry.registerDependency(cls);
- cls.ensureResolved(compiler);
- universe.registerTypeInstantiation(type, byMirrors: mirrorUsage);
- processInstantiatedClass(cls);
- });
- }
-
- void registerInstantiatedClass(ClassElement cls, Registry registry,
- {bool mirrorUsage: false}) {
- cls.ensureResolved(compiler);
- registerInstantiatedType(cls.rawType, registry, mirrorUsage: mirrorUsage);
- }
-
- bool checkNoEnqueuedInvokedInstanceMethods() {
- return filter.checkNoEnqueuedInvokedInstanceMethods(this);
- }
-
- void processInstantiatedClassMembers(ClassElement cls) {
- cls.implementation.forEachMember(processInstantiatedClassMember);
- }
-
- void processInstantiatedClassMember(ClassElement cls, Element member) {
- assert(invariant(member, member.isDeclaration));
- if (isProcessed(member)) return;
- if (!member.isInstanceMember) return;
-
- String memberName = member.name;
-
- if (member.kind == ElementKind.FIELD) {
- // The obvious thing to test here would be "member.isNative",
- // however, that only works after metadata has been parsed/analyzed,
- // and that may not have happened yet.
- // So instead we use the enclosing class, which we know have had
- // 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 (cls.isNative) {
- compiler.world.registerUsedElement(member);
- nativeEnqueuer.handleFieldAnnotations(member);
- if (universe.hasInvokedGetter(member, compiler.world) ||
- universe.hasInvocation(member, compiler.world)) {
- nativeEnqueuer.registerFieldLoad(member);
- // In handleUnseenSelector we can't tell if the field is loaded or
- // stored. We need the basic algorithm to be Church-Rosser, since the
- // resolution 'reduction' order is different to the codegen order. So
- // register that the field is also stored. In other words: if we
- // don't register the store here during resolution, the store could be
- // registered during codegen on the handleUnseenSelector path, and
- // cause the set of codegen elements to include unresolved elements.
- nativeEnqueuer.registerFieldStore(member);
- addToWorkList(member);
- return;
- }
- if (universe.hasInvokedSetter(member, compiler.world)) {
- nativeEnqueuer.registerFieldStore(member);
- // See comment after registerFieldLoad above.
- nativeEnqueuer.registerFieldLoad(member);
- addToWorkList(member);
- return;
- }
- // Native fields need to go into instanceMembersByName as they
- // are virtual instantiation points and escape points.
- } else {
- // All field initializers must be resolved as they could
- // have an observable side-effect (and cannot be tree-shaken
- // away).
- addToWorkList(member);
- return;
- }
- } else if (member.kind == ElementKind.FUNCTION) {
- FunctionElement function = member;
- function.computeSignature(compiler);
- if (function.name == Compiler.NO_SUCH_METHOD) {
- enableNoSuchMethod(function);
- }
- if (function.name == Compiler.CALL_OPERATOR_NAME &&
- !cls.typeVariables.isEmpty) {
- registerCallMethodWithFreeTypeVariables(
- function, compiler.globalDependencies);
- }
- // 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)) {
- registerClosurizedMember(function, compiler.globalDependencies);
- addToWorkList(function);
- return;
- }
- // Store the member in [instanceFunctionsByName] to catch
- // getters on the function.
- instanceFunctionsByName.putIfAbsent(memberName, () => new Set<Element>())
- .add(member);
- if (universe.hasInvocation(function, compiler.world)) {
- addToWorkList(function);
- return;
- }
- } else if (member.kind == ElementKind.GETTER) {
- FunctionElement getter = member;
- getter.computeSignature(compiler);
- if (universe.hasInvokedGetter(getter, compiler.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)) {
- addToWorkList(getter);
- return;
- }
- } else if (member.kind == ElementKind.SETTER) {
- FunctionElement setter = member;
- setter.computeSignature(compiler);
- if (universe.hasInvokedSetter(setter, compiler.world)) {
- addToWorkList(setter);
- return;
- }
- }
-
- // The element is not yet used. Add it to the list of instance
- // members to still be processed.
- instanceMembersByName.putIfAbsent(memberName, () => new Set<Element>())
- .add(member);
- }
-
- void enableNoSuchMethod(Element element) {}
- void enableIsolateSupport() {}
-
- 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(compiler);
-
- void processClass(ClassElement cls) {
- if (_processedClasses.contains(cls)) return;
-
- _processedClasses.add(cls);
- recentClasses.add(cls);
- cls.ensureResolved(compiler);
- cls.implementation.forEachMember(processInstantiatedClassMember);
- if (isResolutionQueue) {
- compiler.resolver.checkClass(cls);
- }
- // We only tell the backend once that [cls] was instantiated, so
- // any additional dependencies must be treated as global
- // dependencies.
- compiler.backend.registerInstantiatedClass(
- cls, this, compiler.globalDependencies);
- }
- processClass(cls);
- for (Link<DartType> supertypes = cls.allSupertypes;
- !supertypes.isEmpty; supertypes = supertypes.tail) {
- processClass(supertypes.head.element);
- }
- });
- }
-
- void registerNewSelector(Selector selector,
- Map<String, Set<Selector>> selectorsMap) {
- String name = selector.name;
- Set<Selector> selectors =
- selectorsMap.putIfAbsent(name, () => new Setlet<Selector>());
- if (!selectors.contains(selector)) {
- selectors.add(selector);
- handleUnseenSelector(name, selector);
- }
- }
-
- void registerInvocation(Selector selector) {
- task.measure(() {
- registerNewSelector(selector, universe.invokedNames);
- });
- }
-
- void registerInvokedGetter(Selector selector) {
- task.measure(() {
- registerNewSelector(selector, universe.invokedGetters);
- });
- }
-
- void registerInvokedSetter(Selector selector) {
- task.measure(() {
- registerNewSelector(selector, universe.invokedSetters);
- });
- }
-
- /**
- * 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");
- }
- }
-
- /// Enqeue the constructor [ctor] if it is required for reflection.
- ///
- /// [enclosingWasIncluded] provides a hint whether the enclosing element was
- /// needed for reflection.
- void enqueueReflectiveConstructor(ConstructorElement ctor,
- bool enclosingWasIncluded) {
- if (shouldIncludeElementDueToMirrors(ctor,
- includedEnclosing: enclosingWasIncluded)) {
- logEnqueueReflectiveAction(ctor);
- ClassElement cls = ctor.declaration.enclosingClass;
- registerInstantiatedType(cls.rawType, compiler.mirrorDependencies,
- mirrorUsage: true);
- registerStaticUse(ctor.declaration);
- }
- }
-
- /// Enqeue the member [element] if it is required for reflection.
- ///
- /// [enclosingWasIncluded] provides a hint whether the enclosing element was
- /// needed for reflection.
- void enqueueReflectiveMember(Element element, bool enclosingWasIncluded) {
- if (shouldIncludeElementDueToMirrors(element,
- includedEnclosing: enclosingWasIncluded)) {
- logEnqueueReflectiveAction(element);
- if (element.isTypedef) {
- TypedefElement typedef = element;
- typedef.ensureResolved(compiler);
- compiler.world.allTypedefs.add(element);
- } else if (Elements.isStaticOrTopLevel(element)) {
- registerStaticUse(element.declaration);
- } else if (element.isInstanceMember) {
- // We need to enqueue all members matching this one in subclasses, as
- // well.
- // TODO(herhut): Use TypedSelector.subtype for enqueueing
- Selector selector = new Selector.fromElement(element);
- registerSelectorUse(selector);
- if (element.isField) {
- Selector selector =
- new Selector.setter(element.name, element.library);
- registerInvokedSetter(selector);
- }
- }
- }
- }
-
- /// Enqeue the member [element] if it is required for reflection.
- ///
- /// [enclosingWasIncluded] provides a hint whether the enclosing element was
- /// needed for reflection.
- void enqueueReflectiveElementsInClass(ClassElement cls,
- Iterable<ClassElement> recents,
- bool enclosingWasIncluded) {
- if (cls.library.isInternalLibrary || cls.isInjected) return;
- bool includeClass = shouldIncludeElementDueToMirrors(cls,
- includedEnclosing: enclosingWasIncluded);
- if (includeClass) {
- logEnqueueReflectiveAction(cls, "register");
- ClassElement decl = cls.declaration;
- registerInstantiatedClass(decl, compiler.mirrorDependencies,
- mirrorUsage: true);
- }
- // If the class is never instantiated, we know nothing of it can possibly
- // be reflected upon.
- // TODO(herhut): Add a warning if a mirrors annotation cannot hit.
- if (recents.contains(cls.declaration)) {
- logEnqueueReflectiveAction(cls, "members");
- cls.constructors.forEach((Element element) {
- enqueueReflectiveConstructor(element, includeClass);
- });
- cls.forEachClassMember((Member member) {
- enqueueReflectiveMember(member.element, includeClass);
- });
- }
- }
-
- /// Enqeue special classes that might not be visible by normal means or that
- /// would not normally be enqueued:
- ///
- /// [Closure] is treated specially as it is the superclass of all closures.
- /// Although it is in an internal library, we mark it as reflectable. Note
- /// that none of its methods are reflectable, unless reflectable by
- /// inheritance.
- void enqueueReflectiveSpecialClasses() {
- Iterable<ClassElement> classes =
- compiler.backend.classesRequiredForReflection;
- for (ClassElement cls in classes) {
- if (compiler.backend.referencedFromMirrorSystem(cls)) {
- logEnqueueReflectiveAction(cls);
- registerInstantiatedClass(cls, compiler.mirrorDependencies,
- mirrorUsage: true);
- }
- }
- }
-
- /// Enqeue all local members of the library [lib] if they are required for
- /// reflection.
- void enqueueReflectiveElementsInLibrary(LibraryElement lib,
- Iterable<ClassElement> recents) {
- bool includeLibrary = shouldIncludeElementDueToMirrors(lib,
- includedEnclosing: false);
- lib.forEachLocalMember((Element member) {
- if (member.isClass) {
- enqueueReflectiveElementsInClass(member, recents, includeLibrary);
- } else {
- enqueueReflectiveMember(member, includeLibrary);
- }
- });
- }
-
- /// Enqueue all elements that are matched by the mirrors used
- /// annotation or, in lack thereof, all elements.
- void enqueueReflectiveElements(Iterable<ClassElement> recents) {
- if (!hasEnqueuedReflectiveElements) {
- logEnqueueReflectiveAction("!START enqueueAll");
- // First round of enqueuing, visit everything that is visible to
- // also pick up static top levels, etc.
- // Also, during the first round, consider all classes that have been seen
- // as recently seen, as we do not know how many rounds of resolution might
- // have run before tree shaking is disabled and thus everything is
- // enqueued.
- recents = _processedClasses.toSet();
- compiler.log('Enqueuing everything');
- for (LibraryElement lib in compiler.libraryLoader.libraries) {
- enqueueReflectiveElementsInLibrary(lib, recents);
- }
- enqueueReflectiveSpecialClasses();
- hasEnqueuedReflectiveElements = true;
- hasEnqueuedReflectiveStaticFields = true;
- logEnqueueReflectiveAction("!DONE enqueueAll");
- } else if (recents.isNotEmpty) {
- // Keep looking at new classes until fixpoint is reached.
- logEnqueueReflectiveAction("!START enqueueRecents");
- recents.forEach((ClassElement cls) {
- enqueueReflectiveElementsInClass(cls, recents,
- shouldIncludeElementDueToMirrors(cls.library,
- includedEnclosing: false));
- });
- logEnqueueReflectiveAction("!DONE enqueueRecents");
- }
- }
-
- /// Enqueue the static fields that have been marked as used by reflective
- /// usage through `MirrorsUsed`.
- void enqueueReflectiveStaticFields(Iterable<Element> elements) {
- if (hasEnqueuedReflectiveStaticFields) return;
- hasEnqueuedReflectiveStaticFields = true;
- for (Element element in elements) {
- enqueueReflectiveMember(element, true);
- }
- }
-
- void processSet(
- Map<String, Set<Element>> map,
- String memberName,
- bool f(Element e)) {
- Set<Element> members = map[memberName];
- if (members == null) return;
- // [f] might add elements to [: map[memberName] :] during the loop below
- // so we create a new list for [: map[memberName] :] and prepend the
- // [remaining] members after the loop.
- map[memberName] = new Set<Element>();
- Set<Element> remaining = new Set<Element>();
- for (Element member in members) {
- if (!f(member)) remaining.add(member);
- }
- map[memberName].addAll(remaining);
- }
-
- processInstanceMembers(String n, bool f(Element e)) {
- processSet(instanceMembersByName, n, f);
- }
-
- processInstanceFunctions(String n, bool f(Element e)) {
- processSet(instanceFunctionsByName, n, f);
- }
-
- void handleUnseenSelector(String methodName, Selector selector) {
- processInstanceMembers(methodName, (Element member) {
- if (selector.appliesUnnamed(member, compiler.world)) {
- if (member.isFunction && selector.isGetter) {
- registerClosurizedMember(member, compiler.globalDependencies);
- }
- if (member.isField && member.enclosingClass.isNative) {
- if (selector.isGetter || selector.isCall) {
- nativeEnqueuer.registerFieldLoad(member);
- // We have to also handle storing to the field because we only get
- // one look at each member and there might be a store we have not
- // seen yet.
- // TODO(sra): Process fields for storing separately.
- nativeEnqueuer.registerFieldStore(member);
- } else {
- assert(selector.isSetter);
- nativeEnqueuer.registerFieldStore(member);
- // We have to also handle loading from the field because we only get
- // one look at each member and there might be a load we have not
- // seen yet.
- // TODO(sra): Process fields for storing separately.
- nativeEnqueuer.registerFieldLoad(member);
- }
- }
- addToWorkList(member);
- return true;
- }
- return false;
- });
- if (selector.isGetter) {
- processInstanceFunctions(methodName, (Element member) {
- if (selector.appliesUnnamed(member, compiler.world)) {
- registerClosurizedMember(member, compiler.globalDependencies);
- return true;
- }
- return false;
- });
- }
- }
-
- /**
- * Documentation wanted -- johnniwinther
- *
- * Invariant: [element] must be a declaration element.
- */
- void registerStaticUse(Element element) {
- if (element == null) return;
- assert(invariant(element, element.isDeclaration));
- addToWorkList(element);
- compiler.backend.registerStaticUse(element, this);
- }
-
- void registerGetOfStaticFunction(FunctionElement element) {
- registerStaticUse(element);
- compiler.backend.registerGetOfStaticFunction(this);
- universe.staticFunctionsNeedingGetter.add(element);
- }
-
- void registerDynamicInvocation(Selector selector) {
- assert(selector != null);
- registerInvocation(selector);
- }
-
- void registerSelectorUse(Selector selector) {
- if (selector.isGetter) {
- registerInvokedGetter(selector);
- } else if (selector.isSetter) {
- registerInvokedSetter(selector);
- } else {
- registerInvocation(selector);
- }
- }
-
- void registerDynamicGetter(Selector selector) {
- registerInvokedGetter(selector);
- }
-
- void registerDynamicSetter(Selector selector) {
- registerInvokedSetter(selector);
- }
-
- void registerGetterForSuperMethod(Element element) {
- universe.methodsNeedingSuperGetter.add(element);
- }
-
- void registerFieldGetter(Element element) {
- universe.fieldGetters.add(element);
- }
-
- void registerFieldSetter(Element element) {
- universe.fieldSetters.add(element);
- }
-
- void registerIsCheck(DartType type, Registry registry) {
- 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.
- assert(type.kind != TypeKind.TYPE_VARIABLE ||
- !type.element.enclosingElement.isTypedef);
- }
-
- /**
- * If a factory constructor is used with type arguments, we lose track
- * which arguments could be used to create instances of classes that use their
- * type variables as expressions, so we have to remember if we saw such a use.
- */
- void registerFactoryWithTypeArguments(Registry registry) {
- universe.usingFactoryWithTypeArguments = true;
- }
-
- void registerCallMethodWithFreeTypeVariables(
- Element element,
- Registry registry) {
- compiler.backend.registerCallMethodWithFreeTypeVariables(
- element, this, registry);
- universe.callMethodsWithFreeTypeVariables.add(element);
- }
-
- void registerClosurizedMember(Element element, Registry registry) {
- assert(element.isInstanceMember);
- registerClosureIfFreeTypeVariables(element, registry);
- compiler.backend.registerBoundClosure(this);
- universe.closurizedMembers.add(element);
- }
-
- void registerClosureIfFreeTypeVariables(Element element, Registry registry) {
- if (element.computeType(compiler).containsTypeVariables) {
- compiler.backend.registerClosureWithFreeTypeVariables(
- element, this, registry);
- universe.closuresWithFreeTypeVariables.add(element);
- }
- }
-
- void registerClosure(LocalFunctionElement element, Registry registry) {
- universe.allClosures.add(element);
- registerClosureIfFreeTypeVariables(element, registry);
- }
-
- void forEach(void f(WorkItem work)) {
- do {
- while (queue.isNotEmpty) {
- // TODO(johnniwinther): Find an optimal process order.
- filter.processWorkItem(f, queue.removeLast());
- }
- List recents = recentClasses.toList(growable: false);
- recentClasses.clear();
- if (!onQueueEmpty(recents)) recentClasses.addAll(recents);
- } 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);
- 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);
- }
-}
-
-/// [Enqueuer] which is specific to resolution.
-class ResolutionEnqueuer extends Enqueuer {
- /**
- * Map from declaration elements to the [TreeElements] object holding the
- * resolution mapping for the element implementation.
- *
- * Invariant: Key elements are declaration elements.
- */
- final Set<AstElement> resolvedElements;
-
- final Queue<ResolutionWorkItem> queue;
-
- /**
- * A deferred task queue for the resolution phase which is processed
- * when the resolution queue has been emptied.
- */
- final Queue<DeferredTask> deferredTaskQueue;
-
- ResolutionEnqueuer(Compiler compiler,
- ItemCompilationContext itemCompilationContextCreator())
- : super('resolution enqueuer', compiler, itemCompilationContextCreator),
- resolvedElements = new Set<AstElement>(),
- queue = new Queue<ResolutionWorkItem>(),
- deferredTaskQueue = new Queue<DeferredTask>();
-
- bool get isResolutionQueue => true;
-
- bool isProcessed(Element member) => resolvedElements.contains(member);
-
- /// Returns `true` if [element] has been processed by the resolution enqueuer.
- bool hasBeenResolved(Element element) {
- return resolvedElements.contains(element.analyzableElement.declaration);
- }
-
- /// Registers [element] as resolved for the resolution enqueuer.
- void registerResolvedElement(AstElement element) {
- resolvedElements.add(element);
- }
-
- /**
- * Decides whether an element should be included to satisfy requirements
- * of the mirror system.
- *
- * During resolution, we have to resort to matching elements against the
- * [MirrorsUsed] pattern, as we do not have a complete picture of the world,
- * yet.
- */
- bool shouldIncludeElementDueToMirrors(Element element,
- {bool includedEnclosing}) {
- return includedEnclosing || compiler.backend.requiredByMirrorSystem(element);
- }
-
- bool internalAddToWorkList(Element element) {
- assert(invariant(element, element is AnalyzableElement,
- message: 'Element $element is not analyzable.'));
- if (hasBeenResolved(element)) return false;
- if (queueIsClosed) {
- throw new SpannableAssertionFailure(element,
- "Resolution work list is closed. Trying to add $element.");
- }
-
- compiler.world.registerUsedElement(element);
-
- queue.add(new ResolutionWorkItem(element, itemCompilationContextCreator()));
-
- // 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)) {
- String uri = library.canonicalUri.toString();
- if (uri == 'dart:isolate') {
- enableIsolateSupport();
- } else if (uri == 'dart:async') {
- if (element.name == '_createTimer' ||
- element.name == '_createPeriodicTimer') {
- // The [:Timer:] class uses the event queue of the isolate
- // library, so we make sure that event queue is generated.
- enableIsolateSupport();
- }
- }
- }
-
- if (element.isGetter && element.name == Compiler.RUNTIME_TYPE) {
- // Enable runtime type support if we discover a getter called runtimeType.
- // 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;
- // TODO(ahe): Record precise dependency here.
- compiler.backend.registerRuntimeType(this, compiler.globalDependencies);
- } else if (element == compiler.functionApplyMethod) {
- compiler.enabledFunctionApply = true;
- }
-
- nativeEnqueuer.registerElement(element);
- return true;
- }
-
- void enableIsolateSupport() {
- compiler.hasIsolateSupport = true;
- compiler.backend.enableIsolateSupport(this);
- }
-
- void enableNoSuchMethod(Element element) {
- if (compiler.enabledNoSuchMethod) return;
- if (compiler.backend.isDefaultNoSuchMethodImplementation(element)) return;
-
- compiler.enabledNoSuchMethod = true;
- compiler.backend.enableNoSuchMethod(element, this);
- }
-
- /**
- * Adds an action to the deferred task queue.
- *
- * The action is performed the next time the resolution queue has been
- * emptied.
- *
- * The queue is processed in FIFO order.
- */
- void addDeferredAction(Element element, DeferredAction action) {
- if (queueIsClosed) {
- throw new SpannableAssertionFailure(element,
- "Resolution work list is closed. "
- "Trying to add deferred action for $element");
- }
- deferredTaskQueue.add(new DeferredTask(element, action));
- }
-
- bool onQueueEmpty(Iterable<ClassElement> recentClasses) {
- emptyDeferredTaskQueue();
- return super.onQueueEmpty(recentClasses);
- }
-
- void emptyDeferredTaskQueue() {
- while (!deferredTaskQueue.isEmpty) {
- DeferredTask task = deferredTaskQueue.removeFirst();
- compiler.withCurrentElement(task.element, task.action);
- }
- }
-
- void registerJsCall(Send node, ResolverVisitor resolver) {
- nativeEnqueuer.registerJsCall(node, resolver);
- }
-
- void registerJsEmbeddedGlobalCall(Send node, ResolverVisitor resolver) {
- nativeEnqueuer.registerJsEmbeddedGlobalCall(node, resolver);
- }
-
- void _logSpecificSummary(log(message)) {
- log('Resolved ${resolvedElements.length} elements.');
- }
-
- void forgetElement(Element element) {
- super.forgetElement(element);
- resolvedElements.remove(element);
- }
-}
-
-/// [Enqueuer] which is specific to code generation.
-class CodegenEnqueuer extends Enqueuer {
- final Queue<CodegenWorkItem> queue;
- final Map<Element, js.Expression> generatedCode =
- new Map<Element, js.Expression>();
-
- final Set<Element> newlyEnqueuedElements;
-
- CodegenEnqueuer(Compiler compiler,
- ItemCompilationContext itemCompilationContextCreator())
- : queue = new Queue<CodegenWorkItem>(),
- newlyEnqueuedElements = compiler.cacheStrategy.newSet(),
- super('codegen enqueuer', compiler, itemCompilationContextCreator);
-
- bool isProcessed(Element member) =>
- member.isAbstract || generatedCode.containsKey(member);
-
- /**
- * Decides whether an element should be included to satisfy requirements
- * of the mirror system.
- *
- * For code generation, we rely on the precomputed set of elements that takes
- * subtyping constraints into account.
- */
- bool shouldIncludeElementDueToMirrors(Element element,
- {bool includedEnclosing}) {
- return compiler.backend.isAccessibleByReflection(element);
- }
-
- bool internalAddToWorkList(Element element) {
- // Don't generate code for foreign elements.
- if (element.isForeign(compiler.backend)) return false;
-
- // Codegen inlines field initializers. It only needs to generate
- // code for checked setters.
- if (element.isField && element.isInstanceMember) {
- if (!compiler.enableTypeAssertions
- || element.enclosingElement.isClosure) {
- return false;
- }
- }
-
- if (compiler.hasIncrementalSupport && !isProcessed(element)) {
- newlyEnqueuedElements.add(element);
- }
-
- if (queueIsClosed) {
- throw new SpannableAssertionFailure(element,
- "Codegen work list is closed. Trying to add $element");
- }
- CodegenWorkItem workItem = new CodegenWorkItem(
- element, itemCompilationContextCreator());
- queue.add(workItem);
- return true;
- }
-
- void _logSpecificSummary(log(message)) {
- log('Compiled ${generatedCode.length} methods.');
- }
-
- void forgetElement(Element element) {
- super.forgetElement(element);
- generatedCode.remove(element);
- if (element is MemberElement) {
- for (Element closure in element.nestedClosures) {
- generatedCode.remove(closure);
- removeFromSet(instanceMembersByName, closure);
- removeFromSet(instanceFunctionsByName, closure);
- }
- }
- }
-}
-
-/// Parameterizes filtering of which work items are enqueued.
-class QueueFilter {
- bool checkNoEnqueuedInvokedInstanceMethods(Enqueuer enqueuer) {
- enqueuer.task.measure(() {
- // Run through the classes and see if we need to compile methods.
- for (ClassElement classElement in
- enqueuer.universe.directlyInstantiatedClasses) {
- for (ClassElement currentClass = classElement;
- currentClass != null;
- currentClass = currentClass.superclass) {
- enqueuer.processInstantiatedClassMembers(currentClass);
- }
- }
- });
- return true;
- }
-
- 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);
-}
« no previous file with comments | « pkg/compiler/lib/src/elements/visitor.dart ('k') | pkg/compiler/lib/src/filenames.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698