[dart2js] Fix modular analysis test.
Change-Id: I066149a6ae052acf7ec2db90cdeec378f73dcfb3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/221142
Commit-Queue: Joshua Litt <joshualitt@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Reviewed-by: Stephen Adams <sra@google.com>
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 3c5f245..49838e5 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -178,8 +178,7 @@
enqueuer = EnqueueTask(this);
tasks = [
- kernelLoader = KernelLoaderTask(
- options, provider, _outputProvider, reporter, measurer),
+ kernelLoader = KernelLoaderTask(options, provider, reporter, measurer),
kernelFrontEndTask,
globalInference = GlobalTypeInferenceTask(this),
deferredLoadTask = frontendStrategy.createDeferredLoadTask(this),
@@ -306,7 +305,6 @@
if (retainDataForTesting) {
componentForTesting = result.component;
}
- if (options.cfeOnly) return;
frontendStrategy.registerLoadedLibraries(result);
@@ -314,12 +312,34 @@
await runModularAnalysis(result);
} else {
List<ModuleData> data;
- if (options.modularAnalysisInputs != null) {
+ if (options.hasModularAnalysisInputs) {
data =
await serializationTask.deserializeModuleData(result.component);
}
frontendStrategy.registerModuleData(data);
- await compileFromKernel(result.rootLibraryUri, result.libraries);
+
+ // After we've deserialized modular data, we set and verify the main
+ // method as well as trim the component of any unnecessary dependencies.
+ // Note: It is critical we wait to trim the dill until after we've
+ // deserialized modular data because some of this data may reference
+ // 'trimmed' elements.
+ if (options.fromDill) {
+ if (options.entryUri != null) {
+ result.setMainAndTrimComponent(options.entryUri);
+ }
+ if (result.component.mainMethod == null) {
+ // TODO(sigmund): move this so that we use the same error template
+ // from the CFE.
+ _reporter.reportError(_reporter.createMessage(NO_LOCATION_SPANNABLE,
+ MessageKind.GENERIC, {'text': "No 'main' method found."}));
+ return;
+ }
+ }
+ if (options.cfeOnly) {
+ await serializationTask.serializeComponent(result.component);
+ } else {
+ await compileFromKernel(result.rootLibraryUri, result.libraries);
+ }
}
}
}
diff --git a/pkg/compiler/lib/src/ir/impact.dart b/pkg/compiler/lib/src/ir/impact.dart
index f3d8702..3e7f7fca 100644
--- a/pkg/compiler/lib/src/ir/impact.dart
+++ b/pkg/compiler/lib/src/ir/impact.dart
@@ -858,4 +858,11 @@
void visitNullConstant(ir.NullConstant node) {
registry.registerNullLiteral();
}
+
+ @override
+ void visitConstructorTearOffConstant(ir.ConstructorTearOffConstant node) {
+ // The CFE encoding of redirecting factories, which dart2js doesn't use,
+ // uses ConstructorTearOff(Constant) to point to its effective target.
+ // However, these should be safe to ignore.
+ }
}
diff --git a/pkg/compiler/lib/src/kernel/loader.dart b/pkg/compiler/lib/src/kernel/loader.dart
index 57c32f2..dbefdbb 100644
--- a/pkg/compiler/lib/src/kernel/loader.dart
+++ b/pkg/compiler/lib/src/kernel/loader.dart
@@ -9,7 +9,6 @@
import 'package:front_end/src/fasta/kernel/utils.dart';
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
-import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
import 'package:front_end/src/api_unstable/dart2js.dart' as fe;
import 'package:kernel/kernel.dart' hide LibraryDependency, Combinator;
@@ -20,7 +19,6 @@
import '../common/tasks.dart' show CompilerTask, Measurer;
import '../common.dart';
import '../options.dart';
-import '../util/sink_adapter.dart';
import 'front_end_adapter.dart';
import 'dart2js_target.dart' show Dart2jsTarget;
@@ -34,7 +32,6 @@
final DiagnosticReporter _reporter;
final api.CompilerInput _compilerInput;
- final api.CompilerOutput _compilerOutput;
final CompilerOptions _options;
@@ -47,58 +44,13 @@
/// This is used for testing.
bool forceSerialization = false;
- KernelLoaderTask(this._options, this._compilerInput, this._compilerOutput,
- this._reporter, Measurer measurer)
+ KernelLoaderTask(
+ this._options, this._compilerInput, this._reporter, Measurer measurer)
: initializedCompilerState = _options.kernelInitializedCompilerState,
super(measurer);
@override
String get name => 'kernel loader';
- Library findEntryLibrary(Component component, Uri entryUri) {
- var entryLibrary = component.libraries
- .firstWhere((l) => l.fileUri == entryUri, orElse: () => null);
- if (entryLibrary == null) {
- throw ArgumentError('Entry uri $entryUri not found in dill.');
- }
- return entryLibrary;
- }
-
- ir.Reference findMainMethod(Library entryLibrary) {
- var mainMethod = entryLibrary.procedures
- .firstWhere((p) => p.name.text == 'main', orElse: () => null);
-
- // In some cases, a main method is defined in another file, and then
- // exported. In these cases, we search for the main method in
- // [additionalExports].
- ir.Reference mainMethodReference;
- if (mainMethod == null) {
- mainMethodReference = entryLibrary.additionalExports.firstWhere(
- (p) => p.canonicalName.name == 'main',
- orElse: () => null);
- } else {
- mainMethodReference = mainMethod.reference;
- }
- if (mainMethodReference == null) {
- throw ArgumentError(
- 'Entry uri ${entryLibrary.fileUri} has no main method.');
- }
- return mainMethodReference;
- }
-
- Set<Library> computeRequiredLibraries(Library entryLibrary) {
- var toVisit = [entryLibrary];
- var visited = <Library>{entryLibrary};
- while (toVisit.isNotEmpty) {
- var library = toVisit.removeLast();
- for (var dependency in library.dependencies) {
- var target = dependency.targetLibrary;
- if (visited.add(target)) {
- toVisit.add(target);
- }
- }
- }
- return visited;
- }
/// Loads an entire Kernel [Component] from a file on disk.
Future<KernelResult> load() {
@@ -116,9 +68,6 @@
var resolvedUri = _options.compilationTarget;
ir.Component component;
List<Uri> moduleLibraries = const [];
- var isDill = resolvedUri.path.endsWith('.dill') ||
- resolvedUri.path.endsWith('.gdill') ||
- resolvedUri.path.endsWith('.mdill');
void inferNullSafetyMode(bool isSound) {
if (_options.nullSafetyMode == NullSafetyMode.unspecified) {
@@ -131,7 +80,7 @@
assert(_options.nullSafetyMode != NullSafetyMode.unspecified);
}
- if (isDill) {
+ if (_options.fromDill) {
component = ir.Component();
Future<void> read(Uri uri) async {
api.Input input = await _compilerInput.readFromUri(uri,
@@ -141,15 +90,6 @@
await read(resolvedUri);
- // If an entryUri is supplied, we use it to manually select the main
- // method.
- Library entryLibrary;
- if (_options.entryUri != null) {
- entryLibrary = findEntryLibrary(component, _options.entryUri);
- var mainMethod = findMainMethod(entryLibrary);
- component.setMainMethodAndMode(mainMethod, true, component.mode);
- }
-
if (_options.modularMode) {
moduleLibraries =
component.libraries.map((lib) => lib.importUri).toList();
@@ -182,38 +122,12 @@
if (platformUri != resolvedUri) await read(platformUri);
}
- // Concatenate dills, trim the resulting monolithic dill, and then
- // reset the main method.
- var mainMethod = component.mainMethodName;
- var mainMode = component.mode;
+ // Concatenate dills.
if (_options.dillDependencies != null) {
for (Uri dependency in _options.dillDependencies) {
await read(dependency);
}
}
- if (entryLibrary != null) {
- var requiredLibraries = computeRequiredLibraries(entryLibrary);
- for (var library in component.libraries) {
- if (library.importUri.scheme == 'dart') {
- requiredLibraries.add(library);
- }
- }
- component = ir.Component(
- libraries: requiredLibraries.toList(),
- uriToSource: component.uriToSource,
- nameRoot: component.root);
- }
- component.setMainMethodAndMode(mainMethod, true, mainMode);
-
- // This is not expected to be null when creating a whole-program .dill
- // file, but needs to be checked for modular inputs.
- if (component.mainMethod == null && !_options.modularMode) {
- // TODO(sigmund): move this so that we use the same error template
- // from the CFE.
- _reporter.reportError(_reporter.createMessage(NO_LOCATION_SPANNABLE,
- MessageKind.GENERIC, {'text': "No 'main' method found."}));
- return null;
- }
} else {
bool verbose = false;
Target target =
@@ -266,18 +180,6 @@
validateNullSafetyMode();
}
- if (_options.cfeOnly) {
- measureSubtask('serialize dill', () {
- _reporter.log('Writing dill to ${_options.outputUri}');
- api.BinaryOutputSink dillOutput =
- _compilerOutput.createBinarySink(_options.outputUri);
- BinaryOutputSinkAdapter irSink = BinaryOutputSinkAdapter(dillOutput);
- BinaryPrinter printer = BinaryPrinter(irSink);
- printer.writeComponentFile(component);
- irSink.close();
- });
- }
-
if (forceSerialization) {
// TODO(johnniwinther): Remove this when #34942 is fixed.
List<int> data = serializeComponent(component);
@@ -324,7 +226,7 @@
/// Result of invoking the CFE to produce the kernel IR.
class KernelResult {
- final ir.Component component;
+ ir.Component component;
/// The [Uri] of the root library containing main.
/// Note: rootLibraryUri will be null for some modules, for example in the
@@ -348,6 +250,55 @@
KernelResult(this.component, this.rootLibraryUri, this.libraries,
this.moduleLibraries);
+ static Library _findEntryLibrary(Component component, Uri entryUri) {
+ var entryLibrary = component.libraries
+ .firstWhere((l) => l.fileUri == entryUri, orElse: () => null);
+ if (entryLibrary == null) {
+ throw ArgumentError('Entry uri $entryUri not found in dill.');
+ }
+ return entryLibrary;
+ }
+
+ static ir.Reference _findMainMethod(Library entryLibrary) {
+ var mainMethod = entryLibrary.procedures
+ .firstWhere((p) => p.name.text == 'main', orElse: () => null);
+
+ // In some cases, a main method is defined in another file, and then
+ // exported. In these cases, we search for the main method in
+ // [additionalExports].
+ ir.Reference mainMethodReference;
+ if (mainMethod == null) {
+ mainMethodReference = entryLibrary.additionalExports.firstWhere(
+ (p) => p.canonicalName.name == 'main',
+ orElse: () => null);
+ } else {
+ mainMethodReference = mainMethod.reference;
+ }
+ if (mainMethodReference == null) {
+ throw ArgumentError(
+ 'Entry uri ${entryLibrary.fileUri} has no main method.');
+ }
+ return mainMethodReference;
+ }
+
+ void setMainAndTrimComponent(Uri entryUri) {
+ var entryLibrary = _findEntryLibrary(component, entryUri);
+ var mainMethod = _findMainMethod(entryLibrary);
+ var irLibraryMap = <Uri, Library>{};
+ var irLibraries = <Library>[];
+ for (var library in component.libraries) {
+ irLibraryMap[library.importUri] = library;
+ }
+ for (var library in libraries) {
+ irLibraries.add(irLibraryMap[library]);
+ }
+ component = ir.Component(
+ libraries: irLibraries,
+ uriToSource: component.uriToSource,
+ nameRoot: component.root);
+ component.setMainMethodAndMode(mainMethod, true, component.mode);
+ }
+
@override
String toString() =>
'root=$rootLibraryUri,libraries=$libraries,module=$moduleLibraries';
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index e6db1d9..79d15b9 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -160,6 +160,13 @@
/// Returns the compilation target specified by these options.
Uri? get compilationTarget => inputDillUri ?? entryUri;
+ bool get fromDill {
+ var targetPath = compilationTarget!.path;
+ return targetPath.endsWith('.dill') ||
+ targetPath.endsWith('.gdill') ||
+ targetPath.endsWith('.mdill');
+ }
+
/// Location of the package configuration file.
///
/// If not null then [packageRoot] should be null.
@@ -185,6 +192,8 @@
List<Uri>? modularAnalysisInputs;
+ bool get hasModularAnalysisInputs => modularAnalysisInputs != null;
+
/// Location from which serialized inference data is read.
///
/// If this is set, the [entryUri] is expected to be a .dill file and the