| Index: runtime/tools/kernel-service.dart
|
| diff --git a/runtime/tools/kernel-service.dart b/runtime/tools/kernel-service.dart
|
| deleted file mode 100644
|
| index e86e6c1acecabe8989733d7cc059709e61f64a9b..0000000000000000000000000000000000000000
|
| --- a/runtime/tools/kernel-service.dart
|
| +++ /dev/null
|
| @@ -1,339 +0,0 @@
|
| -// 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.
|
| -//
|
| -// This is either invoked as the root script of the Kernel isolate when used
|
| -// as a part of
|
| -//
|
| -// dart --dfe=runtime/tools/kernel-service.dart ...
|
| -//
|
| -// invocation or it is invoked as a standalone script to perform batch mode
|
| -// compilation requested via an HTTP interface
|
| -//
|
| -// dart runtime/tools/kernel-service.dart --batch
|
| -//
|
| -// The port for the batch mode worker is controlled by DFE_WORKER_PORT
|
| -// environment declarations (set by -DDFE_WORKER_PORT=... command line flag).
|
| -// When not set (or set to 0) an ephemeral port returned by the OS is used
|
| -// instead.
|
| -//
|
| -// When this script is used as a Kernel isolate root script and DFE_WORKER_PORT
|
| -// is set to non-zero value then Kernel isolate will forward all compilation
|
| -// requests it receives to the batch worker on the given port.
|
| -//
|
| -
|
| -import 'dart:async';
|
| -import 'dart:convert';
|
| -import 'dart:io';
|
| -import 'dart:isolate';
|
| -import 'dart:typed_data';
|
| -
|
| -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 bool verbose = const bool.fromEnvironment('DFE_VERBOSE') ?? false;
|
| -const int workerPort = const int.fromEnvironment('DFE_WORKER_PORT') ?? 0;
|
| -
|
| -class DataSink implements Sink<List<int>> {
|
| - final BytesBuilder builder = new BytesBuilder();
|
| -
|
| - void add(List<int> data) {
|
| - builder.add(data);
|
| - }
|
| -
|
| - void close() {
|
| - // Nothing to do.
|
| - }
|
| -}
|
| -
|
| -// 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;
|
| -
|
| - Map<String, dynamic> toJson();
|
| -
|
| - static CompilationFail fromJson(Map m) {
|
| - switch (m['status']) {
|
| - case STATUS_ERROR:
|
| - return new CompilationError(m['errors']);
|
| - case STATUS_CRASH:
|
| - return new CompilationCrash(m['exception'], m['stack']);
|
| - }
|
| - }
|
| -}
|
| -
|
| -class CompilationError extends CompilationFail {
|
| - final List<String> errors;
|
| -
|
| - CompilationError(this.errors);
|
| -
|
| - List toResponse() => [STATUS_ERROR, errorString];
|
| -
|
| - Map<String, dynamic> toJson() => {
|
| - "status": STATUS_ERROR,
|
| - "errors": errors,
|
| - };
|
| -
|
| - 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];
|
| -
|
| - Map<String, dynamic> toJson() => {
|
| - "status": STATUS_CRASH,
|
| - "exception": exception,
|
| - "stack": stack,
|
| - };
|
| -
|
| - 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.";
|
| - }
|
| -
|
| - if (!FileSystemEntity.isDirectorySync(sdkPath)) {
|
| - throw "Patched sdk directory not found at $sdkPath";
|
| - }
|
| -
|
| - Target target = getTarget("vm", new TargetFlags(strongMode: false));
|
| - DartOptions dartOptions = new DartOptions(
|
| - strongMode: false,
|
| - strongModeSdk: false,
|
| - sdk: sdkPath,
|
| - packagePath: packageConfig,
|
| - customUriMappings: const {},
|
| - declaredVariables: const {});
|
| - DartLoader loader =
|
| - await batch_loader.getLoader(new Repository(), dartOptions);
|
| - var program = loader.loadProgram(fileName, target: target);
|
| -
|
| - var errors = loader.errors;
|
| - if (errors.isNotEmpty) {
|
| - return new CompilationError(loader.errors.toList());
|
| - }
|
| -
|
| - // Link program into one file, cf. --link option in dartk.
|
| - target.transformProgram(program);
|
| -
|
| - // Write the program to a list of bytes and return it.
|
| - var sink = new DataSink();
|
| - new BinaryPrinter(sink).writeProgramFile(program);
|
| - return new CompilationOk(sink.builder.takeBytes());
|
| -}
|
| -
|
| -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());
|
| - }
|
| -}
|
| -
|
| -Future _processLoadRequestImpl(String inputFileUrl) async {
|
| - Uri scriptUri = Uri.parse(inputFileUrl);
|
| -
|
| - // 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}
|
| -}""");
|
| - }
|
| -
|
| - if (workerPort != 0) {
|
| - return await requestParse(scriptUri, packagesUri, patchedSdk);
|
| - } else {
|
| - 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 _processLoadRequestImpl(inputFileUrl);
|
| - } catch (error, stack) {
|
| - result = new CompilationCrash(error.toString(), stack.toString());
|
| - }
|
| -
|
| - 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]);
|
| - }
|
| - }
|
| -}
|
| -
|
| -Future<CompilationResult> requestParse(
|
| - Uri scriptUri, Uri packagesUri, Uri patchedSdk) async {
|
| - if (verbose) {
|
| - print(
|
| - "DFE: forwarding request to worker at http://localhost:${workerPort}/");
|
| - }
|
| -
|
| - HttpClient client = new HttpClient();
|
| - final rq = await client
|
| - .postUrl(new Uri(host: 'localhost', port: workerPort, scheme: 'http'));
|
| - rq.headers.contentType = ContentType.JSON;
|
| - rq.write(JSON.encode({
|
| - "inputFileUrl": scriptUri.toString(),
|
| - "packagesUri": packagesUri.toString(),
|
| - "patchedSdk": patchedSdk.toString(),
|
| - }));
|
| - final rs = await rq.close();
|
| - try {
|
| - if (rs.statusCode == HttpStatus.OK) {
|
| - final BytesBuilder bb = new BytesBuilder();
|
| - await rs.forEach(bb.add);
|
| - return new CompilationOk(bb.takeBytes());
|
| - } else {
|
| - return CompilationFail.fromJson(JSON.decode(await UTF8.decodeStream(rs)));
|
| - }
|
| - } finally {
|
| - await client.close();
|
| - }
|
| -}
|
| -
|
| -void startBatchServer() {
|
| - final loader = new DartLoaderBatch();
|
| - HttpServer.bind(InternetAddress.LOOPBACK_IP_V6, workerPort).then((server) {
|
| - print('READY ${server.port}');
|
| - server.listen((HttpRequest request) async {
|
| - final rq = JSON.decode(await UTF8.decodeStream(request));
|
| -
|
| - final Uri scriptUri = Uri.parse(rq['inputFileUrl']);
|
| - final Uri packagesUri = Uri.parse(rq['packagesUri']);
|
| - final Uri patchedSdk = Uri.parse(rq['patchedSdk']);
|
| -
|
| - final CompilationResult result = await parseScript(
|
| - loader, scriptUri, packagesUri.path, patchedSdk.path);
|
| -
|
| - if (result is CompilationOk) {
|
| - request.response.statusCode = HttpStatus.OK;
|
| - request.response.headers.contentType = ContentType.BINARY;
|
| - request.response.add(result.binary);
|
| - request.response.close();
|
| - } else {
|
| - request.response.statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
|
| - request.response.headers.contentType = ContentType.TEXT;
|
| - request.response.write(JSON.encode(result.toJson()));
|
| - request.response.close();
|
| - }
|
| - });
|
| - ProcessSignal.SIGTERM.watch().first.then((_) => server.close());
|
| - });
|
| -}
|
| -
|
| -main([args]) {
|
| - if (args?.length == 1 && args[0] == '--batch') {
|
| - startBatchServer();
|
| - } else {
|
| - // Entry point for the Kernel isolate.
|
| - return 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.path == dir.path) {
|
| - break;
|
| - }
|
| - dir = dir.parent;
|
| - }
|
| - return null;
|
| -}
|
|
|