9768f74c59
Change-Id: I4fcb759ce8b65a59952506ff83462b92859c13eb Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/262275 Reviewed-by: Nate Biggs <natebiggs@google.com>
146 lines
5.6 KiB
Dart
146 lines
5.6 KiB
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.
|
|
|
|
library dart2js.enqueue;
|
|
|
|
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 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 [element] is statically known to be used. Any
|
|
/// backend specific [WorldImpact] of this is returned.
|
|
WorldImpact registerUsedElement(MemberEntity member);
|
|
|
|
/// 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 log(String message));
|
|
}
|
|
|
|
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 f(WorkItem work));
|
|
|
|
/// 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));
|
|
}
|
|
|
|
bool checkNoEnqueuedInvokedInstanceMethods(
|
|
ElementEnvironment elementEnvironment);
|
|
|
|
/// Check the enqueuer queue is empty or fail otherwise.
|
|
void checkQueueIsEmpty();
|
|
void logSummary(void log(String message));
|
|
|
|
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);
|
|
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);
|
|
}
|