[dart2js] Delete ImpactStrategy.

This strategy is no longer necessary with the single frontend, and
inlining all the logic makes the code much easier to follow.

Change-Id: I73995aa6249b52a932dbfb2d459c2d6633a620d2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/232029
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Joshua Litt <joshualitt@google.com>
This commit is contained in:
Joshua Litt 2022-02-11 17:45:07 +00:00 committed by Commit Bot
parent d5269652d8
commit 95a924d289
9 changed files with 53 additions and 179 deletions

View file

@ -40,7 +40,7 @@ import 'inferrer/types.dart'
show GlobalTypeInferenceResults, GlobalTypeInferenceTask;
import 'io/source_information.dart' show SourceInformation;
import 'ir/modular.dart';
import 'js_backend/backend.dart' show CodegenInputs, JavaScriptImpactStrategy;
import 'js_backend/backend.dart' show CodegenInputs;
import 'js_backend/inferred_data.dart';
import 'js_model/js_strategy.dart';
import 'js_model/js_world.dart';
@ -57,8 +57,7 @@ import 'ssa/nodes.dart' show HInstruction;
import 'universe/selector.dart' show Selector;
import 'universe/codegen_world_builder.dart';
import 'universe/resolution_world_builder.dart';
import 'universe/world_impact.dart'
show ImpactStrategy, WorldImpact, WorldImpactBuilderImpl;
import 'universe/world_impact.dart' show WorldImpact, WorldImpactBuilderImpl;
import 'world.dart' show JClosedWorld, KClosedWorld;
typedef MakeReporterFunction = CompilerDiagnosticReporter Function(
@ -74,8 +73,6 @@ abstract class Compiler {
CompilerDiagnosticReporter _reporter;
Map<Entity, WorldImpact> _impactCache;
ImpactStrategy impactStrategy = const ImpactStrategy();
/// Options provided from command-line arguments.
final CompilerOptions options;
@ -434,10 +431,6 @@ abstract class Compiler {
// this until after the resolution queue is processed.
deferredLoadTask.beforeResolution(rootLibraryUri, libraries);
impactStrategy = JavaScriptImpactStrategy(dumpInfoTask,
supportDeferredLoad: deferredLoadTask.isProgramSplit,
supportDumpInfo: options.dumpInfo);
phase = PHASE_RESOLVING;
resolutionEnqueuer.applyImpact(mainImpact);
if (options.showInternalProgress) reporter.log('Computing closed world');
@ -466,8 +459,6 @@ abstract class Compiler {
_userCodeLocations
.addAll(result.moduleLibraries.map((module) => CodeLocation(module)));
selfTask.measureSubtask('runModularAnalysis', () {
impactStrategy = JavaScriptImpactStrategy(dumpInfoTask,
supportDeferredLoad: true, supportDumpInfo: true);
var included = result.moduleLibraries.toSet();
var elementMap = (frontendStrategy as KernelFrontendStrategy).elementMap;
var moduleData = computeModuleData(result.component, included, options,
@ -607,8 +598,7 @@ abstract class Compiler {
work.element,
() => selfTask.measureSubtask("applyImpact", () {
enqueuer.applyImpact(
selfTask.measureSubtask("work.run", () => work.run()),
impactSource: work.element);
selfTask.measureSubtask("work.run", () => work.run()));
}));
});
});
@ -619,7 +609,6 @@ abstract class Compiler {
{void onProgress(Enqueuer enqueuer)}) {
selfTask.measureSubtask("processQueue", () {
enqueuer.open(
impactStrategy,
mainMethod,
elementEnvironment.libraries
.map((LibraryEntity library) => library.canonicalUri));

View file

@ -286,7 +286,6 @@ import '../constants/values.dart' show ConstantValue;
import '../elements/types.dart';
import '../elements/entities.dart';
import '../kernel/element_map.dart';
import '../universe/world_impact.dart' show ImpactUseCase;
import '../util/util.dart' show makeUnique;
import '../world.dart' show KClosedWorld;
@ -325,8 +324,6 @@ class DeferredLoadTask extends CompilerTask {
/// Will be `true` if the program contains deferred libraries.
bool isProgramSplit = false;
static const ImpactUseCase IMPACT_USE = ImpactUseCase('Deferred load');
/// A cache of the result of calling `computeImportDeferName` on the keys of
/// this map.
final Map<ImportEntity, String> importDeferName = {};

View file

@ -5,7 +5,6 @@
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/type_environment.dart' as ir;
import 'deferred_load.dart';
import 'entity_data.dart';
import '../common.dart';
@ -19,8 +18,7 @@ import '../ir/util.dart';
import '../kernel/kelements.dart' show KLocalFunction;
import '../kernel/element_map.dart';
import '../universe/use.dart';
import '../universe/world_impact.dart'
show ImpactStrategy, WorldImpact, WorldImpactVisitorImpl;
import '../universe/world_impact.dart' show WorldImpact, WorldImpactVisitorImpl;
import '../world.dart' show KClosedWorld;
/// [EntityDataInfo] is meta data about [EntityData] for a given compilation
@ -63,7 +61,6 @@ class EntityDataInfoBuilder {
this.closedWorld, this.elementMap, this.compiler, this.registry);
Map<Entity, WorldImpact> get impactCache => compiler.impactCache;
ImpactStrategy get impactStrategy => compiler.impactStrategy;
KElementEnvironment get elementEnvironment =>
compiler.frontendStrategy.elementEnvironment;
CommonElements get commonElements => compiler.frontendStrategy.commonElements;
@ -242,20 +239,16 @@ class EntityDataInfoBuilder {
/// Extract any dependencies that are known from the impact of [element].
void _addDependenciesFromImpact(MemberEntity element) {
WorldImpact worldImpact = impactCache[element];
impactStrategy.visitImpact(
element,
worldImpact,
WorldImpactVisitorImpl(
visitStaticUse: (MemberEntity member, StaticUse staticUse) {
_addFromStaticUse(element, staticUse);
}, visitTypeUse: (MemberEntity member, TypeUse typeUse) {
_addFromTypeUse(element, typeUse);
}, visitDynamicUse: (MemberEntity member, DynamicUse dynamicUse) {
// TODO(johnniwinther): Use rti need data to skip unneeded type
// arguments.
addTypeListDependencies(dynamicUse.typeArguments);
}),
DeferredLoadTask.IMPACT_USE);
worldImpact.apply(WorldImpactVisitorImpl(
visitStaticUse: (MemberEntity member, StaticUse staticUse) {
_addFromStaticUse(element, staticUse);
}, visitTypeUse: (MemberEntity member, TypeUse typeUse) {
_addFromTypeUse(element, typeUse);
}, visitDynamicUse: (MemberEntity member, DynamicUse dynamicUse) {
// TODO(johnniwinther): Use rti need data to skip unneeded type
// arguments.
addTypeListDependencies(dynamicUse.typeArguments);
}));
}
}

View file

@ -27,8 +27,7 @@ import 'inferrer/types.dart'
import 'js/js.dart' as jsAst;
import 'js_backend/field_analysis.dart';
import 'universe/codegen_world_builder.dart';
import 'universe/world_impact.dart'
show ImpactUseCase, WorldImpact, WorldImpactVisitorImpl;
import 'universe/world_impact.dart' show WorldImpact, WorldImpactVisitorImpl;
import 'util/sink_adapter.dart';
import 'world.dart' show JClosedWorld;
@ -427,7 +426,6 @@ abstract class InfoReporter {
}
class DumpInfoTask extends CompilerTask implements InfoReporter {
static const ImpactUseCase IMPACT_USE = ImpactUseCase('Dump info');
final Compiler compiler;
final bool useBinaryFormat;
@ -493,20 +491,17 @@ class DumpInfoTask extends CompilerTask implements InfoReporter {
if (impact == null) return const <Selection>[];
var selections = <Selection>[];
compiler.impactStrategy.visitImpact(
entity,
impact,
WorldImpactVisitorImpl(visitDynamicUse: (member, dynamicUse) {
AbstractValue mask = dynamicUse.receiverConstraint;
selections.addAll(closedWorld
// TODO(het): Handle `call` on `Closure` through
// `world.includesClosureCall`.
.locateMembers(dynamicUse.selector, mask)
.map((MemberEntity e) => Selection(e, mask)));
}, visitStaticUse: (member, staticUse) {
selections.add(Selection(staticUse.element, null));
}),
IMPACT_USE);
impact.apply(WorldImpactVisitorImpl(visitDynamicUse: (member, dynamicUse) {
AbstractValue mask = dynamicUse.receiverConstraint;
selections.addAll(closedWorld
// TODO(het): Handle `call` on `Closure` through
// `world.includesClosureCall`.
.locateMembers(dynamicUse.selector, mask)
.map((MemberEntity e) => Selection(e, mask)));
}, visitStaticUse: (member, staticUse) {
selections.add(Selection(staticUse.element, null));
}));
unregisterImpact(entity);
return selections;
}

View file

@ -30,8 +30,7 @@ import 'universe/use.dart'
StaticUseKind,
TypeUse,
TypeUseKind;
import 'universe/world_impact.dart'
show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor;
import 'universe/world_impact.dart' show WorldImpact, WorldImpactVisitor;
import 'util/enumset.dart';
import 'util/util.dart' show Setlet;
import 'world.dart' show JClosedWorld;
@ -144,6 +143,7 @@ abstract class Enqueuer {
static bool skipEnqueuerCheckForTesting = false;
WorldBuilder get worldBuilder;
WorldImpactVisitor get impactVisitor;
/// Returns [:true:] if this enqueuer is the resolution enqueuer.
bool get isResolutionQueue;
@ -152,14 +152,14 @@ abstract class Enqueuer {
bool get queueIsEmpty;
ImpactUseCase get impactUse;
void forEach(void f(WorkItem work));
/// Apply the [worldImpact] to this enqueuer. If the [impactSource] is
/// provided the impact strategy will remove it from the element impact cache,
/// if it is no longer needed.
void applyImpact(WorldImpact worldImpact, {var impactSource});
/// Apply the [worldImpact] to this enqueuer.
void applyImpact(WorldImpact worldImpact) {
if (worldImpact.isEmpty) return;
worldImpact.apply(impactVisitor);
}
bool checkNoEnqueuedInvokedInstanceMethods(
ElementEnvironment elementEnvironment);
@ -179,21 +179,11 @@ abstract class Enqueuer {
void processConstantUse(ConstantUse constantUse);
EnqueuerListener get listener;
// TODO(johnniwinther): Initialize [_impactStrategy] to `null`.
ImpactStrategy _impactStrategy = const ImpactStrategy();
ImpactStrategy get impactStrategy => _impactStrategy;
void open(ImpactStrategy impactStrategy, FunctionEntity mainMethod,
Iterable<Uri> libraries) {
_impactStrategy = impactStrategy;
void open(FunctionEntity mainMethod, Iterable<Uri> libraries) {
listener.onQueueOpen(this, mainMethod, libraries);
}
void close() {
// TODO(johnniwinther): Set [_impactStrategy] to `null` and [queueIsClosed]
// to `true` here.
_impactStrategy = const ImpactStrategy();
listener.onQueueClosed();
}
@ -216,8 +206,6 @@ abstract class Enqueuer {
/// [Enqueuer] which is specific to resolution.
class ResolutionEnqueuer extends Enqueuer {
static const ImpactUseCase IMPACT_USE = ImpactUseCase('ResolutionEnqueuer');
@override
final CompilerTask task;
final String name;
@ -234,7 +222,8 @@ class ResolutionEnqueuer extends Enqueuer {
@override
bool queueIsClosed = false;
WorldImpactVisitor _impactVisitor;
@override
WorldImpactVisitor impactVisitor;
final Queue<WorkItem> _queue = Queue<WorkItem>();
@ -245,7 +234,7 @@ class ResolutionEnqueuer extends Enqueuer {
ResolutionEnqueuer(this.task, this._reporter, this.listener,
this._worldBuilder, this._workItemBuilder, this._annotationsData,
[this.name = 'resolution enqueuer']) {
_impactVisitor = EnqueuerImpactVisitor(this);
impactVisitor = EnqueuerImpactVisitor(this);
}
@override
@ -264,13 +253,6 @@ class ResolutionEnqueuer extends Enqueuer {
@override
Iterable<ClassEntity> get processedClasses => _worldBuilder.processedClasses;
@override
void applyImpact(WorldImpact worldImpact, {var impactSource}) {
if (worldImpact.isEmpty) return;
impactStrategy.visitImpact(
impactSource, worldImpact, _impactVisitor, impactUse);
}
void _registerInstantiatedType(InterfaceType type,
{ConstructorEntity constructor,
bool nativeUsage = false,
@ -310,8 +292,7 @@ class ResolutionEnqueuer extends Enqueuer {
_registerClosurizedMember(member);
}
if (useSet.contains(MemberUse.CLOSURIZE_STATIC)) {
applyImpact(listener.registerGetOfStaticFunction(),
impactSource: 'get of static function');
applyImpact(listener.registerGetOfStaticFunction());
}
}
@ -323,12 +304,10 @@ class ResolutionEnqueuer extends Enqueuer {
// We only tell the backend once that [cls] was instantiated, so
// any additional dependencies must be treated as global
// dependencies.
applyImpact(listener.registerInstantiatedClass(cls),
impactSource: 'instantiated class');
applyImpact(listener.registerInstantiatedClass(cls));
}
if (useSet.contains(ClassUse.IMPLEMENTED)) {
applyImpact(listener.registerImplementedClass(cls),
impactSource: 'implemented class');
applyImpact(listener.registerImplementedClass(cls));
}
}
@ -343,8 +322,7 @@ class ResolutionEnqueuer extends Enqueuer {
void processConstantUse(ConstantUse constantUse) {
task.measureSubtask('resolution.constantUse', () {
if (_worldBuilder.registerConstantUse(constantUse)) {
applyImpact(listener.registerUsedConstant(constantUse.value),
impactSource: 'constant use');
applyImpact(listener.registerUsedConstant(constantUse.value));
_recentConstants = true;
}
});
@ -427,8 +405,7 @@ class ResolutionEnqueuer extends Enqueuer {
void _registerClosurizedMember(MemberEntity element) {
assert(element.isInstanceMember);
applyImpact(listener.registerClosurizedMember(element),
impactSource: 'closurized member');
applyImpact(listener.registerClosurizedMember(element));
_worldBuilder.registerClosurizedMember(element);
}
@ -474,9 +451,6 @@ class ResolutionEnqueuer extends Enqueuer {
Iterable<MemberEntity> get processedEntities =>
_worldBuilder.processedMembers;
@override
ImpactUseCase get impactUse => IMPACT_USE;
@override
bool get isResolutionQueue => true;
@ -506,8 +480,7 @@ class ResolutionEnqueuer extends Enqueuer {
entity, "Resolution work list is closed. Trying to add $entity.");
}
applyImpact(listener.registerUsedElement(entity),
impactSource: 'used element');
applyImpact(listener.registerUsedElement(entity));
_worldBuilder.registerUsedElement(entity);
_queue.add(workItem);
}

View file

@ -6,15 +6,10 @@ library js_backend.backend;
import '../common.dart';
import '../common/codegen.dart';
import '../deferred_load/deferred_load.dart' show DeferredLoadTask;
import '../dump_info.dart' show DumpInfoTask;
import '../elements/entities.dart';
import '../enqueue.dart' show ResolutionEnqueuer;
import '../inferrer/types.dart';
import '../js_model/elements.dart';
import '../tracer.dart';
import '../universe/world_impact.dart'
show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor;
import 'annotations.dart';
import 'checked_mode_helpers.dart';
import 'namer.dart';
@ -261,36 +256,6 @@ class FunctionInlineCache {
}
}
class JavaScriptImpactStrategy extends ImpactStrategy {
final DumpInfoTask dumpInfoTask;
final bool supportDeferredLoad;
final bool supportDumpInfo;
JavaScriptImpactStrategy(this.dumpInfoTask,
{this.supportDeferredLoad, this.supportDumpInfo});
@override
void visitImpact(var impactSource, WorldImpact impact,
WorldImpactVisitor visitor, ImpactUseCase impactUse) {
// TODO(johnniwinther): Compute the application strategy once for each use.
if (impactUse == ResolutionEnqueuer.IMPACT_USE) {
if (supportDeferredLoad) {
impact.apply(visitor);
} else {
impact.apply(visitor);
}
} else if (impactUse == DeferredLoadTask.IMPACT_USE) {
impact.apply(visitor);
// Impacts are uncached globally in [onImpactUsed].
} else if (impactUse == DumpInfoTask.IMPACT_USE) {
impact.apply(visitor);
dumpInfoTask.unregisterImpact(impactSource);
} else {
impact.apply(visitor);
}
}
}
/// Interface for resources only used during code generation.
abstract class CodegenInputs {
CheckedModeHelpers get checkedModeHelpers;

View file

@ -24,8 +24,7 @@ import '../universe/use.dart'
StaticUseKind,
TypeUse,
TypeUseKind;
import '../universe/world_impact.dart'
show ImpactUseCase, WorldImpact, WorldImpactVisitor;
import '../universe/world_impact.dart' show WorldImpactVisitor;
import '../util/enumset.dart';
import '../util/util.dart' show Setlet;
@ -45,7 +44,8 @@ class CodegenEnqueuer extends Enqueuer {
final EnqueuerListener listener;
final AnnotationsData _annotationsData;
WorldImpactVisitor _impactVisitor;
@override
WorldImpactVisitor impactVisitor;
final Queue<WorkItem> _queue = Queue<WorkItem>();
@ -56,12 +56,10 @@ class CodegenEnqueuer extends Enqueuer {
// applying additional impacts before re-emptying the queue.
void Function() onEmptyForTesting;
static const ImpactUseCase IMPACT_USE = ImpactUseCase('CodegenEnqueuer');
CodegenEnqueuer(this.task, this._worldBuilder, this._workItemBuilder,
this.listener, this._annotationsData)
: this.name = 'codegen enqueuer' {
_impactVisitor = EnqueuerImpactVisitor(this);
impactVisitor = EnqueuerImpactVisitor(this);
}
@override
@ -97,13 +95,6 @@ class CodegenEnqueuer extends Enqueuer {
_queue.add(workItem);
}
@override
void applyImpact(WorldImpact worldImpact, {var impactSource}) {
if (worldImpact.isEmpty) return;
impactStrategy.visitImpact(
impactSource, worldImpact, _impactVisitor, impactUse);
}
void _registerInstantiatedType(InterfaceType type,
{bool nativeUsage = false}) {
task.measureSubtask('codegen.typeUse', () {
@ -307,9 +298,6 @@ class CodegenEnqueuer extends Enqueuer {
@override
String toString() => 'Enqueuer($name)';
@override
ImpactUseCase get impactUse => IMPACT_USE;
@override
Iterable<MemberEntity> get processedEntities => _processedEntities;

View file

@ -137,18 +137,15 @@ class ResolutionEnqueuerListener extends EnqueuerListener {
void onQueueOpen(
Enqueuer enqueuer, FunctionEntity mainMethod, Iterable<Uri> libraries) {
if (_deferredLoadTask.isProgramSplit) {
enqueuer.applyImpact(_computeDeferredLoadingImpact(),
impactSource: 'deferred load');
enqueuer.applyImpact(_computeDeferredLoadingImpact());
}
enqueuer.applyImpact(_nativeEnqueuer.processNativeClasses(libraries),
impactSource: 'native classes');
enqueuer.applyImpact(_nativeEnqueuer.processNativeClasses(libraries));
if (mainMethod != null) {
enqueuer.applyImpact(_computeMainImpact(mainMethod),
impactSource: 'main impact');
enqueuer.applyImpact(_computeMainImpact(mainMethod));
}
// Elements required by enqueueHelpers are global dependencies
// that are not pulled in by a particular element.
enqueuer.applyImpact(computeHelpersImpact(), impactSource: 'helpers');
enqueuer.applyImpact(computeHelpersImpact());
}
@override
@ -158,8 +155,7 @@ class ResolutionEnqueuerListener extends EnqueuerListener {
//
// Return early if any elements are added to avoid counting the elements as
// due to mirrors.
enqueuer.applyImpact(_customElementsAnalysis.flush(),
impactSource: _customElementsAnalysis);
enqueuer.applyImpact(_customElementsAnalysis.flush());
for (ClassEntity cls in recentClasses) {
MemberEntity element = _elementEnvironment.lookupLocalClassMember(

View file

@ -303,28 +303,6 @@ class TransformedWorldImpact implements WorldImpact, WorldImpactBuilder {
}
}
/// Constant used to denote a specific use of a [WorldImpact].
class ImpactUseCase {
final String name;
const ImpactUseCase(this.name);
@override
String toString() => 'ImpactUseCase($name)';
}
/// Strategy used for processing [WorldImpact] object in various use cases.
class ImpactStrategy {
const ImpactStrategy();
/// Applies [impact] to [visitor] for the [impactUseCase] of [impactSource].
void visitImpact(var impactSource, WorldImpact impact,
WorldImpactVisitor visitor, ImpactUseCase impactUseCase) {
// Apply unconditionally.
impact.apply(visitor);
}
}
/// Visitor used to process the uses of a [WorldImpact].
abstract class WorldImpactVisitor {
void visitStaticUse(MemberEntity member, StaticUse staticUse);