Linter Demo Errors: 5Warnings: 20File: /home/fstrocco/Dart/dart/benchmark/compiler/lib/src/enqueue.dart // 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> instanceMembersByName = new Map>(); final Map> instanceFunctionsByName = new Map>(); final Set _processedClasses = new Set(); Set recentClasses = new Setlet(); 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 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); compiler.backend.registerInstantiatedType(type, registry); }); } 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) { registerNoSuchMethod(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()) .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()) .add(member); } void registerNoSuchMethod(Element noSuchMethod); 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 supertypes = cls.allSupertypes; !supertypes.isEmpty; supertypes = supertypes.tail) { processClass(supertypes.head.element); } }); } void registerNewSelector(Selector selector, Map> selectorsMap) { String name = selector.name; Set selectors = selectorsMap.putIfAbsent(name, () => new Setlet()); 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 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 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 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 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 elements) { if (hasEnqueuedReflectiveStaticFields) return; hasEnqueuedReflectiveStaticFields = true; for (Element element in elements) { enqueueReflectiveMember(element, true); } } void processSet( Map> map, String memberName, bool f(Element e)) { Set 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(); Set remaining = new Set(); 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); } 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 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 resolvedElements; final Queue queue; /** * A deferred task queue for the resolution phase which is processed * when the resolution queue has been emptied. */ final Queue deferredTaskQueue; ResolutionEnqueuer(Compiler compiler, ItemCompilationContext itemCompilationContextCreator()) : super('resolution enqueuer', compiler, itemCompilationContextCreator), resolvedElements = new Set(), queue = new Queue(), deferredTaskQueue = new Queue(); 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) { if (element.isErroneous) return false; 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 registerNoSuchMethod(Element element) { compiler.backend.registerNoSuchMethod(element); } void enableIsolateSupport() { compiler.hasIsolateSupport = true; compiler.backend.enableIsolateSupport(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 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 queue; final Map generatedCode = new Map(); final Set newlyEnqueuedElements; final Set newlySeenSelectors; bool enabledNoSuchMethod = false; CodegenEnqueuer(Compiler compiler, ItemCompilationContext itemCompilationContextCreator()) : queue = new Queue(), newlyEnqueuedElements = compiler.cacheStrategy.newSet(), newlySeenSelectors = 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 registerNoSuchMethod(Element element) { if (!enabledNoSuchMethod && compiler.backend.enabledNoSuchMethod) { compiler.backend.enableNoSuchMethod(this); enabledNoSuchMethod = 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); } } } void handleUnseenSelector(String methodName, Selector selector) { if (compiler.hasIncrementalSupport) { newlySeenSelectors.add(selector); } super.handleUnseenSelector(methodName, selector); } } /// 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> map, Element element) { Set set = map[element.name]; if (set == null) return; set.remove(element); }