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

Unified Diff: runtime/vm/service.cc

Issue 125103004: Move service into VM (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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
Index: runtime/vm/service.cc
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index fe8aaa1b197084bb3e0518bcb6461d126f602382..ff8b8e2a9f4a29dee4c0b3df301112a2d8dd4c2f 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -4,28 +4,87 @@
#include "vm/service.h"
+#include "include/dart_api.h"
+
#include "vm/cpu.h"
+#include "vm/dart_api_impl.h"
#include "vm/dart_entry.h"
#include "vm/debugger.h"
#include "vm/heap_histogram.h"
#include "vm/isolate.h"
#include "vm/message.h"
+#include "vm/native_entry.h"
+#include "vm/native_arguments.h"
#include "vm/object.h"
#include "vm/object_id_ring.h"
#include "vm/object_store.h"
#include "vm/port.h"
#include "vm/profiler.h"
-namespace dart {
-typedef void (*ServiceMessageHandler)(Isolate* isolate, JSONStream* stream);
+namespace dart {
-struct ServiceMessageHandlerEntry {
- const char* command;
- ServiceMessageHandler handler;
+struct ResourcesEntry {
+ const char* path_;
+ const char* resource_;
+ int length_;
};
-static ServiceMessageHandler FindServiceMessageHandler(const char* command);
+extern ResourcesEntry __service_resources_[];
+
+class Resources {
+ public:
+ static const int kNoSuchInstance = -1;
+ static int ResourceLookup(const char* path, const char** resource) {
+ ResourcesEntry* table = get_resources_table();
+ for (int i = 0; table[i].path_ != NULL; i++) {
+ const ResourcesEntry& entry = table[i];
+ if (strcmp(path, entry.path_) == 0) {
+ *resource = entry.resource_;
+ ASSERT(entry.length_ > 0);
+ return entry.length_;
+ }
+ }
+ return kNoSuchInstance;
+ }
+
+ static const char* get_resource_path(int idx) {
siva 2014/01/10 00:01:54 ditto comments about the function names as they ar
Cutch 2014/01/10 21:01:42 Done.
+ ASSERT(idx >= 0);
+ ResourcesEntry* entry = get_resource_entry(idx);
+ if (entry == NULL) {
+ return NULL;
+ }
+ return entry->path_;
+ }
+
+ static const char* get_resource_resource(int idx) {
+ ASSERT(idx >= 0);
+ ResourcesEntry* entry = get_resource_entry(idx);
+ if (entry == NULL) {
+ return NULL;
+ }
+ return entry->resource_;
+ }
+
+ private:
+ static ResourcesEntry* get_resource_entry(int idx) {
+ ASSERT(idx >= 0);
+ ResourcesEntry* table = get_resources_table();
+ for (int i = 0; table[i].path_ != NULL; i++) {
+ if (idx == i) {
+ return &table[i];
+ }
+ }
+ return NULL;
+ }
+
+ static ResourcesEntry* get_resources_table() {
+ return &__service_resources_[0];
+ }
+
+ DISALLOW_ALLOCATION();
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Resources);
+};
static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) {
@@ -34,6 +93,300 @@ static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) {
}
+static void SendServiceMessage(Dart_NativeArguments args) {
+ NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
+ Isolate* isolate = arguments->isolate();
+ StackZone zone(isolate);
+ HANDLESCOPE(isolate);
+ GET_NON_NULL_NATIVE_ARGUMENT(Instance, sp, arguments->NativeArgAt(0));
+ GET_NON_NULL_NATIVE_ARGUMENT(Instance, message, arguments->NativeArgAt(1));
+
+ // Extract SendPort port id.
+ const Object& sp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(sp));
+ if (sp_id_obj.IsError()) {
+ Exceptions::PropagateError(Error::Cast(sp_id_obj));
+ }
+ Integer& id = Integer::Handle();
+ id ^= sp_id_obj.raw();
+ Dart_Port sp_id = static_cast<Dart_Port>(id.AsInt64Value());
+ ASSERT(sp_id != ILLEGAL_PORT);
+
+ // Serialize message.
+ uint8_t* data = NULL;
+ MessageWriter writer(&data, &allocator);
+ writer.WriteMessage(message);
+
+ // TODO(turnidge): Throw an exception when the return value is false?
+ PortMap::PostMessage(new Message(sp_id, data, writer.BytesWritten(),
+ Message::kOOBPriority));
+}
+
+
+struct VmServiceNativeEntry {
+ const char* name;
+ int num_arguments;
+ Dart_NativeFunction function;
+};
+
+
+static VmServiceNativeEntry _VmServiceNativeEntries[] = {
+ {"VMService_SendServiceMessage", 2, SendServiceMessage}
+};
+
+
+static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name,
+ int num_arguments,
+ bool* auto_setup_scope) {
+ const Object& obj = Object::Handle(Api::UnwrapHandle(name));
+ if (!obj.IsString()) {
+ return NULL;
+ }
+ const char* function_name = obj.ToCString();
+ ASSERT(function_name != NULL);
+ ASSERT(auto_setup_scope != NULL);
+ *auto_setup_scope = true;
+ intptr_t n =
+ sizeof(_VmServiceNativeEntries) / sizeof(_VmServiceNativeEntries[0]);
+ for (intptr_t i = 0; i < n; i++) {
+ VmServiceNativeEntry entry = _VmServiceNativeEntries[i];
+ if (!strcmp(function_name, entry.name) &&
+ (num_arguments == entry.num_arguments)) {
+ return entry.function;
+ }
+ }
siva 2014/01/10 00:01:54 There is only one entry in the table does it need
Cutch 2014/01/10 21:01:42 There will be more natives later. Todd has a CL wh
+ return NULL;
+}
+
+#define SHUTDOWN(error_msg) \
+ printf("Service Isolate Error: %s\n", error_msg); \
+ Dart_ExitScope(); \
+ Dart_ShutdownIsolate(); \
+ return NULL
+
+#define SHUTDOWN_ON_ERROR(handle) \
+ if (Dart_IsError(handle)) { \
+ SHUTDOWN(Dart_GetError(handle)); \
+ }
+
+Isolate* Service::service_isolate_ = NULL;
+Dart_LibraryTagHandler Service::default_handler_ = NULL;
+Dart_Port Service::port_ = ILLEGAL_PORT;
+
+Isolate* Service::GetServiceIsolate(void* callback_data) {
+ if (service_isolate_ != NULL) {
+ // Already initialized, return service isolate.
+ return service_isolate_;
+ }
siva 2014/01/10 00:01:54 What happens if multiple threads from the embedder
Cutch 2014/01/10 21:01:42 Good point. Do we make thread safety guarantees ab
+ Dart_ServiceIsolateCreateCallback create_callback =
+ Isolate::ServiceCreateCallback();
+ if (create_callback == NULL) {
+ return NULL;
+ }
+ if (Dart_CurrentIsolate() != NULL) {
+ // Clear current isolate.
+ Dart_ExitIsolate();
+ }
+ char* error = NULL;
+ Dart_Isolate isolate = create_callback(callback_data, &error);
+ if (isolate == NULL) {
+ printf("Service Isolate Error: %s\n", error);
+ return NULL;
+ }
+ Dart_EnterIsolate(isolate);
+ Dart_EnterScope();
+ Dart_Handle result;
+ Dart_Handle root_library = Dart_RootLibrary();
+ SHUTDOWN_ON_ERROR(root_library);
+ ASSERT(root_library == Dart_Null());
+ // Retrieve the embedder default library tag handler.
+ default_handler_ = reinterpret_cast<Isolate*>(isolate)->library_tag_handler();
+ ASSERT(default_handler_ != NULL);
+ // Temporarily install our own.
+ Dart_SetLibraryTagHandler(LibraryTagHandler);
+ // Load VM service library.
+ Dart_Handle library;
+ {
+ const char* resource = NULL;
+ const char* path = "/vmservice.dart";
+ int r = Resources::ResourceLookup(path, &resource);
+ ASSERT(r != Resources::kNoSuchInstance);
+ ASSERT(resource != NULL);
+ Dart_Handle url = Dart_NewStringFromCString("dart:vmservice");
+ SHUTDOWN_ON_ERROR(url);
+ Dart_Handle source = Dart_NewStringFromCString(resource);
+ SHUTDOWN_ON_ERROR(source);
+ library = Dart_LoadLibrary(url, source);
+ SHUTDOWN_ON_ERROR(library);
+ result = Dart_SetNativeResolver(library, VmServiceNativeResolver);
+ SHUTDOWN_ON_ERROR(result);
+ }
+ // Install embedder default library tag handler again.
+ Dart_SetLibraryTagHandler(default_handler_);
+ default_handler_ = NULL;
+ // Boot the service.
+ {
+ result = Dart_Invoke(library, Dart_NewStringFromCString("boot"), 0, NULL);
+ SHUTDOWN_ON_ERROR(result);
+ HANDLESCOPE(Isolate::Current());
+ const Object& unwrapped_rp = Object::Handle(Api::UnwrapHandle(result));
+ const Instance& rp = Instance::Cast(unwrapped_rp);
+ // Extract RawReceivePort port id.
+ const Object& rp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(rp));
+ if (rp_id_obj.IsError()) {
+ const Error& error = Error::Cast(rp_id_obj);
+ SHUTDOWN(error.ToErrorCString());
+ }
+ ASSERT(rp_id_obj.IsSmi() || rp_id_obj.IsMint());
+ Integer& id = Integer::Handle();
+ id ^= rp_id_obj.raw();
siva 2014/01/10 00:01:54 Since you are asserting that rp_id_obj is a Smi or
Cutch 2014/01/10 21:01:42 Done.
+ port_ = static_cast<Dart_Port>(id.AsInt64Value());
+ }
+ Dart_ExitScope();
+ Dart_ExitIsolate();
+ service_isolate_ = reinterpret_cast<Isolate*>(isolate);
+ return service_isolate_;
+}
+
+
+// These must be kept in sync with service/constants.dart
+#define VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID 1
+#define VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID 2
+
+
+static Dart_Handle MakeServiceControlMessage(Dart_Port port_id, intptr_t code,
+ Dart_Handle name) {
+ Dart_Handle result;
+ Dart_Handle list = Dart_NewList(4);
+ ASSERT(!Dart_IsError(list));
+ Dart_Handle code_handle = Dart_NewInteger(code);
+ ASSERT(!Dart_IsError(code_handle));
+ result = Dart_ListSetAt(list, 0, code_handle);
+ ASSERT(!Dart_IsError(result));
+ Dart_Handle port_id_handle = Dart_NewInteger(port_id);
+ ASSERT(!Dart_IsError(port_id_handle));
+ result = Dart_ListSetAt(list, 1, port_id_handle);
+ ASSERT(!Dart_IsError(result));
+ Dart_Handle sendPort = Dart_NewSendPort(port_id);
+ ASSERT(!Dart_IsError(sendPort));
+ result = Dart_ListSetAt(list, 2, sendPort);
+ ASSERT(!Dart_IsError(result));
+ result = Dart_ListSetAt(list, 3, name);
+ ASSERT(!Dart_IsError(result));
+ return list;
+}
+
+
+bool Service::SendIsolateStartupMessage() {
+ if (!IsRunning()) {
+ return false;
+ }
+ Isolate* isolate = Isolate::Current();
+ ASSERT(isolate != NULL);
+ HANDLESCOPE(isolate);
+ Dart_EnterScope();
+ Dart_Handle name = Api::NewHandle(isolate, String::New(isolate->name()));
+ ASSERT(!Dart_IsError(name));
+ Dart_Handle list =
+ MakeServiceControlMessage(Dart_GetMainPortId(),
+ VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID,
+ name);
+ ASSERT(!Dart_IsError(list));
+ bool r = Dart_Post(port_, list);
+ Dart_ExitScope();
+ return r;
+}
+
+
+bool Service::SendIsolateShutdownMessage() {
+ if (!IsRunning()) {
+ return false;
+ }
+ Isolate* isolate = Isolate::Current();
+ ASSERT(isolate != NULL);
+ HANDLESCOPE(isolate);
+ Dart_EnterScope();
+ Dart_Handle list =
+ MakeServiceControlMessage(Dart_GetMainPortId(),
+ VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID,
+ Dart_Null());
+ ASSERT(!Dart_IsError(list));
+ bool r = Dart_Post(port_, list);
+ Dart_ExitScope();
+ return r;
+}
+
+
+bool Service::IsRunning() {
+ return port_ != ILLEGAL_PORT;
+}
+
+
+Dart_Handle Service::GetSource(const char* name) {
+ ASSERT(name != NULL);
+ int i = 0;
+ while (true) {
+ const char* path = Resources::get_resource_path(i);
+ if (path == NULL) {
+ break;
+ }
+ ASSERT(*path != '\0');
+ // Skip the '/'.
+ path++;
+ if (strcmp(name, path) == 0) {
+ return Dart_NewStringFromCString(Resources::get_resource_resource(i));
+ }
+ i++;
+ }
+ return Dart_Null();
+}
+
+
+Dart_Handle Service::LibraryTagHandler(Dart_LibraryTag tag, Dart_Handle library,
+ Dart_Handle url) {
+ if (!Dart_IsLibrary(library)) {
+ return Dart_NewApiError("not a library");
+ }
+ if (!Dart_IsString(url)) {
+ return Dart_NewApiError("url is not a string");
+ }
+ const char* url_string = NULL;
+ Dart_Handle result = Dart_StringToCString(url, &url_string);
+ if (Dart_IsError(result)) {
+ return result;
+ }
+ Dart_Handle library_url = Dart_LibraryUrl(library);
+ const char* library_url_string = NULL;
+ result = Dart_StringToCString(library_url, &library_url_string);
+ if (Dart_IsError(result)) {
+ return result;
+ }
siva 2014/01/10 00:01:54 What is the conversion to C string library_url_str
Cutch 2014/01/10 21:01:42 Done.
+ if (tag == Dart_kImportTag) {
+ // Embedder handles all requests for external libraries.
+ ASSERT(default_handler_ != NULL);
+ return default_handler_(tag, library, url);
+ }
+ ASSERT((tag == Dart_kSourceTag) || (tag == Dart_kCanonicalizeUrl));
+ if (tag == Dart_kCanonicalizeUrl) {
+ // url is already canonicalized.
+ return url;
+ }
+ Dart_Handle source = GetSource(url_string);
+ if (Dart_IsError(source)) {
+ return source;
+ }
+ return Dart_LoadSource(library, url, source);
+}
+
+
+typedef void (*ServiceMessageHandler)(Isolate* isolate, JSONStream* stream);
+
+struct ServiceMessageHandlerEntry {
+ const char* command;
+ ServiceMessageHandler handler;
+};
+
+static ServiceMessageHandler FindServiceMessageHandler(const char* command);
+
static void PostReply(const String& reply, const Instance& reply_port) {
const Object& id_obj = Object::Handle(
DartLibraryCalls::PortGetId(reply_port));

Powered by Google App Engine
This is Rietveld 408576698