[CFE] Incremental compiler can load additionalDillModules

Change-Id: I8de4c703377eabacd4e423d5a2045f9411da11a6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/505301
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Jens Johansen <jensj@google.com>
This commit is contained in:
Jens Johansen
2026-05-26 23:58:20 -07:00
committed by dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent a1a881b49f
commit 7e348949c1
3 changed files with 126 additions and 2 deletions
@@ -165,6 +165,7 @@ class IncrementalCompilerResult {
final Component component;
final ClassHierarchy classHierarchy;
final CoreTypes coreTypes;
final List<Component> loadedComponents;
final Set<Library>? neededDillLibraries;
IncrementalCompilerResult(
@@ -172,5 +173,6 @@ class IncrementalCompilerResult {
required this.classHierarchy,
required this.coreTypes,
this.neededDillLibraries,
this.loadedComponents = const [],
});
}
@@ -11,6 +11,7 @@ import 'package:_fe_analyzer_shared/src/parser/experimental_features.dart'
import 'package:_fe_analyzer_shared/src/scanner/abstract_scanner.dart'
show ScannerConfiguration;
import 'package:front_end/src/base/name_space.dart';
import 'package:front_end/src/base/processed_options.dart';
import 'package:front_end/src/codes/diagnostic.dart' as diag;
import 'package:front_end/src/type_inference/inference_results.dart';
import 'package:front_end/src/type_inference/object_access_target.dart';
@@ -617,6 +618,7 @@ class IncrementalCompiler implements IncrementalKernelGenerator {
classHierarchy: currentKernelTarget.loader.hierarchy,
coreTypes: currentKernelTarget.loader.coreTypes,
neededDillLibraries: neededDillLibraries,
loadedComponents: data.loadedModules ?? const [],
);
});
}
@@ -1821,6 +1823,13 @@ class IncrementalCompiler implements IncrementalKernelGenerator {
byteCount: bytesLength,
);
}
List<Component>? loadedModules = data.loadedModules;
if (loadedModules != null) {
// Coverage-ignore-block(suite): Not run.
for (Component module in loadedModules) {
_dillLoadedData!.loader.appendLibraries(module);
}
}
_ticker.logMs("Appended libraries");
}
@@ -2730,6 +2739,7 @@ class InitializeFromComponentError {
class IncrementalCompilerData {
Component? component = null;
List<int>? initializationBytes = null;
List<Component>? loadedModules = null;
}
class ReusageResult {
@@ -2858,14 +2868,24 @@ class _InitializationFromSdkSummary extends _InitializationStrategy {
IncrementalSerializer? incrementalSerializer,
RecorderForTesting? recorderForTesting,
) async {
Uint8List? summaryBytes = await context.options.loadSdkSummaryBytes();
return _prepareSummary(
ProcessedOptions options = context.options;
Uint8List? summaryBytes = await options.loadSdkSummaryBytes();
int bytesLength = _prepareSummary(
dillLoadedData,
summaryBytes,
uriTranslator,
context,
data,
);
if (options.hasAdditionalDillModules) {
List<Component> loadedModules = await options.loadAdditionalDillModules(
data.component?.root,
);
data.loadedModules = loadedModules;
}
return bytesLength;
}
// Coverage-ignore(suite): Not run.
+102
View File
@@ -1081,6 +1081,16 @@ class NewWorldTest {
);
if (subtestResult != null) return subtestResult;
// Load modules via additionalDillModules.
subtestResult = await _loadModulesViaAdditionalDillModules(
world,
worldTestData,
newWorldTestData,
prevFormattedErrors,
prevFormattedWarnings,
);
if (subtestResult != null) return subtestResult;
// Dummy tree nodes can (currently) leak though the parent pointer.
// To avoid that (here) (for leak testing) we'll null them out.
for (TreeNode treeNode in dummyTreeNodes) {
@@ -2394,6 +2404,98 @@ class NewWorldTest {
return newWorldTestData;
}
Future<Result<TestData>?> _loadModulesViaAdditionalDillModules(
World world,
WorldSpecificTestData worldTestData,
NewWorldTestData newWorldTestData,
Set<String> prevFormattedErrors,
Set<String> prevFormattedWarnings,
) async {
// Load modules via additionalDillModules.
if (!world.noFullComponent && world.modules != null) {
// Do compile from scratch and compare.
worldTestData.clearPrevErrorsEtc();
CompilerOptions options = _createOptionsForWorld(
newWorldTestData,
worldTestData,
world,
// The DDC target saves stuff in the target that causes leaks
// in this config where we've loaded a new sdk etc, so we create
// a new target to avoid it.
createNewTarget: true,
);
List<Uri> additionalDillModules = [];
int moduleNum = 0;
for (String moduleName in world.modules!) {
moduleNum++;
final Uri moduleUri = newWorldTestData.base.resolve(
"module_$moduleNum.dill",
);
newWorldTestData.fs
.entityForUri(moduleUri)
.writeAsBytesSync(newWorldTestData.moduleData![moduleName]!);
additionalDillModules.add(moduleUri);
}
options.additionalDillModules = additionalDillModules;
TestIncrementalCompiler? compilerFromScratch =
new TestIncrementalCompiler(
options,
worldTestData.entries.first,
null,
world.outlineOnly,
);
Stopwatch stopwatch = new Stopwatch()..start();
IncrementalCompilerResult? compilerResultLocal = await compilerFromScratch
.computeDelta(
entryPoints: worldTestData.entries,
simulateTransformer: world.simulateTransformer,
);
Component? componentLocal = compilerResultLocal.component;
compilerResultLocal = null;
compilerFromScratch = null;
Result<TestData>? result = _performErrorAndWarningCheck(
world,
data,
worldTestData,
);
if (result != null) return result;
util.throwOnEmptyMixinBodies(componentLocal);
await util.throwOnInsufficientUriToSource(componentLocal);
print("Compile took ${stopwatch.elapsedMilliseconds} ms");
List<int> thisWholeComponent = util.postProcess(componentLocal);
String component4String = _componentToStringSdkFiltered(
componentLocal,
printErrors: world.printErrorsInExpect
? worldTestData.formattedErrors
: null,
);
print("*****\n\ncomponent (4):\n$component4String\n\n\n");
if (world.compareWithFromScratch) {
checkIsEqual(
newWorldTestData.newestWholeComponentData!,
thisWholeComponent,
);
}
_checkErrorsAndWarnings(
prevFormattedErrors,
worldTestData.formattedErrors,
prevFormattedWarnings,
worldTestData.formattedWarnings,
);
componentLocal = null;
// For whatever reason the above introduces a "temporary leak" that
// awaiting something here removes.
await null;
}
return null;
}
void _loadWorldModules(
World world,
NewWorldTestData newWorldTestData,