mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 04:27:17 +00:00
[dart2js] Disable kernel transformer when using modular analysis.
Mutating the kernel AST can cause serialization and deserialization to go out of sync when modular analysis is enabled, crashing dart2js. Change-Id: If19afabacf1cb120a6804bd12ef268316de41f1b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/286862 Reviewed-by: Sigmund Cherem <sigmund@google.com> Reviewed-by: Nate Biggs <natebiggs@google.com> Commit-Queue: Mayank Patke <fishythefish@google.com>
This commit is contained in:
parent
3c633384d3
commit
6414db5327
|
@ -397,7 +397,7 @@ class Compiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<load_kernel.Output?> produceKernel() async {
|
Future<load_kernel.Output?> produceKernel() async {
|
||||||
if (options.readClosedWorldUri == null) {
|
if (shouldComputeClosedWorld) {
|
||||||
load_kernel.Output? output = await loadKernel();
|
load_kernel.Output? output = await loadKernel();
|
||||||
if (output == null || compilationFailed) return null;
|
if (output == null || compilationFailed) return null;
|
||||||
ir.Component component = output.component;
|
ir.Component component = output.component;
|
||||||
|
@ -445,42 +445,37 @@ class Compiler {
|
||||||
bool shouldStopAfterLoadKernel(load_kernel.Output? output) =>
|
bool shouldStopAfterLoadKernel(load_kernel.Output? output) =>
|
||||||
output == null || compilationFailed || options.cfeOnly;
|
output == null || compilationFailed || options.cfeOnly;
|
||||||
|
|
||||||
void simplifyConstConditionals(load_kernel.Output output) {
|
void simplifyConstConditionals(ir.Component component) {
|
||||||
if (options.readClosedWorldUri == null) {
|
void reportMessage(
|
||||||
void reportMessage(
|
fe.LocatedMessage message, List<fe.LocatedMessage>? context) {
|
||||||
fe.LocatedMessage message, List<fe.LocatedMessage>? context) {
|
reportLocatedMessage(reporter, message, context);
|
||||||
reportLocatedMessage(reporter, message, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool shouldNotInline(ir.TreeNode node) {
|
|
||||||
if (node is! ir.Annotatable) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return computePragmaAnnotationDataFromIr(node).any((pragma) =>
|
|
||||||
pragma == const PragmaAnnotationData('noInline') ||
|
|
||||||
pragma == const PragmaAnnotationData('never-inline'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// No existing closed world means we're in phase 1, so run the
|
|
||||||
// transformer.
|
|
||||||
fe.ConstConditionalSimplifier(
|
|
||||||
const Dart2jsDartLibrarySupport(),
|
|
||||||
const Dart2jsConstantsBackend(
|
|
||||||
supportsUnevaluatedConstants: false),
|
|
||||||
output.component,
|
|
||||||
reportMessage,
|
|
||||||
environmentDefines: environment.definitions,
|
|
||||||
evaluationMode: options.useLegacySubtyping
|
|
||||||
? fe.EvaluationMode.weak
|
|
||||||
: fe.EvaluationMode.strong,
|
|
||||||
shouldNotInline: shouldNotInline)
|
|
||||||
.run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the closed world is deserialized instead, then the input .dill should
|
bool shouldNotInline(ir.TreeNode node) {
|
||||||
// already have the modified AST.
|
if (node is! ir.Annotatable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return computePragmaAnnotationDataFromIr(node).any((pragma) =>
|
||||||
|
pragma == const PragmaAnnotationData('noInline') ||
|
||||||
|
pragma == const PragmaAnnotationData('never-inline'));
|
||||||
|
}
|
||||||
|
|
||||||
|
fe.ConstConditionalSimplifier(
|
||||||
|
const Dart2jsDartLibrarySupport(),
|
||||||
|
const Dart2jsConstantsBackend(supportsUnevaluatedConstants: false),
|
||||||
|
component,
|
||||||
|
reportMessage,
|
||||||
|
environmentDefines: environment.definitions,
|
||||||
|
evaluationMode: options.useLegacySubtyping
|
||||||
|
? fe.EvaluationMode.weak
|
||||||
|
: fe.EvaluationMode.strong,
|
||||||
|
shouldNotInline: shouldNotInline)
|
||||||
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get usingModularAnalysis =>
|
||||||
|
options.modularMode || options.hasModularAnalysisInputs;
|
||||||
|
|
||||||
Future<ModuleData> runModularAnalysis(
|
Future<ModuleData> runModularAnalysis(
|
||||||
load_kernel.Output output, Set<Uri> moduleLibraries) async {
|
load_kernel.Output output, Set<Uri> moduleLibraries) async {
|
||||||
ir.Component component = output.component;
|
ir.Component component = output.component;
|
||||||
|
@ -600,11 +595,28 @@ class Compiler {
|
||||||
globalTypeInferenceResultsData);
|
globalTypeInferenceResultsData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get shouldComputeClosedWorld => options.readClosedWorldUri == null;
|
||||||
|
|
||||||
Future<DataAndIndices<JClosedWorld>?> produceClosedWorld(
|
Future<DataAndIndices<JClosedWorld>?> produceClosedWorld(
|
||||||
load_kernel.Output output, ModuleData? moduleData) async {
|
load_kernel.Output output, ModuleData? moduleData) async {
|
||||||
ir.Component component = output.component;
|
ir.Component component = output.component;
|
||||||
DataAndIndices<JClosedWorld> closedWorldAndIndices;
|
DataAndIndices<JClosedWorld> closedWorldAndIndices;
|
||||||
if (options.readClosedWorldUri == null) {
|
if (shouldComputeClosedWorld) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
Uri rootLibraryUri = output.rootLibraryUri!;
|
Uri rootLibraryUri = output.rootLibraryUri!;
|
||||||
List<Uri> libraries = output.libraries!;
|
List<Uri> libraries = output.libraries!;
|
||||||
final closedWorld =
|
final closedWorld =
|
||||||
|
@ -724,19 +736,17 @@ class Compiler {
|
||||||
final output = await produceKernel();
|
final output = await produceKernel();
|
||||||
if (shouldStopAfterLoadKernel(output)) return;
|
if (shouldStopAfterLoadKernel(output)) return;
|
||||||
|
|
||||||
simplifyConstConditionals(output!);
|
|
||||||
|
|
||||||
// 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.
|
||||||
ModuleData? moduleData;
|
ModuleData? moduleData;
|
||||||
if (options.modularMode || options.hasModularAnalysisInputs) {
|
if (usingModularAnalysis) {
|
||||||
moduleData = await produceModuleData(output);
|
moduleData = await produceModuleData(output!);
|
||||||
}
|
}
|
||||||
if (shouldStopAfterModularAnalysis) return;
|
if (shouldStopAfterModularAnalysis) return;
|
||||||
|
|
||||||
// Compute closed world.
|
// Compute closed world.
|
||||||
DataAndIndices<JClosedWorld>? closedWorldAndIndices =
|
DataAndIndices<JClosedWorld>? closedWorldAndIndices =
|
||||||
await produceClosedWorld(output, moduleData);
|
await produceClosedWorld(output!, moduleData);
|
||||||
if (shouldStopAfterClosedWorld(closedWorldAndIndices)) return;
|
if (shouldStopAfterClosedWorld(closedWorldAndIndices)) return;
|
||||||
|
|
||||||
// Run global analysis.
|
// Run global analysis.
|
||||||
|
|
Loading…
Reference in a new issue