Skip to content

Commit b3e7e2f

Browse files
natebiggsCommit Queue
authored andcommitted
[dart2wasm] Serialize dill before and after TFA for dynamic module enabled main modules.
Modifies the serialization strategy used for dynamic modules. Emits 2 dill files, main.dill and main.opt.dill. main.dill serialized before TFA runs and is used by the CFE to compile the dynamic module faster (it doesn't have to recompile the main module libraries from source). main.opt.dill is serialized at the end of the compilation of the main module and contains a copy of all the main module libraries after TFA. This dill is used by dart2wasm to produce consistent references into the main module. Also emit new record classes into a distinct library so that all downstream code will appropriately emit the new code without special logic. Change-Id: Idf7a87d2014dad513c753330743f753312aa472f Tested: Just updating signature, no testing needed. Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/422342 Reviewed-by: Martin Kustermann <[email protected]>
1 parent 776c058 commit b3e7e2f

File tree

9 files changed

+364
-434
lines changed

9 files changed

+364
-434
lines changed

pkg/dart2wasm/lib/compile.dart

Lines changed: 69 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,10 @@ import 'package:front_end/src/api_unstable/vm.dart'
1919
import 'package:kernel/ast.dart';
2020
import 'package:kernel/class_hierarchy.dart';
2121
import 'package:kernel/core_types.dart';
22-
import 'package:kernel/kernel.dart'
23-
show writeComponentToBinary, writeComponentToText;
22+
import 'package:kernel/kernel.dart' show writeComponentToText;
2423
import 'package:kernel/library_index.dart';
2524
import 'package:kernel/type_environment.dart';
2625
import 'package:kernel/verifier.dart';
27-
import 'package:path/path.dart' as path show setExtension;
2826
import 'package:vm/kernel_front_end.dart' show writeDepfile;
2927
import 'package:vm/transformations/mixin_deduplication.dart'
3028
as mixin_deduplication show transformLibraries;
@@ -45,7 +43,6 @@ import 'js/runtime_generator.dart' as js;
4543
import 'modules.dart';
4644
import 'record_class_generator.dart';
4745
import 'records.dart';
48-
import 'serialization.dart';
4946
import 'target.dart' as wasm show Mode;
5047
import 'target.dart' hide Mode;
5148
import 'translator.dart';
@@ -85,6 +82,24 @@ class CFECompileTimeErrors extends CompilationError {
8582
CFECompileTimeErrors();
8683
}
8784

85+
const List<String> _librariesToIndex = [
86+
"dart:_boxed_bool",
87+
"dart:_boxed_double",
88+
"dart:_boxed_int",
89+
"dart:_compact_hash",
90+
"dart:_internal",
91+
"dart:_js_helper",
92+
"dart:_js_types",
93+
"dart:_list",
94+
"dart:_string",
95+
"dart:_wasm",
96+
"dart:async",
97+
"dart:collection",
98+
"dart:core",
99+
"dart:ffi",
100+
"dart:typed_data",
101+
];
102+
88103
/// Compile a Dart file into a Wasm module.
89104
///
90105
/// Returns `null` if an error occurred during compilation. The
@@ -159,8 +174,6 @@ Future<CompilationResult> compileToModule(
159174
compilerOptions.compileSdk = true;
160175
}
161176

162-
final dynamicMainModuleUri = options.dynamicModuleMainUri;
163-
164177
final dynamicModuleMainUri = await resolveUri(options.dynamicModuleMainUri);
165178
final dynamicInterfaceUri = await resolveUri(options.dynamicInterfaceUri);
166179
final isDynamicMainModule =
@@ -183,25 +196,10 @@ Future<CompilationResult> compileToModule(
183196

184197
Component component = compilerResult!.component!;
185198
CoreTypes coreTypes = compilerResult.coreTypes!;
186-
final classHierarchy =
199+
200+
ClosedWorldClassHierarchy classHierarchy =
187201
ClassHierarchy(component, coreTypes) as ClosedWorldClassHierarchy;
188-
LibraryIndex libraryIndex = LibraryIndex(component, [
189-
"dart:_boxed_bool",
190-
"dart:_boxed_double",
191-
"dart:_boxed_int",
192-
"dart:_compact_hash",
193-
"dart:_internal",
194-
"dart:_js_helper",
195-
"dart:_js_types",
196-
"dart:_list",
197-
"dart:_string",
198-
"dart:_wasm",
199-
"dart:async",
200-
"dart:collection",
201-
"dart:core",
202-
"dart:ffi",
203-
"dart:typed_data",
204-
]);
202+
LibraryIndex libraryIndex = LibraryIndex(component, _librariesToIndex);
205203

206204
if (options.dumpKernelAfterCfe != null) {
207205
writeComponentToText(component, path: options.dumpKernelAfterCfe!);
@@ -212,6 +210,43 @@ Future<CompilationResult> compileToModule(
212210
component, options.deleteToStringPackageUri);
213211
}
214212

213+
var jsInteropMethods = js.performJSInteropTransformations(
214+
component.getDynamicModuleLibraries(coreTypes),
215+
coreTypes,
216+
classHierarchy);
217+
218+
if (isDynamicModule) {
219+
// Join the dynamic module libraries with the TFAed component from the main
220+
// module compilation. JS interop transformer must be run before this since
221+
// some methods it uses may have been tree-shaken from the TFAed component.
222+
(component, jsInteropMethods) = await generateDynamicModuleComponent(
223+
component, coreTypes, dynamicModuleMainUri, jsInteropMethods);
224+
coreTypes = CoreTypes(component);
225+
classHierarchy =
226+
ClassHierarchy(component, coreTypes) as ClosedWorldClassHierarchy;
227+
libraryIndex = LibraryIndex(component, _librariesToIndex);
228+
}
229+
230+
final librariesToTransform = isDynamicModule
231+
? component.getDynamicModuleLibraries(coreTypes)
232+
: component.libraries;
233+
final constantEvaluator = ConstantEvaluator(
234+
options, target, component, coreTypes, classHierarchy, libraryIndex);
235+
unreachable_code_elimination.transformLibraries(target, librariesToTransform,
236+
constantEvaluator, options.translatorOptions.enableAsserts);
237+
238+
final Map<RecordShape, Class> recordClasses = generateRecordClasses(
239+
component, coreTypes,
240+
isDynamicMainModule: isDynamicMainModule,
241+
isDynamicModule: isDynamicModule);
242+
target.recordClasses = recordClasses;
243+
244+
if (options.dumpKernelBeforeTfa != null) {
245+
writeComponentToText(component, path: options.dumpKernelBeforeTfa!);
246+
}
247+
248+
mixin_deduplication.transformLibraries(librariesToTransform);
249+
215250
ModuleStrategy moduleStrategy;
216251
if (options.translatorOptions.enableDeferredLoading) {
217252
moduleStrategy =
@@ -232,51 +267,19 @@ Future<CompilationResult> compileToModule(
232267
moduleStrategy = DefaultModuleStrategy(component);
233268
}
234269

235-
final librariesToTransform = isDynamicModule
236-
? component.getDynamicModuleLibraries(coreTypes)
237-
: component.libraries;
238-
ConstantEvaluator constantEvaluator = ConstantEvaluator(
239-
options, target, component, coreTypes, classHierarchy, libraryIndex);
240-
unreachable_code_elimination.transformLibraries(target, librariesToTransform,
241-
constantEvaluator, options.translatorOptions.enableAsserts);
242-
243-
js.RuntimeFinalizer? jsRuntimeFinalizer = js.RuntimeFinalizer(
244-
js.performJSInteropTransformations(
245-
librariesToTransform, coreTypes, classHierarchy));
246-
247-
final Map<RecordShape, Class> recordClasses = generateRecordClasses(
248-
component, coreTypes, isDynamicMainModule || isDynamicModule);
249-
target.recordClasses = recordClasses;
250-
251-
if (options.dumpKernelBeforeTfa != null) {
252-
writeComponentToText(component, path: options.dumpKernelBeforeTfa!);
253-
}
254-
255-
mixin_deduplication.transformLibraries(librariesToTransform);
256-
257270
moduleStrategy.prepareComponent();
258271

259272
MainModuleMetadata mainModuleMetadata =
260273
MainModuleMetadata.empty(options.translatorOptions, options.environment);
261274

262275
if (isDynamicModule) {
263-
final filename = options.dynamicModuleMetadataFile ??
264-
Uri.parse(
265-
path.setExtension(dynamicMainModuleUri!.toFilePath(), '.dyndata'));
266-
final dynamicModuleMetadataBytes =
267-
await File.fromUri(filename).readAsBytes();
268-
final source = DataDeserializer(dynamicModuleMetadataBytes, component);
269-
mainModuleMetadata = MainModuleMetadata.deserialize(source);
276+
mainModuleMetadata =
277+
await deserializeMainModuleMetadata(component, options);
270278
mainModuleMetadata.verifyDynamicModuleOptions(options);
271-
mainModuleMetadata.initializeDynamicModuleKernel(
272-
component,
273-
coreTypes,
274-
// Create a new hierarchy with generated record classes.
275-
ClassHierarchy(component, coreTypes) as ClosedWorldClassHierarchy);
276279
} else if (isDynamicMainModule) {
277280
MainModuleMetadata.verifyMainModuleOptions(options);
278-
writeComponentToBinary(component, dynamicModuleMainUri.path,
279-
includeSource: false);
281+
await serializeMainModuleComponent(component, dynamicModuleMainUri,
282+
optimized: false);
280283
}
281284

282285
if (!isDynamicModule) {
@@ -327,7 +330,9 @@ Future<CompilationResult> compileToModule(
327330
(moduleBytes: wasmModuleSerialized, sourceMap: sourceMap);
328331
});
329332

330-
final jsRuntime = translator.isDynamicModule
333+
final jsRuntimeFinalizer = js.RuntimeFinalizer(jsInteropMethods);
334+
335+
final jsRuntime = isDynamicModule
331336
? jsRuntimeFinalizer.generateDynamicModule(
332337
translator.functions.translatedProcedures,
333338
translator.internalizedStringsForJSRuntime)
@@ -341,12 +346,9 @@ Future<CompilationResult> compileToModule(
341346

342347
final supportJs = _generateSupportJs(options.translatorOptions);
343348
if (isDynamicMainModule) {
344-
final filename = options.dynamicModuleMetadataFile ??
345-
Uri.parse(
346-
path.setExtension(dynamicMainModuleUri!.toFilePath(), '.dyndata'));
347-
final serializer = DataSerializer(translator.component);
348-
translator.dynamicModuleInfo!.metadata.serialize(serializer, translator);
349-
await File.fromUri(filename).writeAsBytes(serializer.takeBytes());
349+
await serializeMainModuleMetadata(component, translator, options);
350+
await serializeMainModuleComponent(component, dynamicModuleMainUri,
351+
optimized: true);
350352
}
351353

352354
return CompilationSuccess(wasmModules, jsRuntime, supportJs);

pkg/dart2wasm/lib/constant_evaluator.dart

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ class ConstantEvaluator extends kernel.ConstantEvaluator
2020
final bool _hasDynamicModuleSupport;
2121
final bool _deferredLoadingEnabled;
2222

23-
final Procedure _dartInternalCheckBoundsGetter;
24-
final Procedure _dartInternalMinifyGetter;
25-
final Procedure _dartInternalHasDynamicModuleSupportGetter;
26-
final Procedure _dartInternalDeferredLoadingEnabled;
23+
final Procedure? _dartInternalCheckBoundsGetter;
24+
final Procedure? _dartInternalMinifyGetter;
25+
final Procedure? _dartInternalHasDynamicModuleSupportGetter;
26+
final Procedure? _dartInternalDeferredLoadingEnabled;
2727

2828
ConstantEvaluator(
2929
WasmCompilerOptions options,
@@ -38,15 +38,17 @@ class ConstantEvaluator extends kernel.ConstantEvaluator
3838
_deferredLoadingEnabled =
3939
options.translatorOptions.enableDeferredLoading ||
4040
options.translatorOptions.enableMultiModuleStressTestMode,
41-
_dartInternalCheckBoundsGetter = libraryIndex.getTopLevelProcedure(
42-
"dart:_internal", "get:checkBounds"),
43-
_dartInternalMinifyGetter =
44-
libraryIndex.getTopLevelProcedure("dart:_internal", "get:minify"),
41+
_dartInternalCheckBoundsGetter = libraryIndex.tryGetProcedure(
42+
"dart:_internal", LibraryIndex.topLevel, "get:checkBounds"),
43+
_dartInternalMinifyGetter = libraryIndex.tryGetProcedure(
44+
"dart:_internal", LibraryIndex.topLevel, "get:minify"),
4545
_dartInternalHasDynamicModuleSupportGetter =
46-
libraryIndex.getTopLevelProcedure(
47-
"dart:_internal", "get:hasDynamicModuleSupport"),
48-
_dartInternalDeferredLoadingEnabled = libraryIndex.getTopLevelProcedure(
49-
"dart:_internal", "get:deferredLoadingEnabled"),
46+
libraryIndex.tryGetProcedure("dart:_internal",
47+
LibraryIndex.topLevel, "get:hasDynamicModuleSupport"),
48+
_dartInternalDeferredLoadingEnabled = libraryIndex.tryGetProcedure(
49+
"dart:_internal",
50+
LibraryIndex.topLevel,
51+
"get:deferredLoadingEnabled"),
5052
super(
5153
target.dartLibrarySupport,
5254
target.constantsBackend,

pkg/dart2wasm/lib/dispatch_table.dart

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import 'package:vm/metadata/table_selector.dart';
1010
import 'package:wasm_builder/wasm_builder.dart' as w;
1111

1212
import 'class_info.dart';
13+
import 'dynamic_module_kernel_metadata.dart';
1314
import 'dynamic_modules.dart';
1415
import 'param_info.dart';
1516
import 'reference_extensions.dart';
@@ -367,16 +368,25 @@ class DispatchTable {
367368
late final Map<TreeNode, ProcedureAttributesMetadata>
368369
procedureAttributeMetadata =
369370
translator.isDynamicModule && !isDynamicModuleTable
370-
? translator.dynamicModuleInfo!.mainModuleProcedureAttributes
371+
? (translator.component
372+
.metadata[dynamicMainModuleProcedureAttributeMetadataTag]
373+
as ProcedureAttributesMetadataRepository)
374+
.mapping
371375
: translator.procedureAttributeMetadata;
372376

373377
late final Translator translator;
374378

375379
late final List<TableSelectorInfo> _selectorMetadata =
376-
(translator.component.metadata["vm.table-selector.metadata"]
377-
as TableSelectorMetadataRepository)
378-
.mapping[translator.component]!
379-
.selectors;
380+
translator.isDynamicModule && !isDynamicModuleTable
381+
? (translator.component.metadata[dynamicMainModuleSelectorMetadataTag]
382+
as TableSelectorMetadataRepository)
383+
.mapping[translator.component]!
384+
.selectors
385+
: (translator.component
386+
.metadata[TableSelectorMetadataRepository.repositoryTag]
387+
as TableSelectorMetadataRepository)
388+
.mapping[translator.component]!
389+
.selectors;
380390
late final int minClassId = isDynamicModuleTable
381391
? translator.classIdNumbering.firstDynamicModuleClassId
382392
: 0;

0 commit comments

Comments
 (0)