Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(285)

Unified Diff: utils/kernel-service/kernel-service.dart

Issue 2993013002: Introduce IKG into kernel-service to support incremental compilation. (Closed)
Patch Set: Add TODO to add assert that isolate exists. Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/unit_test.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: utils/kernel-service/kernel-service.dart
diff --git a/utils/kernel-service/kernel-service.dart b/utils/kernel-service/kernel-service.dart
index 92cb34eb2da696525bf4b9982f17e9839399e0c0..cd5ae0ca70a75cb02189cff016fa9163875b6de5 100644
--- a/utils/kernel-service/kernel-service.dart
+++ b/utils/kernel-service/kernel-service.dart
@@ -21,12 +21,14 @@
library runtime.tools.kernel_service;
import 'dart:async' show Future;
+import 'dart:convert' show JSON;
import 'dart:io' show Platform hide FileSystemEntity;
import 'dart:isolate';
import 'dart:typed_data' show Uint8List;
import 'package:front_end/file_system.dart';
import 'package:front_end/front_end.dart';
+import 'package:front_end/incremental_kernel_generator.dart';
import 'package:front_end/memory_file_system.dart';
import 'package:front_end/physical_file_system.dart';
import 'package:front_end/src/fasta/kernel/utils.dart';
@@ -38,6 +40,119 @@ import 'package:kernel/target/vm_fasta.dart' show VmFastaTarget;
const bool verbose = const bool.fromEnvironment('DFE_VERBOSE');
const bool strongMode = const bool.fromEnvironment('DFE_STRONG_MODE');
+abstract class Compiler {
+ final FileSystem fileSystem;
+ final List<String> errors = new List<String>();
+
+ CompilerOptions options;
+
+ Compiler(this.fileSystem) {
+ Uri packagesUri = (Platform.packageConfig != null)
+ ? Uri.parse(Platform.packageConfig)
+ : null;
+
+ Uri sdkSummary = Uri.base
+ .resolveUri(new Uri.file(Platform.resolvedExecutable))
+ .resolveUri(new Uri.directory("patched_sdk"))
+ // TODO(sigmund): use outline.dill when the mixin transformer is
+ // modular.
+ .resolve('platform.dill');
+
+ if (verbose) {
+ print("DFE: Platform.packageConfig: ${Platform.packageConfig}");
+ print("DFE: packagesUri: ${packagesUri}");
+ print("DFE: Platform.resolvedExecutable: ${Platform.resolvedExecutable}");
+ print("DFE: sdkSummary: ${sdkSummary}");
+ }
+
+ options = new CompilerOptions()
+ ..strongMode = strongMode
+ ..fileSystem = fileSystem
+ ..target = new VmFastaTarget(new TargetFlags(strongMode: strongMode))
+ ..packagesFileUri = packagesUri
+ ..sdkSummary = sdkSummary
+ ..verbose = verbose
+ ..throwOnErrors = false
+ ..reportMessages = true
+ ..onError = (CompilationMessage e) {
+ if (e.severity == Severity.error) {
+ // TODO(sigmund): support emitting code with errors as long as they
+ // are handled in the generated code (issue #30194).
+ errors.add(e.message);
+ }
+ };
+ }
+
+ Future<Program> compile(Uri script);
+}
+
+class IncrementalCompiler extends Compiler {
+ IncrementalKernelGenerator generator;
+
+ IncrementalCompiler(FileSystem fileSystem) : super(fileSystem);
+
+ @override
+ Future<Program> compile(Uri script) async {
+ if (generator == null) {
+ generator = await IncrementalKernelGenerator.newInstance(options, script);
+ }
+ DeltaProgram deltaProgram = await generator.computeDelta();
+ // TODO(aam): Accepting/rejecting should be done based on VM response.
+ generator.acceptLastDelta();
+ return deltaProgram.newProgram;
+ }
+
+ void invalidate(Uri uri) {
+ generator.invalidate(uri);
+ }
+}
+
+class SingleShotCompiler extends Compiler {
+ final bool requireMain;
+
+ SingleShotCompiler(FileSystem fileSystem, this.requireMain)
+ : super(fileSystem);
+
+ @override
+ Future<Program> compile(Uri script) async {
+ return requireMain
+ ? kernelForProgram(script, options)
+ : kernelForBuildUnit([script], options..chaseDependencies = true);
+ }
+}
+
+final Map<int, Compiler> isolateCompilers = new Map<int, Compiler>();
+
+Future<Compiler> lookupOrBuildNewIncrementalCompiler(
+ int isolateId, List sourceFiles) async {
+ IncrementalCompiler compiler;
+ if (isolateCompilers.containsKey(isolateId)) {
+ compiler = isolateCompilers[isolateId];
+ final HybridFileSystem fileSystem = compiler.fileSystem;
+ if (sourceFiles != null) {
+ for (int i = 0; i < sourceFiles.length ~/ 2; i++) {
+ Uri uri = Uri.parse(sourceFiles[i * 2]);
+ fileSystem.memory
+ .entityForUri(uri)
+ .writeAsBytesSync(sourceFiles[i * 2 + 1]);
+ compiler.invalidate(uri);
+ }
+ }
+ } else {
+ final FileSystem fileSystem = sourceFiles == null
+ ? PhysicalFileSystem.instance
+ : _buildFileSystem(sourceFiles);
+
+ // TODO(aam): IncrementalCompiler instance created below have to be
+ // destroyed when corresponding isolate is shut down. To achieve that kernel
+ // isolate needs to receive a message indicating that particular
+ // isolate was shut down. Message should be handled here in this script.
+ compiler = new IncrementalCompiler(fileSystem);
+ isolateCompilers[isolateId] = compiler;
+ }
+ return compiler;
+}
+
// Process a request from the runtime. See KernelIsolate::CompileToKernel in
// kernel_isolate.cc and Loader::SendKernelRequest in loader.cc.
Future _processLoadRequest(request) async {
@@ -47,66 +162,44 @@ Future _processLoadRequest(request) async {
final SendPort port = request[1];
final String inputFileUri = request[2];
final Uri script = Uri.base.resolve(inputFileUri);
-
- FileSystem fileSystem = PhysicalFileSystem.instance;
- bool requireMain = true;
-
- if (request.length > 3) {
- fileSystem = _buildFileSystem(request[3]);
- requireMain = false;
- }
-
- Uri packagesUri = (Platform.packageConfig != null)
- ? Uri.parse(Platform.packageConfig)
- : null;
-
- Uri sdkSummary = Uri.base
- .resolveUri(new Uri.file(Platform.resolvedExecutable))
- .resolveUri(new Uri.directory("patched_sdk"))
- // TODO(sigmund): use outline.dill when the mixin transformer is modular.
- .resolve('platform.dill');
-
- if (verbose) {
- print("DFE: scriptUri: ${script}");
- print("DFE: Platform.packageConfig: ${Platform.packageConfig}");
- print("DFE: packagesUri: ${packagesUri}");
- print("DFE: Platform.resolvedExecutable: ${Platform.resolvedExecutable}");
- print("DFE: sdkSummary: ${sdkSummary}");
+ final bool incremental = request[3];
+
+ final List sourceFiles = request.length > 5 ? request[5] : null;
+
+ Compiler compiler;
+ // TODO(aam): There should be no need to have an option to choose
+ // one compiler or another. We should always use an incremental
+ // compiler as its functionality is a super set of the other one. We need to
+ // watch the performance though.
+ if (incremental) {
+ final int isolateId = request[4];
+ compiler =
+ await lookupOrBuildNewIncrementalCompiler(isolateId, sourceFiles);
+ } else {
+ final FileSystem fileSystem = sourceFiles == null
+ ? PhysicalFileSystem.instance
+ : _buildFileSystem(sourceFiles);
+ compiler = new SingleShotCompiler(
+ fileSystem, sourceFiles == null /* requireMain */);
}
- var errors = <String>[];
- var options = new CompilerOptions()
- ..strongMode = strongMode
- ..fileSystem = fileSystem
- ..target = new VmFastaTarget(new TargetFlags(strongMode: strongMode))
- ..packagesFileUri = packagesUri
- ..sdkSummary = sdkSummary
- ..verbose = verbose
- ..throwOnErrors = false
- ..reportMessages = true
- ..onError = (CompilationMessage e) {
- if (e.severity == Severity.error) {
- // TODO(sigmund): support emitting code with errors as long as they are
- // handled in the generated code (issue #30194).
- errors.add(e.message);
- }
- };
-
CompilationResult result;
try {
- Program program = requireMain
- ? await kernelForProgram(script, options)
- : await kernelForBuildUnit([script], options..chaseDependencies = true);
+ if (verbose) {
+ print("DFE: scriptUri: ${script}");
+ }
+
+ Program program = await compiler.compile(script);
- if (errors.isNotEmpty) {
+ if (compiler.errors.isNotEmpty) {
// TODO(sigmund): the compiler prints errors to the console, so we
// shouldn't print those messages again here.
- result = new CompilationResult.errors(errors);
+ result = new CompilationResult.errors(compiler.errors);
} else {
// We serialize the program excluding platform.dill because the VM has
// these sources built-in. Everything loaded as a summary in
// [kernelForProgram] is marked `external`, so we can use that bit to
- // decide what to excluce.
+ // decide what to exclude.
// TODO(sigmund): remove the following line (Issue #30111)
program.libraries.forEach((e) => e.isExternal = false);
result = new CompilationResult.ok(
@@ -166,7 +259,13 @@ train(String scriptUri) {
throw "Unexpected response: $response";
}
};
- var request = [tag, responsePort.sendPort, scriptUri];
+ var request = [
+ tag,
+ responsePort.sendPort,
+ scriptUri,
+ 1 /* isolateId chosen randomly */,
+ false /* incremental */
+ ];
_processLoadRequest(request);
}
« no previous file with comments | « runtime/vm/unit_test.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698