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

Unified Diff: runtime/tools/kernel-service.dart

Issue 2651633002: VM: [Kernel] Fix bootstraping when Kernel isolate is used. (Closed)
Patch Set: Landing issue Created 3 years, 11 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/include/dart_native_api.h ('k') | runtime/vm/dart_api_impl.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/tools/kernel-service.dart
diff --git a/runtime/tools/kernel-service.dart b/runtime/tools/kernel-service.dart
index f473c154775f0376174f49614e7eb7ace589ec48..b1b441db2ed5e7d1f6efe595150f09d973bb1c93 100644
--- a/runtime/tools/kernel-service.dart
+++ b/runtime/tools/kernel-service.dart
@@ -1,22 +1,26 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+library runtime.tools.kernel_service;
// This is an interface to the Dart Kernel parser and Kernel binary generator.
+//
// It is used by the kernel-isolate to load Dart source code and generate
// Kernel binary format.
+//
-import 'dart:isolate';
import 'dart:async';
+import 'dart:convert';
import 'dart:io';
+import 'dart:isolate';
import 'dart:typed_data';
-import 'package:kernel/binary/ast_to_binary.dart';
import 'package:kernel/analyzer/loader.dart';
+import 'package:kernel/binary/ast_to_binary.dart';
import 'package:kernel/kernel.dart';
import 'package:kernel/target/targets.dart';
-const verbose = false;
+const bool verbose = const bool.fromEnvironment('DFE_VERBOSE') ?? false;
class DataSink implements Sink<List<int>> {
final BytesBuilder builder = new BytesBuilder();
@@ -30,7 +34,55 @@ class DataSink implements Sink<List<int>> {
}
}
-Future<Uint8List> parseScript(
+// Note: these values must match Dart_KernelCompilationStatus in dart_api.h.
+const int STATUS_OK = 0; // Compilation was successful.
+const int STATUS_ERROR = 1; // Compilation failed with a compile time error.
+const int STATUS_CRASH = 2; // Compiler crashed.
+
+abstract class CompilationResult {
+ List toResponse();
+}
+
+class CompilationOk extends CompilationResult {
+ final Uint8List binary;
+
+ CompilationOk(this.binary);
+
+ List toResponse() => [STATUS_OK, binary];
+
+ String toString() => "CompilationOk(${binary.length} bytes)";
+}
+
+abstract class CompilationFail extends CompilationResult {
+ String get errorString;
+}
+
+class CompilationError extends CompilationFail {
+ final List<String> errors;
+
+ CompilationError(this.errors);
+
+ List toResponse() => [STATUS_ERROR, errorString];
+
+ String get errorString => errors.take(10).join('\n');
+
+ String toString() => "CompilationError(${errorString})";
+}
+
+class CompilationCrash extends CompilationFail {
+ final String exception;
+ final String stack;
+
+ CompilationCrash(this.exception, this.stack);
+
+ List toResponse() => [STATUS_CRASH, errorString];
+
+ String get errorString => "${exception}\n${stack}";
+
+ String toString() => "CompilationCrash(${errorString})";
+}
+
+Future<CompilationResult> parseScriptImpl(DartLoaderBatch batch_loader,
Uri fileName, String packageConfig, String sdkPath) async {
if (!FileSystemEntity.isFileSync(fileName.path)) {
throw "Input file '${fileName.path}' does not exist.";
@@ -49,12 +101,12 @@ Future<Uint8List> parseScript(
customUriMappings: const {},
declaredVariables: const {});
DartLoader loader =
- await new DartLoaderBatch().getLoader(new Repository(), dartOptions);
+ await batch_loader.getLoader(new Repository(), dartOptions);
var program = loader.loadProgram(fileName, target: target);
var errors = loader.errors;
if (errors.isNotEmpty) {
- throw loader.errors.first;
+ return new CompilationError(loader.errors.toList());
}
// Link program into one file, cf. --link option in dartk.
@@ -63,33 +115,111 @@ Future<Uint8List> parseScript(
// Write the program to a list of bytes and return it.
var sink = new DataSink();
new BinaryPrinter(sink).writeProgramFile(program);
- return sink.builder.takeBytes();
+ return new CompilationOk(sink.builder.takeBytes());
}
-Future _processLoadRequest(request) async {
- if (verbose) {
- print("FROM DART KERNEL: load request: $request");
- print("FROM DART KERNEL: package: ${Platform.packageConfig}");
- print("FROM DART KERNEL: exec: ${Platform.resolvedExecutable}");
+Future<CompilationResult> parseScript(DartLoaderBatch loader, Uri fileName,
+ String packageConfig, String sdkPath) async {
+ try {
+ return await parseScriptImpl(loader, fileName, packageConfig, sdkPath);
+ } catch (err, stack) {
+ return new CompilationCrash(err.toString(), stack.toString());
}
+}
- int tag = request[0];
- SendPort port = request[1];
- String inputFileUrl = request[2];
+Future _processLoadRequestImpl(String inputFileUrl) async {
Uri scriptUri = Uri.parse(inputFileUrl);
- Uri packagesUri = Uri.parse(Platform.packageConfig ?? ".packages");
- Uri patchedSdk =
+
+ // Because we serve both Loader and bootstrapping requests we need to
+ // duplicate the logic from _resolveScriptUri(...) here and attempt to
+ // resolve schemaless uris using current working directory.
+ if (scriptUri.scheme == '') {
+ // Script does not have a scheme, assume that it is a path,
+ // resolve it against the working directory.
+ scriptUri = Directory.current.uri.resolveUri(scriptUri);
+ }
+
+ if (scriptUri.scheme != 'file') {
+ // TODO: reuse loader code to support other schemes.
+ throw "Expected 'file' scheme for a script uri: got ${scriptUri.scheme}";
+ }
+
+ final Uri packagesUri = (Platform.packageConfig != null)
+ ? Uri.parse(Platform.packageConfig)
+ : await _findPackagesFile(scriptUri);
+ if (packagesUri == null) {
+ throw "Could not find .packages";
+ }
+
+ final Uri patchedSdk =
Uri.parse(Platform.resolvedExecutable).resolve("patched_sdk");
+ if (verbose) {
+ print("""DFE: Requesting compilation {
+ scriptUri: ${scriptUri}
+ packagesUri: ${packagesUri}
+ patchedSdk: ${patchedSdk}
+}""");
+ }
+
+ return await parseScript(
+ new DartLoaderBatch(), scriptUri, packagesUri.path, patchedSdk.path);
+}
+
+// Process a request from the runtime. See KernelIsolate::CompileToKernel in
+// kernel_isolate.cc and Loader::SendKernelRequest in loader.cc.
+Future _processLoadRequest(request) async {
+ if (verbose) {
+ print("DFE: request: $request");
+ print("DFE: Platform.packageConfig: ${Platform.packageConfig}");
+ print("DFE: Platform.resolvedExecutable: ${Platform.resolvedExecutable}");
+ }
+
+ final int tag = request[0];
+ final SendPort port = request[1];
+ final String inputFileUrl = request[2];
+
var result;
try {
- result = await parseScript(scriptUri, packagesUri.path, patchedSdk.path);
- } catch (error) {
- tag = -tag; // Mark reply as an exception.
- result = error.toString();
+ result = await _processLoadRequestImpl(inputFileUrl);
+ } catch (error, stack) {
+ result = new CompilationCrash(error.toString(), stack.toString());
}
- port.send([tag, inputFileUrl, inputFileUrl, null, result]);
+ if (verbose) {
+ print("DFE:> ${result}");
+ }
+
+ // Check whether this is a Loader request or a bootstrapping request from
+ // KernelIsolate::CompileToKernel.
+ final isBootstrapRequest = tag == null;
+ if (isBootstrapRequest) {
+ port.send(result.toResponse());
+ } else {
+ // See loader.cc for the code that handles these replies.
+ if (result is CompilationOk) {
+ port.send([tag, inputFileUrl, inputFileUrl, null, result]);
+ } else {
+ port.send([-tag, inputFileUrl, inputFileUrl, null, result.errorString]);
+ }
+ }
}
main() => new RawReceivePort()..handler = _processLoadRequest;
+
+// This duplicates functionality from the Loader which we can't easily
+// access from here.
+Uri _findPackagesFile(Uri base) async {
+ var dir = new File.fromUri(base).parent;
+ while (true) {
+ final packagesFile = dir.uri.resolve(".packages");
+ if (await new File.fromUri(packagesFile).exists()) {
+ return packagesFile;
+ }
+ if (dir.parent == dir) {
+ break;
+ }
+ dir = dir.parent;
+ }
+ return null;
+}
« no previous file with comments | « runtime/include/dart_native_api.h ('k') | runtime/vm/dart_api_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698