| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "bin/vmservice_impl.h" | 5 #include "bin/vmservice_impl.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 | 8 |
| 9 #include "bin/builtin.h" | 9 #include "bin/builtin.h" |
| 10 #include "bin/dartutils.h" | 10 #include "bin/dartutils.h" |
| 11 #include "bin/isolate_data.h" | 11 #include "bin/isolate_data.h" |
| 12 #include "bin/resources.h" | |
| 13 #include "bin/thread.h" | 12 #include "bin/thread.h" |
| 14 | 13 |
| 15 #include "vm/dart_api_impl.h" | |
| 16 #include "vm/dart_entry.h" | |
| 17 #include "vm/isolate.h" | |
| 18 #include "vm/message.h" | |
| 19 #include "vm/native_entry.h" | |
| 20 #include "vm/native_arguments.h" | |
| 21 #include "vm/object.h" | |
| 22 #include "vm/port.h" | |
| 23 #include "vm/snapshot.h" | |
| 24 | |
| 25 namespace dart { | 14 namespace dart { |
| 26 namespace bin { | 15 namespace bin { |
| 27 | 16 |
| 28 // snapshot_buffer points to a snapshot if we link in a snapshot otherwise | |
| 29 // it is initialized to NULL. | |
| 30 extern const uint8_t* snapshot_buffer; | |
| 31 #define RETURN_ERROR_HANDLE(handle) \ | 17 #define RETURN_ERROR_HANDLE(handle) \ |
| 32 if (Dart_IsError(handle)) { \ | 18 if (Dart_IsError(handle)) { \ |
| 33 return handle; \ | 19 return handle; \ |
| 34 } | 20 } |
| 35 | 21 |
| 36 #define SHUTDOWN_ON_ERROR(handle) \ | 22 #define SHUTDOWN_ON_ERROR(handle) \ |
| 37 if (Dart_IsError(handle)) { \ | 23 if (Dart_IsError(handle)) { \ |
| 38 error_msg_ = strdup(Dart_GetError(handle)); \ | 24 error_msg_ = strdup(Dart_GetError(handle)); \ |
| 39 Dart_ExitScope(); \ | 25 Dart_ExitScope(); \ |
| 40 Dart_ShutdownIsolate(); \ | 26 Dart_ShutdownIsolate(); \ |
| 41 return false; \ | 27 return false; \ |
| 42 } | 28 } |
| 43 | 29 |
| 44 #define kLibraryResourceNamePrefix "/vmservice" | 30 #define kLibrarySourceNamePrefix "/vmservice" |
| 45 static const char* kVMServiceIOLibraryScriptResourceName = | 31 static const char* kVMServiceIOLibraryScriptResourceName = "vmservice_io.dart"; |
| 46 kLibraryResourceNamePrefix "/vmservice_io.dart"; | |
| 47 static const char* kVMServiceLibraryName = | |
| 48 kLibraryResourceNamePrefix "/vmservice.dart"; | |
| 49 | |
| 50 #define kClientResourceNamePrefix "/vmservice/client/deployed/web" | 32 #define kClientResourceNamePrefix "/vmservice/client/deployed/web" |
| 51 | 33 |
| 52 Dart_Isolate VmService::isolate_ = NULL; | 34 struct ResourcesEntry { |
| 53 Dart_Port VmService::port_ = ILLEGAL_PORT; | 35 const char* path_; |
| 54 dart::Monitor* VmService::monitor_ = NULL; | 36 const char* resource_; |
| 37 int length_; |
| 38 }; |
| 39 |
| 40 extern ResourcesEntry __service_bin_resources_[]; |
| 41 |
| 42 class Resources { |
| 43 public: |
| 44 static const int kNoSuchInstance = -1; |
| 45 static int ResourceLookup(const char* path, const char** resource) { |
| 46 ResourcesEntry* table = ResourcesTable(); |
| 47 for (int i = 0; table[i].path_ != NULL; i++) { |
| 48 const ResourcesEntry& entry = table[i]; |
| 49 if (strcmp(path, entry.path_) == 0) { |
| 50 *resource = entry.resource_; |
| 51 ASSERT(entry.length_ > 0); |
| 52 return entry.length_; |
| 53 } |
| 54 } |
| 55 return kNoSuchInstance; |
| 56 } |
| 57 |
| 58 static const char* Path(int idx) { |
| 59 ASSERT(idx >= 0); |
| 60 ResourcesEntry* entry = At(idx); |
| 61 if (entry == NULL) { |
| 62 return NULL; |
| 63 } |
| 64 ASSERT(entry->path_ != NULL); |
| 65 return entry->path_; |
| 66 } |
| 67 |
| 68 private: |
| 69 static ResourcesEntry* At(int idx) { |
| 70 ASSERT(idx >= 0); |
| 71 ResourcesEntry* table = ResourcesTable(); |
| 72 for (int i = 0; table[i].path_ != NULL; i++) { |
| 73 if (idx == i) { |
| 74 return &table[i]; |
| 75 } |
| 76 } |
| 77 return NULL; |
| 78 } |
| 79 static ResourcesEntry* ResourcesTable() { |
| 80 return &__service_bin_resources_[0]; |
| 81 } |
| 82 |
| 83 DISALLOW_ALLOCATION(); |
| 84 DISALLOW_IMPLICIT_CONSTRUCTORS(Resources); |
| 85 }; |
| 86 |
| 55 const char* VmService::error_msg_ = NULL; | 87 const char* VmService::error_msg_ = NULL; |
| 56 | 88 |
| 57 // These must be kept in sync with vmservice/constants.dart | |
| 58 #define VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID 1 | |
| 59 #define VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID 2 | |
| 60 | |
| 61 | |
| 62 static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name, | |
| 63 int num_arguments, | |
| 64 bool* auto_setup_scope); | |
| 65 | |
| 66 | |
| 67 bool VmService::Start(intptr_t server_port) { | 89 bool VmService::Start(intptr_t server_port) { |
| 68 monitor_ = new dart::Monitor(); | 90 bool r = _Start(server_port); |
| 69 ASSERT(monitor_ != NULL); | 91 if (!r) { |
| 70 error_msg_ = NULL; | 92 return r; |
| 71 | |
| 72 | |
| 73 { | |
| 74 // Take lock before spawning new thread. | |
| 75 MonitorLocker ml(monitor_); | |
| 76 // Spawn new thread. | |
| 77 dart::Thread::Start(ThreadMain, server_port); | |
| 78 // Wait until service is running on spawned thread. | |
| 79 ml.Wait(); | |
| 80 } | 93 } |
| 81 return port_ != ILLEGAL_PORT; | 94 // Start processing messages in a new thread. |
| 95 dart::Thread::Start(ThreadMain, NULL); |
| 96 return true; |
| 82 } | 97 } |
| 83 | 98 |
| 84 | 99 |
| 85 bool VmService::_Start(intptr_t server_port) { | 100 bool VmService::_Start(intptr_t server_port) { |
| 86 ASSERT(isolate_ == NULL); | 101 ASSERT(Dart_CurrentIsolate() == NULL); |
| 87 char* error = NULL; | 102 Dart_Isolate isolate = Dart_GetServiceIsolate(NULL); |
| 88 const char* script_uri = "vmservice:"; | 103 if (isolate == NULL) { |
| 89 IsolateData* isolate_data = new IsolateData(script_uri); | 104 error_msg_ = "Internal error."; |
| 90 isolate_ = Dart_CreateIsolate(script_uri, "main", snapshot_buffer, | |
| 91 isolate_data, | |
| 92 &error); | |
| 93 if (isolate_ == NULL) { | |
| 94 error_msg_ = error; | |
| 95 return false; | 105 return false; |
| 96 } | 106 } |
| 97 | 107 Dart_EnterIsolate(isolate); |
| 98 Dart_EnterScope(); | 108 Dart_EnterScope(); |
| 99 | 109 // Install our own library tag handler. |
| 100 if (snapshot_buffer != NULL) { | 110 Dart_SetLibraryTagHandler(LibraryTagHandler); |
| 101 // Setup the native resolver as the snapshot does not carry it. | 111 Dart_Handle result; |
| 102 Builtin::SetNativeResolver(Builtin::kBuiltinLibrary); | 112 Dart_Handle library = LoadScript(kVMServiceIOLibraryScriptResourceName); |
| 103 Builtin::SetNativeResolver(Builtin::kIOLibrary); | 113 // Expect a library. |
| 104 } | 114 ASSERT(library != Dart_Null()); |
| 105 | 115 SHUTDOWN_ON_ERROR(library); |
| 106 // Set up the library tag handler for this isolate. | |
| 107 Dart_Handle result = Dart_SetLibraryTagHandler(LibraryTagHandler); | |
| 108 SHUTDOWN_ON_ERROR(result); | |
| 109 | |
| 110 // Load the specified application script into the newly created isolate. | |
| 111 | |
| 112 // Prepare builtin and its dependent libraries for use to resolve URIs. | |
| 113 // The builtin library is part of the core snapshot and would already be | |
| 114 // available here in the case of script snapshot loading. | |
| 115 Dart_Handle builtin_lib = | |
| 116 Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary); | |
| 117 SHUTDOWN_ON_ERROR(builtin_lib); | |
| 118 | |
| 119 // Prepare for script loading by setting up the 'print' and 'timer' | |
| 120 // closures and setting up 'package root' for URI resolution. | |
| 121 result = DartUtils::PrepareForScriptLoading("", builtin_lib); | |
| 122 SHUTDOWN_ON_ERROR(result); | |
| 123 | |
| 124 { | |
| 125 // Load source into service isolate. | |
| 126 Dart_Handle library = LoadScript(kVMServiceIOLibraryScriptResourceName); | |
| 127 SHUTDOWN_ON_ERROR(library); | |
| 128 } | |
| 129 | |
| 130 // Make the isolate runnable so that it is ready to handle messages. | |
| 131 Dart_ExitScope(); | 116 Dart_ExitScope(); |
| 132 Dart_ExitIsolate(); | 117 Dart_ExitIsolate(); |
| 133 | 118 bool retval = Dart_IsolateMakeRunnable(isolate); |
| 134 bool retval = Dart_IsolateMakeRunnable(isolate_); | |
| 135 if (!retval) { | 119 if (!retval) { |
| 136 Dart_EnterIsolate(isolate_); | 120 Dart_EnterIsolate(isolate); |
| 137 Dart_ShutdownIsolate(); | 121 Dart_ShutdownIsolate(); |
| 138 error_msg_ = "Invalid isolate state - Unable to make it runnable."; | 122 error_msg_ = "Invalid isolate state - Unable to make it runnable."; |
| 139 return false; | 123 return false; |
| 140 } | 124 } |
| 141 | 125 |
| 142 Dart_EnterIsolate(isolate_); | 126 Dart_EnterIsolate(isolate); |
| 143 Dart_EnterScope(); | 127 Dart_EnterScope(); |
| 144 | 128 library = Dart_RootLibrary(); |
| 145 | |
| 146 Dart_Handle library = Dart_RootLibrary(); | |
| 147 // Set requested TCP port. | 129 // Set requested TCP port. |
| 148 DartUtils::SetIntegerField(library, "_port", server_port); | 130 DartUtils::SetIntegerField(library, "_port", server_port); |
| 149 result = Dart_Invoke(library, DartUtils::NewString("main"), 0, NULL); | 131 result = Dart_Invoke(library, DartUtils::NewString("main"), 0, NULL); |
| 150 SHUTDOWN_ON_ERROR(result); | 132 SHUTDOWN_ON_ERROR(result); |
| 151 | 133 // Load resources. |
| 152 // Retrieve the ReceivePort that the service is waiting on. The _receivePort | |
| 153 // variable is setup in the call to main. | |
| 154 Dart_Handle receivePort = Dart_GetField(library, | |
| 155 DartUtils::NewString("_receivePort")); | |
| 156 SHUTDOWN_ON_ERROR(receivePort); | |
| 157 | |
| 158 { | |
| 159 // Extract the Dart_Port from the receive port. | |
| 160 HANDLESCOPE(Isolate::Current()); | |
| 161 const Object& unwrapped_rp = Object::Handle(Api::UnwrapHandle(receivePort)); | |
| 162 const Instance& rp = Instance::Cast(unwrapped_rp); | |
| 163 // Extract ReceivePort port id. | |
| 164 const Object& rp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(rp)); | |
| 165 if (rp_id_obj.IsError()) { | |
| 166 const Error& error = Error::Cast(rp_id_obj); | |
| 167 error_msg_ = strdup(error.ToErrorCString()); | |
| 168 Dart_ExitScope(); | |
| 169 Dart_ShutdownIsolate(); | |
| 170 return false; | |
| 171 } | |
| 172 ASSERT(rp_id_obj.IsSmi() || rp_id_obj.IsMint()); | |
| 173 Integer& id = Integer::Handle(); | |
| 174 id ^= rp_id_obj.raw(); | |
| 175 port_ = static_cast<Dart_Port>(id.AsInt64Value()); | |
| 176 } | |
| 177 | |
| 178 Dart_Handle library_name = Dart_NewStringFromCString(kVMServiceLibraryName); | |
| 179 library = Dart_LookupLibrary(library_name); | |
| 180 SHUTDOWN_ON_ERROR(library); | |
| 181 result = LoadResources(library); | 134 result = LoadResources(library); |
| 182 SHUTDOWN_ON_ERROR(result); | 135 SHUTDOWN_ON_ERROR(result); |
| 183 | 136 |
| 184 Dart_ExitScope(); | 137 Dart_ExitScope(); |
| 185 Dart_ExitIsolate(); | 138 Dart_ExitIsolate(); |
| 186 | 139 |
| 187 return true; | 140 return true; |
| 188 } | 141 } |
| 189 | 142 |
| 190 | 143 |
| 191 void VmService::_Stop() { | |
| 192 port_ = ILLEGAL_PORT; | |
| 193 } | |
| 194 | |
| 195 | |
| 196 const char* VmService::GetErrorMessage() { | 144 const char* VmService::GetErrorMessage() { |
| 197 return error_msg_ == NULL ? "No error." : error_msg_; | 145 return error_msg_ == NULL ? "No error." : error_msg_; |
| 198 } | 146 } |
| 199 | 147 |
| 200 | 148 |
| 201 Dart_Port VmService::port() { | |
| 202 return port_; | |
| 203 } | |
| 204 | |
| 205 | |
| 206 bool VmService::IsRunning() { | |
| 207 return port_ != ILLEGAL_PORT; | |
| 208 } | |
| 209 | |
| 210 | |
| 211 Dart_Handle VmService::GetSource(const char* name) { | 149 Dart_Handle VmService::GetSource(const char* name) { |
| 150 const intptr_t kBufferSize = 512; |
| 151 char buffer[kBufferSize]; |
| 152 snprintf(&buffer[0], kBufferSize-1, "%s/%s", kLibrarySourceNamePrefix, name); |
| 212 const char* vmservice_source = NULL; | 153 const char* vmservice_source = NULL; |
| 213 int r = Resources::ResourceLookup(name, &vmservice_source); | 154 int r = Resources::ResourceLookup(buffer, &vmservice_source); |
| 214 ASSERT(r != Resources::kNoSuchInstance); | 155 ASSERT(r != Resources::kNoSuchInstance); |
| 215 return Dart_NewStringFromCString(vmservice_source); | 156 return Dart_NewStringFromCString(vmservice_source); |
| 216 } | 157 } |
| 217 | 158 |
| 218 | 159 |
| 219 Dart_Handle VmService::LoadScript(const char* name) { | 160 Dart_Handle VmService::LoadScript(const char* name) { |
| 220 Dart_Handle url = Dart_NewStringFromCString(name); | 161 Dart_Handle url = Dart_NewStringFromCString("dart:vmservice_io"); |
| 221 Dart_Handle source = GetSource(name); | 162 Dart_Handle source = GetSource(name); |
| 222 return Dart_LoadScript(url, source, 0, 0); | 163 return Dart_LoadScript(url, source, 0, 0); |
| 223 } | 164 } |
| 224 | 165 |
| 225 | 166 |
| 226 Dart_Handle VmService::LoadSource(Dart_Handle library, const char* name) { | 167 Dart_Handle VmService::LoadSource(Dart_Handle library, const char* name) { |
| 227 Dart_Handle url = Dart_NewStringFromCString(name); | 168 Dart_Handle url = Dart_NewStringFromCString(name); |
| 228 Dart_Handle source = GetSource(name); | 169 Dart_Handle source = GetSource(name); |
| 229 return Dart_LoadSource(library, url, source); | 170 return Dart_LoadSource(library, url, source); |
| 230 } | 171 } |
| 231 | 172 |
| 232 | 173 |
| 233 Dart_Handle VmService::LoadSources(Dart_Handle library, const char* names[]) { | |
| 234 Dart_Handle result = Dart_Null(); | |
| 235 for (int i = 0; names[i] != NULL; i++) { | |
| 236 result = LoadSource(library, names[i]); | |
| 237 if (Dart_IsError(result)) { | |
| 238 break; | |
| 239 } | |
| 240 } | |
| 241 return result; | |
| 242 } | |
| 243 | |
| 244 | |
| 245 Dart_Handle VmService::LoadResource(Dart_Handle library, | 174 Dart_Handle VmService::LoadResource(Dart_Handle library, |
| 246 const char* resource_name, | 175 const char* resource_name, |
| 247 const char* prefix) { | 176 const char* prefix) { |
| 248 intptr_t prefix_len = strlen(prefix); | 177 intptr_t prefix_len = strlen(prefix); |
| 249 // Prepare for invoke call. | 178 // Prepare for invoke call. |
| 250 Dart_Handle name = Dart_NewStringFromCString(resource_name+prefix_len); | 179 Dart_Handle name = Dart_NewStringFromCString(resource_name+prefix_len); |
| 251 RETURN_ERROR_HANDLE(name); | 180 RETURN_ERROR_HANDLE(name); |
| 252 const char* data_buffer = NULL; | 181 const char* data_buffer = NULL; |
| 253 int data_buffer_length = Resources::ResourceLookup(resource_name, | 182 int data_buffer_length = Resources::ResourceLookup(resource_name, |
| 254 &data_buffer); | 183 &data_buffer); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 278 Dart_Handle args[kNumArgs] = { name, data_list }; | 207 Dart_Handle args[kNumArgs] = { name, data_list }; |
| 279 result = Dart_Invoke(library, Dart_NewStringFromCString("_addResource"), | 208 result = Dart_Invoke(library, Dart_NewStringFromCString("_addResource"), |
| 280 kNumArgs, args); | 209 kNumArgs, args); |
| 281 return result; | 210 return result; |
| 282 } | 211 } |
| 283 | 212 |
| 284 | 213 |
| 285 Dart_Handle VmService::LoadResources(Dart_Handle library) { | 214 Dart_Handle VmService::LoadResources(Dart_Handle library) { |
| 286 Dart_Handle result = Dart_Null(); | 215 Dart_Handle result = Dart_Null(); |
| 287 intptr_t prefixLen = strlen(kClientResourceNamePrefix); | 216 intptr_t prefixLen = strlen(kClientResourceNamePrefix); |
| 288 for (intptr_t i = 0; i < Resources::get_resource_count(); i++) { | 217 for (intptr_t i = 0; Resources::Path(i) != NULL; i++) { |
| 289 const char* path = Resources::get_resource_path(i); | 218 const char* path = Resources::Path(i); |
| 290 if (!strncmp(path, kClientResourceNamePrefix, prefixLen)) { | 219 if (!strncmp(path, kClientResourceNamePrefix, prefixLen)) { |
| 291 result = LoadResource(library, path, kClientResourceNamePrefix); | 220 result = LoadResource(library, path, kClientResourceNamePrefix); |
| 292 if (Dart_IsError(result)) { | 221 if (Dart_IsError(result)) { |
| 293 break; | 222 break; |
| 294 } | 223 } |
| 295 } | 224 } |
| 296 } | 225 } |
| 297 return result; | 226 return result; |
| 298 } | 227 } |
| 299 | 228 |
| 300 | 229 |
| 301 static bool IsVMServiceURL(const char* url) { | |
| 302 static const intptr_t kLibraryResourceNamePrefixLen = | |
| 303 strlen(kLibraryResourceNamePrefix); | |
| 304 return 0 == strncmp(kLibraryResourceNamePrefix, url, | |
| 305 kLibraryResourceNamePrefixLen); | |
| 306 } | |
| 307 | |
| 308 | |
| 309 static bool IsVMServiceLibrary(const char* url) { | |
| 310 return 0 == strcmp(kVMServiceLibraryName, url); | |
| 311 } | |
| 312 | |
| 313 | |
| 314 Dart_Handle VmService::LibraryTagHandler(Dart_LibraryTag tag, | 230 Dart_Handle VmService::LibraryTagHandler(Dart_LibraryTag tag, |
| 315 Dart_Handle library, | 231 Dart_Handle library, |
| 316 Dart_Handle url) { | 232 Dart_Handle url) { |
| 317 if (!Dart_IsLibrary(library)) { | 233 if (!Dart_IsLibrary(library)) { |
| 318 return Dart_NewApiError("not a library"); | 234 return Dart_NewApiError("not a library"); |
| 319 } | 235 } |
| 320 if (!Dart_IsString(url)) { | 236 if (!Dart_IsString(url)) { |
| 321 return Dart_NewApiError("url is not a string"); | 237 return Dart_NewApiError("url is not a string"); |
| 322 } | 238 } |
| 323 const char* url_string = NULL; | 239 const char* url_string = NULL; |
| 324 Dart_Handle result = Dart_StringToCString(url, &url_string); | 240 Dart_Handle result = Dart_StringToCString(url, &url_string); |
| 325 if (Dart_IsError(result)) { | 241 if (Dart_IsError(result)) { |
| 326 return result; | 242 return result; |
| 327 } | 243 } |
| 328 Dart_Handle library_url = Dart_LibraryUrl(library); | 244 Dart_Handle library_url = Dart_LibraryUrl(library); |
| 329 const char* library_url_string = NULL; | 245 const char* library_url_string = NULL; |
| 330 result = Dart_StringToCString(library_url, &library_url_string); | 246 result = Dart_StringToCString(library_url, &library_url_string); |
| 331 if (Dart_IsError(result)) { | 247 if (Dart_IsError(result)) { |
| 332 return result; | 248 return result; |
| 333 } | 249 } |
| 334 bool is_vm_service_url = IsVMServiceURL(url_string); | 250 if (tag == Dart_kImportTag) { |
| 335 if (!is_vm_service_url) { | 251 // Embedder handles all requests for external libraries. |
| 336 // Pass to DartUtils. | |
| 337 return DartUtils::LibraryTagHandler(tag, library, url); | 252 return DartUtils::LibraryTagHandler(tag, library, url); |
| 338 } | 253 } |
| 339 switch (tag) { | 254 ASSERT((tag == Dart_kSourceTag) || (tag == Dart_kCanonicalizeUrl)); |
| 340 case Dart_kCanonicalizeUrl: | 255 if (tag == Dart_kCanonicalizeUrl) { |
| 341 // The URL is already canonicalized. | 256 // url is already canonicalized. |
| 342 return url; | 257 return url; |
| 343 break; | |
| 344 case Dart_kImportTag: { | |
| 345 Dart_Handle source = GetSource(url_string); | |
| 346 if (Dart_IsError(source)) { | |
| 347 return source; | |
| 348 } | |
| 349 Dart_Handle lib = Dart_LoadLibrary(url, source); | |
| 350 if (Dart_IsError(lib)) { | |
| 351 return lib; | |
| 352 } | |
| 353 if (IsVMServiceLibrary(url_string)) { | |
| 354 // Install native resolver for this library. | |
| 355 result = Dart_SetNativeResolver(lib, VmServiceNativeResolver); | |
| 356 if (Dart_IsError(result)) { | |
| 357 return result; | |
| 358 } | |
| 359 } | |
| 360 return lib; | |
| 361 } | |
| 362 break; | |
| 363 case Dart_kSourceTag: { | |
| 364 Dart_Handle source = GetSource(url_string); | |
| 365 if (Dart_IsError(source)) { | |
| 366 return source; | |
| 367 } | |
| 368 return Dart_LoadSource(library, url, source); | |
| 369 } | |
| 370 break; | |
| 371 default: | |
| 372 UNIMPLEMENTED(); | |
| 373 break; | |
| 374 } | 258 } |
| 375 UNREACHABLE(); | 259 Dart_Handle source = GetSource(url_string); |
| 376 return result; | 260 if (Dart_IsError(source)) { |
| 261 return source; |
| 262 } |
| 263 return Dart_LoadSource(library, url, source); |
| 377 } | 264 } |
| 378 | 265 |
| 379 | 266 |
| 380 void VmService::ThreadMain(uword parameters) { | 267 void VmService::ThreadMain(uword parameters) { |
| 381 ASSERT(Dart_CurrentIsolate() == NULL); | 268 ASSERT(Dart_CurrentIsolate() == NULL); |
| 382 ASSERT(isolate_ == NULL); | 269 Dart_Isolate service_isolate = Dart_GetServiceIsolate(NULL); |
| 383 | 270 Dart_EnterIsolate(service_isolate); |
| 384 intptr_t server_port = static_cast<intptr_t>(parameters); | 271 Dart_EnterScope(); |
| 385 ASSERT(server_port >= 0); | |
| 386 | |
| 387 // Lock scope. | |
| 388 { | |
| 389 MonitorLocker ml(monitor_); | |
| 390 bool r = _Start(server_port); | |
| 391 if (!r) { | |
| 392 port_ = ILLEGAL_PORT; | |
| 393 monitor_->Notify(); | |
| 394 return; | |
| 395 } | |
| 396 | |
| 397 Dart_EnterIsolate(isolate_); | |
| 398 Dart_EnterScope(); | |
| 399 | |
| 400 Dart_Handle receievePort = Dart_GetReceivePort(port_); | |
| 401 ASSERT(!Dart_IsError(receievePort)); | |
| 402 monitor_->Notify(); | |
| 403 } | |
| 404 | |
| 405 // Keep handling messages until the last active receive port is closed. | |
| 406 Dart_Handle result = Dart_RunLoop(); | 272 Dart_Handle result = Dart_RunLoop(); |
| 407 if (Dart_IsError(result)) { | 273 if (Dart_IsError(result)) { |
| 408 printf("VmService has exited with an error:\n%s\n", Dart_GetError(result)); | 274 printf("Service exited with an error:\n%s\n", Dart_GetError(result)); |
| 409 } | 275 } |
| 410 | |
| 411 _Stop(); | |
| 412 | |
| 413 Dart_ExitScope(); | 276 Dart_ExitScope(); |
| 414 Dart_ExitIsolate(); | 277 Dart_ExitIsolate(); |
| 415 } | 278 } |
| 416 | 279 |
| 417 | 280 |
| 418 static Dart_Handle MakeServiceControlMessage(Dart_Port port_id, intptr_t code, | |
| 419 Dart_Handle name) { | |
| 420 Dart_Handle result; | |
| 421 Dart_Handle list = Dart_NewList(4); | |
| 422 ASSERT(!Dart_IsError(list)); | |
| 423 Dart_Handle code_handle = Dart_NewInteger(code); | |
| 424 ASSERT(!Dart_IsError(code_handle)); | |
| 425 result = Dart_ListSetAt(list, 0, code_handle); | |
| 426 ASSERT(!Dart_IsError(result)); | |
| 427 Dart_Handle port_id_handle = Dart_NewInteger(port_id); | |
| 428 ASSERT(!Dart_IsError(port_id_handle)); | |
| 429 result = Dart_ListSetAt(list, 1, port_id_handle); | |
| 430 ASSERT(!Dart_IsError(result)); | |
| 431 Dart_Handle sendPort = Dart_NewSendPort(port_id); | |
| 432 ASSERT(!Dart_IsError(sendPort)); | |
| 433 result = Dart_ListSetAt(list, 2, sendPort); | |
| 434 ASSERT(!Dart_IsError(result)); | |
| 435 result = Dart_ListSetAt(list, 3, name); | |
| 436 ASSERT(!Dart_IsError(result)); | |
| 437 return list; | |
| 438 } | |
| 439 | |
| 440 | |
| 441 bool VmService::SendIsolateStartupMessage() { | |
| 442 if (!IsRunning()) { | |
| 443 return false; | |
| 444 } | |
| 445 Isolate* isolate = Isolate::Current(); | |
| 446 ASSERT(isolate != NULL); | |
| 447 HANDLESCOPE(isolate); | |
| 448 Dart_Handle name = Api::NewHandle(isolate, String::New(isolate->name())); | |
| 449 ASSERT(!Dart_IsError(name)); | |
| 450 Dart_Handle list = | |
| 451 MakeServiceControlMessage(Dart_GetMainPortId(), | |
| 452 VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID, | |
| 453 name); | |
| 454 ASSERT(!Dart_IsError(list)); | |
| 455 return Dart_Post(port_, list); | |
| 456 } | |
| 457 | |
| 458 | |
| 459 bool VmService::SendIsolateShutdownMessage() { | |
| 460 if (!IsRunning()) { | |
| 461 return false; | |
| 462 } | |
| 463 Isolate* isolate = Isolate::Current(); | |
| 464 ASSERT(isolate != NULL); | |
| 465 HANDLESCOPE(isolate); | |
| 466 Dart_Handle list = | |
| 467 MakeServiceControlMessage(Dart_GetMainPortId(), | |
| 468 VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID, | |
| 469 Dart_Null()); | |
| 470 ASSERT(!Dart_IsError(list)); | |
| 471 return Dart_Post(port_, list); | |
| 472 } | |
| 473 | |
| 474 | |
| 475 void VmService::VmServiceShutdownCallback(void* callback_data) { | |
| 476 ASSERT(Dart_CurrentIsolate() != NULL); | |
| 477 Dart_EnterScope(); | |
| 478 VmService::SendIsolateShutdownMessage(); | |
| 479 Dart_ExitScope(); | |
| 480 } | |
| 481 | |
| 482 | |
| 483 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { | |
| 484 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); | |
| 485 return reinterpret_cast<uint8_t*>(new_ptr); | |
| 486 } | |
| 487 | |
| 488 | |
| 489 static void SendServiceMessage(Dart_NativeArguments args) { | |
| 490 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | |
| 491 Isolate* isolate = arguments->isolate(); | |
| 492 StackZone zone(isolate); | |
| 493 HANDLESCOPE(isolate); | |
| 494 GET_NON_NULL_NATIVE_ARGUMENT(Instance, sp, arguments->NativeArgAt(0)); | |
| 495 GET_NON_NULL_NATIVE_ARGUMENT(Instance, message, arguments->NativeArgAt(1)); | |
| 496 | |
| 497 // Extract SendPort port id. | |
| 498 const Object& sp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(sp)); | |
| 499 if (sp_id_obj.IsError()) { | |
| 500 Exceptions::PropagateError(Error::Cast(sp_id_obj)); | |
| 501 } | |
| 502 Integer& id = Integer::Handle(); | |
| 503 id ^= sp_id_obj.raw(); | |
| 504 Dart_Port sp_id = static_cast<Dart_Port>(id.AsInt64Value()); | |
| 505 ASSERT(sp_id != ILLEGAL_PORT); | |
| 506 | |
| 507 // Serialize message. | |
| 508 uint8_t* data = NULL; | |
| 509 MessageWriter writer(&data, &allocator); | |
| 510 writer.WriteMessage(message); | |
| 511 | |
| 512 // TODO(turnidge): Throw an exception when the return value is false? | |
| 513 PortMap::PostMessage(new Message(sp_id, data, writer.BytesWritten(), | |
| 514 Message::kOOBPriority)); | |
| 515 } | |
| 516 | |
| 517 | |
| 518 struct VmServiceNativeEntry { | |
| 519 const char* name; | |
| 520 int num_arguments; | |
| 521 Dart_NativeFunction function; | |
| 522 }; | |
| 523 | |
| 524 | |
| 525 static VmServiceNativeEntry _VmServiceNativeEntries[] = { | |
| 526 {"VMService_SendServiceMessage", 2, SendServiceMessage} | |
| 527 }; | |
| 528 | |
| 529 | |
| 530 static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name, | |
| 531 int num_arguments, | |
| 532 bool* auto_setup_scope) { | |
| 533 const Object& obj = Object::Handle(Api::UnwrapHandle(name)); | |
| 534 if (!obj.IsString()) { | |
| 535 return NULL; | |
| 536 } | |
| 537 const char* function_name = obj.ToCString(); | |
| 538 ASSERT(function_name != NULL); | |
| 539 ASSERT(auto_setup_scope != NULL); | |
| 540 *auto_setup_scope = true; | |
| 541 intptr_t n = | |
| 542 sizeof(_VmServiceNativeEntries) / sizeof(_VmServiceNativeEntries[0]); | |
| 543 for (intptr_t i = 0; i < n; i++) { | |
| 544 VmServiceNativeEntry entry = _VmServiceNativeEntries[i]; | |
| 545 if (!strcmp(function_name, entry.name) && | |
| 546 (num_arguments == entry.num_arguments)) { | |
| 547 return entry.function; | |
| 548 } | |
| 549 } | |
| 550 return NULL; | |
| 551 } | |
| 552 | 281 |
| 553 } // namespace bin | 282 } // namespace bin |
| 554 } // namespace dart | 283 } // namespace dart |
| OLD | NEW |