VM: [Kernel] Fix bootstraping when Kernel isolate is used.

We must bootstrap from Kernel instead of Source when running with --dfe

BUG=
R=asiva@google.com, kustermann@google.com

Review-Url: https://codereview.chromium.org/2651633002 .
This commit is contained in:
Vyacheslav Egorov 2017-01-30 20:52:59 +01:00
parent 1bb198ccc7
commit 43a0500e37
18 changed files with 451 additions and 102 deletions

View file

@ -27,7 +27,9 @@ namespace bin {
response = type::method##Request(data); \
break;
void IOServiceCallback(Dart_Port dest_port_id, Dart_CObject* message) {
void IOServiceCallback(Dart_Port dest_port_id,
Dart_CObject* message,
void* peer) {
Dart_Port reply_port_id = ILLEGAL_PORT;
CObject* response = CObject::IllegalArgumentError();
CObjectArray request(message);
@ -55,7 +57,7 @@ void IOServiceCallback(Dart_Port dest_port_id, Dart_CObject* message) {
Dart_Port IOService::GetServicePort() {
return Dart_NewNativePort("IOService", IOServiceCallback, true);
return Dart_NewNativePort("IOService", IOServiceCallback, true, NULL);
}

View file

@ -26,7 +26,9 @@ namespace bin {
response = type::method##Request(data); \
break;
void IOServiceCallback(Dart_Port dest_port_id, Dart_CObject* message) {
void IOServiceCallback(Dart_Port dest_port_id,
Dart_CObject* message,
void* peer) {
Dart_Port reply_port_id = ILLEGAL_PORT;
CObject* response = CObject::IllegalArgumentError();
CObjectArray request(message);
@ -54,7 +56,7 @@ void IOServiceCallback(Dart_Port dest_port_id, Dart_CObject* message) {
Dart_Port IOService::GetServicePort() {
return Dart_NewNativePort("IOService", IOServiceCallback, true);
return Dart_NewNativePort("IOService", IOServiceCallback, true, NULL);
}

View file

@ -34,7 +34,8 @@ Loader::Loader(IsolateData* isolate_data)
payload_length_(0) {
monitor_ = new Monitor();
ASSERT(isolate_data_ != NULL);
port_ = Dart_NewNativePort("Loader", Loader::NativeMessageHandler, false);
port_ =
Dart_NewNativePort("Loader", Loader::NativeMessageHandler, false, this);
isolate_data_->set_loader(this);
AddLoader(port_, isolate_data_);
}
@ -817,13 +818,10 @@ Loader* Loader::LoaderFor(Dart_Port port) {
void Loader::NativeMessageHandler(Dart_Port dest_port_id,
Dart_CObject* message) {
Dart_CObject* message,
void* peer) {
MutexLocker ml(loader_infos_lock_);
Loader* loader = LoaderForLocked(dest_port_id);
if (loader == NULL) {
return;
}
loader->QueueMessage(message);
static_cast<Loader*>(peer)->QueueMessage(message);
}
} // namespace bin

View file

@ -142,7 +142,8 @@ class Loader {
// This is the global callback for the native message handlers.
static void NativeMessageHandler(Dart_Port dest_port_id,
Dart_CObject* message);
Dart_CObject* message,
void* peer);
};
} // namespace bin

View file

@ -125,6 +125,8 @@ static int vm_service_server_port = -1;
// checks are disabled.
static bool vm_service_dev_mode = false;
// Exit code indicating an internal Dart Frontend error.
static const int kDartFrontendErrorExitCode = 252;
// Exit code indicating an API error.
static const int kApiErrorExitCode = 253;
// Exit code indicating a compilation error.
@ -809,7 +811,7 @@ static Dart_Handle EnvironmentCallback(Dart_Handle name) {
static void SnapshotOnExitHook(int64_t exit_code);
// Returns true on success, false on failure.
// Returns newly created Isolate on success, NULL on failure.
static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
const char* script_uri,
const char* main,
@ -819,7 +821,11 @@ static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
char** error,
int* exit_code) {
ASSERT(script_uri != NULL);
if (strcmp(script_uri, DART_KERNEL_ISOLATE_NAME) == 0) {
const bool is_service_isolate =
strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0;
const bool is_kernel_isolate =
strcmp(script_uri, DART_KERNEL_ISOLATE_NAME) == 0;
if (is_kernel_isolate) {
if (!use_dart_frontend) {
*error = strdup("Kernel isolate not supported.");
return NULL;
@ -852,13 +858,36 @@ static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
}
#endif
// If the script is a Kernel binary, then we will try to bootstrap from the
// script.
const uint8_t* kernel_file = NULL;
intptr_t kernel_length = -1;
const bool is_kernel =
!isolate_run_app_snapshot &&
TryReadKernel(script_uri, &kernel_file, &kernel_length);
bool is_kernel = false;
if (use_dart_frontend && !is_kernel_isolate && !is_service_isolate) {
Dart_KernelCompilationResult result = Dart_CompileToKernel(script_uri);
*error = result.error; // Copy error message (if any).
switch (result.status) {
case Dart_KernelCompilationStatus_Ok:
is_kernel = true;
kernel_file = result.kernel;
kernel_length = result.kernel_size;
break;
case Dart_KernelCompilationStatus_Error:
*exit_code = kCompilationErrorExitCode;
return NULL;
case Dart_KernelCompilationStatus_Crash:
*exit_code = kDartFrontendErrorExitCode;
return NULL;
case Dart_KernelCompilationStatus_Unknown:
*exit_code = kErrorExitCode;
return NULL;
}
}
// If the script is a Kernel binary, then we will try to bootstrap from the
// script.
if (!is_kernel && !isolate_run_app_snapshot) {
is_kernel = TryReadKernel(script_uri, &kernel_file, &kernel_length);
}
void* kernel_program = NULL;
if (is_kernel) {
@ -940,16 +969,6 @@ static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
result = Dart_SetEnvironmentCallback(EnvironmentCallback);
CHECK_RESULT(result);
if (!Dart_IsKernelIsolate(isolate) && use_dart_frontend) {
// This must be the main script to be loaded. Wait for Kernel isolate
// to finish initialization.
Dart_Port port = Dart_ServiceWaitForKernelPort();
if (port == ILLEGAL_PORT) {
*error = strdup("Error while initializing Kernel isolate");
return NULL;
}
}
if (isolate_run_app_snapshot) {
result = DartUtils::SetupIOLibrary(script_uri);
CHECK_RESULT(result);
@ -975,6 +994,12 @@ static Dart_Isolate CreateIsolateAndSetupHelper(bool is_main_isolate,
if (!is_kernel) {
result = Loader::LibraryTagHandler(Dart_kScriptTag, Dart_Null(), uri);
CHECK_RESULT(result);
} else {
// Various core-library parts will send requests to the Loader to resolve
// relative URIs and perform other related tasks. We need Loader to be
// initialized for this to work because loading from Kernel binary
// bypasses normal source code loading paths that initialize it.
Loader::InitForSnapshot(script_uri);
}
Dart_TimelineEvent("LoadScript", Dart_TimelineGetMicros(),

View file

@ -3127,10 +3127,26 @@ DART_EXPORT Dart_Handle Dart_SetPeer(Dart_Handle object, void* peer);
*
*/
typedef enum {
Dart_KernelCompilationStatus_Unknown = -1,
Dart_KernelCompilationStatus_Ok = 0,
Dart_KernelCompilationStatus_Error = 1,
Dart_KernelCompilationStatus_Crash = 2,
} Dart_KernelCompilationStatus;
typedef struct {
Dart_KernelCompilationStatus status;
char* error;
uint8_t* kernel;
intptr_t kernel_size;
} Dart_KernelCompilationResult;
DART_EXPORT bool Dart_IsKernelIsolate(Dart_Isolate isolate);
DART_EXPORT bool Dart_KernelIsolateIsRunning();
DART_EXPORT Dart_Port Dart_ServiceWaitForKernelPort();
DART_EXPORT Dart_Port Dart_KernelPort();
DART_EXPORT Dart_KernelCompilationResult
Dart_CompileToKernel(const char* script_uri);
#define DART_KERNEL_ISOLATE_NAME "kernel-service"

View file

@ -124,7 +124,8 @@ DART_EXPORT bool Dart_PostInteger(Dart_Port port_id, int64_t message);
*/
typedef void (*Dart_NativeMessageHandler)(Dart_Port dest_port_id,
Dart_CObject* message);
Dart_CObject* message,
void* peer);
/**
* Creates a new native port. When messages are received on this
@ -135,13 +136,16 @@ typedef void (*Dart_NativeMessageHandler)(Dart_Port dest_port_id,
* \param handler The C handler to run when messages arrive on the port.
* \param handle_concurrently Is it okay to process requests on this
* native port concurrently?
* \param peer Peer associated with this port. It will be passed down to the
handler when new message arrives.
*
* \return If successful, returns the port id for the native port. In
* case of error, returns ILLEGAL_PORT.
*/
DART_EXPORT Dart_Port Dart_NewNativePort(const char* name,
Dart_NativeMessageHandler handler,
bool handle_concurrently);
bool handle_concurrently,
void* peer);
/* TODO(turnidge): Currently handle_concurrently is ignored. */
/**

View file

@ -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());
}
}
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);
}
int tag = request[0];
SendPort port = request[1];
String inputFileUrl = request[2];
Uri scriptUri = Uri.parse(inputFileUrl);
Uri packagesUri = Uri.parse(Platform.packageConfig ?? ".packages");
Uri patchedSdk =
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;
}

View file

@ -6013,14 +6013,6 @@ DART_EXPORT bool Dart_KernelIsolateIsRunning() {
}
DART_EXPORT Dart_Port Dart_ServiceWaitForKernelPort() {
#ifdef DART_PRECOMPILED_RUNTIME
return ILLEGAL_PORT;
#else
return KernelIsolate::WaitForKernelPort();
#endif
}
DART_EXPORT Dart_Port Dart_KernelPort() {
#ifdef DART_PRECOMPILED_RUNTIME
return false;
@ -6030,6 +6022,18 @@ DART_EXPORT Dart_Port Dart_KernelPort() {
}
DART_EXPORT Dart_KernelCompilationResult
Dart_CompileToKernel(const char* script_uri) {
#ifdef DART_PRECOMPILED_RUNTIME
Dart_KernelCompilationResult result;
result.status = Dart_KernelCompilationStatus_Unknown;
result.error = strdup("Dart_CompileToKernel is unsupported.");
return result;
#else
return KernelIsolate::CompileToKernel(script_uri);
#endif
}
// --- Service support ---
DART_EXPORT bool Dart_IsServiceIsolate(Dart_Isolate isolate) {

View file

@ -7150,12 +7150,19 @@ TEST_CASE(ImportLibrary5) {
}
void NewNativePort_send123(Dart_Port dest_port_id, Dart_CObject* message) {
void NewNativePort_send123(Dart_Port dest_port_id,
Dart_CObject* message,
void* peer) {
// Gets a send port message.
EXPECT_NOTNULL(message);
EXPECT_EQ(Dart_CObject_kArray, message->type);
EXPECT_EQ(Dart_CObject_kSendPort, message->value.as_array.values[0]->type);
// Check peer validity.
EXPECT_NOTNULL(peer);
EXPECT_EQ(0xDEADBEEF, *static_cast<intptr_t*>(peer));
*static_cast<intptr_t*>(peer) = 123;
// Post integer value.
Dart_CObject* response =
reinterpret_cast<Dart_CObject*>(Dart_ScopeAllocate(sizeof(Dart_CObject)));
@ -7166,12 +7173,19 @@ void NewNativePort_send123(Dart_Port dest_port_id, Dart_CObject* message) {
}
void NewNativePort_send321(Dart_Port dest_port_id, Dart_CObject* message) {
void NewNativePort_send321(Dart_Port dest_port_id,
Dart_CObject* message,
void* peer) {
// Gets a null message.
EXPECT_NOTNULL(message);
EXPECT_EQ(Dart_CObject_kArray, message->type);
EXPECT_EQ(Dart_CObject_kSendPort, message->value.as_array.values[0]->type);
// Check peer validity.
EXPECT_NOTNULL(peer);
EXPECT_EQ(0xDEADBEEF, *static_cast<intptr_t*>(peer));
*static_cast<intptr_t*>(peer) = 321;
// Post integer value.
Dart_CObject* response =
reinterpret_cast<Dart_CObject*>(Dart_ScopeAllocate(sizeof(Dart_CObject)));
@ -7198,12 +7212,13 @@ TEST_CASE(IllegalPost) {
UNIT_TEST_CASE(NewNativePort) {
// Create a port with a bogus handler.
Dart_Port error_port = Dart_NewNativePort("Foo", NULL, true);
Dart_Port error_port = Dart_NewNativePort("Foo", NULL, true, NULL);
EXPECT_EQ(ILLEGAL_PORT, error_port);
intptr_t peer1 = 0xDEADBEEF;
// Create the port w/o a current isolate, just to make sure that works.
Dart_Port port_id1 =
Dart_NewNativePort("Port123", NewNativePort_send123, true);
Dart_NewNativePort("Port123", NewNativePort_send123, true, &peer1);
TestIsolateScope __test_isolate__;
const char* kScriptChars =
@ -7221,8 +7236,9 @@ UNIT_TEST_CASE(NewNativePort) {
Dart_EnterScope();
// Create a port w/ a current isolate, to make sure that works too.
intptr_t peer2 = 0xDEADBEEF;
Dart_Port port_id2 =
Dart_NewNativePort("Port321", NewNativePort_send321, true);
Dart_NewNativePort("Port321", NewNativePort_send321, true, &peer2);
Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
EXPECT_VALID(send_port1);
@ -7238,6 +7254,7 @@ UNIT_TEST_CASE(NewNativePort) {
EXPECT(Dart_IsError(result));
EXPECT(Dart_ErrorHasException(result));
EXPECT_SUBSTRING("Exception: 123\n", Dart_GetError(result));
EXPECT_EQ(123, peer1);
// result second port.
dart_args[0] = send_port2;
@ -7247,6 +7264,7 @@ UNIT_TEST_CASE(NewNativePort) {
EXPECT(Dart_IsError(result));
EXPECT(Dart_ErrorHasException(result));
EXPECT_SUBSTRING("Exception: 321\n", Dart_GetError(result));
EXPECT_EQ(321, peer2);
Dart_ExitScope();
@ -7257,7 +7275,8 @@ UNIT_TEST_CASE(NewNativePort) {
void NewNativePort_sendInteger123(Dart_Port dest_port_id,
Dart_CObject* message) {
Dart_CObject* message,
void* peer) {
// Gets a send port message.
EXPECT_NOTNULL(message);
EXPECT_EQ(Dart_CObject_kArray, message->type);
@ -7270,7 +7289,8 @@ void NewNativePort_sendInteger123(Dart_Port dest_port_id,
void NewNativePort_sendInteger321(Dart_Port dest_port_id,
Dart_CObject* message) {
Dart_CObject* message,
void* peer) {
// Gets a null message.
EXPECT_NOTNULL(message);
EXPECT_EQ(Dart_CObject_kArray, message->type);
@ -7298,9 +7318,9 @@ TEST_CASE(NativePortPostInteger) {
Dart_EnterScope();
Dart_Port port_id1 =
Dart_NewNativePort("Port123", NewNativePort_sendInteger123, true);
Dart_NewNativePort("Port123", NewNativePort_sendInteger123, true, NULL);
Dart_Port port_id2 =
Dart_NewNativePort("Port321", NewNativePort_sendInteger321, true);
Dart_NewNativePort("Port321", NewNativePort_sendInteger321, true, NULL);
Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
EXPECT_VALID(send_port1);
@ -7335,7 +7355,8 @@ TEST_CASE(NativePortPostInteger) {
void NewNativePort_nativeReceiveNull(Dart_Port dest_port_id,
Dart_CObject* message) {
Dart_CObject* message,
void* peer) {
EXPECT_NOTNULL(message);
if ((message->type == Dart_CObject_kArray) &&
@ -7365,8 +7386,8 @@ TEST_CASE(NativePortReceiveNull) {
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
Dart_EnterScope();
Dart_Port port_id1 =
Dart_NewNativePort("PortNull", NewNativePort_nativeReceiveNull, true);
Dart_Port port_id1 = Dart_NewNativePort(
"PortNull", NewNativePort_nativeReceiveNull, true, NULL);
Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
EXPECT_VALID(send_port1);
@ -7388,7 +7409,8 @@ TEST_CASE(NativePortReceiveNull) {
void NewNativePort_nativeReceiveInteger(Dart_Port dest_port_id,
Dart_CObject* message) {
Dart_CObject* message,
void* peer) {
EXPECT_NOTNULL(message);
if ((message->type == Dart_CObject_kArray) &&
@ -7419,8 +7441,8 @@ TEST_CASE(NativePortReceiveInteger) {
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
Dart_EnterScope();
Dart_Port port_id1 =
Dart_NewNativePort("PortNull", NewNativePort_nativeReceiveInteger, true);
Dart_Port port_id1 = Dart_NewNativePort(
"PortNull", NewNativePort_nativeReceiveInteger, true, NULL);
Dart_Handle send_port1 = Dart_NewSendPort(port_id1);
EXPECT_VALID(send_port1);

View file

@ -1284,6 +1284,14 @@ bool ApiMessageWriter::WriteCObjectInlined(Dart_CObject* object,
WriteRawPointerValue(reinterpret_cast<intptr_t>(callback));
break;
}
case Dart_CObject_kSendPort: {
WriteInlinedHeader(object);
WriteIndexedObject(kSendPortCid);
WriteTags(0);
Write<int64_t>(object->value.as_send_port.id);
Write<uint64_t>(object->value.as_send_port.origin_id);
break;
}
case Dart_CObject_kCapability: {
WriteInlinedHeader(object);
WriteIndexedObject(kCapabilityCid);

View file

@ -5,6 +5,7 @@
#include "vm/kernel_isolate.h"
#include "vm/compiler.h"
#include "include/dart_native_api.h"
#include "vm/dart_api_impl.h"
#include "vm/dart_entry.h"
#include "vm/isolate.h"
@ -33,7 +34,7 @@ DEFINE_FLAG(bool,
false,
"Parse scripts with Dart-to-Kernel parser");
const char* KernelIsolate::kName = "kernel-service";
const char* KernelIsolate::kName = DART_KERNEL_ISOLATE_NAME;
Dart_IsolateCreateCallback KernelIsolate::create_callback_ = NULL;
Monitor* KernelIsolate::monitor_ = new Monitor();
Isolate* KernelIsolate::isolate_ = NULL;
@ -74,7 +75,8 @@ class RunKernelTask : public ThreadPool::Task {
KernelIsolate::kName, NULL, NULL, NULL, &api_flags, NULL, &error));
if (isolate == NULL) {
if (FLAG_trace_kernel) {
OS::PrintErr("kernel-service: Isolate creation error: %s\n", error);
OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Isolate creation error: %s\n",
error);
}
KernelIsolate::SetKernelIsolate(NULL);
KernelIsolate::FinishedInitializing();
@ -104,7 +106,7 @@ class RunKernelTask : public ThreadPool::Task {
protected:
static void ShutdownIsolate(uword parameter) {
if (FLAG_trace_kernel) {
OS::Print("kernel-service: ShutdownIsolate\n");
OS::Print(DART_KERNEL_ISOLATE_NAME ": ShutdownIsolate\n");
}
Isolate* I = reinterpret_cast<Isolate*>(parameter);
ASSERT(KernelIsolate::IsKernelIsolate(I));
@ -123,18 +125,20 @@ class RunKernelTask : public ThreadPool::Task {
Error& error = Error::Handle(Z);
error = T->sticky_error();
if (!error.IsNull() && !error.IsUnwindError()) {
OS::PrintErr("kernel-service: Error: %s\n", error.ToErrorCString());
OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Error: %s\n",
error.ToErrorCString());
}
error = I->sticky_error();
if (!error.IsNull() && !error.IsUnwindError()) {
OS::PrintErr("kernel-service: Error: %s\n", error.ToErrorCString());
OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Error: %s\n",
error.ToErrorCString());
}
Dart::RunShutdownCallback();
}
// Shut the isolate down.
Dart::ShutdownIsolate(I);
if (FLAG_trace_kernel) {
OS::Print("kernel-service: Shutdown.\n");
OS::Print(DART_KERNEL_ISOLATE_NAME ": Shutdown.\n");
}
}
@ -148,7 +152,8 @@ class RunKernelTask : public ThreadPool::Task {
Library::Handle(Z, I->object_store()->root_library());
if (root_library.IsNull()) {
if (FLAG_trace_kernel) {
OS::Print("kernel-service: Embedder did not install a script.");
OS::Print(DART_KERNEL_ISOLATE_NAME
": Embedder did not install a script.");
}
// Kernel isolate is not supported by embedder.
return false;
@ -161,7 +166,8 @@ class RunKernelTask : public ThreadPool::Task {
if (entry.IsNull()) {
// Kernel isolate is not supported by embedder.
if (FLAG_trace_kernel) {
OS::Print("kernel-service: Embedder did not provide a main function.");
OS::Print(DART_KERNEL_ISOLATE_NAME
": Embedder did not provide a main function.");
}
return false;
}
@ -173,7 +179,8 @@ class RunKernelTask : public ThreadPool::Task {
// Kernel isolate did not initialize properly.
if (FLAG_trace_kernel) {
const Error& error = Error::Cast(result);
OS::Print("kernel-service: Calling main resulted in an error: %s",
OS::Print(DART_KERNEL_ISOLATE_NAME
": Calling main resulted in an error: %s",
error.ToErrorCString());
}
return false;
@ -203,13 +210,13 @@ void KernelIsolate::InitCallback(Isolate* I) {
ASSERT(I != NULL);
ASSERT(I->name() != NULL);
if (!FLAG_use_dart_frontend ||
(strstr(I->name(), "kernel-service") == NULL)) {
(strstr(I->name(), DART_KERNEL_ISOLATE_NAME) == NULL)) {
// Not kernel isolate.
return;
}
ASSERT(!Exists());
if (FLAG_trace_kernel) {
OS::Print("kernel-service: InitCallback for %s.\n", I->name());
OS::Print(DART_KERNEL_ISOLATE_NAME ": InitCallback for %s.\n", I->name());
}
SetKernelIsolate(I);
}
@ -238,11 +245,13 @@ void KernelIsolate::SetKernelIsolate(Isolate* isolate) {
isolate_ = isolate;
}
void KernelIsolate::SetLoadPort(Dart_Port port) {
MonitorLocker ml(monitor_);
kernel_port_ = port;
}
void KernelIsolate::FinishedInitializing() {
MonitorLocker ml(monitor_);
initializing_ = false;
@ -261,6 +270,130 @@ Dart_Port KernelIsolate::WaitForKernelPort() {
return kernel_port_;
}
class KernelCompilationRequest : public ValueObject {
public:
KernelCompilationRequest()
: monitor_(new Monitor()),
port_(Dart_NewNativePort("kernel-compilation-port",
&HandleResponse,
false,
this)) {
result_.status = Dart_KernelCompilationStatus_Unknown;
result_.error = NULL;
result_.kernel = NULL;
result_.kernel_size = 0;
}
~KernelCompilationRequest() {
Dart_CloseNativePort(port_);
delete monitor_;
}
Dart_KernelCompilationResult SendAndWaitForResponse(Dart_Port kernel_port,
const char* script_uri) {
// Build the [null, send_port, script_uri] message for the Kernel isolate:
// null tag tells it that request came from this code, instead of Loader
// so that it can given a more informative response.
Dart_CObject tag;
tag.type = Dart_CObject_kNull;
Dart_CObject send_port;
send_port.type = Dart_CObject_kSendPort;
send_port.value.as_send_port.id = port_;
send_port.value.as_send_port.origin_id = ILLEGAL_PORT;
Dart_CObject uri;
uri.type = Dart_CObject_kString;
uri.value.as_string = const_cast<char*>(script_uri);
static const intptr_t kMessageLen = 3;
Dart_CObject* message_arr[kMessageLen] = {&tag, &send_port, &uri};
Dart_CObject message;
message.type = Dart_CObject_kArray;
message.value.as_array.length = kMessageLen;
message.value.as_array.values = message_arr;
// Send the message.
Dart_PostCObject(kernel_port, &message);
// Wait for reply to arrive.
MonitorLocker ml(monitor_);
while (result_.status == Dart_KernelCompilationStatus_Unknown) {
ml.Wait();
}
return result_;
}
private:
// Possible responses from the Kernel isolate:
//
// [Ok, Uint8List KernelBinary]
// [Error, String error]
// [Crash, String error]
//
void HandleResponseImpl(Dart_CObject* message) {
ASSERT(message->type == Dart_CObject_kArray);
ASSERT(message->value.as_array.length >= 1);
Dart_CObject** response = message->value.as_array.values;
MonitorLocker ml(monitor_);
ASSERT(response[0]->type == Dart_CObject_kInt32);
result_.status = static_cast<Dart_KernelCompilationStatus>(
message->value.as_array.values[0]->value.as_int32);
if (result_.status == Dart_KernelCompilationStatus_Ok) {
ASSERT(response[1]->type == Dart_CObject_kTypedData);
ASSERT(response[1]->value.as_typed_data.type == Dart_TypedData_kUint8);
result_.kernel_size = response[1]->value.as_typed_data.length;
result_.kernel = static_cast<uint8_t*>(malloc(result_.kernel_size));
memmove(result_.kernel, response[1]->value.as_typed_data.values,
result_.kernel_size);
} else {
ASSERT(result_.status == Dart_KernelCompilationStatus_Crash ||
result_.status == Dart_KernelCompilationStatus_Error);
// This is an error.
ASSERT(response[1]->type == Dart_CObject_kString);
result_.error = strdup(response[1]->value.as_string);
}
ml.Notify();
}
static void HandleResponse(Dart_Port dest_port_id,
Dart_CObject* message,
void* peer) {
static_cast<KernelCompilationRequest*>(peer)->HandleResponseImpl(message);
}
Monitor* monitor_;
Dart_Port port_;
Dart_KernelCompilationResult result_;
};
Dart_KernelCompilationResult KernelIsolate::CompileToKernel(
const char* script_uri) {
// This must be the main script to be loaded. Wait for Kernel isolate
// to finish initialization.
Dart_Port kernel_port = WaitForKernelPort();
if (kernel_port == ILLEGAL_PORT) {
Dart_KernelCompilationResult result;
result.status = Dart_KernelCompilationStatus_Unknown;
result.error = strdup("Error while initializing Kernel isolate");
return result;
}
KernelCompilationRequest request;
return request.SendAndWaitForResponse(kernel_port, script_uri);
}
#endif // DART_PRECOMPILED_RUNTIME
} // namespace dart

View file

@ -27,7 +27,7 @@ class KernelIsolate : public AllStatic {
static Dart_Port WaitForKernelPort();
static Dart_Port KernelPort() { return kernel_port_; }
static bool LoadScript(const String& url, const String& source);
static Dart_KernelCompilationResult CompileToKernel(const char* script_uri);
protected:
static Monitor* monitor_;

View file

@ -82,7 +82,8 @@ DART_EXPORT bool Dart_PostInteger(Dart_Port port_id, int64_t message) {
DART_EXPORT Dart_Port Dart_NewNativePort(const char* name,
Dart_NativeMessageHandler handler,
bool handle_concurrently) {
bool handle_concurrently,
void* peer) {
if (name == NULL) {
name = "<UnnamedNativePort>";
}
@ -94,7 +95,7 @@ DART_EXPORT Dart_Port Dart_NewNativePort(const char* name,
// Start the native port without a current isolate.
IsolateSaver saver(Isolate::Current());
NativeMessageHandler* nmh = new NativeMessageHandler(name, handler);
NativeMessageHandler* nmh = new NativeMessageHandler(name, handler, peer);
Dart_Port port_id = PortMap::CreatePort(nmh);
PortMap::SetPortState(port_id, PortMap::kLivePort);
nmh->Run(Dart::thread_pool(), NULL, NULL, 0);

View file

@ -12,8 +12,9 @@
namespace dart {
NativeMessageHandler::NativeMessageHandler(const char* name,
Dart_NativeMessageHandler func)
: name_(strdup(name)), func_(func) {}
Dart_NativeMessageHandler func,
void* peer)
: name_(strdup(name)), func_(func), peer_(peer) {}
NativeMessageHandler::~NativeMessageHandler() {
@ -41,7 +42,7 @@ MessageHandler::MessageStatus NativeMessageHandler::HandleMessage(
Dart_CObject* object;
ApiMessageReader reader(message);
object = reader.ReadMessage();
(*func())(message->dest_port(), object);
(*func())(message->dest_port(), object, peer());
delete message;
return kOK;
}

View file

@ -15,11 +15,14 @@ namespace dart {
// native C handlers.
class NativeMessageHandler : public MessageHandler {
public:
NativeMessageHandler(const char* name, Dart_NativeMessageHandler func);
NativeMessageHandler(const char* name,
Dart_NativeMessageHandler func,
void* peer);
~NativeMessageHandler();
const char* name() const { return name_; }
Dart_NativeMessageHandler func() const { return func_; }
void* peer() const { return peer_; }
MessageStatus HandleMessage(Message* message);
@ -34,6 +37,7 @@ class NativeMessageHandler : public MessageHandler {
private:
char* name_;
Dart_NativeMessageHandler func_;
void* peer_;
};
} // namespace dart

View file

@ -102,7 +102,7 @@ Dart_Port ServiceIsolate::origin_ = ILLEGAL_PORT;
Dart_IsolateCreateCallback ServiceIsolate::create_callback_ = NULL;
uint8_t* ServiceIsolate::exit_message_ = NULL;
intptr_t ServiceIsolate::exit_message_length_ = 0;
Monitor* ServiceIsolate::monitor_ = NULL;
Monitor* ServiceIsolate::monitor_ = new Monitor();
bool ServiceIsolate::initializing_ = true;
bool ServiceIsolate::shutting_down_ = false;
char* ServiceIsolate::server_address_ = NULL;
@ -483,9 +483,6 @@ class RunServiceTask : public ThreadPool::Task {
void ServiceIsolate::Run() {
ASSERT(monitor_ == NULL);
monitor_ = new Monitor();
ASSERT(monitor_ != NULL);
// Grab the isolate create callback here to avoid race conditions with tests
// that change this after Dart_Initialize returns.
create_callback_ = Isolate::CreateCallback();

View file

@ -80,7 +80,8 @@ uint8_t* randomArray(int seed, int length) {
void wrappedRandomArray(Dart_Port dest_port_id,
Dart_CObject* message) {
Dart_CObject* message,
void* peer) {
Dart_Port reply_port_id = ILLEGAL_PORT;
if (message->type == Dart_CObject_kArray &&
3 == message->value.as_array.length) {
@ -120,7 +121,7 @@ void randomArrayServicePort(Dart_NativeArguments arguments) {
Dart_EnterScope();
Dart_SetReturnValue(arguments, Dart_Null());
Dart_Port service_port =
Dart_NewNativePort("RandomArrayService", wrappedRandomArray, true);
Dart_NewNativePort("RandomArrayService", wrappedRandomArray, true, NULL);
if (service_port != ILLEGAL_PORT) {
Dart_Handle send_port = HandleError(Dart_NewSendPort(service_port));
Dart_SetReturnValue(arguments, send_port);