diff --git a/pkg/compiler/README.md b/pkg/compiler/README.md index 4cd84416823..793b0864552 100644 --- a/pkg/compiler/README.md +++ b/pkg/compiler/README.md @@ -28,19 +28,7 @@ The current compiler phases are: The result of this phase is a kernel AST which is serialized as a `.dill` file. - 2. **modular analysis**: Using kernel as input, compute data recording - properties about each method in the program, especially around dependencies - and features they may need. We call this "impact data" (i1). - - When the compiler runs as a single process, this is done lazily/on-demand - during the tree-shaking phase (below). However, this data can also be - computed independently for individual methods, files, or packages in the - application. That makes it possible to run this modularly and in parallel. - - The result of this phase can be emitted as files containing impact data in - a serialized format. - - 3. **tree-shake and create world**: Create a model to understand what parts of + 2. **tree-shake and create world**: Create a model to understand what parts of the code are used by an application. This consists of: * creating an intermediate representation called the "K model" that wraps our kernel representation @@ -56,7 +44,7 @@ The current compiler phases are: in any subtype of some interface? The answers to these questions can help the compiler generate higher quality JavaScript. - 4. **global analysis**: Run a global analysis that assumes closed world + 3. **global analysis**: Run a global analysis that assumes closed world semantics (from w1) and propagates information across method boundaries to further understand what values flow through the program. This phase is very valuable in narrowing down possibilities that are ambiguous based @@ -66,13 +54,13 @@ The current compiler phases are: The result of this phase is a "global result" (g). - 5. **codegen model**: Create a JS or backend model of the program. This is an + 4. **codegen model**: Create a JS or backend model of the program. This is an intermediate representation of the entities in the program we referred to as the "J model". It is very similar to the "K model", but it is tailored to model JavaScript specific concepts (like the split of constructor bodies as separate elements) and provide a mapping to the Dart model. - 6. **codegen**: Generate code for each method that is deemed necessary. This + 5. **codegen**: Generate code for each method that is deemed necessary. This includes: * build an SSA graph from kernel ASTs and global results (g) * optimize the SSA representation @@ -80,7 +68,7 @@ The current compiler phases are: * emit JS ASTs for the code - 7. **link tree-shake**: Using the results of codegen, we perform a second + 6. **link tree-shake**: Using the results of codegen, we perform a second round of tree-shaking. This is important because code that was deemed reachable in (w1) may be found unreachable after optimizations. The process is very similar to the earlier phase: we combine incrementally the codegen @@ -90,7 +78,7 @@ The current compiler phases are: When dart2js runs as a single process the codegen phase is done lazily and on-demand, together with the tree-shaking phase. - 8. **emit JavaScript files**: The final step is to assemble and minify the + 7. **emit JavaScript files**: The final step is to assemble and minify the final program. This includes: * Build a JavaScript program structure from the compiled pieces (w2) * Use frequency namer to minify names. diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart index 118c336e0b4..7f59d40d951 100644 --- a/pkg/compiler/lib/src/compiler.dart +++ b/pkg/compiler/lib/src/compiler.dart @@ -47,7 +47,6 @@ import 'inferrer/types.dart' import 'inferrer/wrapped.dart' show WrappedAbstractValueStrategy; import 'io/source_information.dart'; import 'ir/annotations.dart'; -import 'ir/modular.dart' hide reportLocatedMessage; import 'js_backend/codegen_inputs.dart' show CodegenInputs; import 'js_backend/enqueuer.dart'; import 'js_backend/inferred_data.dart'; @@ -62,7 +61,6 @@ import 'kernel/kernel_world.dart'; import 'null_compiler_output.dart' show NullCompilerOutput; import 'options.dart' show CompilerOptions, Dart2JSStage; import 'phase/load_kernel.dart' as load_kernel; -import 'phase/modular_analysis.dart' as modular_analysis; import 'resolution/enqueuer.dart'; import 'serialization/serialization.dart'; import 'serialization/task.dart'; @@ -337,10 +335,9 @@ class Compiler { } } - JClosedWorld? computeClosedWorld(ir.Component component, - ModuleData? moduleData, Uri rootLibraryUri, List libraries) { + JClosedWorld? computeClosedWorld( + ir.Component component, Uri rootLibraryUri, List libraries) { frontendStrategy.registerLoadedLibraries(component, libraries); - frontendStrategy.registerModuleData(moduleData); ResolutionEnqueuer resolutionEnqueuer = frontendStrategy .createResolutionEnqueuer(enqueueTask, this) ..onEmptyForTesting = onResolutionQueueEmptyForTesting; @@ -410,13 +407,6 @@ class Compiler { untrimmedComponentForDumpInfo = component; } if (stage.shouldOnlyComputeDill) { - // [ModuleData] must be deserialized with the full component, i.e. - // before trimming. - ModuleData? moduleData; - if (options.modularAnalysisInputs != null) { - moduleData = await serializationTask.deserializeModuleData(component); - } - Set includedLibraries = output.libraries!.toSet(); if (stage.shouldLoadFromDill) { if (options.dumpUnusedLibraries) { @@ -426,15 +416,7 @@ class Compiler { component = trimComponent(component, includedLibraries); } } - if (moduleData == null) { - serializationTask.serializeComponent(component); - } else { - // Trim [moduleData] down to only the included libraries. - moduleData.impactData - .removeWhere((uri, _) => !includedLibraries.contains(uri)); - serializationTask.serializeModuleData( - moduleData, component, includedLibraries); - } + serializationTask.serializeComponent(component); } return output.withNewComponent(component); } else { @@ -443,7 +425,7 @@ class Compiler { if (retainDataForTesting) { componentForTesting = component; } - return load_kernel.Output(component, null, null, null, null); + return load_kernel.Output(component, null, null, null); } } @@ -478,38 +460,6 @@ class Compiler { .run(); } - bool get usingModularAnalysis => - stage.shouldComputeModularAnalysis || options.hasModularAnalysisInputs; - - Future runModularAnalysis( - load_kernel.Output output, Set moduleLibraries) async { - ir.Component component = output.component; - List libraries = output.libraries!; - final input = modular_analysis.Input( - options, reporter, environment, component, libraries, moduleLibraries); - return await selfTask.measureSubtask( - 'runModularAnalysis', () async => modular_analysis.run(input)); - } - - Future produceModuleData(load_kernel.Output output) async { - ir.Component component = output.component; - if (stage.shouldComputeModularAnalysis) { - Set moduleLibraries = output.moduleLibraries!.toSet(); - ModuleData moduleData = await runModularAnalysis(output, moduleLibraries); - if (!compilationFailed) { - serializationTask.testModuleSerialization(moduleData, component); - serializationTask.serializeModuleData( - moduleData, component, moduleLibraries); - } - return moduleData; - } else { - return await serializationTask.deserializeModuleData(component); - } - } - - bool get shouldStopAfterModularAnalysis => - compilationFailed || stage.shouldComputeModularAnalysis; - GlobalTypeInferenceResults performGlobalTypeInference( JClosedWorld closedWorld) { FunctionEntity mainFunction = closedWorld.elementEnvironment.mainFunction!; @@ -591,30 +541,19 @@ class Compiler { indices); } - Future produceClosedWorld(load_kernel.Output output, - ModuleData? moduleData, SerializationIndices indices) async { + Future produceClosedWorld( + load_kernel.Output output, SerializationIndices indices) async { ir.Component component = output.component; JClosedWorld? closedWorld; if (!stage.shouldReadClosedWorld) { - if (!usingModularAnalysis) { - // If we're deserializing the closed world, the input .dill already - // contains the modified AST, so the transformer only needs to run if - // the closed world is being computed from scratch. - // - // However, the transformer is not currently compatible with modular - // analysis. When modular analysis is enabled in Blaze, some aspects run - // before this phase of the compiler. This can cause dart2js to crash if - // the kernel AST is mutated, since we will attempt to serialize and - // deserialize against different ASTs. - // - // TODO(fishythefish): Make this compatible with modular analysis. - simplifyConstConditionals(component); - } + // If we're deserializing the closed world, the input .dill already + // contains the modified AST, so the transformer only needs to run if + // the closed world is being computed from scratch. + simplifyConstConditionals(component); Uri rootLibraryUri = output.rootLibraryUri!; List libraries = output.libraries!; - closedWorld = - computeClosedWorld(component, moduleData, rootLibraryUri, libraries); + closedWorld = computeClosedWorld(component, rootLibraryUri, libraries); if (stage == Dart2JSStage.closedWorld && closedWorld != null) { serializationTask.serializeComponent( closedWorld.elementMap.programEnv.mainComponent, @@ -719,18 +658,10 @@ class Compiler { final output = await produceKernel(); if (shouldStopAfterLoadKernel(output)) return; - // Run modular analysis. This may be null if modular analysis was not - // requested for this pipeline. - ModuleData? moduleData; - if (usingModularAnalysis) { - moduleData = await produceModuleData(output!); - } - if (shouldStopAfterModularAnalysis) return; final indices = SerializationIndices(); // Compute closed world. - JClosedWorld? closedWorld = - await produceClosedWorld(output!, moduleData, indices); + JClosedWorld? closedWorld = await produceClosedWorld(output!, indices); if (shouldStopAfterClosedWorld(closedWorld)) return; // Run global analysis. diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart index 44becd143a7..4c5541ad235 100644 --- a/pkg/compiler/lib/src/dart2js.dart +++ b/pkg/compiler/lib/src/dart2js.dart @@ -156,7 +156,6 @@ Future compile(List argv, bool? showWarnings; bool? showHints; bool? enableColors; - List? sources; int? optimizationLevel; Uri? platformBinaries; Map environment = Map(); @@ -326,18 +325,10 @@ Future compile(List argv, return uris; } - void setModularAnalysisInputs(String argument) { - setUriList(Flags.readModularAnalysis, argument); - } - void setDillDependencies(String argument) { setUriList(Flags.dillDependencies, argument); } - void setSources(String argument) { - sources = setUriList(Flags.sources, argument); - } - void setDumpInfo(String argument) { passThrough(Flags.dumpInfo); if (argument == Flags.dumpInfo || argument == "${Flags.dumpInfo}=json") { @@ -425,10 +416,9 @@ Future compile(List argv, _OneOption('--library-root=.+', ignoreOption), _OneOption('--libraries-spec=.+', setLibrarySpecificationUri), _OneOption('${Flags.dillDependencies}=.+', setDillDependencies), - _OneOption('${Flags.sources}=.+', setSources), - _OneOption('${Flags.readModularAnalysis}=.+', setModularAnalysisInputs), - _OneOption('${Flags.writeModularAnalysis}=.+', - setDataUri(Flags.writeModularAnalysis)), + _OneOption('${Flags.sources}=.+', ignoreOption), + _OneOption('${Flags.readModularAnalysis}=.+', ignoreOption), + _OneOption('${Flags.writeModularAnalysis}=.+', ignoreOption), _OneOption('${Flags.readData}=.+', setDataUri(Flags.readData)), _OneOption('${Flags.writeData}=.+', setDataUri(Flags.writeData)), _OneOption( @@ -651,10 +641,7 @@ Future compile(List argv, print("Compiler invoked from: '$invoker'"); } - if (arguments.isEmpty && - entryUri == null && - inputDillUri == null && - sources == null) { + if (arguments.isEmpty && entryUri == null && inputDillUri == null) { _helpAndFail('No Dart file specified.'); } @@ -682,12 +669,8 @@ Future compile(List argv, } // Make [scriptName] a relative path. - String scriptName = sources == null - ? fe.relativizeUri( - Uri.base, inputDillUri ?? entryUri!, Platform.isWindows) - : sources! - .map((uri) => fe.relativizeUri(Uri.base, uri, Platform.isWindows)) - .join(','); + String scriptName = + fe.relativizeUri(Uri.base, inputDillUri ?? entryUri!, Platform.isWindows); CompilerOptions compilerOptions = CompilerOptions.parse(options, featureOptions: features, @@ -768,8 +751,6 @@ Future compile(List argv, case Dart2JSStage.cfe: case Dart2JSStage.allFromDill: case Dart2JSStage.cfeFromDill: - case Dart2JSStage.modularAnalysis: - case Dart2JSStage.modularAnalysisFromDill: case Dart2JSStage.closedWorld: final sourceCharCount = _formatCharacterCount(inputProvider.sourceBytesFromDill); @@ -848,18 +829,6 @@ Future compile(List argv, String output = fe.relativizeUri(Uri.base, out!, Platform.isWindows); summary += 'compiled to dill: ${output}.'; break; - case Dart2JSStage.modularAnalysis: - case Dart2JSStage.modularAnalysisFromDill: - processName = 'Serialized'; - outputName = 'bytes data'; - outputSize = outputProvider.totalDataWritten; - String output = fe.relativizeUri(Uri.base, out!, Platform.isWindows); - String dataOutput = fe.relativizeUri( - Uri.base, - compilerOptions.dataOutputUriForStage(compilerOptions.stage), - Platform.isWindows); - summary += 'serialized to dill and data: ${output} and ${dataOutput}.'; - break; case Dart2JSStage.closedWorld: processName = 'Serialized'; outputName = 'bytes data'; @@ -1400,27 +1369,3 @@ void batchMain(List batchArguments) { }); }); } - -// TODO(joshualitt): Clean up the combinatorial explosion of read strategies. -// Right now only fromClosedWorld, fromDataAndClosedWorld, and -// fromCodegenAndClosedWorldAndData are valid. -enum ReadStrategy { - fromDart, - fromClosedWorld, - fromData, - fromDataAndClosedWorld, - fromCodegen, - fromCodegenAndClosedWorld, - fromCodegenAndData, - fromCodegenAndClosedWorldAndData, -} - -enum WriteStrategy { - toKernel, - toKernelWithModularAnalysis, - toModularAnalysis, - toClosedWorld, - toData, - toCodegen, - toJs -} diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart index 1d059292b7b..4dda73430e7 100644 --- a/pkg/compiler/lib/src/options.dart +++ b/pkg/compiler/lib/src/options.dart @@ -30,15 +30,8 @@ enum Dart2JSStage { fromDillFlag: Dart2JSStage.cfeFromDill, emitsKernel: true, emitsJs: false), - modularAnalysis('modular-analysis', - fromDillFlag: Dart2JSStage.modularAnalysisFromDill, - dataOutputName: 'modular.data', - emitsKernel: true, - emitsJs: false), allFromDill(null, emitsKernel: false, emitsJs: true), cfeFromDill('cfe', emitsKernel: true, emitsJs: false), - modularAnalysisFromDill('modular-analysis', - dataOutputName: 'modular.data', emitsKernel: true, emitsJs: false), deferredLoadIds('deferred-load-ids', dataOutputName: 'deferred_load_ids.data', emitsKernel: false, @@ -74,27 +67,14 @@ enum Dart2JSStage { this == Dart2JSStage.all || this == Dart2JSStage.allFromDill; bool get shouldLoadFromDill => this.index >= Dart2JSStage.allFromDill.index; - bool get shouldComputeModularAnalysis => - this == Dart2JSStage.modularAnalysis || - this == Dart2JSStage.modularAnalysisFromDill; /// Global kernel transformations should be run in phase 0b, i.e. after /// concatenating dills, but before serializing the output of phase 0. - /// We also need to include modular analysis, or else the modular test suite - /// breaks when it deserializes module data because it reads transformed AST - /// nodes when it's expecting untransformed ones. - // TODO(fishythefish, natebiggs): Address the modular analysis inconsistency. - // Ideally, modular analysis shouldn't require global transformations to be - // run again, so we need to either delete modular analysis or make the data - // less brittle in the presence of AST modifications. // TODO(fishythefish): Add AST metadata to ensure transformations aren't rerun // unnecessarily. bool get shouldRunGlobalTransforms => - this.index <= Dart2JSStage.modularAnalysisFromDill.index; + this.index <= Dart2JSStage.cfeFromDill.index; - bool get canUseModularAnalysis => - this == Dart2JSStage.modularAnalysis || - this.index >= Dart2JSStage.modularAnalysisFromDill.index; bool get shouldReadClosedWorld => this.index > Dart2JSStage.closedWorld.index; bool get shouldReadGlobalInference => this.index > Dart2JSStage.globalInference.index; @@ -125,11 +105,6 @@ enum Dart2JSStage { if (options._cfeOnly) { return options._fromDill ? Dart2JSStage.cfeFromDill : Dart2JSStage.cfe; } - if (options._writeModularAnalysisUri != null) { - return options._fromDill - ? Dart2JSStage.modularAnalysisFromDill - : Dart2JSStage.modularAnalysis; - } if (options._deferredLoadIdMapUri != null) { return Dart2JSStage.deferredLoadIds; } @@ -323,7 +298,6 @@ class CompilerOptions implements DiagnosticOptions { _inputDillUri ?? entryUri ?? _defaultInputDillUri; bool get _fromDill { - if (sources != null) return false; var targetPath = (_inputDillUri ?? entryUri)?.path; return targetPath == null || targetPath.endsWith('.dill'); } @@ -333,26 +307,10 @@ class CompilerOptions implements DiagnosticOptions { /// List of kernel files to load. /// - /// When compiling modularly, this contains kernel files that are needed - /// to compile a single module. - /// - /// When linking, this contains all kernel files that form part of the final - /// program. - /// - /// At this time, this list points to full kernel files. In the future, we may - /// use a list of outline files for modular compiles, and only use full kernel - /// files for linking. + /// This contains all kernel files that form part of the final program. The + /// dills passed here should contain full kernel ASTs, not just outlines. List? dillDependencies; - /// A list of sources to compile, only used for modular analysis. - List? sources; - - Uri? _writeModularAnalysisUri; - - List? modularAnalysisInputs; - - bool get hasModularAnalysisInputs => modularAnalysisInputs != null; - /// Uses a memory mapped view of files for I/O. bool memoryMappedFiles = false; @@ -825,8 +783,6 @@ class CompilerOptions implements DiagnosticOptions { case Dart2JSStage.cfeFromDill: case Dart2JSStage.jsEmitter: case Dart2JSStage.codegenAndJsEmitter: - case Dart2JSStage.modularAnalysis: - case Dart2JSStage.modularAnalysisFromDill: case Dart2JSStage.deferredLoadIds: return null; case Dart2JSStage.closedWorld: @@ -860,9 +816,6 @@ class CompilerOptions implements DiagnosticOptions { return _deferredLoadIdMapUri; case Dart2JSStage.cfe: case Dart2JSStage.cfeFromDill: - case Dart2JSStage.modularAnalysis: - case Dart2JSStage.modularAnalysisFromDill: - return _writeModularAnalysisUri; case Dart2JSStage.closedWorld: return _writeClosedWorldUri; case Dart2JSStage.globalInference: @@ -995,13 +948,8 @@ class CompilerOptions implements DiagnosticOptions { ..showInternalProgress = _hasOption(options, Flags.progress) ..dillDependencies = _extractUriListOption(options, '${Flags.dillDependencies}') - ..sources = _extractUriListOption(options, '${Flags.sources}') ..readProgramSplit = _extractUriOption(options, '${Flags.readProgramSplit}=') - .._writeModularAnalysisUri = - _extractUriOption(options, '${Flags.writeModularAnalysis}=') - ..modularAnalysisInputs = - _extractUriListOption(options, '${Flags.readModularAnalysis}') .._readDataUri = _extractUriOption(options, '${Flags.readData}=') .._writeDataUri = _extractUriOption(options, '${Flags.writeData}=') ..memoryMappedFiles = _hasOption(options, Flags.memoryMappedFiles) @@ -1038,8 +986,6 @@ class CompilerOptions implements DiagnosticOptions { bool expectSourcesIn = false; bool expectKernelIn = false; bool expectKernelOut = false; - bool expectModularIn = false; - bool expectModularOut = false; bool expectDeferredLoadIdsOut = false; bool expectClosedWorldIn = false; bool expectClosedWorldOut = false; @@ -1057,22 +1003,10 @@ class CompilerOptions implements DiagnosticOptions { case Dart2JSStage.cfe: expectSourcesIn = true; expectKernelOut = true; - expectModularIn = true; - expectModularOut = true; break; case Dart2JSStage.cfeFromDill: expectKernelIn = true; expectKernelOut = true; - expectModularIn = true; - expectModularOut = true; - break; - case Dart2JSStage.modularAnalysis: - expectKernelOut = true; - expectModularOut = true; - break; - case Dart2JSStage.modularAnalysisFromDill: - expectKernelOut = true; - expectModularOut = true; break; case Dart2JSStage.deferredLoadIds: expectKernelIn = true; @@ -1081,30 +1015,25 @@ class CompilerOptions implements DiagnosticOptions { case Dart2JSStage.closedWorld: expectClosedWorldOut = true; expectKernelIn = true; - expectModularIn = true; break; case Dart2JSStage.globalInference: expectGlobalOut = true; expectKernelIn = true; - expectModularIn = true; expectClosedWorldIn = true; break; case Dart2JSStage.codegenSharded: expectCodegenOut = true; expectKernelIn = true; - expectModularIn = true; expectClosedWorldIn = true; expectGlobalIn = true; break; case Dart2JSStage.codegenAndJsEmitter: expectKernelIn = true; - expectModularIn = true; expectClosedWorldIn = true; expectGlobalIn = true; break; case Dart2JSStage.jsEmitter: expectKernelIn = true; - expectModularIn = true; expectClosedWorldIn = true; expectGlobalIn = true; expectCodegenIn = true; @@ -1124,15 +1053,6 @@ class CompilerOptions implements DiagnosticOptions { return 'Cannot write serialized data during ${stage.name} stage.'; } - // Check modular analysis flags. - if (_writeModularAnalysisUri != null && !expectModularOut) { - return 'Cannot write modular data during ${stage.name} stage.'; - } - if (modularAnalysisInputs != null && !expectModularIn) { - return 'Cannot read modular analysis inputs in ' - 'stage ${stage.name}.'; - } - if (_deferredLoadIdMapUri != null && !expectDeferredLoadIdsOut) { return 'Cannot write deferred load ID map during ${stage.name} stage.'; } diff --git a/pkg/compiler/lib/src/phase/load_kernel.dart b/pkg/compiler/lib/src/phase/load_kernel.dart index 0ec7a543987..f4ed90891d6 100644 --- a/pkg/compiler/lib/src/phase/load_kernel.dart +++ b/pkg/compiler/lib/src/phase/load_kernel.dart @@ -59,21 +59,13 @@ class Output { /// Note that [component] may contain some libraries that are excluded here. final List? libraries; - /// When running only dart2js modular analysis, returns the [Uri]s for - /// libraries loaded in the input module. - /// - /// This excludes other libraries reachable from them that were loaded as - /// dependencies. The result of [moduleLibraries] is always a subset of - /// [libraries]. - final List? moduleLibraries; - final fe.InitializedCompilerState? initializedCompilerState; - Output withNewComponent(ir.Component component) => Output(component, - rootLibraryUri, libraries, moduleLibraries, initializedCompilerState); + Output withNewComponent(ir.Component component) => + Output(component, rootLibraryUri, libraries, initializedCompilerState); Output(this.component, this.rootLibraryUri, this.libraries, - this.moduleLibraries, this.initializedCompilerState); + this.initializedCompilerState); } Library _findEntryLibrary(Component component, Uri entryUri) { @@ -114,10 +106,8 @@ String _getPlatformFilename(CompilerOptions options, String targetName) { class _LoadFromKernelResult { final ir.Component? component; final Library? entryLibrary; - final List moduleLibraries; - _LoadFromKernelResult( - this.component, this.entryLibrary, this.moduleLibraries); + _LoadFromKernelResult(this.component, this.entryLibrary); } // Perform any backend-specific transforms here that can be done on both @@ -142,7 +132,6 @@ Future<_LoadFromKernelResult> _loadFromKernel(CompilerOptions options, Library? entryLibrary; var resolvedUri = options.compilationTarget; ir.Component component = ir.Component(); - List moduleLibraries = []; Future read(Uri uri) async { api.Input input = @@ -152,10 +141,6 @@ Future<_LoadFromKernelResult> _loadFromKernel(CompilerOptions options, await read(resolvedUri); - if (options.stage.shouldComputeModularAnalysis) { - moduleLibraries = component.libraries.map((lib) => lib.importUri).toList(); - } - var isStrongDill = component.mode == ir.NonNullableByDefaultCompiledMode.Strong; var incompatibleNullSafetyMode = @@ -167,18 +152,10 @@ Future<_LoadFromKernelResult> _loadFromKernel(CompilerOptions options, "safety and is incompatible with the '$option' option"); } - // When compiling modularly, a dill for the SDK will be provided. In those - // cases we ignore the implicit platform binary. - bool platformBinariesIncluded = options.stage.shouldComputeModularAnalysis || - options.hasModularAnalysisInputs; if (options.platformBinaries != null && - options.stage.shouldReadPlatformBinaries && - !platformBinariesIncluded) { + options.stage.shouldReadPlatformBinaries) { var platformUri = options.platformBinaries ?.resolve(_getPlatformFilename(options, targetName)); - // Modular analysis can be run on the sdk by providing directly the - // path to the platform.dill file. In that case, we do not load the - // platform file implicitly. // TODO(joshualitt): Change how we detect this case so it is less // brittle. if (platformUri != resolvedUri) await read(platformUri!); @@ -199,16 +176,14 @@ Future<_LoadFromKernelResult> _loadFromKernel(CompilerOptions options, _doTransformsOnKernelLoad(component, options); registerSources(component, compilerInput); - return _LoadFromKernelResult(component, entryLibrary, moduleLibraries); + return _LoadFromKernelResult(component, entryLibrary); } class _LoadFromSourceResult { final ir.Component? component; final fe.InitializedCompilerState initializedCompilerState; - final List moduleLibraries; - _LoadFromSourceResult( - this.component, this.initializedCompilerState, this.moduleLibraries); + _LoadFromSourceResult(this.component, this.initializedCompilerState); } Future<_LoadFromSourceResult> _loadFromSource( @@ -234,53 +209,41 @@ Future<_LoadFromSourceResult> _loadFromSource( } }; - // If we are passed a list of sources, then we are performing a modular - // compile. In this case, we cannot infer null safety from the source files - // and must instead rely on the options passed in on the command line. - bool isModularCompile = false; - List sources = []; - if (options.sources != null) { - isModularCompile = true; - sources.addAll(options.sources!); - } else { - fe.CompilerOptions feOptions = fe.CompilerOptions() - ..target = target - ..librariesSpecificationUri = options.librariesSpecificationUri - ..packagesFileUri = options.packageConfig - ..explicitExperimentalFlags = options.explicitExperimentalFlags - ..environmentDefines = environment - ..verbose = verbose - ..fileSystem = fileSystem - ..onDiagnostic = onDiagnostic - ..verbosity = verbosity; - Uri resolvedUri = options.compilationTarget; - bool isLegacy = - await fe.uriUsesLegacyLanguageVersion(resolvedUri, feOptions); - if (isLegacy && options.experimentNullSafetyChecks) { - reporter.reportErrorMessage(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, { - 'text': 'The ${Flags.experimentNullSafetyChecks} option may be used ' - 'only after all libraries have been migrated to null safety. Some ' - 'libraries reached from $resolvedUri are still opted out of null ' - 'safety. Please migrate these libraries before passing ' - '${Flags.experimentNullSafetyChecks}.', - }); - } - if (isLegacy && options.nullSafetyMode == NullSafetyMode.sound) { - reporter.reportErrorMessage(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, { - 'text': "Starting with Dart 3.0, `dart compile js` expects programs to " - "be null-safe by default. Some libraries reached from $resolvedUri " - "are opted out of null safety. You can temporarily compile this " - "application using the deprecated '${Flags.noSoundNullSafety}' " - "option." - }); - } - sources.add(options.compilationTarget); + List sources = [options.compilationTarget]; + + fe.CompilerOptions feOptions = fe.CompilerOptions() + ..target = target + ..librariesSpecificationUri = options.librariesSpecificationUri + ..packagesFileUri = options.packageConfig + ..explicitExperimentalFlags = options.explicitExperimentalFlags + ..environmentDefines = environment + ..verbose = verbose + ..fileSystem = fileSystem + ..onDiagnostic = onDiagnostic + ..verbosity = verbosity; + Uri resolvedUri = options.compilationTarget; + bool isLegacy = await fe.uriUsesLegacyLanguageVersion(resolvedUri, feOptions); + if (isLegacy && options.experimentNullSafetyChecks) { + reporter.reportErrorMessage(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, { + 'text': 'The ${Flags.experimentNullSafetyChecks} option may be used ' + 'only after all libraries have been migrated to null safety. Some ' + 'libraries reached from $resolvedUri are still opted out of null ' + 'safety. Please migrate these libraries before passing ' + '${Flags.experimentNullSafetyChecks}.', + }); + } + if (isLegacy && options.nullSafetyMode == NullSafetyMode.sound) { + reporter.reportErrorMessage(NO_LOCATION_SPANNABLE, MessageKind.GENERIC, { + 'text': "Starting with Dart 3.0, `dart compile js` expects programs to " + "be null-safe by default. Some libraries reached from $resolvedUri " + "are opted out of null safety. You can temporarily compile this " + "application using the deprecated '${Flags.noSoundNullSafety}' " + "option." + }); } - // If we are performing a modular compile, we expect the platform binary to be - // supplied along with other dill dependencies. List dependencies = []; - if (options.platformBinaries != null && !isModularCompile) { + if (options.platformBinaries != null) { dependencies.add(options.platformBinaries! .resolve(_getPlatformFilename(options, targetName))); } @@ -300,8 +263,8 @@ Future<_LoadFromSourceResult> _loadFromSource( options.useLegacySubtyping ? fe.NnbdMode.Weak : fe.NnbdMode.Strong, invocationModes: options.cfeInvocationModes, verbosity: verbosity); - ir.Component? component = await fe.compile(initializedCompilerState, verbose, - fileSystem, onDiagnostic, sources, isModularCompile); + ir.Component? component = await fe.compile( + initializedCompilerState, verbose, fileSystem, onDiagnostic, sources); if (component != null) { assert(() { @@ -312,17 +275,10 @@ Future<_LoadFromSourceResult> _loadFromSource( _doTransformsOnKernelLoad(component, options); - // We have to compute canonical names on the component here to avoid missing - // canonical names downstream. - if (isModularCompile) { - component.computeCanonicalNames(); - } - registerSources(component, compilerInput); } - return _LoadFromSourceResult( - component, initializedCompilerState, isModularCompile ? sources : []); + return _LoadFromSourceResult(component, initializedCompilerState); } Output _createOutput( @@ -330,66 +286,57 @@ Output _createOutput( DiagnosticReporter reporter, Library? entryLibrary, ir.Component component, - List moduleLibraries, fe.InitializedCompilerState? initializedCompilerState) { Uri? rootLibraryUri = null; Iterable libraries = component.libraries; - if (!options.stage.shouldComputeModularAnalysis) { - // For non-modular builds we should always have a [mainMethod] at this - // point. - if (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."})); - } - - // If we are building from dill and are passed an [entryUri], then we use - // that to find the appropriate [entryLibrary]. Otherwise, we fallback to - // the [enclosingLibrary] of the [mainMethod]. - // NOTE: Under some circumstances, the [entryLibrary] exports the - // [mainMethod] from another library, and thus the [enclosingLibrary] of - // the [mainMethod] may not be the same as the [entryLibrary]. - var root = entryLibrary ?? component.mainMethod!.enclosingLibrary; - rootLibraryUri = root.importUri; - - // Filter unreachable libraries: [Component] was built by linking in the - // entire SDK libraries, not all of them are used. We include anything - // that is reachable from `main`. Note that all internal libraries that - // the compiler relies on are reachable from `dart:core`. - var seen = Set(); - search(ir.Library current) { - if (!seen.add(current)) return; - for (ir.LibraryDependency dep in current.dependencies) { - search(dep.targetLibrary); - } - } - - search(root); - - // Libraries dependencies do not show implicit imports to certain internal - // libraries. - const Set alwaysInclude = { - 'dart:_internal', - 'dart:core', - 'dart:async', - ...implicitlyUsedLibraries, - }; - for (String uri in alwaysInclude) { - Library library = component.libraries.firstWhere((lib) { - return '${lib.importUri}' == uri; - }); - search(library); - } - - libraries = libraries.where(seen.contains); + if (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 Output( - component, - rootLibraryUri, - libraries.map((lib) => lib.importUri).toList(), - moduleLibraries, - initializedCompilerState); + + // If we are building from dill and are passed an [entryUri], then we use + // that to find the appropriate [entryLibrary]. Otherwise, we fallback to + // the [enclosingLibrary] of the [mainMethod]. + // NOTE: Under some circumstances, the [entryLibrary] exports the + // [mainMethod] from another library, and thus the [enclosingLibrary] of + // the [mainMethod] may not be the same as the [entryLibrary]. + var root = entryLibrary ?? component.mainMethod!.enclosingLibrary; + rootLibraryUri = root.importUri; + + // Filter unreachable libraries: [Component] was built by linking in the + // entire SDK libraries, not all of them are used. We include anything + // that is reachable from `main`. Note that all internal libraries that + // the compiler relies on are reachable from `dart:core`. + var seen = Set(); + search(ir.Library current) { + if (!seen.add(current)) return; + for (ir.LibraryDependency dep in current.dependencies) { + search(dep.targetLibrary); + } + } + + search(root); + + // Libraries dependencies do not show implicit imports to certain internal + // libraries. + const Set alwaysInclude = { + 'dart:_internal', + 'dart:core', + 'dart:async', + ...implicitlyUsedLibraries, + }; + for (String uri in alwaysInclude) { + Library library = component.libraries.firstWhere((lib) { + return '${lib.importUri}' == uri; + }); + search(library); + } + + libraries = libraries.where(seen.contains); + return Output(component, rootLibraryUri, + libraries.map((lib) => lib.importUri).toList(), initializedCompilerState); } /// Loads an entire Kernel [Component] from a file on disk. @@ -402,7 +349,6 @@ Future run(Input input) async { Library? entryLibrary; ir.Component? component; - List moduleLibraries = const []; fe.InitializedCompilerState? initializedCompilerState = input.initializedCompilerState; if (options.stage.shouldLoadFromDill) { @@ -410,13 +356,11 @@ Future run(Input input) async { await _loadFromKernel(options, compilerInput, targetName); component = result.component; entryLibrary = result.entryLibrary; - moduleLibraries = result.moduleLibraries; } else { _LoadFromSourceResult result = await _loadFromSource(options, compilerInput, reporter, input.initializedCompilerState, targetName); component = result.component; initializedCompilerState = result.initializedCompilerState; - moduleLibraries = result.moduleLibraries; } if (component == null) return null; if (input.forceSerialization) { @@ -427,14 +371,14 @@ Future run(Input input) async { // Ensure we use the new deserialized entry point library. entryLibrary = _findEntryLibrary(component, options.entryUri!); } - return _createOutput(options, reporter, entryLibrary, component, - moduleLibraries, initializedCompilerState); + return _createOutput( + options, reporter, entryLibrary, component, initializedCompilerState); } /// Registers with the dart2js compiler all sources embedded in a kernel /// component. This may include sources that were read from disk directly as /// files, but also sources that were embedded in binary `.dill` files (like the -/// platform kernel file and kernel files from modular compilation pipelines). +/// platform kernel file). /// /// This registration improves how locations are presented when errors /// or crashes are reported by the dart2js compiler. diff --git a/pkg/compiler/lib/src/phase/modular_analysis.dart b/pkg/compiler/lib/src/phase/modular_analysis.dart deleted file mode 100644 index 4866ed9ab14..00000000000 --- a/pkg/compiler/lib/src/phase/modular_analysis.dart +++ /dev/null @@ -1,88 +0,0 @@ -// 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:kernel/ast.dart' as ir; - -import '../common.dart'; -import '../elements/entities.dart'; -import '../environment.dart'; -import '../ir/annotations.dart'; -import '../ir/impact.dart'; -import '../ir/modular.dart'; -import '../ir/scope.dart'; -import '../kernel/dart2js_target.dart'; -import '../kernel/native_basic_data.dart'; -import '../js_backend/annotations.dart'; -import '../kernel/element_map.dart'; -import '../options.dart'; - -class Input { - final CompilerOptions options; - final DiagnosticReporter reporter; - final Environment environment; - final ir.Component component; - final List libraries; - final Set moduleLibraries; - - Input(this.options, this.reporter, this.environment, this.component, - this.libraries, this.moduleLibraries); -} - -KernelToElementMap _createElementMap( - CompilerOptions options, - DiagnosticReporter reporter, - Environment environment, - ir.Component component, - List libraries) { - final elementMap = KernelToElementMap(reporter, environment, options); - elementMap.addComponent(component); - IrAnnotationData irAnnotationData = - processAnnotations(ModularCore(component, elementMap.constantEvaluator)); - final annotationProcessor = KernelAnnotationProcessor( - elementMap, elementMap.nativeBasicDataBuilder, irAnnotationData); - for (final uri in libraries) { - LibraryEntity library = elementMap.elementEnvironment.lookupLibrary(uri)!; - if (maybeEnableNative(library.canonicalUri)) { - annotationProcessor.extractNativeAnnotations(library); - } - annotationProcessor.extractJsInteropAnnotations(library); - } - return elementMap; -} - -Map _computeForLibrary( - CompilerOptions options, - DiagnosticReporter reporter, - KernelToElementMap elementMap, - ir.Library library) { - Map result = {}; - void computeForMember(ir.Member member) { - final scopeModel = ScopeModel.from(member, elementMap.constantEvaluator); - final annotations = processMemberAnnotations( - options, reporter, member, computePragmaAnnotationDataFromIr(member)); - result[member] = - computeModularMemberData(elementMap, member, scopeModel, annotations) - .impactBuilderData; - } - - library.members.forEach(computeForMember); - for (final cls in library.classes) { - cls.members.forEach(computeForMember); - } - return 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> 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); -} diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart index 694b70c72fe..e6ba8181de0 100644 --- a/pkg/compiler/lib/src/serialization/task.dart +++ b/pkg/compiler/lib/src/serialization/task.dart @@ -6,7 +6,6 @@ import 'dart:async'; import 'package:kernel/ast.dart' as ir; import 'package:kernel/binary/ast_from_binary.dart' as ir; import 'package:kernel/binary/ast_to_binary.dart' as ir; -import 'package:front_end/src/fasta/util/bytes_sink.dart'; import '../../compiler_api.dart' as api; import '../commandline_options.dart' show Flags; import '../common/codegen.dart'; @@ -20,7 +19,6 @@ import '../inferrer/abstract_value_domain.dart'; import '../inferrer/abstract_value_strategy.dart'; import '../inferrer/types.dart'; import '../io/source_information.dart'; -import '../ir/modular.dart'; import '../js_backend/codegen_inputs.dart'; import '../js_backend/inferred_data.dart'; import '../js_model/js_world.dart'; @@ -59,9 +57,6 @@ class SerializationTask extends CompilerTask { void serializeComponent(ir.Component component, {bool includeSourceBytes = true}) { measureSubtask('serialize dill', () { - // TODO(sigmund): remove entirely: we will do this immediately as soon as - // we get the component in the kernel/loader.dart task once we refactor - // how we apply our modular kernel transformation for super mixin calls. _reporter.log('Writing dill to ${_options.outputUri}'); api.BinaryOutputSink dillOutput = _outputProvider.createBinarySink(_options.outputUri!); @@ -112,80 +107,6 @@ class SerializationTask extends CompilerTask { return component; } - void serializeModuleData( - ModuleData data, ir.Component component, Set includedLibraries) { - measureSubtask('serialize transformed dill', () { - _reporter.log('Writing dill to ${_options.outputUri}'); - var dillOutput = _outputProvider.createBinarySink(_options.outputUri!); - ir.BinaryPrinter printer = ir.BinaryPrinter(dillOutput, - libraryFilter: (ir.Library l) => - includedLibraries.contains(l.importUri)); - printer.writeComponentFile(component); - dillOutput.close(); - }); - - measureSubtask('serialize module data', () { - final outputUri = - _options.dataOutputUriForStage(Dart2JSStage.modularAnalysis); - _reporter.log('Writing data to $outputUri'); - api.BinaryOutputSink dataOutput = - _outputProvider.createBinarySink(outputUri); - // Use empty indices since module data is ephemeral, later phases should - // not depend on data indexed in this file. - DataSinkWriter sink = DataSinkWriter( - BinaryDataSink(dataOutput), _options, SerializationIndices()); - data.toDataSink(sink); - sink.close(); - }); - } - - void testModuleSerialization(ModuleData data, ir.Component component) { - if (_options.testMode) { - // TODO(joshualitt): - // Consider using a strategy like we do for the global data, so we can also - // test it with the objectSink/objectSource: - // List encoding = []; - // DataSink sink = ObjectSink(encoding, useDataKinds: true); - // data.toDataSink(sink); - // DataSource source = ObjectSource(encoding, useDataKinds: true); - // source.registerComponentLookup(new ComponentLookup(component)); - // ModuleData.fromDataSource(source); - - // Use empty indices since module data is ephemeral, later phases should - // not depend on data indexed in this file. - BytesSink bytes = BytesSink(); - DataSinkWriter binarySink = DataSinkWriter( - BinaryDataSink(bytes), _options, SerializationIndices(), - useDataKinds: true); - data.toDataSink(binarySink); - binarySink.close(); - var source = DataSourceReader(BinaryDataSource(bytes.builder.toBytes()), - _options, SerializationIndices(), - useDataKinds: true, interner: _valueInterner); - source.registerComponentLookup(ComponentLookup(component)); - ModuleData.fromDataSource(source); - } - } - - Future deserializeModuleData(ir.Component component) async { - return await measureIoSubtask('deserialize module data', () async { - _reporter.log('Reading data from ${_options.modularAnalysisInputs}'); - final results = ModuleData(); - for (Uri uri in _options.modularAnalysisInputs!) { - final dataInput = - await _provider.readFromUri(uri, inputKind: api.InputKind.binary); - // Use empty indices since module data is ephemeral, later phases should - // not depend on data indexed in this file. - DataSourceReader source = DataSourceReader( - BinaryDataSource(dataInput.data), _options, SerializationIndices(), - interner: _valueInterner); - source.registerComponentLookup(ComponentLookup(component)); - results.readMoreFromDataSource(source); - } - return results; - }); - } - void serializeClosedWorld( JClosedWorld closedWorld, SerializationIndices indices) { measureSubtask('serialize closed world', () { diff --git a/pkg/compiler/test/end_to_end/command_line_test.dart b/pkg/compiler/test/end_to_end/command_line_test.dart index 7b5da0ebb6d..b09d61e0bf8 100644 --- a/pkg/compiler/test/end_to_end/command_line_test.dart +++ b/pkg/compiler/test/end_to_end/command_line_test.dart @@ -48,17 +48,6 @@ main() { await test([Flags.cfeOnly, 'foo.dart', '--out=prefix-'], out: 'prefix-'); await test([Flags.cfeOnly, 'foo.dart', '--out=/some/path/prefix-'], out: '/some/path/prefix-'); - await test( - [ - Flags.cfeOnly, - 'foo.dart', - '${Flags.readModularAnalysis}=modular1.data,modular2.data', - '${Flags.writeModularAnalysis}=modularcfe.data', - ], - cfeModularAnalysis: true, - readModularAnalysis: ['modular1.data', 'modular2.data'], - writeModularAnalysis: 'modularcfe.data', - out: 'out.dill'); await test(['foo.dart', '${Flags.stage}=cfe', '--out=/some/path/'], out: '/some/path/out.dill'); await test(['foo.dart', '${Flags.stage}=cfe', '--out=prefix-'], @@ -83,18 +72,6 @@ main() { cfeFromDill: true, out: 'prefix-'); await test([Flags.cfeOnly, 'foo.dill', '--out=/some/path/prefix-'], cfeFromDill: true, out: '/some/path/prefix-'); - await test( - [ - Flags.cfeOnly, - 'foo.dill', - '${Flags.readModularAnalysis}=modular1.data,modular2.data', - '${Flags.writeModularAnalysis}=modularcfe.data', - ], - cfeFromDill: true, - cfeModularAnalysis: true, - readModularAnalysis: ['modular1.data', 'modular2.data'], - writeModularAnalysis: 'modularcfe.data', - out: 'out.dill'); await test(['foo.dill', '${Flags.stage}=cfe', '--out=/some/path/'], cfeFromDill: true, out: '/some/path/out.dill'); await test(['foo.dill', '${Flags.stage}=cfe', '--out=prefix-'], @@ -105,43 +82,6 @@ main() { '--out=/some/path/prefix-', ], cfeFromDill: true, out: '/some/path/prefix-out.dill'); - // Run modular analysis only - await test(['${Flags.stage}=modular-analysis', 'foo.dart'], - writeModularAnalysis: 'modular.data', out: 'out.dill'); - await test( - ['${Flags.stage}=modular-analysis', '--out=out1.dill', 'foo.dart'], - writeModularAnalysis: 'modular.data', out: 'out1.dill'); - await test([ - '${Flags.stage}=modular-analysis', - '${Flags.writeModularAnalysis}=modular1.data', - 'foo.dart' - ], writeModularAnalysis: 'modular1.data', out: 'out.dill'); - await test(['${Flags.writeModularAnalysis}=modular1.data', 'foo.dart'], - out: 'out.dill', writeModularAnalysis: 'modular1.data'); - await test([ - '${Flags.writeModularAnalysis}=modular1.data', - 'foo.dart', - '--out=out1.dill' - ], out: 'out1.dill', writeModularAnalysis: 'modular1.data'); - await test([ - '${Flags.writeModularAnalysis}=modular1.data', - 'foo.dart', - '-oout1.dill' - ], out: 'out1.dill', writeModularAnalysis: 'modular1.data'); - await test( - ['foo.dart', '${Flags.stage}=modular-analysis', '--out=/some/path/'], - writeModularAnalysis: '/some/path/modular.data', - out: '/some/path/out.dill'); - await test(['foo.dart', '${Flags.stage}=modular-analysis', '--out=prefix-'], - writeModularAnalysis: 'prefix-modular.data', out: 'prefix-out.dill'); - await test([ - 'foo.dart', - '${Flags.stage}=modular-analysis', - '--out=/some/path/prefix-' - ], - writeModularAnalysis: '/some/path/prefix-modular.data', - out: '/some/path/prefix-out.dill'); - // Run deferred load ids only await test([ '${Flags.stage}=deferred-load-ids', @@ -183,15 +123,6 @@ main() { 'foo.dill', '--out=/some/path/prefix-' ], out: '/some/path/prefix-', writeClosedWorld: 'world1.data'); - await test( - [ - '${Flags.readModularAnalysis}=modular1.data,modular2.data', - '${Flags.writeClosedWorld}=world1.data', - 'foo.dill' - ], - out: 'out.dill', - readModularAnalysis: ['modular1.data', 'modular2.data'], - writeClosedWorld: 'world1.data'); await test(['foo.dill', '${Flags.stage}=closed-world', '--out=/some/path/'], writeClosedWorld: '/some/path/world.data', out: '/some/path/out.dill'); await test(['foo.dill', '${Flags.stage}=closed-world', '--out=prefix-'], @@ -234,15 +165,6 @@ main() { 'foo.dill', '--out=/some/path/prefix-' ], readClosedWorld: 'world1.data', writeData: 'global1.data'); - await test([ - '${Flags.readModularAnalysis}=modular1.data,modular2.data', - '${Flags.readClosedWorld}=world1.data', - '${Flags.writeData}=global1.data', - 'foo.dill' - ], readModularAnalysis: [ - 'modular1.data', - 'modular2.data' - ], readClosedWorld: 'world1.data', writeData: 'global1.data'); await test( ['foo.dill', '${Flags.stage}=global-inference', '--out=/some/path/'], readClosedWorld: '/some/path/world.data', @@ -368,24 +290,6 @@ main() { writeCodegen: 'codegen1', codegenShard: 10, codegenShards: 11); - await test([ - '${Flags.readModularAnalysis}=modular1.data,modular2.data', - '${Flags.readClosedWorld}=world1.data', - '${Flags.readData}=global1.data', - '${Flags.writeCodegen}=codegen1', - '${Flags.codegenShard}=10', - '${Flags.codegenShards}=11', - 'foo.dill' - ], - readModularAnalysis: [ - 'modular1.data', - 'modular2.data' - ], - readClosedWorld: 'world1.data', - readData: 'global1.data', - writeCodegen: 'codegen1', - codegenShard: 10, - codegenShards: 11); await test([ 'foo.dill', '${Flags.stage}=codegen', @@ -527,23 +431,6 @@ main() { readCodegen: 'codegen1', codegenShards: 11, out: 'out1.js'); - await test([ - '${Flags.readModularAnalysis}=modular1.data,modular2.data', - '${Flags.readClosedWorld}=world1.data', - '${Flags.readData}=global1.data', - '${Flags.readCodegen}=codegen1', - '${Flags.codegenShards}=11', - 'foo.dill' - ], - readModularAnalysis: [ - 'modular1.data', - 'modular2.data' - ], - readClosedWorld: 'world1.data', - readData: 'global1.data', - readCodegen: 'codegen1', - codegenShards: 11, - out: 'out.js'); await test([ 'foo.dill', '${Flags.stage}=emit-js', @@ -615,15 +502,6 @@ main() { readClosedWorld: 'world1.data', readData: 'global1.data', out: 'out1.js'); - await test([ - '${Flags.readModularAnalysis}=modular1.data,modular2.data', - '${Flags.readClosedWorld}=world1.data', - '${Flags.readData}=global1.data', - 'foo.dill' - ], readModularAnalysis: [ - 'modular1.data', - 'modular2.data' - ], readClosedWorld: 'world1.data', readData: 'global1.data', out: 'out.js'); await test( ['foo.dill', '${Flags.stage}=codegen-emit-js', '--out=/some/path/'], readClosedWorld: '/some/path/world.data', @@ -938,8 +816,6 @@ main() { Future test(List arguments, {int? exitCode, String? out, - List? readModularAnalysis, - String? writeModularAnalysis, bool allFromDill = false, bool cfeFromDill = false, bool cfeModularAnalysis = false, @@ -982,27 +858,6 @@ Future test(List arguments, if (cfeFromDill) { Expect.equals(Dart2JSStage.cfeFromDill, options.stage); } - if (readModularAnalysis != null) { - Expect.isNotNull(options.modularAnalysisInputs, - "modularAnalysisInputs expected to be non-null."); - Expect.listEquals( - readModularAnalysis.map(toUri).toList(), - options.modularAnalysisInputs!, - "Unexpected modularAnalysisInputs uri"); - } - if (writeModularAnalysis == null) { - Expect.notEquals(options.stage, Dart2JSStage.modularAnalysis); - } else { - Expect.equals( - options.stage, - cfeModularAnalysis - ? (cfeFromDill ? Dart2JSStage.cfeFromDill : Dart2JSStage.cfe) - : Dart2JSStage.modularAnalysis); - Expect.equals( - toUri(writeModularAnalysis), - options.dataOutputUriForStage(Dart2JSStage.modularAnalysis), - "Unexpected writeModularAnalysis uri"); - } if (writeDeferredLoadIds == null) { Expect.notEquals(options.stage, Dart2JSStage.deferredLoadIds); } else { diff --git a/pkg/compiler/test/end_to_end/modular_loader_test.dart b/pkg/compiler/test/end_to_end/modular_loader_test.dart index 84c1aa89c41..ef2f80d3090 100644 --- a/pkg/compiler/test/end_to_end/modular_loader_test.dart +++ b/pkg/compiler/test/end_to_end/modular_loader_test.dart @@ -30,6 +30,8 @@ main() { var cDill = await compileUnit( ['c2.dart'], {'c2.dart': sourceC, 'a.dill': aDill, 'b.dill': bDill}, deps: ['a.dill', 'b.dill']); + var unusedDill = + await compileUnit(['unused0.dart'], {'unused0.dart': unusedSource}); DiagnosticCollector diagnostics = DiagnosticCollector(); OutputCollector output = OutputCollector(); @@ -38,10 +40,15 @@ main() { entryPoint: entryPoint, options: [ '--input-dill=memory:c.dill', - '--dill-dependencies=memory:a.dill,memory:b.dill', + '--dill-dependencies=memory:a.dill,memory:b.dill,memory:unused.dill', '--sound-null-safety', ], - memorySourceFiles: {'a.dill': aDill, 'b.dill': bDill, 'c.dill': cDill}, + memorySourceFiles: { + 'a.dill': aDill, + 'b.dill': bDill, + 'c.dill': cDill, + 'unused.dill': unusedDill + }, diagnosticHandler: diagnostics, outputProvider: output); load_kernel.Output result = (await load_kernel.run(load_kernel.Input( @@ -50,6 +57,9 @@ main() { compiler.reporter, compiler.initializedCompilerState, false)))!; + + // Make sure we trim the unused library. + Expect.isFalse(result.libraries!.any((l) => l.path == '/unused0.dart')); compiler.frontendStrategy .registerLoadedLibraries(result.component, result.libraries!); @@ -146,3 +156,7 @@ class C2 extends B1 { main() => print(C2().foo.buffer.toString()); '''; + +const unusedSource = ''' +void unused() => throw 'Unused'; +'''; diff --git a/pkg/compiler/test/end_to_end/no_platform_test.dart b/pkg/compiler/test/end_to_end/no_platform_test.dart index 9a1cabe0110..a4e7cb9e532 100644 --- a/pkg/compiler/test/end_to_end/no_platform_test.dart +++ b/pkg/compiler/test/end_to_end/no_platform_test.dart @@ -29,8 +29,9 @@ main() { (fe.DiagnosticMessage message) { message.plainTextFormatted.forEach(print); Expect.notEquals(fe.Severity.error, message.severity); - }, [Uri.base.resolve('pkg/compiler/test/end_to_end/data/hello_world.dart')], - false))!; + }, [ + Uri.base.resolve('pkg/compiler/test/end_to_end/data/hello_world.dart') + ]))!; Expect.isNotNull(new ir.CoreTypes(component).futureClass); } diff --git a/pkg/compiler/test/end_to_end/trim_component_test.dart b/pkg/compiler/test/end_to_end/trim_component_test.dart deleted file mode 100644 index 5da8a165ed1..00000000000 --- a/pkg/compiler/test/end_to_end/trim_component_test.dart +++ /dev/null @@ -1,102 +0,0 @@ -// 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 'package:kernel/ast.dart' as ir; -import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder; -import 'package:compiler/src/util/memory_compiler.dart'; - -const memorySourceFiles = const { - 'main.dart': ''' -// @dart=2.12 -import 'used.dart'; - -void main() { - foo(); -} - -''', - 'used.dart': ''' -// @dart=2.12 - -void foo() { - print('foo'); -} -''', - 'unused.dart': ''' -// @dart=2.12 - -void unused() { - throw 'unused'; -} -''' -}; - -void verifyComponent( - ir.Component component, List included, List excluded) { - Set uris = {}; - component.libraries - .forEach((library) => uris.add(library.importUri.toString())); - for (String include in included) { - Expect.isTrue(uris.contains(include)); - } - for (String exclude in excluded) { - Expect.isFalse(uris.contains(exclude)); - } -} - -Future> buildDillAndVerify( - Map memorySourceFiles, - List flags, - List includedLibraries, - List excludedLibraries) async { - final dillUri = Uri.parse('out.dill'); - final collector = OutputCollector(); - CompilationResult result = await runCompiler( - memorySourceFiles: memorySourceFiles, - options: flags, - outputProvider: collector); - Expect.isTrue(result.isSuccess); - Expect.isTrue(collector.binaryOutputMap.containsKey(dillUri)); - List bytes = collector.binaryOutputMap[dillUri]!.list; - Expect.isTrue(bytes.isNotEmpty); - ir.Component component = ir.Component(); - BinaryBuilder(bytes).readComponent(component); - verifyComponent(component, includedLibraries, excludedLibraries); - return bytes; -} - -Future verifyComponentTrim() async { - List buildDillFromSourceFlags = [ - '--cfe-only', - '--out=out.dill', - '--sources=memory:main.dart,memory:used.dart,memory:unused.dart', - '--sound-null-safety', - ]; - List bytes = await buildDillAndVerify( - memorySourceFiles, - buildDillFromSourceFlags, - ['memory:main.dart', 'memory:used.dart', 'memory:unused.dart'], - []); - - // The combination of `--cfe-only` + `--entry-uri` should trigger the - // component trimming logic. - List trimDillFlags = [ - '--input-dill=memory:main.dill', - '--cfe-only', - '--out=out.dill', - '--entry-uri=memory:main.dart', - '--sound-null-safety', - ]; - List newBytes = await buildDillAndVerify( - {'main.dill': bytes}, - trimDillFlags, - ['memory:main.dart', 'memory:used.dart'], - ['memory:unused.dart']); - Expect.isTrue(newBytes.length < bytes.length); -} - -void main() async { - await verifyComponentTrim(); -} diff --git a/pkg/compiler/tool/modular_test_suite.dart b/pkg/compiler/tool/modular_test_suite.dart index 2d063c00889..61a49cd8d98 100644 --- a/pkg/compiler/tool/modular_test_suite.dart +++ b/pkg/compiler/tool/modular_test_suite.dart @@ -2,7 +2,7 @@ // 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. -/// Test the modular compilation pipeline of dart2js. +/// Test the compilation pipeline of dart2js. /// /// This is a shell that runs multiple tests, one per folder under `data/`. import 'dart:async'; @@ -21,11 +21,9 @@ main(List args) async { options, IOPipeline([ OutlineDillCompilationStep(), - FullDillCompilationStep(onlyOnSdk: true), - ModularAnalysisStep(onlyOnSdk: true), - ModularAnalysisStep(), - ConcatenateDillsStep(useModularAnalysis: true), - ComputeClosedWorldStep(useModularAnalysis: true), + FullDillCompilationStep(), + ConcatenateDillsStep(), + ComputeClosedWorldStep(), GlobalAnalysisStep(), Dart2jsCodegenStep(codeId0), Dart2jsCodegenStep(codeId1), diff --git a/pkg/compiler/tool/modular_test_suite_helper.dart b/pkg/compiler/tool/modular_test_suite_helper.dart index b1caf2e2475..0934824ad79 100644 --- a/pkg/compiler/tool/modular_test_suite_helper.dart +++ b/pkg/compiler/tool/modular_test_suite_helper.dart @@ -28,9 +28,6 @@ late String _kernelWorkerScript; const dillSummaryId = DataId("summary.dill"); const dillId = DataId("full.dill"); const fullDillId = DataId("concatenate.dill"); -const modularUpdatedDillId = DataId("modular.dill"); -const modularDataId = DataId("modular.data"); -const modularFullDataId = DataId("concatenate.modular.data"); const closedWorldId = DataId("world"); const globalUpdatedDillId = DataId("global.dill"); const globalDataId = DataId("global.data"); @@ -74,7 +71,7 @@ List getSources(Module module) { abstract class CFEStep extends IOModularStep { final String stepName; - CFEStep(this.stepName, this.onlyOnSdk); + CFEStep(this.stepName); @override bool get needsSources => true; @@ -82,9 +79,6 @@ abstract class CFEStep extends IOModularStep { @override bool get onlyOnMain => false; - @override - final bool onlyOnSdk; - @override Future execute(Module module, Uri root, ModuleDataToRelativeUri toUri, List flags) async { @@ -181,7 +175,7 @@ class OutlineDillCompilationStep extends CFEStep { @override DataId get outputData => dillSummaryId; - OutlineDillCompilationStep() : super('outline-dill-compilation', false); + OutlineDillCompilationStep() : super('outline-dill-compilation'); } // Step that compiles sources in a module to a .dill file. @@ -208,113 +202,14 @@ class FullDillCompilationStep extends CFEStep { @override DataId get outputData => dillId; - FullDillCompilationStep({bool onlyOnSdk = false}) - : super('full-dill-compilation', onlyOnSdk); -} - -class ModularAnalysisStep extends IOModularStep { - @override - List get resultData => [modularDataId, modularUpdatedDillId]; - - @override - bool get needsSources => !onlyOnSdk; - - /// The SDK has no dependencies, and for all other modules we only need - /// summaries. - @override - List get dependencyDataNeeded => [dillSummaryId]; - - /// All non SDK modules only need sources for module data. - @override - List get moduleDataNeeded => onlyOnSdk ? [dillId] : const []; - - @override - bool get onlyOnMain => false; - - @override - final bool onlyOnSdk; - - @override - bool get notOnSdk => !onlyOnSdk; - - // TODO(joshualitt): We currently special case the SDK both because it is not - // trivial to build it in the same fashion as other modules, and because it is - // a special case in other build environments. Eventually, we should - // standardize this a bit more and always build the SDK modularly, if we have - // to build it. - ModularAnalysisStep({this.onlyOnSdk = false}); - - @override - Future execute(Module module, Uri root, ModuleDataToRelativeUri toUri, - List flags) async { - if (_options.verbose) print("\nstep: modular analysis on $module"); - Set transitiveDependencies = computeTransitiveDependencies(module); - List dillDependencies = []; - List sources = []; - List extraArgs = []; - if (!module.isSdk) { - await writePackageConfig(module, transitiveDependencies, root); - String rootScheme = getRootScheme(module); - sources = getSources(module); - dillDependencies = transitiveDependencies - .map((m) => '${toUri(m, dillSummaryId)}') - .toList(); - extraArgs = [ - '--packages=${root.resolve(packageConfigJsonPath)}', - '--multi-root=$root', - '--multi-root-scheme=$rootScheme', - ]; - } - - List args = [ - '--packages=${sdkRoot.toFilePath()}/$packageConfigJsonPath', - _dart2jsScript, - Flags.soundNullSafety, - if (_options.useSdk) '--libraries-spec=$_librarySpecForSnapshot', - if (_options.useSdk) '--invoker=modular_test', - // If we have sources, then we aren't building the SDK, otherwise we - // assume we are building the sdk and pass in a full dill. - if (sources.isNotEmpty) - '${Flags.sources}=${sources.join(',')}' - else - '${Flags.inputDill}=${toUri(module, dillId)}', - '${Flags.cfeConstants}', - if (dillDependencies.isNotEmpty) - '--dill-dependencies=${dillDependencies.join(',')}', - '--out=${toUri(module, modularUpdatedDillId)}', - '${Flags.writeModularAnalysis}=${toUri(module, modularDataId)}', - for (String flag in flags) '--enable-experiment=$flag', - ...extraArgs - ]; - var result = - await _runProcess(Platform.resolvedExecutable, args, root.toFilePath()); - - _checkExitCode(result, this, module); - } - - @override - void notifyCached(Module module) { - if (_options.verbose) { - print("cached step: dart2js modular analysis on $module"); - } - } + FullDillCompilationStep() : super('full-dill-compilation'); } class ConcatenateDillsStep extends IOModularStep { - final bool useModularAnalysis; - - DataId get idForDill => useModularAnalysis ? modularUpdatedDillId : dillId; - - List get dependencies => [ - idForDill, - if (useModularAnalysis) modularDataId, - ]; + List get dependencies => [dillId]; @override - List get resultData => [ - fullDillId, - if (useModularAnalysis) modularFullDataId, - ]; + List get resultData => [fullDillId]; @override bool get needsSources => false; @@ -328,20 +223,15 @@ class ConcatenateDillsStep extends IOModularStep { @override bool get onlyOnMain => true; - ConcatenateDillsStep({required this.useModularAnalysis}); + ConcatenateDillsStep(); @override Future execute(Module module, Uri root, ModuleDataToRelativeUri toUri, List flags) async { if (_options.verbose) print("\nstep: dart2js concatenate dills on $module"); Set transitiveDependencies = computeTransitiveDependencies(module); - DataId dillId = idForDill; Iterable dillDependencies = transitiveDependencies.map((m) => '${toUri(m, dillId)}'); - List dataDependencies = transitiveDependencies - .map((m) => '${toUri(m, modularDataId)}') - .toList(); - dataDependencies.add('${toUri(module, modularDataId)}'); List args = [ '--packages=${sdkRoot.toFilePath()}/$packageConfigJsonPath', _dart2jsScript, @@ -353,10 +243,6 @@ class ConcatenateDillsStep extends IOModularStep { '${Flags.inputDill}=${toUri(module, dillId)}', for (String flag in flags) '--enable-experiment=$flag', '${Flags.dillDependencies}=${dillDependencies.join(',')}', - if (useModularAnalysis) ...[ - '${Flags.readModularAnalysis}=${dataDependencies.join(',')}', - '${Flags.writeModularAnalysis}=${toUri(module, modularFullDataId)}', - ], '${Flags.cfeOnly}', '--out=${toUri(module, fullDillId)}', ]; @@ -375,14 +261,9 @@ class ConcatenateDillsStep extends IOModularStep { // Step that invokes the dart2js closed world computation. class ComputeClosedWorldStep extends IOModularStep { - final bool useModularAnalysis; + ComputeClosedWorldStep(); - ComputeClosedWorldStep({required this.useModularAnalysis}); - - List get dependencies => [ - fullDillId, - if (useModularAnalysis) modularFullDataId, - ]; + List get dependencies => [fullDillId]; @override List get resultData => const [closedWorldId, globalUpdatedDillId]; @@ -414,8 +295,6 @@ class ComputeClosedWorldStep extends IOModularStep { '${Flags.entryUri}=$fakeRoot${module.mainSource}', '${Flags.inputDill}=${toUri(module, fullDillId)}', for (String flag in flags) '--enable-experiment=$flag', - if (useModularAnalysis) - '${Flags.readModularAnalysis}=${toUri(module, modularFullDataId)}', '${Flags.writeClosedWorld}=${toUri(module, closedWorldId)}', Flags.noClosedWorldInData, '--out=${toUri(module, globalUpdatedDillId)}', diff --git a/pkg/compiler/tool/modular_test_suite_legacy.dart b/pkg/compiler/tool/modular_test_suite_legacy.dart deleted file mode 100644 index f1700694853..00000000000 --- a/pkg/compiler/tool/modular_test_suite_legacy.dart +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2019, 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. - -/// Test the modular compilation pipeline of dart2js. -/// -/// This is a shell that runs multiple tests, one per folder under `data/`. -import 'dart:async'; - -import 'package:modular_test/src/io_pipeline.dart'; -import 'package:modular_test/src/runner.dart'; -import 'modular_test_suite_helper.dart'; - -main(List args) async { - var options = Options.parse(args); - await resolveScripts(options); - await Future.wait([ - runSuite( - sdkRoot.resolve('tests/modular/'), - 'tests/modular', - options, - IOPipeline([ - OutlineDillCompilationStep(), - FullDillCompilationStep(), - ConcatenateDillsStep(useModularAnalysis: false), - ComputeClosedWorldStep(useModularAnalysis: false), - GlobalAnalysisStep(), - Dart2jsCodegenStep(codeId0), - Dart2jsCodegenStep(codeId1), - Dart2jsEmissionStep(), - RunD8(), - ], cacheSharedModules: true)), - ]); -} diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart index 2fced4479ff..0ce03320d3e 100644 --- a/pkg/front_end/lib/src/api_unstable/dart2js.dart +++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart @@ -179,9 +179,8 @@ Future compile( bool verbose, FileSystem fileSystem, DiagnosticMessageHandler onDiagnostic, - List inputs, - bool isModularCompile) async { - assert(inputs.length == 1 || isModularCompile); + List inputs) async { + assert(inputs.length == 1); CompilerOptions options = state.options; options ..onDiagnostic = onDiagnostic @@ -198,7 +197,7 @@ Future compile( CompilerResult compilerResult = await generateKernelInternal(); Component? component = compilerResult.component; if (component == null) return null; - if (component.mainMethod == null && !isModularCompile) { + if (component.mainMethod == null) { context.options.report( messageMissingMain.withLocation(inputs.single, -1, 0), Severity.error); diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json index b07e79cddbf..691de9a8380 100644 --- a/tools/bots/test_matrix.json +++ b/tools/bots/test_matrix.json @@ -2424,17 +2424,6 @@ "shards": 4, "fileset": "js_platform_2" }, - { - "name": "dart2js legacy modular tests", - "script": "out/ReleaseX64/dart-sdk/bin/dart", - "testRunner": true, - "arguments": [ - "pkg/compiler/tool/modular_test_suite_legacy.dart", - "-nweb-unittest-asserts-legacy-linux", - "--verbose", - "--use-sdk" - ] - }, { "name": "dart2js modular tests", "script": "out/ReleaseX64/dart-sdk/bin/dart",