Skip to content

Commit ecc7a21

Browse files
alexmarkovcommit-bot@chromium.org
authored andcommitted
[vm/kernel] Add --from-dill option to kernel compilers
This option can be used to split AOT kernel generation into two rounds: * The 1st round uses CFE to parse source files and generate intermediate dill file in *non-AOT* mode. * The 2nd round loads intermediate dill file and applies AOT global transformations, then generates final dill file. Each round is faster than one-shot generation of a dill file in AOT mode. In order to use this 2-round compilation, command gen_kernel <other-options> --aot -o output.dill main.dart should be replaced with the following 2 commands: gen_kernel <other-options> --no-aot -o intermediate.dill main.dart gen_kernel <other-options> --aot --from-dill intermediate.dill -o output.dill main.dart Bug: b/158101962 Change-Id: I2d4deef45b50eab11df47f4a372598e6cf1d0edf Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150272 Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Alexander Aprelev <aam@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
1 parent e3c3d4d commit ecc7a21

File tree

5 files changed

+160
-4
lines changed

5 files changed

+160
-4
lines changed

pkg/frontend_server/lib/frontend_server.dart

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ ArgParser argParser = ArgParser(allowTrailingOptions: true)
7575
defaultsTo: true)
7676
..addOption('import-dill',
7777
help: 'Import libraries from existing dill file', defaultsTo: null)
78+
..addOption('from-dill',
79+
help: 'Read existing dill file instead of compiling from sources',
80+
defaultsTo: null)
7881
..addOption('output-dill',
7982
help: 'Output path for the generated dill', defaultsTo: null)
8083
..addOption('output-incremental-dill',
@@ -452,6 +455,13 @@ class FrontendCompiler implements CompilerInterface {
452455
}
453456
}
454457

