mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 20:51:19 +00:00
[dart2js] Support trimming modular analysis data.
Change-Id: I0e0902813fd71c0bda5de6171487fa0e941f6bad Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/241246 Reviewed-by: Sigmund Cherem <sigmund@google.com> Commit-Queue: Joshua Litt <joshualitt@google.com>
This commit is contained in:
parent
49f10b2ab8
commit
43cfa8cea3
|
@ -246,9 +246,8 @@ class Compiler {
|
||||||
/// Dumps a list of unused [ir.Library]'s in the [KernelResult]. This *must*
|
/// Dumps a list of unused [ir.Library]'s in the [KernelResult]. This *must*
|
||||||
/// be called before [setMainAndTrimComponent], because that method will
|
/// be called before [setMainAndTrimComponent], because that method will
|
||||||
/// discard the unused [ir.Library]s.
|
/// discard the unused [ir.Library]s.
|
||||||
void dumpUnusedLibraries(ir.Component component, List<Uri> libraries) {
|
void dumpUnusedLibraries(ir.Component component, Set<Uri> libraries) {
|
||||||
var usedUris = libraries.toSet();
|
bool isUnused(ir.Library l) => !libraries.contains(l.importUri);
|
||||||
bool isUnused(ir.Library l) => !usedUris.contains(l.importUri);
|
|
||||||
String libraryString(ir.Library library) {
|
String libraryString(ir.Library library) {
|
||||||
return '${library.importUri}(${library.fileUri})';
|
return '${library.importUri}(${library.fileUri})';
|
||||||
}
|
}
|
||||||
|
@ -270,7 +269,7 @@ class Compiler {
|
||||||
|
|
||||||
/// Trims a component down to only the provided library uris.
|
/// Trims a component down to only the provided library uris.
|
||||||
ir.Component trimComponent(
|
ir.Component trimComponent(
|
||||||
ir.Component component, List<Uri> librariesToInclude) {
|
ir.Component component, Set<Uri> librariesToInclude) {
|
||||||
var irLibraryMap = <Uri, ir.Library>{};
|
var irLibraryMap = <Uri, ir.Library>{};
|
||||||
var irLibraries = <ir.Library>[];
|
var irLibraries = <ir.Library>[];
|
||||||
for (var library in component.libraries) {
|
for (var library in component.libraries) {
|
||||||
|
@ -325,11 +324,8 @@ class Compiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JClosedWorld computeClosedWorld(
|
JClosedWorld computeClosedWorld(ir.Component component, ModuleData moduleData,
|
||||||
ir.Component component,
|
Uri rootLibraryUri, Iterable<Uri> libraries) {
|
||||||
List<ModuleData> moduleData,
|
|
||||||
Uri rootLibraryUri,
|
|
||||||
Iterable<Uri> libraries) {
|
|
||||||
frontendStrategy.registerLoadedLibraries(component, libraries);
|
frontendStrategy.registerLoadedLibraries(component, libraries);
|
||||||
frontendStrategy.registerModuleData(moduleData);
|
frontendStrategy.registerModuleData(moduleData);
|
||||||
ResolutionEnqueuer resolutionEnqueuer = frontendStrategy
|
ResolutionEnqueuer resolutionEnqueuer = frontendStrategy
|
||||||
|
@ -402,16 +398,31 @@ class Compiler {
|
||||||
untrimmedComponentForDumpInfo = component;
|
untrimmedComponentForDumpInfo = component;
|
||||||
}
|
}
|
||||||
if (options.cfeOnly) {
|
if (options.cfeOnly) {
|
||||||
|
// [ModuleData] must be deserialized with the full component, i.e.
|
||||||
|
// before trimming.
|
||||||
|
ModuleData moduleData;
|
||||||
|
if (options.modularAnalysisInputs != null) {
|
||||||
|
moduleData = await serializationTask.deserializeModuleData(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<Uri> includedLibraries = output.libraries.toSet();
|
||||||
if (options.fromDill) {
|
if (options.fromDill) {
|
||||||
List<Uri> libraries = output.libraries;
|
|
||||||
if (options.dumpUnusedLibraries) {
|
if (options.dumpUnusedLibraries) {
|
||||||
dumpUnusedLibraries(component, libraries);
|
dumpUnusedLibraries(component, includedLibraries);
|
||||||
}
|
}
|
||||||
if (options.entryUri != null) {
|
if (options.entryUri != null) {
|
||||||
component = trimComponent(component, libraries);
|
component = trimComponent(component, includedLibraries);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (moduleData == null) {
|
||||||
await serializationTask.serializeComponent(component);
|
await serializationTask.serializeComponent(component);
|
||||||
|
} else {
|
||||||
|
// Trim [moduleData] down to only the included libraries.
|
||||||
|
moduleData.impactData
|
||||||
|
.removeWhere((uri, _) => !includedLibraries.contains(uri));
|
||||||
|
await serializationTask.serializeModuleData(
|
||||||
|
moduleData, component, includedLibraries);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return output.withNewComponent(component);
|
return output.withNewComponent(component);
|
||||||
} else {
|
} else {
|
||||||
|
@ -434,7 +445,7 @@ class Compiler {
|
||||||
'runModularAnalysis', () async => modular_analysis.run(input));
|
'runModularAnalysis', () async => modular_analysis.run(input));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<ModuleData>> produceModuleData(load_kernel.Output output) async {
|
Future<ModuleData> produceModuleData(load_kernel.Output output) async {
|
||||||
ir.Component component = output.component;
|
ir.Component component = output.component;
|
||||||
if (options.modularMode) {
|
if (options.modularMode) {
|
||||||
Set<Uri> moduleLibraries = output.moduleLibraries.toSet();
|
Set<Uri> moduleLibraries = output.moduleLibraries.toSet();
|
||||||
|
@ -444,7 +455,7 @@ class Compiler {
|
||||||
serializationTask.serializeModuleData(
|
serializationTask.serializeModuleData(
|
||||||
moduleData, component, moduleLibraries);
|
moduleData, component, moduleLibraries);
|
||||||
}
|
}
|
||||||
return [moduleData];
|
return moduleData;
|
||||||
} else {
|
} else {
|
||||||
return await serializationTask.deserializeModuleData(component);
|
return await serializationTask.deserializeModuleData(component);
|
||||||
}
|
}
|
||||||
|
@ -530,7 +541,7 @@ class Compiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ClosedWorldAndIndices> produceClosedWorld(
|
Future<ClosedWorldAndIndices> produceClosedWorld(
|
||||||
load_kernel.Output output, List<ModuleData> moduleData) async {
|
load_kernel.Output output, ModuleData moduleData) async {
|
||||||
ir.Component component = output.component;
|
ir.Component component = output.component;
|
||||||
ClosedWorldAndIndices closedWorldAndIndices;
|
ClosedWorldAndIndices closedWorldAndIndices;
|
||||||
if (options.readClosedWorldUri == null) {
|
if (options.readClosedWorldUri == null) {
|
||||||
|
@ -626,7 +637,7 @@ class Compiler {
|
||||||
|
|
||||||
// Run modular analysis. This may be null if modular analysis was not
|
// Run modular analysis. This may be null if modular analysis was not
|
||||||
// requested for this pipeline.
|
// requested for this pipeline.
|
||||||
List<ModuleData> moduleData;
|
ModuleData moduleData;
|
||||||
if (options.modularMode || options.hasModularAnalysisInputs) {
|
if (options.modularMode || options.hasModularAnalysisInputs) {
|
||||||
moduleData = await produceModuleData(output);
|
moduleData = await produceModuleData(output);
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,15 +318,13 @@ Future<api.CompilationResult> compile(List<String> argv,
|
||||||
fail("Cannot use ${Flags.writeModularAnalysis} "
|
fail("Cannot use ${Flags.writeModularAnalysis} "
|
||||||
"and write serialized codegen simultaneously.");
|
"and write serialized codegen simultaneously.");
|
||||||
}
|
}
|
||||||
if (writeStrategy == WriteStrategy.toKernel) {
|
|
||||||
fail("Cannot use ${Flags.writeModularAnalysis} "
|
|
||||||
"and run the CFE simultaneously.");
|
|
||||||
}
|
|
||||||
if (argument != Flags.writeModularAnalysis) {
|
if (argument != Flags.writeModularAnalysis) {
|
||||||
writeModularAnalysisUri =
|
writeModularAnalysisUri =
|
||||||
fe.nativeToUri(extractPath(argument, isDirectory: false));
|
fe.nativeToUri(extractPath(argument, isDirectory: false));
|
||||||
}
|
}
|
||||||
writeStrategy = WriteStrategy.toModularAnalysis;
|
writeStrategy = writeStrategy == WriteStrategy.toKernel
|
||||||
|
? WriteStrategy.toKernelWithModularAnalysis
|
||||||
|
: WriteStrategy.toModularAnalysis;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setReadData(String argument) {
|
void setReadData(String argument) {
|
||||||
|
@ -371,10 +369,6 @@ Future<api.CompilationResult> compile(List<String> argv,
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCfeOnly(String argument) {
|
void setCfeOnly(String argument) {
|
||||||
if (writeStrategy == WriteStrategy.toModularAnalysis) {
|
|
||||||
fail("Cannot use ${Flags.cfeOnly} "
|
|
||||||
"and write serialized modular analysis simultaneously.");
|
|
||||||
}
|
|
||||||
if (writeStrategy == WriteStrategy.toClosedWorld) {
|
if (writeStrategy == WriteStrategy.toClosedWorld) {
|
||||||
fail("Cannot use ${Flags.cfeOnly} "
|
fail("Cannot use ${Flags.cfeOnly} "
|
||||||
"and write serialized closed world simultaneously.");
|
"and write serialized closed world simultaneously.");
|
||||||
|
@ -387,7 +381,9 @@ Future<api.CompilationResult> compile(List<String> argv,
|
||||||
fail("Cannot use ${Flags.cfeOnly} "
|
fail("Cannot use ${Flags.cfeOnly} "
|
||||||
"and write serialized codegen simultaneously.");
|
"and write serialized codegen simultaneously.");
|
||||||
}
|
}
|
||||||
writeStrategy = WriteStrategy.toKernel;
|
writeStrategy = writeStrategy == WriteStrategy.toModularAnalysis
|
||||||
|
? WriteStrategy.toKernelWithModularAnalysis
|
||||||
|
: WriteStrategy.toKernel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setReadCodegen(String argument) {
|
void setReadCodegen(String argument) {
|
||||||
|
@ -825,6 +821,12 @@ Future<api.CompilationResult> compile(List<String> argv,
|
||||||
"and read serialized codegen simultaneously.");
|
"and read serialized codegen simultaneously.");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case WriteStrategy.toKernelWithModularAnalysis:
|
||||||
|
out ??= Uri.base.resolve('out.dill');
|
||||||
|
options.add(Flags.cfeOnly);
|
||||||
|
writeModularAnalysisUri ??= Uri.base.resolve('$out.mdata');
|
||||||
|
options.add('${Flags.writeModularAnalysis}=${writeModularAnalysisUri}');
|
||||||
|
break;
|
||||||
case WriteStrategy.toModularAnalysis:
|
case WriteStrategy.toModularAnalysis:
|
||||||
writeModularAnalysisUri ??= Uri.base.resolve('$out.mdata');
|
writeModularAnalysisUri ??= Uri.base.resolve('$out.mdata');
|
||||||
options.add('${Flags.writeModularAnalysis}=${writeModularAnalysisUri}');
|
options.add('${Flags.writeModularAnalysis}=${writeModularAnalysisUri}');
|
||||||
|
@ -1007,6 +1009,15 @@ Future<api.CompilationResult> compile(List<String> argv,
|
||||||
String output = fe.relativizeUri(Uri.base, out, Platform.isWindows);
|
String output = fe.relativizeUri(Uri.base, out, Platform.isWindows);
|
||||||
summary += 'compiled to dill: ${output}.';
|
summary += 'compiled to dill: ${output}.';
|
||||||
break;
|
break;
|
||||||
|
case WriteStrategy.toKernelWithModularAnalysis:
|
||||||
|
processName = 'Compiled';
|
||||||
|
outputName = 'kernel and bytes data';
|
||||||
|
outputSize = outputProvider.totalDataWritten;
|
||||||
|
String output = fe.relativizeUri(Uri.base, out, Platform.isWindows);
|
||||||
|
String dataOutput = fe.relativizeUri(
|
||||||
|
Uri.base, writeModularAnalysisUri, Platform.isWindows);
|
||||||
|
summary += 'compiled to dill and data: ${output} and ${dataOutput}.';
|
||||||
|
break;
|
||||||
case WriteStrategy.toModularAnalysis:
|
case WriteStrategy.toModularAnalysis:
|
||||||
processName = 'Serialized';
|
processName = 'Serialized';
|
||||||
outputName = 'bytes data';
|
outputName = 'bytes data';
|
||||||
|
@ -1547,6 +1558,7 @@ enum ReadStrategy {
|
||||||
|
|
||||||
enum WriteStrategy {
|
enum WriteStrategy {
|
||||||
toKernel,
|
toKernel,
|
||||||
|
toKernelWithModularAnalysis,
|
||||||
toModularAnalysis,
|
toModularAnalysis,
|
||||||
toClosedWorld,
|
toClosedWorld,
|
||||||
toData,
|
toData,
|
||||||
|
|
|
@ -46,27 +46,45 @@ abstract class ModularStrategy {
|
||||||
ir.Member node, EnumSet<PragmaAnnotation> pragmaAnnotations);
|
ir.Member node, EnumSet<PragmaAnnotation> pragmaAnnotations);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data computed for an entire compilation module.
|
/// [ModuleData] is the data computed modularly, i.e. modularly computed impact
|
||||||
|
/// data. Currently, we aggregate this data when computing the closed world, so it
|
||||||
|
/// reflects all of the modularly computed data across the entire program.
|
||||||
class ModuleData {
|
class ModuleData {
|
||||||
static const String tag = 'ModuleData';
|
static const String tag = 'ModuleData';
|
||||||
|
|
||||||
// TODO(joshualitt) Support serializing ModularMemberData;
|
// TODO(joshualitt) Support serializing ModularMemberData;
|
||||||
final Map<ir.Member, ImpactBuilderData> impactData;
|
final Map<Uri, Map<ir.Member, ImpactBuilderData>> impactData;
|
||||||
|
|
||||||
ModuleData(this.impactData);
|
ModuleData([Map<Uri, Map<ir.Member, ImpactBuilderData>> impactData])
|
||||||
|
: this.impactData = impactData ?? {};
|
||||||
|
|
||||||
factory ModuleData.fromDataSource(DataSourceReader source) {
|
factory ModuleData.fromImpactData(
|
||||||
|
Map<Uri, Map<ir.Member, ImpactBuilderData>> impactData) =>
|
||||||
|
ModuleData(impactData);
|
||||||
|
|
||||||
|
ModuleData readMoreFromDataSource(DataSourceReader source) {
|
||||||
source.begin(tag);
|
source.begin(tag);
|
||||||
var impactData = source
|
int uriCount = source.readInt();
|
||||||
|
for (int i = 0; i < uriCount; i++) {
|
||||||
|
Uri uri = source.readUri();
|
||||||
|
impactData[uri] = source
|
||||||
.readMemberNodeMap(() => ImpactBuilderData.fromDataSource(source));
|
.readMemberNodeMap(() => ImpactBuilderData.fromDataSource(source));
|
||||||
source.end(tag);
|
|
||||||
return ModuleData(impactData);
|
|
||||||
}
|
}
|
||||||
|
source.end(tag);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
factory ModuleData.fromDataSource(DataSourceReader source) =>
|
||||||
|
ModuleData().readMoreFromDataSource(source);
|
||||||
|
|
||||||
void toDataSink(DataSinkWriter sink) {
|
void toDataSink(DataSinkWriter sink) {
|
||||||
sink.begin(tag);
|
sink.begin(tag);
|
||||||
|
sink.writeInt(impactData.keys.length);
|
||||||
|
impactData.forEach((uri, data) {
|
||||||
|
sink.writeUri(uri);
|
||||||
sink.writeMemberNodeMap<ImpactBuilderData>(
|
sink.writeMemberNodeMap<ImpactBuilderData>(
|
||||||
impactData, (e) => e.toDataSink(sink));
|
data, (e) => e.toDataSink(sink));
|
||||||
|
});
|
||||||
sink.end(tag);
|
sink.end(tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -235,6 +235,14 @@ class Dart2jsTarget extends Target {
|
||||||
const Dart2jsDartLibrarySupport();
|
const Dart2jsDartLibrarySupport();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const implicitlyUsedLibraries = <String>[
|
||||||
|
'dart:_foreign_helper',
|
||||||
|
'dart:_interceptors',
|
||||||
|
'dart:_js_helper',
|
||||||
|
'dart:_late_helper',
|
||||||
|
'dart:js_util'
|
||||||
|
];
|
||||||
|
|
||||||
// TODO(sigmund): this "extraRequiredLibraries" needs to be removed...
|
// TODO(sigmund): this "extraRequiredLibraries" needs to be removed...
|
||||||
// compile-platform should just specify which libraries to compile instead.
|
// compile-platform should just specify which libraries to compile instead.
|
||||||
const requiredLibraries = <String, List<String>>{
|
const requiredLibraries = <String, List<String>>{
|
||||||
|
|
|
@ -229,7 +229,7 @@ class KernelFrontendStrategy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerModuleData(List<ModuleData> data) {
|
void registerModuleData(ModuleData data) {
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
_modularStrategy = KernelModularStrategy(_compilerTask, _elementMap);
|
_modularStrategy = KernelModularStrategy(_compilerTask, _elementMap);
|
||||||
} else {
|
} else {
|
||||||
|
@ -452,9 +452,10 @@ class DeserializedModularStrategy extends ModularStrategy {
|
||||||
final Map<ir.Member, ImpactBuilderData> _cache = {};
|
final Map<ir.Member, ImpactBuilderData> _cache = {};
|
||||||
|
|
||||||
DeserializedModularStrategy(
|
DeserializedModularStrategy(
|
||||||
this._compilerTask, this._elementMap, List<ModuleData> data) {
|
this._compilerTask, this._elementMap, ModuleData data) {
|
||||||
for (var module in data) {
|
for (Map<ir.Member, ImpactBuilderData> moduleData
|
||||||
_cache.addAll(module.impactData);
|
in data.impactData.values) {
|
||||||
|
_cache.addAll(moduleData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -208,7 +208,7 @@ class CompilerOptions implements DiagnosticOptions {
|
||||||
Uri? writeModularAnalysisUri;
|
Uri? writeModularAnalysisUri;
|
||||||
|
|
||||||
/// Helper to determine if compiler is being run just for modular analysis.
|
/// Helper to determine if compiler is being run just for modular analysis.
|
||||||
bool get modularMode => writeModularAnalysisUri != null;
|
bool get modularMode => writeModularAnalysisUri != null && !cfeOnly;
|
||||||
|
|
||||||
List<Uri>? modularAnalysisInputs;
|
List<Uri>? modularAnalysisInputs;
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,8 @@ import '../../compiler.dart' as api;
|
||||||
import '../commandline_options.dart';
|
import '../commandline_options.dart';
|
||||||
import '../common.dart';
|
import '../common.dart';
|
||||||
import '../kernel/front_end_adapter.dart';
|
import '../kernel/front_end_adapter.dart';
|
||||||
import '../kernel/dart2js_target.dart' show Dart2jsTarget;
|
import '../kernel/dart2js_target.dart'
|
||||||
|
show Dart2jsTarget, implicitlyUsedLibraries;
|
||||||
import '../kernel/transformations/clone_mixin_methods_with_super.dart'
|
import '../kernel/transformations/clone_mixin_methods_with_super.dart'
|
||||||
as transformMixins show transformLibraries;
|
as transformMixins show transformLibraries;
|
||||||
import '../options.dart';
|
import '../options.dart';
|
||||||
|
@ -164,9 +165,11 @@ Future<_LoadFromKernelResult> _loadFromKernel(CompilerOptions options,
|
||||||
_inferNullSafetyMode(options, isStrongDill);
|
_inferNullSafetyMode(options, isStrongDill);
|
||||||
_validateNullSafetyMode(options);
|
_validateNullSafetyMode(options);
|
||||||
|
|
||||||
// Modular compiles do not include the platform on the input dill
|
// When compiling modularly, a dill for the SDK will be provided. In those
|
||||||
// either.
|
// cases we ignore the implicit platform binary.
|
||||||
if (options.platformBinaries != null) {
|
bool platformBinariesIncluded =
|
||||||
|
options.modularMode || options.hasModularAnalysisInputs;
|
||||||
|
if (options.platformBinaries != null && !platformBinariesIncluded) {
|
||||||
var platformUri = options.platformBinaries
|
var platformUri = options.platformBinaries
|
||||||
.resolve(_getPlatformFilename(options, targetName));
|
.resolve(_getPlatformFilename(options, targetName));
|
||||||
// Modular analysis can be run on the sdk by providing directly the
|
// Modular analysis can be run on the sdk by providing directly the
|
||||||
|
@ -331,11 +334,20 @@ Output _createOutput(
|
||||||
|
|
||||||
search(root);
|
search(root);
|
||||||
|
|
||||||
// Libraries dependencies do not show implicit imports to `dart:core`.
|
// Libraries dependencies do not show implicit imports to certain internal
|
||||||
var dartCore = component.libraries.firstWhere((lib) {
|
// libraries.
|
||||||
return lib.importUri.isScheme('dart') && lib.importUri.path == 'core';
|
const Set<String> alwaysInclude = {
|
||||||
|
'dart:_internal',
|
||||||
|
'dart:core',
|
||||||
|
'dart:async',
|
||||||
|
...implicitlyUsedLibraries,
|
||||||
|
};
|
||||||
|
for (String uri in alwaysInclude) {
|
||||||
|
Library library = component.libraries.firstWhere((lib) {
|
||||||
|
return '${lib.importUri}' == uri;
|
||||||
});
|
});
|
||||||
search(dartCore);
|
search(library);
|
||||||
|
}
|
||||||
|
|
||||||
libraries = libraries.where(seen.contains);
|
libraries = libraries.where(seen.contains);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,12 +53,12 @@ KernelToElementMap _createElementMap(
|
||||||
return elementMap;
|
return elementMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleData run(Input input) {
|
Map<ir.Member, ImpactBuilderData> _computeForLibrary(
|
||||||
final options = input.options;
|
CompilerOptions options,
|
||||||
final reporter = input.reporter;
|
DiagnosticReporter reporter,
|
||||||
final elementMap = _createElementMap(
|
KernelToElementMap elementMap,
|
||||||
options, reporter, input.environment, input.component, input.libraries);
|
ir.Library library) {
|
||||||
final result = <ir.Member, ImpactBuilderData>{};
|
Map<ir.Member, ImpactBuilderData> result = {};
|
||||||
void computeForMember(ir.Member member) {
|
void computeForMember(ir.Member member) {
|
||||||
final scopeModel = ScopeModel.from(member, elementMap.constantEvaluator);
|
final scopeModel = ScopeModel.from(member, elementMap.constantEvaluator);
|
||||||
final annotations = processMemberAnnotations(
|
final annotations = processMemberAnnotations(
|
||||||
|
@ -68,12 +68,23 @@ ModuleData run(Input input) {
|
||||||
.impactBuilderData;
|
.impactBuilderData;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final library in input.component.libraries) {
|
|
||||||
if (!input.moduleLibraries.contains(library.importUri)) continue;
|
|
||||||
library.members.forEach(computeForMember);
|
library.members.forEach(computeForMember);
|
||||||
for (final cls in library.classes) {
|
for (final cls in library.classes) {
|
||||||
cls.members.forEach(computeForMember);
|
cls.members.forEach(computeForMember);
|
||||||
}
|
}
|
||||||
}
|
return result;
|
||||||
return ModuleData(result);
|
}
|
||||||
|
|
||||||
|
ModuleData run(Input input) {
|
||||||
|
final options = input.options;
|
||||||
|
final reporter = input.reporter;
|
||||||
|
final elementMap = _createElementMap(
|
||||||
|
options, reporter, input.environment, input.component, input.libraries);
|
||||||
|
Map<Uri, Map<ir.Member, ImpactBuilderData>> result = {};
|
||||||
|
for (final library in input.component.libraries) {
|
||||||
|
if (!input.moduleLibraries.contains(library.importUri)) continue;
|
||||||
|
result[library.importUri] =
|
||||||
|
_computeForLibrary(options, reporter, elementMap, library);
|
||||||
|
}
|
||||||
|
return ModuleData.fromImpactData(result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,7 +198,6 @@ class SerializationTask extends CompilerTask {
|
||||||
// DataSource source = new ObjectSource(encoding, useDataKinds: true);
|
// DataSource source = new ObjectSource(encoding, useDataKinds: true);
|
||||||
// source.registerComponentLookup(new ComponentLookup(component));
|
// source.registerComponentLookup(new ComponentLookup(component));
|
||||||
// ModuleData.fromDataSource(source);
|
// ModuleData.fromDataSource(source);
|
||||||
|
|
||||||
BytesSink bytes = BytesSink();
|
BytesSink bytes = BytesSink();
|
||||||
DataSinkWriter binarySink =
|
DataSinkWriter binarySink =
|
||||||
DataSinkWriter(BinaryDataSink(bytes), useDataKinds: true);
|
DataSinkWriter(BinaryDataSink(bytes), useDataKinds: true);
|
||||||
|
@ -211,17 +210,17 @@ class SerializationTask extends CompilerTask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<ModuleData>> deserializeModuleData(ir.Component component) async {
|
Future<ModuleData> deserializeModuleData(ir.Component component) async {
|
||||||
return await measureIoSubtask('deserialize module data', () async {
|
return await measureIoSubtask('deserialize module data', () async {
|
||||||
_reporter.log('Reading data from ${_options.modularAnalysisInputs}');
|
_reporter.log('Reading data from ${_options.modularAnalysisInputs}');
|
||||||
List<ModuleData> results = [];
|
final results = ModuleData();
|
||||||
for (Uri uri in _options.modularAnalysisInputs) {
|
for (Uri uri in _options.modularAnalysisInputs) {
|
||||||
api.Input<List<int>> dataInput =
|
api.Input<List<int>> dataInput =
|
||||||
await _provider.readFromUri(uri, inputKind: api.InputKind.binary);
|
await _provider.readFromUri(uri, inputKind: api.InputKind.binary);
|
||||||
DataSourceReader source =
|
DataSourceReader source =
|
||||||
DataSourceReader(BinaryDataSource(dataInput.data));
|
DataSourceReader(BinaryDataSource(dataInput.data));
|
||||||
source.registerComponentLookup(ComponentLookup(component));
|
source.registerComponentLookup(ComponentLookup(component));
|
||||||
results.add(ModuleData.fromDataSource(source));
|
results.readMoreFromDataSource(source);
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
});
|
});
|
||||||
|
|
|
@ -26,9 +26,7 @@ main(List<String> args) async {
|
||||||
FullDillCompilationStep(onlyOnSdk: true),
|
FullDillCompilationStep(onlyOnSdk: true),
|
||||||
ModularAnalysisStep(onlyOnSdk: true),
|
ModularAnalysisStep(onlyOnSdk: true),
|
||||||
ModularAnalysisStep(),
|
ModularAnalysisStep(),
|
||||||
// TODO(joshualitt): Re-enable ConcatenateDillStep after it works
|
ConcatenateDillsStep(useModularAnalysis: true),
|
||||||
// correctly alongside modular analysis.
|
|
||||||
// ConcatenateDillsStep(useModularAnalysis: true),
|
|
||||||
ComputeClosedWorldStep(useModularAnalysis: true),
|
ComputeClosedWorldStep(useModularAnalysis: true),
|
||||||
GlobalAnalysisStep(),
|
GlobalAnalysisStep(),
|
||||||
Dart2jsCodegenStep(codeId0),
|
Dart2jsCodegenStep(codeId0),
|
||||||
|
|
|
@ -32,6 +32,7 @@ const dillId = DataId("full.dill");
|
||||||
const fullDillId = DataId("concatenate.dill");
|
const fullDillId = DataId("concatenate.dill");
|
||||||
const modularUpdatedDillId = DataId("modular.dill");
|
const modularUpdatedDillId = DataId("modular.dill");
|
||||||
const modularDataId = DataId("modular.data");
|
const modularDataId = DataId("modular.data");
|
||||||
|
const modularFullDataId = DataId("concatenate.modular.data");
|
||||||
const closedWorldId = DataId("world");
|
const closedWorldId = DataId("world");
|
||||||
const globalUpdatedDillId = DataId("global.dill");
|
const globalUpdatedDillId = DataId("global.dill");
|
||||||
const globalDataId = DataId("global.data");
|
const globalDataId = DataId("global.data");
|
||||||
|
@ -304,10 +305,16 @@ class ConcatenateDillsStep extends IOModularStep {
|
||||||
|
|
||||||
DataId get idForDill => useModularAnalysis ? modularUpdatedDillId : dillId;
|
DataId get idForDill => useModularAnalysis ? modularUpdatedDillId : dillId;
|
||||||
|
|
||||||
List<DataId> get dependencies => [idForDill];
|
List<DataId> get dependencies => [
|
||||||
|
idForDill,
|
||||||
|
if (useModularAnalysis) modularDataId,
|
||||||
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<DataId> get resultData => const [fullDillId];
|
List<DataId> get resultData => [
|
||||||
|
fullDillId,
|
||||||
|
if (useModularAnalysis) modularFullDataId,
|
||||||
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool get needsSources => false;
|
bool get needsSources => false;
|
||||||
|
@ -344,6 +351,10 @@ class ConcatenateDillsStep extends IOModularStep {
|
||||||
'${Flags.inputDill}=${toUri(module, dillId)}',
|
'${Flags.inputDill}=${toUri(module, dillId)}',
|
||||||
for (String flag in flags) '--enable-experiment=$flag',
|
for (String flag in flags) '--enable-experiment=$flag',
|
||||||
'${Flags.dillDependencies}=${dillDependencies.join(',')}',
|
'${Flags.dillDependencies}=${dillDependencies.join(',')}',
|
||||||
|
if (useModularAnalysis) ...[
|
||||||
|
'${Flags.readModularAnalysis}=${dataDependencies.join(',')}',
|
||||||
|
'${Flags.writeModularAnalysis}=${toUri(module, modularFullDataId)}',
|
||||||
|
],
|
||||||
'${Flags.cfeOnly}',
|
'${Flags.cfeOnly}',
|
||||||
'--out=${toUri(module, fullDillId)}',
|
'--out=${toUri(module, fullDillId)}',
|
||||||
];
|
];
|
||||||
|
@ -364,14 +375,11 @@ class ConcatenateDillsStep extends IOModularStep {
|
||||||
class ComputeClosedWorldStep extends IOModularStep {
|
class ComputeClosedWorldStep extends IOModularStep {
|
||||||
final bool useModularAnalysis;
|
final bool useModularAnalysis;
|
||||||
|
|
||||||
DataId get idForDill =>
|
|
||||||
useModularAnalysis ? modularUpdatedDillId : fullDillId;
|
|
||||||
|
|
||||||
ComputeClosedWorldStep({this.useModularAnalysis});
|
ComputeClosedWorldStep({this.useModularAnalysis});
|
||||||
|
|
||||||
List<DataId> get dependencies => [
|
List<DataId> get dependencies => [
|
||||||
idForDill,
|
fullDillId,
|
||||||
if (useModularAnalysis) modularDataId,
|
if (useModularAnalysis) modularFullDataId,
|
||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -394,25 +402,16 @@ class ComputeClosedWorldStep extends IOModularStep {
|
||||||
List<String> flags) async {
|
List<String> flags) async {
|
||||||
if (_options.verbose)
|
if (_options.verbose)
|
||||||
print("\nstep: dart2js compute closed world on $module");
|
print("\nstep: dart2js compute closed world on $module");
|
||||||
Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
|
|
||||||
Iterable<String> dillDependencies =
|
|
||||||
transitiveDependencies.map((m) => '${toUri(m, idForDill)}');
|
|
||||||
List<String> dataDependencies = transitiveDependencies
|
|
||||||
.map((m) => '${toUri(m, modularDataId)}')
|
|
||||||
.toList();
|
|
||||||
dataDependencies.add('${toUri(module, modularDataId)}');
|
|
||||||
List<String> args = [
|
List<String> args = [
|
||||||
'--packages=${sdkRoot.toFilePath()}/$packageConfigJsonPath',
|
'--packages=${sdkRoot.toFilePath()}/$packageConfigJsonPath',
|
||||||
_dart2jsScript,
|
_dart2jsScript,
|
||||||
// TODO(sigmund): remove this dependency on libraries.json
|
// TODO(sigmund): remove this dependency on libraries.json
|
||||||
if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
|
if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot',
|
||||||
'${Flags.entryUri}=$fakeRoot${module.mainSource}',
|
'${Flags.entryUri}=$fakeRoot${module.mainSource}',
|
||||||
'${Flags.inputDill}=${toUri(module, idForDill)}',
|
'${Flags.inputDill}=${toUri(module, fullDillId)}',
|
||||||
for (String flag in flags) '--enable-experiment=$flag',
|
for (String flag in flags) '--enable-experiment=$flag',
|
||||||
if (useModularAnalysis) ...[
|
if (useModularAnalysis)
|
||||||
'${Flags.dillDependencies}=${dillDependencies.join(',')}',
|
'${Flags.readModularAnalysis}=${toUri(module, modularFullDataId)}',
|
||||||
'${Flags.readModularAnalysis}=${dataDependencies.join(',')}',
|
|
||||||
],
|
|
||||||
'${Flags.writeClosedWorld}=${toUri(module, closedWorldId)}',
|
'${Flags.writeClosedWorld}=${toUri(module, closedWorldId)}',
|
||||||
Flags.noClosedWorldInData,
|
Flags.noClosedWorldInData,
|
||||||
'--out=${toUri(module, globalUpdatedDillId)}',
|
'--out=${toUri(module, globalUpdatedDillId)}',
|
||||||
|
|
11
tests/modular/unused_library_and_module/main.dart
Normal file
11
tests/modular/unused_library_and_module/main.dart
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright (c) 2022, 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.
|
||||||
|
|
||||||
|
import 'package:expect/expect.dart';
|
||||||
|
|
||||||
|
import 'used_module/used_library.dart';
|
||||||
|
|
||||||
|
main() {
|
||||||
|
Expect.equals(usedConstant, 1);
|
||||||
|
}
|
8
tests/modular/unused_library_and_module/modules.yaml
Normal file
8
tests/modular/unused_library_and_module/modules.yaml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Copyright (c) 2022, 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.
|
||||||
|
#
|
||||||
|
# Regression test: integral numbers should be treated as int and not double
|
||||||
|
# after serialization across modules.
|
||||||
|
dependencies:
|
||||||
|
main: [expect, used_module, unused_module]
|
|
@ -0,0 +1,4 @@
|
||||||
|
// Copyright (c) 2022, 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.
|
||||||
|
const int unusedConstant2 = 3;
|
|
@ -0,0 +1,4 @@
|
||||||
|
// Copyright (c) 2022, 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.
|
||||||
|
const int unusedConstant1 = 2;
|
|
@ -0,0 +1,4 @@
|
||||||
|
// Copyright (c) 2022, 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.
|
||||||
|
const int usedConstant = 1;
|
Loading…
Reference in a new issue