| // 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. | |
| library; | |
| import 'common/elements.dart' show ElementEnvironment; | |
| import 'common/tasks.dart' show CompilerTask; | |
| import 'common/work.dart' show WorkItem; | |
| import 'constants/values.dart'; | |
| import 'elements/entities.dart'; | |
| import 'elements/types.dart'; | |
| import 'universe/use.dart' | |
| show ConditionalUse, ConstantUse, DynamicUse, StaticUse, TypeUse; | |
| import 'universe/world_impact.dart' show WorldImpact; | |
| abstract class EnqueuerListener { | |
| /// Called to instruct to the backend that [type] has been instantiated. | |
| void registerInstantiatedType( | |
| InterfaceType type, { | |
| bool isGlobal = false, | |
| bool nativeUsage = false, | |
| }); | |
| /// Called to notify to the backend that a class is being instantiated. Any | |
| /// backend specific [WorldImpact] of this is returned. | |
| WorldImpact registerInstantiatedClass(ClassEntity cls); | |
| /// Called to notify to the backend that a class is implemented by an | |
| /// instantiated class. Any backend specific [WorldImpact] of this is | |
| /// returned. | |
| WorldImpact registerImplementedClass(ClassEntity cls); | |
| /// Called to register that a static function has been closurized. Any backend | |
| /// specific [WorldImpact] of this is returned. | |
| WorldImpact registerGetOfStaticFunction(); | |
| /// Called to register that [function] has been closurized. Any backend | |
| /// specific [WorldImpact] of this is returned. | |
| WorldImpact registerClosurizedMember(FunctionEntity function); | |
| /// Called to register that [member] is statically known to be used. Any | |
| /// backend specific [WorldImpact] of this is returned. | |
| WorldImpact registerUsedElement(MemberEntity member); | |
| /// Called to register a new conditional impact, [use]. If the conditional | |
| /// impact's condition is satisfied, the returned [WorldImpact] will contain | |
| /// the implied impact. | |
| WorldImpact registerConditionalUse(ConditionalUse use); | |
| /// Called to register that [value] is statically known to be used. Any | |
| /// backend specific [WorldImpact] of this is returned. | |
| WorldImpact registerUsedConstant(ConstantValue value); | |
| void onQueueOpen( | |
| Enqueuer enqueuer, | |
| FunctionEntity? mainMethod, | |
| Iterable<Uri> libraries, | |
| ); | |
| /// Called when [enqueuer]'s queue is empty, but before it is closed. | |
| /// | |
| /// This is used, for example, by the JS backend to enqueue additional | |
| /// elements needed for reflection. [recentClasses] is a collection of | |
| /// all classes seen for the first time by the [enqueuer] since the last call | |
| /// to [onQueueEmpty]. | |
| /// | |
| /// A return value of `true` indicates that [recentClasses] has been | |
| /// processed and its elements do not need to be seen in the next round. When | |
| /// `false` is returned, [onQueueEmpty] will be called again once the | |
| /// resolution queue has drained and [recentClasses] will be a superset of the | |
| /// current value. | |
| /// | |
| /// There is no guarantee that a class is only present once in | |
| /// [recentClasses], but every class seen by the [enqueuer] will be present in | |
| /// [recentClasses] at least once. | |
| bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassEntity> recentClasses); | |
| /// Called when to the queue has been closed. | |
| void onQueueClosed(); | |
| /// Called after the queue has been emptied. | |
| void logSummary(void Function(String message) log); | |
| } | |
| abstract class Enqueuer { | |
| /// If `true` the checking for unenqueued members is skipped. The current | |
| /// implementation registers parameter usages as a side-effect so unit | |
| /// testing of member usage we need to test both with and without the | |
| /// enqueuer check. | |
| // TODO(johnniwinther): [checkEnqueuerConsistency] should not have | |
| // side-effects. | |
| static bool skipEnqueuerCheckForTesting = false; | |
| bool get queueIsClosed; | |
| set queueIsClosed(bool closed); | |
| bool get queueIsEmpty; | |
| void forEach(void Function(WorkItem work) f); | |
| /// Apply the [worldImpact] to this enqueuer. | |
| void applyImpact(WorldImpact worldImpact) { | |
| if (worldImpact.isEmpty) return; | |
| worldImpact.forEachStaticUse(processStaticUse); | |
| worldImpact.forEachDynamicUse((_, use) => processDynamicUse(use)); | |
| worldImpact.forEachTypeUse(processTypeUse); | |
| worldImpact.forEachConstantUse((_, use) => processConstantUse(use)); | |
| worldImpact.forEachConditionalUse((_, use) => processConditionalUse(use)); | |
| } | |
| bool checkNoEnqueuedInvokedInstanceMethods( | |
| ElementEnvironment elementEnvironment, | |
| ); | |
| /// Check the enqueuer queue is empty or fail otherwise. | |
| void checkQueueIsEmpty(); | |
| void logSummary(void Function(String message) log); | |
| Iterable<MemberEntity> get processedEntities; | |
| Iterable<ClassEntity> get directlyInstantiatedClasses; | |
| CompilerTask get task; | |
| void checkClass(ClassEntity cls); | |
| void processStaticUse(MemberEntity? member, StaticUse staticUse); | |
| void processTypeUse(MemberEntity? member, TypeUse typeUse); | |
| void processDynamicUse(DynamicUse dynamicUse); | |
| void processConstantUse(ConstantUse constantUse); | |
| void processConditionalUse(ConditionalUse conditionalUse); | |
| EnqueuerListener get listener; | |
| void open(FunctionEntity? mainMethod, Iterable<Uri> libraries) { | |
| listener.onQueueOpen(this, mainMethod, libraries); | |
| } | |
| void close() { | |
| listener.onQueueClosed(); | |
| } | |
| /// Check enqueuer consistency after the queue has been closed. | |
| bool checkEnqueuerConsistency(ElementEnvironment elementEnvironment) { | |
| task.measureSubtask('resolution.check', () { | |
| // Run through the classes and see if we need to enqueue more methods. | |
| for (ClassEntity classElement in directlyInstantiatedClasses) { | |
| for ( | |
| ClassEntity? currentClass = classElement; | |
| currentClass != null; | |
| currentClass = elementEnvironment.getSuperClass(currentClass) | |
| ) { | |
| checkClass(currentClass); | |
| } | |
| } | |
| }); | |
| return true; | |
| } | |
| } | |
| /// Interface for creating work items for enqueued member entities. | |
| abstract class WorkItemBuilder { | |
| WorkItem? createWorkItem(covariant MemberEntity entity); | |
| } |