Chromium Code Reviews| Index: runtime/bin/vmservice_impl.cc |
| diff --git a/runtime/bin/vmservice_impl.cc b/runtime/bin/vmservice_impl.cc |
| index 9e738cdfe883e783fea8ac8d966ababec00cf923..f38e6d41715b88621995ba4e688e1f313cbafa5d 100644 |
| --- a/runtime/bin/vmservice_impl.cc |
| +++ b/runtime/bin/vmservice_impl.cc |
| @@ -9,25 +9,11 @@ |
| #include "bin/builtin.h" |
| #include "bin/dartutils.h" |
| #include "bin/isolate_data.h" |
| -#include "bin/resources.h" |
| #include "bin/thread.h" |
| -#include "vm/dart_api_impl.h" |
| -#include "vm/dart_entry.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/port.h" |
| -#include "vm/snapshot.h" |
| - |
| namespace dart { |
| namespace bin { |
| -// snapshot_buffer points to a snapshot if we link in a snapshot otherwise |
| -// it is initialized to NULL. |
| -extern const uint8_t* snapshot_buffer; |
| #define RETURN_ERROR_HANDLE(handle) \ |
| if (Dart_IsError(handle)) { \ |
| return handle; \ |
| @@ -41,143 +27,118 @@ extern const uint8_t* snapshot_buffer; |
| return false; \ |
| } |
| -#define kLibraryResourceNamePrefix "/vmservice" |
| -static const char* kVMServiceIOLibraryScriptResourceName = |
| - kLibraryResourceNamePrefix "/vmservice_io.dart"; |
| -static const char* kVMServiceLibraryName = |
| - kLibraryResourceNamePrefix "/vmservice.dart"; |
| - |
| +#define kLibrarySourceNamePrefix "/vmservice" |
| +static const char* kVMServiceIOLibraryScriptResourceName = "vmservice_io.dart"; |
| #define kClientResourceNamePrefix "/vmservice/client/deployed/web" |
| -Dart_Isolate VmService::isolate_ = NULL; |
| -Dart_Port VmService::port_ = ILLEGAL_PORT; |
| -dart::Monitor* VmService::monitor_ = NULL; |
| -const char* VmService::error_msg_ = NULL; |
| +struct ResourcesEntry { |
| + const char* path_; |
| + const char* resource_; |
| + int length_; |
| +}; |
| -// These must be kept in sync with vmservice/constants.dart |
| -#define VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID 1 |
| -#define VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID 2 |
| +extern ResourcesEntry __service_bin_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
These are not strictly accessors so you probably n
|
| + ASSERT(idx >= 0); |
| + ResourcesEntry* entry = get_resource_entry(idx); |
| + if (entry == NULL) { |
| + return NULL; |
| + } |
| + return entry->path_; |
|
siva
2014/01/10 00:01:54
should we assert that entry_path_ is not NULL ?
|
| + } |
| -static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name, |
| - int num_arguments, |
| - bool* auto_setup_scope); |
| + static const char* get_resource_resource(int idx) { |
|
siva
2014/01/10 00:01:54
How about Resource for this.
Cutch
2014/01/10 21:01:42
Killed it.
|
| + 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) { |
|
siva
2014/01/10 00:01:54
Ditto Entry?
Cutch
2014/01/10 21:01:42
Renamed to "At".
|
| + 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() { |
|
siva
2014/01/10 00:01:54
service_bin_resources() or ResourcesTable for this
Cutch
2014/01/10 21:01:42
Done.
|
| + return &__service_bin_resources_[0]; |
| + } |
| + |
| + DISALLOW_ALLOCATION(); |
| + DISALLOW_IMPLICIT_CONSTRUCTORS(Resources); |
| +}; |
| + |
| +const char* VmService::error_msg_ = NULL; |
| bool VmService::Start(intptr_t server_port) { |
| - monitor_ = new dart::Monitor(); |
| - ASSERT(monitor_ != NULL); |
| - error_msg_ = NULL; |
| - |
| - |
| - { |
| - // Take lock before spawning new thread. |
| - MonitorLocker ml(monitor_); |
| - // Spawn new thread. |
| - dart::Thread::Start(ThreadMain, server_port); |
| - // Wait until service is running on spawned thread. |
| - ml.Wait(); |
| + bool r = _Start(server_port); |
| + if (!r) { |
| + return r; |
| } |
| - return port_ != ILLEGAL_PORT; |
| + // Start processing messages in a new thread. |
| + dart::Thread::Start(ThreadMain, NULL); |
| + return true; |
| } |
| bool VmService::_Start(intptr_t server_port) { |
| - ASSERT(isolate_ == NULL); |
| - char* error = NULL; |
| - const char* script_uri = "vmservice:"; |
| - IsolateData* isolate_data = new IsolateData(script_uri); |
| - isolate_ = Dart_CreateIsolate(script_uri, "main", snapshot_buffer, |
| - isolate_data, |
| - &error); |
| - if (isolate_ == NULL) { |
| - error_msg_ = error; |
| + ASSERT(Dart_CurrentIsolate() == NULL); |
| + Dart_Isolate isolate = Dart_GetServiceIsolate(); |
|
siva
2014/01/10 00:01:54
As discussed offline it would be great if we just
Cutch
2014/01/10 21:01:42
Agree that I should follow this cleanup with anoth
|
| + if (isolate == NULL) { |
| + error_msg_ = "Internal error."; |
| return false; |
| } |
| - |
| + Dart_EnterIsolate(isolate); |
| Dart_EnterScope(); |
| - |
| - if (snapshot_buffer != NULL) { |
| - // Setup the native resolver as the snapshot does not carry it. |
| - Builtin::SetNativeResolver(Builtin::kBuiltinLibrary); |
| - Builtin::SetNativeResolver(Builtin::kIOLibrary); |
| - } |
| - |
| - // Set up the library tag handler for this isolate. |
| - Dart_Handle result = Dart_SetLibraryTagHandler(LibraryTagHandler); |
| - SHUTDOWN_ON_ERROR(result); |
| - |
| - // Load the specified application script into the newly created isolate. |
| - |
| - // Prepare builtin and its dependent libraries for use to resolve URIs. |
| - // The builtin library is part of the core snapshot and would already be |
| - // available here in the case of script snapshot loading. |
| - Dart_Handle builtin_lib = |
| - Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary); |
| - SHUTDOWN_ON_ERROR(builtin_lib); |
| - |
| - // Prepare for script loading by setting up the 'print' and 'timer' |
| - // closures and setting up 'package root' for URI resolution. |
| - result = DartUtils::PrepareForScriptLoading("", builtin_lib); |
| - SHUTDOWN_ON_ERROR(result); |
| - |
| - { |
| - // Load source into service isolate. |
| - Dart_Handle library = LoadScript(kVMServiceIOLibraryScriptResourceName); |
| - SHUTDOWN_ON_ERROR(library); |
| - } |
| - |
| - // Make the isolate runnable so that it is ready to handle messages. |
| + // Install our own library tag handler. |
| + Dart_SetLibraryTagHandler(LibraryTagHandler); |
| + Dart_Handle result; |
| + Dart_Handle library = LoadScript(kVMServiceIOLibraryScriptResourceName); |
| + // Expect a library. |
| + ASSERT(library != Dart_Null()); |
| + SHUTDOWN_ON_ERROR(library); |
| Dart_ExitScope(); |
| Dart_ExitIsolate(); |
| - |
| - bool retval = Dart_IsolateMakeRunnable(isolate_); |
| + bool retval = Dart_IsolateMakeRunnable(isolate); |
| if (!retval) { |
| - Dart_EnterIsolate(isolate_); |
| + Dart_EnterIsolate(isolate); |
| Dart_ShutdownIsolate(); |
| error_msg_ = "Invalid isolate state - Unable to make it runnable."; |
| return false; |
| } |
| - Dart_EnterIsolate(isolate_); |
| + Dart_EnterIsolate(isolate); |
| Dart_EnterScope(); |
| - |
| - |
| - Dart_Handle library = Dart_RootLibrary(); |
| + library = Dart_RootLibrary(); |
| // Set requested TCP port. |
| DartUtils::SetIntegerField(library, "_port", server_port); |
| result = Dart_Invoke(library, DartUtils::NewString("main"), 0, NULL); |
| SHUTDOWN_ON_ERROR(result); |
| - |
| - // Retrieve the ReceivePort that the service is waiting on. The _receivePort |
| - // variable is setup in the call to main. |
| - Dart_Handle receivePort = Dart_GetField(library, |
| - DartUtils::NewString("_receivePort")); |
| - SHUTDOWN_ON_ERROR(receivePort); |
| - |
| - { |
| - // Extract the Dart_Port from the receive port. |
| - HANDLESCOPE(Isolate::Current()); |
| - const Object& unwrapped_rp = Object::Handle(Api::UnwrapHandle(receivePort)); |
| - const Instance& rp = Instance::Cast(unwrapped_rp); |
| - // Extract ReceivePort 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); |
| - error_msg_ = strdup(error.ToErrorCString()); |
| - Dart_ExitScope(); |
| - Dart_ShutdownIsolate(); |
| - return false; |
| - } |
| - ASSERT(rp_id_obj.IsSmi() || rp_id_obj.IsMint()); |
| - Integer& id = Integer::Handle(); |
| - id ^= rp_id_obj.raw(); |
| - port_ = static_cast<Dart_Port>(id.AsInt64Value()); |
| - } |
| - |
| - Dart_Handle library_name = Dart_NewStringFromCString(kVMServiceLibraryName); |
| - library = Dart_LookupLibrary(library_name); |
| - SHUTDOWN_ON_ERROR(library); |
| + // Load resources. |
| result = LoadResources(library); |
| SHUTDOWN_ON_ERROR(result); |
| @@ -188,36 +149,24 @@ bool VmService::_Start(intptr_t server_port) { |
| } |
| -void VmService::_Stop() { |
| - port_ = ILLEGAL_PORT; |
| -} |
| - |
| - |
| const char* VmService::GetErrorMessage() { |
| return error_msg_ == NULL ? "No error." : error_msg_; |
| } |
| -Dart_Port VmService::port() { |
| - return port_; |
| -} |
| - |
| - |
| -bool VmService::IsRunning() { |
| - return port_ != ILLEGAL_PORT; |
| -} |
| - |
| - |
| Dart_Handle VmService::GetSource(const char* name) { |
| + const intptr_t kBufferSize = 512; |
| + char buffer[kBufferSize]; |
| + snprintf(&buffer[0], kBufferSize-1, "%s/%s", kLibrarySourceNamePrefix, name); |
| const char* vmservice_source = NULL; |
| - int r = Resources::ResourceLookup(name, &vmservice_source); |
| + int r = Resources::ResourceLookup(buffer, &vmservice_source); |
| ASSERT(r != Resources::kNoSuchInstance); |
| return Dart_NewStringFromCString(vmservice_source); |
| } |
| Dart_Handle VmService::LoadScript(const char* name) { |
| - Dart_Handle url = Dart_NewStringFromCString(name); |
| + Dart_Handle url = Dart_NewStringFromCString("dart:vmservice_io"); |
| Dart_Handle source = GetSource(name); |
| return Dart_LoadScript(url, source, 0, 0); |
| } |
| @@ -230,18 +179,6 @@ Dart_Handle VmService::LoadSource(Dart_Handle library, const char* name) { |
| } |
| -Dart_Handle VmService::LoadSources(Dart_Handle library, const char* names[]) { |
| - Dart_Handle result = Dart_Null(); |
| - for (int i = 0; names[i] != NULL; i++) { |
| - result = LoadSource(library, names[i]); |
| - if (Dart_IsError(result)) { |
| - break; |
| - } |
| - } |
| - return result; |
| -} |
| - |
| - |
| Dart_Handle VmService::LoadResource(Dart_Handle library, |
| const char* resource_name, |
| const char* prefix) { |
| @@ -285,7 +222,7 @@ Dart_Handle VmService::LoadResource(Dart_Handle library, |
| Dart_Handle VmService::LoadResources(Dart_Handle library) { |
| Dart_Handle result = Dart_Null(); |
| intptr_t prefixLen = strlen(kClientResourceNamePrefix); |
| - for (intptr_t i = 0; i < Resources::get_resource_count(); i++) { |
| + for (intptr_t i = 0; Resources::get_resource_path(i) != NULL; i++) { |
| const char* path = Resources::get_resource_path(i); |
| if (!strncmp(path, kClientResourceNamePrefix, prefixLen)) { |
| result = LoadResource(library, path, kClientResourceNamePrefix); |
| @@ -298,19 +235,6 @@ Dart_Handle VmService::LoadResources(Dart_Handle library) { |
| } |
| -static bool IsVMServiceURL(const char* url) { |
| - static const intptr_t kLibraryResourceNamePrefixLen = |
| - strlen(kLibraryResourceNamePrefix); |
| - return 0 == strncmp(kLibraryResourceNamePrefix, url, |
| - kLibraryResourceNamePrefixLen); |
| -} |
| - |
| - |
| -static bool IsVMServiceLibrary(const char* url) { |
| - return 0 == strcmp(kVMServiceLibraryName, url); |
| -} |
| - |
| - |
| Dart_Handle VmService::LibraryTagHandler(Dart_LibraryTag tag, |
| Dart_Handle library, |
| Dart_Handle url) { |
| @@ -331,224 +255,37 @@ Dart_Handle VmService::LibraryTagHandler(Dart_LibraryTag tag, |
| if (Dart_IsError(result)) { |
| return result; |
| } |
| - bool is_vm_service_url = IsVMServiceURL(url_string); |
| - if (!is_vm_service_url) { |
| - // Pass to DartUtils. |
| + if (tag == Dart_kImportTag) { |
| + // Embedder handles all requests for external libraries. |
| return DartUtils::LibraryTagHandler(tag, library, url); |
| } |
| - switch (tag) { |
| - case Dart_kCanonicalizeUrl: |
| - // The URL is already canonicalized. |
| - return url; |
| - break; |
| - case Dart_kImportTag: { |
| - Dart_Handle source = GetSource(url_string); |
| - if (Dart_IsError(source)) { |
| - return source; |
| - } |
| - Dart_Handle lib = Dart_LoadLibrary(url, source); |
| - if (Dart_IsError(lib)) { |
| - return lib; |
| - } |
| - if (IsVMServiceLibrary(url_string)) { |
| - // Install native resolver for this library. |
| - result = Dart_SetNativeResolver(lib, VmServiceNativeResolver); |
| - if (Dart_IsError(result)) { |
| - return result; |
| - } |
| - } |
| - return lib; |
| - } |
| - break; |
| - case Dart_kSourceTag: { |
| - Dart_Handle source = GetSource(url_string); |
| - if (Dart_IsError(source)) { |
| - return source; |
| - } |
| - return Dart_LoadSource(library, url, source); |
| - } |
| - break; |
| - default: |
| - UNIMPLEMENTED(); |
| - break; |
| + ASSERT((tag == Dart_kSourceTag) || (tag == Dart_kCanonicalizeUrl)); |
| + if (tag == Dart_kCanonicalizeUrl) { |
| + // url is already canonicalized. |
| + return url; |
| } |
| - UNREACHABLE(); |
| - return result; |
| + Dart_Handle source = GetSource(url_string); |
| + if (Dart_IsError(source)) { |
| + return source; |
| + } |
| + return Dart_LoadSource(library, url, source); |
| } |
| void VmService::ThreadMain(uword parameters) { |
| ASSERT(Dart_CurrentIsolate() == NULL); |
| - ASSERT(isolate_ == NULL); |
| - |
| - intptr_t server_port = static_cast<intptr_t>(parameters); |
| - ASSERT(server_port >= 0); |
| - |
| - // Lock scope. |
| - { |
| - MonitorLocker ml(monitor_); |
| - bool r = _Start(server_port); |
| - if (!r) { |
| - port_ = ILLEGAL_PORT; |
| - monitor_->Notify(); |
| - return; |
| - } |
| - |
| - Dart_EnterIsolate(isolate_); |
| - Dart_EnterScope(); |
| - |
| - Dart_Handle receievePort = Dart_GetReceivePort(port_); |
| - ASSERT(!Dart_IsError(receievePort)); |
| - monitor_->Notify(); |
| - } |
| - |
| - // Keep handling messages until the last active receive port is closed. |
| + Dart_Isolate service_isolate = Dart_GetServiceIsolate(); |
| + Dart_EnterIsolate(service_isolate); |
| + Dart_EnterScope(); |
| Dart_Handle result = Dart_RunLoop(); |
| if (Dart_IsError(result)) { |
| - printf("VmService has exited with an error:\n%s\n", Dart_GetError(result)); |
| + printf("Service exited with an error:\n%s\n", Dart_GetError(result)); |
| } |
| - |
| - _Stop(); |
| - |
| Dart_ExitScope(); |
| Dart_ExitIsolate(); |
| } |
| -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 VmService::SendIsolateStartupMessage() { |
| - if (!IsRunning()) { |
| - return false; |
| - } |
| - Isolate* isolate = Isolate::Current(); |
| - ASSERT(isolate != NULL); |
| - HANDLESCOPE(isolate); |
| - 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)); |
| - return Dart_Post(port_, list); |
| -} |
| - |
| - |
| -bool VmService::SendIsolateShutdownMessage() { |
| - if (!IsRunning()) { |
| - return false; |
| - } |
| - Isolate* isolate = Isolate::Current(); |
| - ASSERT(isolate != NULL); |
| - HANDLESCOPE(isolate); |
| - Dart_Handle list = |
| - MakeServiceControlMessage(Dart_GetMainPortId(), |
| - VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID, |
| - Dart_Null()); |
| - ASSERT(!Dart_IsError(list)); |
| - return Dart_Post(port_, list); |
| -} |
| - |
| - |
| -void VmService::VmServiceShutdownCallback(void* callback_data) { |
| - ASSERT(Dart_CurrentIsolate() != NULL); |
| - Dart_EnterScope(); |
| - VmService::SendIsolateShutdownMessage(); |
| - Dart_ExitScope(); |
| -} |
| - |
| - |
| -static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { |
| - void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); |
| - return reinterpret_cast<uint8_t*>(new_ptr); |
| -} |
| - |
| - |
| -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; |
| - } |
| - } |
| - return NULL; |
| -} |
| } // namespace bin |
| } // namespace dart |