458+
if (options['incremental']) {
459+
if (options['from-dill'] != null) {
460+
print('Error: --from-dill option cannot be used with --incremental');
461+
return false;
462+
}
463+
}
464+
455465
if (options['null-safety'] == null &&
456466
compilerOptions.experimentalFlags[ExperimentalFlag.nonNullable]) {
457467
await autoDetectNullSafetyMode(_mainSource, compilerOptions);
@@ -533,7 +543,8 @@ class FrontendCompiler implements CompilerInterface {
533543
enableAsserts: options['enable-asserts'],
534544
useProtobufTreeShaker: options['protobuf-tree-shaker'],
535545
minimalKernel: options['minimal-kernel'],
536-
treeShakeWriteOnlyFields: options['tree-shake-write-only-fields']));
546+
treeShakeWriteOnlyFields: options['tree-shake-write-only-fields'],
547+
fromDillFile: options['from-dill']));
537548
}
538549
if (results.component != null) {
539550
transformer?.transform(results.component);

pkg/vm/lib/kernel_front_end.dart

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
4444
import 'package:kernel/ast.dart' show Component, Library, Reference;
4545
import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
4646
import 'package:kernel/core_types.dart' show CoreTypes;
47+
import 'package:kernel/kernel.dart' show loadComponentFromBinary;
4748
import 'package:kernel/target/targets.dart' show Target, TargetFlags, getTarget;
4849

4950
import 'bytecode/bytecode_serialization.dart' show BytecodeSizeStatistics;
@@ -80,6 +81,9 @@ void declareCompilerOptions(ArgParser args) {
8081
'Produce kernel file for AOT compilation (enables global transformations).',
8182
defaultsTo: false);
8283
args.addOption('depfile', help: 'Path to output Ninja depfile');
84+
args.addOption('from-dill',
85+
help: 'Read existing dill file instead of compiling from sources',
86+
defaultsTo: null);
8387
args.addFlag('link-platform',
8488
help: 'Include platform into resulting kernel file.', defaultsTo: true);
8589
args.addFlag('minimal-kernel',
@@ -165,6 +169,7 @@ Future<int> runCompiler(ArgResults options, String usage) async {
165169
final String targetName = options['target'];
166170
final String fileSystemScheme = options['filesystem-scheme'];
167171
final String depfile = options['depfile'];
172+
final String fromDillFile = options['from-dill'];
168173
final List<String> fileSystemRoots = options['filesystem-root'];
169174
final bool aot = options['aot'];
170175
final bool tfa = options['tfa'];
@@ -260,7 +265,8 @@ Future<int> runCompiler(ArgResults options, String usage) async {
260265
dropAST: dropAST && !splitOutputByPackages,
261266
useProtobufTreeShaker: useProtobufTreeShaker,
262267
minimalKernel: minimalKernel,
263-
treeShakeWriteOnlyFields: treeShakeWriteOnlyFields);
268+
treeShakeWriteOnlyFields: treeShakeWriteOnlyFields,
269+
fromDillFile: fromDillFile);
264270

265271
errorPrinter.printCompilationMessages();
266272

@@ -335,7 +341,8 @@ Future<KernelCompilationResults> compileToKernel(
335341
bool dropAST: false,
336342
bool useProtobufTreeShaker: false,
337343
bool minimalKernel: false,
338-
bool treeShakeWriteOnlyFields: false}) async {
344+
bool treeShakeWriteOnlyFields: false,
345+
String fromDillFile: null}) async {
339346
// Replace error handler to detect if there are compilation errors.
340347
final errorDetector =
341348
new ErrorDetector(previousErrorHandler: options.onDiagnostic);
@@ -344,7 +351,13 @@ Future<KernelCompilationResults> compileToKernel(
344351
options.environmentDefines =
345352
options.target.updateEnvironmentDefines(environmentDefines);
346353

347-
CompilerResult compilerResult = await kernelForProgram(source, options);
354+
CompilerResult compilerResult;
355+
if (fromDillFile != null) {
356+
compilerResult =
357+
await loadKernel(options.fileSystem, resolveInputUri(fromDillFile));
358+
} else {
359+
compilerResult = await kernelForProgram(source, options);
360+
}
348361
Component component = compilerResult?.component;
349362
Iterable<Uri> compiledSources = component?.uriToSource?.keys;
350363

@@ -859,5 +872,25 @@ Future<void> createFarManifest(
859872
await packageManifest.close();
860873
}
861874

875+
class CompilerResultLoadedFromKernel implements CompilerResult {
876+
final Component component;
877+
final Component sdkComponent = Component();
878+
879+
CompilerResultLoadedFromKernel(this.component);
880+
881+
List<int> get summary => null;
882+
List<Component> get loadedComponents => const <Component>[];
883+
List<Uri> get deps => const <Uri>[];
884+
CoreTypes get coreTypes => null;
885+
ClassHierarchy get classHierarchy => null;
886+
}
887+
888+
Future<CompilerResult> loadKernel(
889+
FileSystem fileSystem, Uri dillFileUri) async {
890+
final component = loadComponentFromBinary(
891+
(await asFileUri(fileSystem, dillFileUri)).toFilePath());
892+
return CompilerResultLoadedFromKernel(component);
893+
}
894+
862895
// Used by kernel_front_end_test.dart
863896
main() {}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
// OtherResources=splay_test.dart
6+
7+
// Tests AOT compilation split into 2 steps using '--from-dill' option.
8+
9+
import 'dart:io' show Platform;
10+
11+
import 'package:path/path.dart' as path;
12+
import 'snapshot_test_helper.dart';
13+
14+
main() async {
15+
final testScriptUri = Platform.script.resolve('splay_test.dart');
16+
17+
await withTempDir((String temp) async {
18+
final intermediateDillPath = path.join(temp, 'intermediate.dill');
19+
final outputDillPath = path.join(temp, 'output.dill');
20+
final snapshotPath = path.join(temp, 'aot.snapshot');
21+
22+
final extraGenKernelOptions = Platform.executableArguments
23+
.where((arg) =>
24+
arg.startsWith('--enable-experiment=') ||
25+
arg == '--null-safety' ||
26+
arg == '--no-null-safety')
27+
.toList();
28+
29+
await runGenKernel('BUILD INTERMEDIATE DILL FILE', [
30+
...extraGenKernelOptions,
31+
'--no-aot',
32+
'--link-platform',
33+
'--output=$intermediateDillPath',
34+
testScriptUri.toFilePath(),
35+
]);
36+
37+
await runGenKernel('BUILD FINAL DILL FILE', [
38+
...extraGenKernelOptions,
39+
'--aot',
40+
'--from-dill=$intermediateDillPath',
41+
'--link-platform',
42+
'--output=$outputDillPath',
43+
testScriptUri.toFilePath(),
44+
]);
45+
46+
await runGenSnapshot('GENERATE SNAPSHOT', [
47+
'--snapshot-kind=app-aot-elf',
48+
'--elf=$snapshotPath',
49+
outputDillPath,
50+
]);
51+
52+
await runBinary('RUN SNAPSHOT', dartPrecompiledRuntime, [snapshotPath]);
53+
});
54+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
// OtherResources=splay_test.dart
6+
7+
// Tests AOT compilation split into 2 steps using '--from-dill' option.
8+
9+
import 'dart:io' show Platform;
10+
11+
import 'package:path/path.dart' as path;
12+
import 'snapshot_test_helper.dart';
13+
14+
main() async {
15+
final testScriptUri = Platform.script.resolve('splay_test.dart');
16+
17+
await withTempDir((String temp) async {
18+
final intermediateDillPath = path.join(temp, 'intermediate.dill');
19+
final outputDillPath = path.join(temp, 'output.dill');
20+
final snapshotPath = path.join(temp, 'aot.snapshot');
21+
22+
final extraGenKernelOptions = Platform.executableArguments
23+
.where((arg) =>
24+
arg.startsWith('--enable-experiment=') ||
25+
arg == '--null-safety' ||
26+
arg == '--no-null-safety')
27+
.toList();
28+
29+
await runGenKernel('BUILD INTERMEDIATE DILL FILE', [
30+
...extraGenKernelOptions,
31+
'--no-aot',
32+
'--link-platform',
33+
'--output=$intermediateDillPath',
34+
testScriptUri.toFilePath(),
35+
]);
36+
37+
await runGenKernel('BUILD FINAL DILL FILE', [
38+
...extraGenKernelOptions,
39+
'--aot',
40+
'--from-dill=$intermediateDillPath',
41+
'--link-platform',
42+
'--output=$outputDillPath',
43+
testScriptUri.toFilePath(),
44+
]);
45+
46+
await runGenSnapshot('GENERATE SNAPSHOT', [
47+
'--snapshot-kind=app-aot-elf',
48+
'--elf=$snapshotPath',
49+
outputDillPath,
50+
]);
51+
52+
await runBinary('RUN SNAPSHOT', dartPrecompiledRuntime, [snapshotPath]);
53+
});
54+
}

runtime/tests/vm/vm.status

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,10 @@ dart_2/transferable_throws_oom_test: SkipByDesign # This test tries to allocate
7676
[ $builder_tag == crossword || $builder_tag == crossword_ast ]
7777
dart/emit_aot_size_info_flag_test: SkipByDesign # The test itself cannot determine the location of gen_snapshot (only tools/test.py knows where it is).
7878
dart/bytecode_with_ast_in_aot_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
79+
dart/split_aot_compilation_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
7980
dart_2/emit_aot_size_info_flag_test: SkipByDesign # The test itself cannot determine the location of gen_snapshot (only tools/test.py knows where it is).
8081
dart_2/bytecode_with_ast_in_aot_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
82+
dart_2/split_aot_compilation_test: SkipByDesign # The test doesn't know location of cross-platform gen_snapshot
8183

8284
[ $builder_tag == obfuscated ]
8385
dart/causal_stacks/async_throws_stack_lazy_test: SkipByDesign # Asserts exact stacktrace output.
@@ -396,9 +398,11 @@ dart_2/redirection_type_shuffling_test/none: RuntimeError
396398
dart/emit_aot_size_info_flag_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
397399
dart/use_bare_instructions_flag_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
398400
dart/bytecode_with_ast_in_aot_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
401+
dart/split_aot_compilation_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
399402
dart_2/emit_aot_size_info_flag_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
400403
dart_2/use_bare_instructions_flag_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
401404
dart_2/bytecode_with_ast_in_aot_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
405+
dart_2/split_aot_compilation_test: SkipByDesign # This test is for VM AOT only and is quite slow (so we don't run it in debug mode).
402406

403407
# It makes no sense to run any test that uses spawnURI under the simulator
404408
# as that would involve running CFE (the front end) in simulator mode

0 commit comments

Comments
 (0)