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(); | |
|
siva
2013/07/15 21:40:16
ASSERT(monitor_ != NULL);
Cutch
2013/07/15 21:58:38
Done.
| |
| 56 | |
| 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::get_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); | |
| 260 intptr_t server_port = static_cast<intptr_t>(parameters); | |
| 261 ASSERT(server_port >= 0); | |
|
siva
2013/07/15 21:40:16
This code needs a
MonitorLocker ml(monitor
Cutch
2013/07/15 21:58:38
Done. Thanks.
| |
| 262 | |
| 263 bool r = _Start(server_port); | |
| 264 if (!r) { | |
| 265 port_ = ILLEGAL_PORT; | |
| 266 monitor_->Notify(); | |
| 267 return; | |
| 268 } | |
| 269 | |
| 270 Dart_EnterIsolate(isolate_); | |
| 271 Dart_EnterScope(); | |
| 272 | |
| 273 Dart_Handle receievePort = Dart_GetReceivePort(port_); | |
| 274 ASSERT(!Dart_IsError(receievePort)); | |
| 275 | |
| 276 monitor_->Notify(); | |
| 277 // Keep handling messages until the last active receive port is closed. | |
| 278 Dart_Handle result = Dart_RunLoop(); | |
| 279 if (Dart_IsError(result)) { | |
| 280 printf("VmService error %s\n", Dart_GetError(result)); | |
| 281 } | |
| 282 | |
| 283 _Stop(); | |
| 284 | |
| 285 Dart_ExitScope(); | |
| 286 Dart_ExitIsolate(); | |
| 287 } | |
| 288 | |
| 289 | |
| 290 | |
| 291 | |
| 292 static Dart_Handle MakeServiceControlMessage(Dart_Port port) { | |
| 293 Dart_Handle list = Dart_NewList(2); | |
| 294 ASSERT(!Dart_IsError(list)); | |
| 295 Dart_Handle sendPort = Dart_NewSendPort(port); | |
| 296 ASSERT(!Dart_IsError(sendPort)); | |
| 297 Dart_ListSetAt(list, 1, sendPort); | |
| 298 return list; | |
| 299 } | |
| 300 | |
| 301 | |
| 302 bool VmService::SendIsolateStartupMessage(Dart_Port port) { | |
| 303 if (!IsRunning()) { | |
| 304 return false; | |
| 305 } | |
| 306 Dart_Isolate isolate = Dart_CurrentIsolate(); | |
| 307 ASSERT(isolate != NULL); | |
| 308 ASSERT(Dart_GetMainPortId() == port); | |
| 309 Dart_Handle list = MakeServiceControlMessage(port); | |
| 310 Dart_ListSetAt(list, 0, | |
| 311 Dart_NewInteger(VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID)); | |
| 312 return Dart_Post(port_, list); | |
| 313 } | |
| 314 | |
| 315 | |
| 316 bool VmService::SendIsolateShutdownMessage(Dart_Port port) { | |
| 317 if (!IsRunning()) { | |
| 318 return false; | |
| 319 } | |
| 320 Dart_Isolate isolate = Dart_CurrentIsolate(); | |
| 321 ASSERT(isolate != NULL); | |
| 322 ASSERT(Dart_GetMainPortId() == port); | |
| 323 Dart_Handle list = MakeServiceControlMessage(port); | |
| 324 Dart_ListSetAt(list, 0, | |
| 325 Dart_NewInteger(VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID)); | |
| 326 return Dart_Post(port_, list); | |
| 327 } | |
| 328 | |
| 329 | |
| 330 void Dart_VmServiceShutdownCallback() { | |
| 331 ASSERT(Dart_CurrentIsolate() != NULL); | |
| 332 Dart_EnterScope(); | |
| 333 VmService::SendIsolateShutdownMessage(Dart_GetMainPortId()); | |
| 334 Dart_ExitScope(); | |
| 335 } | |
|
siva
2013/07/15 21:40:16
Where is this method used? Can we add it when it i
Cutch
2013/07/15 21:58:38
Done.
| |
| 336 | |
| 337 | |
| 338 } // namespace bin | |
| 339 } // namespace dart | |
| OLD | NEW |