[ddc] Add options to emit, read and diff delta dills for hot reload.
This will allow DartPad (which invokes DDC directly) to maintain delta dills across each reload.
Change-Id: I801208c6b8f50a0aa20b6f509aa3e32a827a9cdb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/405661
Reviewed-by: Nicholas Shahan <nshahan@google.com>
Commit-Queue: Nate Biggs <natebiggs@google.com>
diff --git a/pkg/dev_compiler/lib/src/command/command.dart b/pkg/dev_compiler/lib/src/command/command.dart
index 5025d44..968158c 100644
--- a/pkg/dev_compiler/lib/src/command/command.dart
+++ b/pkg/dev_compiler/lib/src/command/command.dart
@@ -11,6 +11,8 @@
import 'package:front_end/src/api_prototype/macros.dart' as macros
show isMacroLibraryUri;
import 'package:front_end/src/api_unstable/ddc.dart' as fe;
+import 'package:kernel/binary/ast_from_binary.dart' as kernel
+ show BinaryBuilder;
import 'package:kernel/binary/ast_to_binary.dart' as kernel show BinaryPrinter;
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/core_types.dart';
@@ -28,6 +30,7 @@
import '../js_ast/source_map_printer.dart' show SourceMapPrintingContext;
import '../kernel/compiler.dart';
import '../kernel/compiler_new.dart';
+import '../kernel/hot_reload_delta_inspector.dart';
import '../kernel/module_metadata.dart';
import '../kernel/module_symbols.dart';
import '../kernel/module_symbols_collector.dart';
@@ -363,6 +366,33 @@
var component = result.component;
var compiledLibraries = result.compiledLibraries;
+ final reloadDeltaKernel = options.reloadDeltaKernel;
+ final reloadLastAcceptedKernel = options.reloadLastAcceptedKernel;
+ if (reloadDeltaKernel != null) {
+ if (reloadLastAcceptedKernel != null) {
+ final lastAcceptedComponent = Component();
+ kernel.BinaryBuilder((await File(reloadLastAcceptedKernel).readAsBytes()))
+ .readComponent(lastAcceptedComponent);
+ final deltaInspector = HotReloadDeltaInspector();
+ final rejectionReasons = deltaInspector.compareGenerations(
+ lastAcceptedComponent, compiledLibraries);
+ if (rejectionReasons.isNotEmpty) {
+ throw StateError(
+ 'Hot reload rejected due to:\n${rejectionReasons.join('\n')}');
+ }
+ }
+ var sink = File(reloadDeltaKernel).openWrite();
+ kernel.BinaryPrinter(sink, includeSources: false, includeSourceBytes: false)
+ .writeComponentFile(compiledLibraries);
+ await sink.flush();
+ await sink.close();
+ } else {
+ if (reloadLastAcceptedKernel != null) {
+ throw ArgumentError("Must provide 'new-reload-delta-kernel' if "
+ "'old-reload-delta-kernel' provided.");
+ }
+ }
+
// Output files can be written in parallel, so collect the futures.
var outFiles = <Future>[];
if (argResults['summarize'] as bool) {
diff --git a/pkg/dev_compiler/lib/src/command/options.dart b/pkg/dev_compiler/lib/src/command/options.dart
index 8000136..fdb3527 100644
--- a/pkg/dev_compiler/lib/src/command/options.dart
+++ b/pkg/dev_compiler/lib/src/command/options.dart
@@ -30,6 +30,9 @@
/// expressions on demand in the current scope of a breakpoint.
final bool emitFullCompiledKernel;
+ final String? reloadLastAcceptedKernel;
+ final String? reloadDeltaKernel;
+
/// Whether to emit a summary file containing API signatures.
///
/// This is required for a modular build process.
@@ -117,6 +120,8 @@
this.emitDebugMetadata = false,
this.emitDebugSymbols = false,
this.emitFullCompiledKernel = false,
+ this.reloadLastAcceptedKernel,
+ this.reloadDeltaKernel,
this.summaryModules = const {},
this.moduleFormats = const [],
required this.moduleName,
@@ -143,6 +148,9 @@
emitDebugSymbols: args['emit-debug-symbols'] as bool,
emitFullCompiledKernel:
args['experimental-output-compiled-kernel'] as bool,
+ reloadLastAcceptedKernel:
+ args['reload-last-accepted-kernel'] as String?,
+ reloadDeltaKernel: args['reload-delta-kernel'] as String?,
summaryModules:
_parseCustomSummaryModules(args['summary'] as List<String>),
moduleFormats: parseModuleFormatOption(args),
@@ -213,6 +221,17 @@
'the .js output.',
defaultsTo: false,
hide: true)
+ ..addOption('reload-last-accepted-kernel',
+ help: 'Provides a file path to read a dill file. The enclosed kernel '
+ 'will be diffed against the kernel produced by this compilation '
+ 'as an incremental hot reload step.',
+ hide: true)
+ ..addOption('reload-delta-kernel',
+ help: 'Provides a file path to write a dill file to. The resulting '
+ 'kernel can be passed to future compilations via '
+ '`reload-last-accepted-kernel` to get incremental hot reload '
+ 'checks.',
+ hide: true)
..addMultiOption('precompiled-macro',
help:
'Configuration for precompiled macro binaries or kernel files.\n'
diff --git a/pkg/dev_compiler/lib/src/kernel/hot_reload_delta_inspector.dart b/pkg/dev_compiler/lib/src/kernel/hot_reload_delta_inspector.dart
index 5dae19e..ad0e3c2 100644
--- a/pkg/dev_compiler/lib/src/kernel/hot_reload_delta_inspector.dart
+++ b/pkg/dev_compiler/lib/src/kernel/hot_reload_delta_inspector.dart
@@ -23,7 +23,7 @@
// TODO(nshahan): Annotate delta component with information for DDC.
List<String> compareGenerations(Component lastAccepted, Component delta) {
_partialLastAcceptedLibraryIndex = LibraryIndex(lastAccepted,
- [for (var library in delta.libraries) '${library.fileUri}']);
+ [for (var library in delta.libraries) '${library.importUri}']);
_rejectionMessages.clear();
for (var library in delta.libraries) {