Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 #include "bin/vmservice_impl.h" | |
| 6 | |
| 7 #include "include/dart_api.h" | |
| 8 | |
| 9 #include "bin/builtin.h" | |
| 10 #include "bin/dartutils.h" | |
| 11 #include "bin/resources.h" | |
| 12 #include "bin/thread.h" | |
| 13 #include "bin/isolate_data.h" | |
| 14 | |
| 15 | |
| 16 namespace dart { | |
| 17 namespace bin { | |
| 18 | |
| 19 // snapshot_buffer points to a snapshot if we link in a snapshot otherwise | |
| 20 // it is initialized to NULL. | |
| 21 extern const uint8_t* snapshot_buffer; | |
| 22 #define RETURN_ERROR_HANDLE(handle) \ | |
| 23 if (Dart_IsError(handle)) { \ | |
| 24 return handle; \ | |
| 25 } | |
| 26 | |
| 27 #define SHUTDOWN_ON_ERROR(handle) \ | |
| 28 if (Dart_IsError(handle)) { \ | |
| 29 error_msg_ = strdup(Dart_GetError(handle)); \ | |
| 30 Dart_ExitScope(); \ | |
| 31 Dart_ShutdownIsolate(); \ | |
| 32 return false; \ | |
| 33 } | |
| 34 | |
| 35 #define kLibraryResourceNamePrefix "/vmservice" | |
| 36 static const char* kLibraryScriptResourceName = | |
| 37 kLibraryResourceNamePrefix "/vmservice.dart"; | |
| 38 static const char* kLibrarySourceResourceNames[] = { | |
| 39 NULL | |
| 40 }; | |
| 41 | |
| 42 #define kClientResourceNamePrefix "/client/web/out" | |
| 43 | |
| 44 Dart_Isolate VmService::isolate_ = NULL; | |
| 45 Dart_Port VmService::port_ = ILLEGAL_PORT; | |
| 46 dart::Monitor* VmService::monitor_ = NULL; | |
| 47 const char* VmService::error_msg_ = NULL; | |
| 48 | |
| 49 // These must be kept in sync with vmservice/constants.dart | |
| 50 #define VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID 1 | |
| 51 #define VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID 2 | |
| 52 | |
| 53 | |
| 54 bool VmService::Start(intptr_t server_port) { | |
| 55 monitor_ = new dart::Monitor(); | |
| 56 ASSERT(monitor_ != NULL); | |
| 57 error_msg_ = NULL; | |
| 58 | |
| 59 // The VM service is initialized on a new thread. | |
| 60 dart::Thread::Start(ThreadMain, server_port); | |
| 61 { | |
| 62 // Wait until service is running. | |
| 63 MonitorLocker ml(monitor_); | |
| 64 ml.Wait(); | |
| 65 } | |
| 66 return port_ != ILLEGAL_PORT; | |
| 67 } | |
| 68 | |
| 69 | |
| 70 bool VmService::_Start(intptr_t server_port) { | |
| 71 ASSERT(isolate_ == NULL); | |
| 72 char* error = NULL; | |
| 73 isolate_ = Dart_CreateIsolate("vmservice:", "main", snapshot_buffer, | |
| 74 new IsolateData(), | |
| 75 &error); | |
| 76 if (isolate_ == NULL) { | |
| 77 error_msg_ = error; | |
| 78 return false; | |
| 79 } | |
| 80 | |
| 81 Dart_EnterScope(); | |
| 82 | |
| 83 if (snapshot_buffer != NULL) { | |
| 84 // Setup the native resolver as the snapshot does not carry it. | |
| 85 Builtin::SetNativeResolver(Builtin::kBuiltinLibrary); | |
| 86 Builtin::SetNativeResolver(Builtin::kIOLibrary); | |
| 87 } | |
| 88 | |
| 89 // Set up the library tag handler for this isolate. | |
| 90 Dart_Handle result = Dart_SetLibraryTagHandler(DartUtils::LibraryTagHandler); | |
| 91 SHUTDOWN_ON_ERROR(result); | |
| 92 | |
| 93 // Load the specified application script into the newly created isolate. | |
| 94 | |
| 95 // Prepare builtin and its dependent libraries for use to resolve URIs. | |
| 96 // The builtin library is part of the core snapshot and would already be | |
| 97 // available here in the case of script snapshot loading. | |
| 98 Dart_Handle builtin_lib = | |
| 99 Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary); | |
| 100 SHUTDOWN_ON_ERROR(builtin_lib); | |
| 101 | |
| 102 // Prepare for script loading by setting up the 'print' and 'timer' | |
| 103 // closures and setting up 'package root' for URI resolution. | |
| 104 result = DartUtils::PrepareForScriptLoading("", builtin_lib); | |
| 105 SHUTDOWN_ON_ERROR(result); | |
| 106 | |
| 107 { | |
| 108 // Load source into service isolate. | |
| 109 Dart_Handle library = LoadScript(kLibraryScriptResourceName); | |
| 110 SHUTDOWN_ON_ERROR(library); | |
| 111 result = LoadSources(library, kLibrarySourceResourceNames); | |
| 112 SHUTDOWN_ON_ERROR(result); | |
| 113 } | |
| 114 | |
| 115 // Make the isolate runnable so that it is ready to handle messages. | |
| 116 Dart_ExitScope(); | |
| 117 Dart_ExitIsolate(); | |
| 118 | |
| 119 bool retval = Dart_IsolateMakeRunnable(isolate_); | |
| 120 if (!retval) { | |
| 121 Dart_EnterIsolate(isolate_); | |
| 122 Dart_ShutdownIsolate(); | |
| 123 error_msg_ = "Invalid isolate state - Unable to make it runnable."; | |
| 124 return false; | |
| 125 } | |
| 126 | |
| 127 Dart_EnterIsolate(isolate_); | |
| 128 Dart_EnterScope(); | |
| 129 | |
| 130 Dart_Handle library = Dart_RootLibrary(); | |
| 131 result = Dart_Invoke(library, DartUtils::NewString("main"), 0, NULL); | |
| 132 SHUTDOWN_ON_ERROR(result); | |
| 133 | |
| 134 result = LoadResources(library); | |
| 135 SHUTDOWN_ON_ERROR(result); | |
| 136 | |
| 137 port_ = Dart_GetMainPortId(); | |
| 138 | |
| 139 Dart_ExitScope(); | |
| 140 Dart_ExitIsolate(); | |
| 141 | |
| 142 return true; | |
| 143 } | |
| 144 | |
| 145 | |
| 146 void VmService::_Stop() { | |
| 147 port_ = ILLEGAL_PORT; | |
| 148 } | |
| 149 | |
| 150 | |
| 151 const char* VmService::GetErrorMessage() { | |
| 152 return error_msg_ == NULL ? "No error." : error_msg_; | |
| 153 } | |
| 154 | |
| 155 | |
| 156 Dart_Port VmService::port() { | |
| 157 return port_; | |
| 158 } | |
| 159 | |
| 160 | |
| 161 bool VmService::IsRunning() { | |
| 162 return port_ != ILLEGAL_PORT; | |
| 163 } | |
| 164 | |
| 165 | |
| 166 Dart_Handle VmService::LoadScript(const char* name) { | |
| 167 Dart_Handle url = Dart_NewStringFromCString(name); | |
| 168 const char* vmservice_source = NULL; | |
| 169 int r = Resources::ResourceLookup(name, &vmservice_source); | |
| 170 ASSERT(r != Resources::kNoSuchInstance); | |
| 171 Dart_Handle source = Dart_NewStringFromCString(vmservice_source); | |
| 172 return Dart_LoadScript(url, source, 0, 0); | |
| 173 } | |
| 174 | |
| 175 | |
| 176 Dart_Handle VmService::LoadSource(Dart_Handle library, const char* name) { | |
| 177 Dart_Handle url = Dart_NewStringFromCString(name); | |
| 178 const char* vmservice_source = NULL; | |
| 179 int r = Resources::ResourceLookup(name, &vmservice_source); | |
| 180 if (r == Resources::kNoSuchInstance) { | |
| 181 printf("Can't find %s\n", name); | |
| 182 } | |
| 183 ASSERT(r != Resources::kNoSuchInstance); | |
| 184 Dart_Handle source = Dart_NewStringFromCString(vmservice_source); | |
| 185 return Dart_LoadSource(library, url, source); | |
| 186 } | |
| 187 | |
| 188 | |
| 189 Dart_Handle VmService::LoadSources(Dart_Handle library, const char* names[]) { | |
| 190 Dart_Handle result = Dart_Null(); | |
| 191 for (int i = 0; names[i] != NULL; i++) { | |
| 192 result = LoadSource(library, names[i]); | |
| 193 if (Dart_IsError(result)) { | |
| 194 break; | |
| 195 } | |
| 196 } | |
| 197 return result; | |
| 198 } | |
| 199 | |
| 200 | |
| 201 Dart_Handle VmService::LoadResource(Dart_Handle library, | |
| 202 const char* resource_name, | |
| 203 const char* prefix) { | |
| 204 intptr_t prefix_len = strlen(prefix); | |
| 205 // Prepare for invoke call. | |
| 206 Dart_Handle name = Dart_NewStringFromCString(resource_name+prefix_len); | |
| 207 RETURN_ERROR_HANDLE(name); | |
| 208 const char* data_buffer = NULL; | |
| 209 int data_buffer_length = Resources::ResourceLookup(resource_name, | |
| 210 &data_buffer); | |
| 211 if (data_buffer_length == Resources::kNoSuchInstance) { | |
| 212 printf("Could not find %s %s\n", resource_name, resource_name+prefix_len); | |
| 213 } | |
| 214 ASSERT(data_buffer_length != Resources::kNoSuchInstance); | |
| 215 Dart_Handle data_list = Dart_NewTypedData(Dart_TypedData_kUint8, | |
| 216 data_buffer_length); | |
| 217 RETURN_ERROR_HANDLE(data_list); | |
| 218 Dart_TypedData_Type type = Dart_TypedData_kInvalid; | |
| 219 void* data_list_buffer = NULL; | |
| 220 intptr_t data_list_buffer_length = 0; | |
| 221 Dart_Handle result = Dart_TypedDataAcquireData(data_list, &type, | |
| 222 &data_list_buffer, | |
| 223 &data_list_buffer_length); | |
| 224 RETURN_ERROR_HANDLE(result); | |
| 225 ASSERT(data_buffer_length == data_list_buffer_length); | |
| 226 ASSERT(data_list_buffer != NULL); | |
| 227 ASSERT(type = Dart_TypedData_kUint8); | |
| 228 memmove(data_list_buffer, &data_buffer[0], data_buffer_length); | |
| 229 result = Dart_TypedDataReleaseData(data_list); | |
| 230 RETURN_ERROR_HANDLE(result); | |
| 231 | |
| 232 // Make invoke call. | |
| 233 const intptr_t kNumArgs = 2; | |
| 234 Dart_Handle args[kNumArgs] = { name, data_list }; | |
| 235 result = Dart_Invoke(library, Dart_NewStringFromCString("_addResource"), | |
| 236 kNumArgs, args); | |
| 237 return result; | |
| 238 } | |
| 239 | |
| 240 | |
| 241 Dart_Handle VmService::LoadResources(Dart_Handle library) { | |
| 242 Dart_Handle result = Dart_Null(); | |
| 243 intptr_t prefixLen = strlen(kClientResourceNamePrefix); | |
| 244 for (intptr_t i = 0; i < Resources::get_resource_count(); i++) { | |
| 245 const char* path = Resources::get_resource_path(i); | |
| 246 if (!strncmp(path, kClientResourceNamePrefix, prefixLen)) { | |
| 247 result = LoadResource(library, path, kClientResourceNamePrefix); | |
| 248 if (Dart_IsError(result)) { | |
| 249 break; | |
| 250 } | |
| 251 } | |
| 252 } | |
| 253 return result; | |
| 254 } | |
| 255 | |
| 256 | |
| 257 void VmService::ThreadMain(uword parameters) { | |
| 258 ASSERT(Dart_CurrentIsolate() == NULL); | |
| 259 ASSERT(isolate_ == NULL); | |
|
siva
2013/07/16 00:00:04
I think you would have to close the MonitorLocker
| |
| 260 MonitorLocker ml(monitor_); | |
| 261 intptr_t server_port = static_cast<intptr_t>(parameters); | |
| 262 ASSERT(server_port >= 0); | |
| 263 | |
| 264 bool r = _Start(server_port); | |
| 265 if (!r) { | |
| 266 port_ = ILLEGAL_PORT; | |
| 267 monitor_->Notify(); | |
| 268 return; | |
| 269 } | |
| 270 | |
| 271 Dart_EnterIsolate(isolate_); | |
| 272 Dart_EnterScope(); | |
| 273 | |
| 274 Dart_Handle receievePort = Dart_GetReceivePort(port_); | |
| 275 ASSERT(!Dart_IsError(receievePort)); | |
| 276 | |
| 277 monitor_->Notify(); | |
|
siva
2013/07/16 00:00:04
}
| |
| 278 // Keep handling messages until the last active receive port is closed. | |
| 279 Dart_Handle result = Dart_RunLoop(); | |
| 280 if (Dart_IsError(result)) { | |
| 281 printf("VmService error %s\n", Dart_GetError(result)); | |
| 282 } | |
| 283 | |
| 284 _Stop(); | |
| 285 | |
| 286 Dart_ExitScope(); | |
| 287 Dart_ExitIsolate(); | |
| 288 } | |
| 289 | |
| 290 | |
| 291 | |
| 292 | |
| 293 static Dart_Handle MakeServiceControlMessage(Dart_Port port) { | |
| 294 Dart_Handle list = Dart_NewList(2); | |
| 295 ASSERT(!Dart_IsError(list)); | |
| 296 Dart_Handle sendPort = Dart_NewSendPort(port); | |
| 297 ASSERT(!Dart_IsError(sendPort)); | |
| 298 Dart_ListSetAt(list, 1, sendPort); | |
| 299 return list; | |
| 300 } | |
| 301 | |
| 302 | |
| 303 bool VmService::SendIsolateStartupMessage(Dart_Port port) { | |
| 304 if (!IsRunning()) { | |
| 305 return false; | |
| 306 } | |
| 307 Dart_Isolate isolate = Dart_CurrentIsolate(); | |
| 308 ASSERT(isolate != NULL); | |
| 309 ASSERT(Dart_GetMainPortId() == port); | |
| 310 Dart_Handle list = MakeServiceControlMessage(port); | |
| 311 Dart_ListSetAt(list, 0, | |
| 312 Dart_NewInteger(VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID)); | |
| 313 return Dart_Post(port_, list); | |
| 314 } | |
| 315 | |
| 316 | |
| 317 bool VmService::SendIsolateShutdownMessage(Dart_Port port) { | |
| 318 if (!IsRunning()) { | |
| 319 return false; | |
| 320 } | |
| 321 Dart_Isolate isolate = Dart_CurrentIsolate(); | |
| 322 ASSERT(isolate != NULL); | |
| 323 ASSERT(Dart_GetMainPortId() == port); | |
| 324 Dart_Handle list = MakeServiceControlMessage(port); | |
| 325 Dart_ListSetAt(list, 0, | |
| 326 Dart_NewInteger(VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID)); | |
| 327 return Dart_Post(port_, list); | |
| 328 } | |
| 329 | |
| 330 | |
| 331 } // namespace bin | |
| 332 } // namespace dart | |
| OLD | NEW |