OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2015, 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 "vm/service_isolate.h" |
| 6 |
| 7 #include "vm/compiler.h" |
| 8 #include "vm/dart_api_impl.h" |
| 9 #include "vm/dart_entry.h" |
| 10 #include "vm/isolate.h" |
| 11 #include "vm/lockers.h" |
| 12 #include "vm/message.h" |
| 13 #include "vm/message_handler.h" |
| 14 #include "vm/native_entry.h" |
| 15 #include "vm/native_arguments.h" |
| 16 #include "vm/object.h" |
| 17 #include "vm/object_store.h" |
| 18 #include "vm/port.h" |
| 19 #include "vm/service.h" |
| 20 #include "vm/symbols.h" |
| 21 #include "vm/thread_pool.h" |
| 22 |
| 23 namespace dart { |
| 24 |
| 25 DEFINE_FLAG(bool, trace_service, false, "Trace VM service requests."); |
| 26 DEFINE_FLAG(bool, trace_service_pause_events, false, |
| 27 "Trace VM service isolate pause events."); |
| 28 |
| 29 struct ResourcesEntry { |
| 30 const char* path_; |
| 31 const char* resource_; |
| 32 int length_; |
| 33 }; |
| 34 |
| 35 extern ResourcesEntry __service_resources_[]; |
| 36 |
| 37 class Resources { |
| 38 public: |
| 39 static const int kNoSuchInstance = -1; |
| 40 static int ResourceLookup(const char* path, const char** resource) { |
| 41 ResourcesEntry* table = ResourceTable(); |
| 42 for (int i = 0; table[i].path_ != NULL; i++) { |
| 43 const ResourcesEntry& entry = table[i]; |
| 44 if (strcmp(path, entry.path_) == 0) { |
| 45 *resource = entry.resource_; |
| 46 ASSERT(entry.length_ > 0); |
| 47 return entry.length_; |
| 48 } |
| 49 } |
| 50 return kNoSuchInstance; |
| 51 } |
| 52 |
| 53 static const char* Path(int idx) { |
| 54 ASSERT(idx >= 0); |
| 55 ResourcesEntry* entry = At(idx); |
| 56 if (entry == NULL) { |
| 57 return NULL; |
| 58 } |
| 59 ASSERT(entry->path_ != NULL); |
| 60 return entry->path_; |
| 61 } |
| 62 |
| 63 static int Length(int idx) { |
| 64 ASSERT(idx >= 0); |
| 65 ResourcesEntry* entry = At(idx); |
| 66 if (entry == NULL) { |
| 67 return kNoSuchInstance; |
| 68 } |
| 69 ASSERT(entry->path_ != NULL); |
| 70 return entry->length_; |
| 71 } |
| 72 |
| 73 static const uint8_t* Resource(int idx) { |
| 74 ASSERT(idx >= 0); |
| 75 ResourcesEntry* entry = At(idx); |
| 76 if (entry == NULL) { |
| 77 return NULL; |
| 78 } |
| 79 return reinterpret_cast<const uint8_t*>(entry->resource_); |
| 80 } |
| 81 |
| 82 private: |
| 83 static ResourcesEntry* At(int idx) { |
| 84 ASSERT(idx >= 0); |
| 85 ResourcesEntry* table = ResourceTable(); |
| 86 for (int i = 0; table[i].path_ != NULL; i++) { |
| 87 if (idx == i) { |
| 88 return &table[i]; |
| 89 } |
| 90 } |
| 91 return NULL; |
| 92 } |
| 93 |
| 94 static ResourcesEntry* ResourceTable() { |
| 95 return &__service_resources_[0]; |
| 96 } |
| 97 |
| 98 DISALLOW_ALLOCATION(); |
| 99 DISALLOW_IMPLICIT_CONSTRUCTORS(Resources); |
| 100 }; |
| 101 |
| 102 |
| 103 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { |
| 104 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); |
| 105 return reinterpret_cast<uint8_t*>(new_ptr); |
| 106 } |
| 107 |
| 108 |
| 109 static Dart_Port ExtractPort(Isolate* isolate, Dart_Handle receivePort) { |
| 110 const ReceivePort& rp = Api::UnwrapReceivePortHandle(isolate, receivePort); |
| 111 if (rp.IsNull()) { |
| 112 return ILLEGAL_PORT; |
| 113 } |
| 114 return rp.Id(); |
| 115 } |
| 116 |
| 117 |
| 118 // These must be kept in sync with service/constants.dart |
| 119 #define VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID 1 |
| 120 #define VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID 2 |
| 121 |
| 122 static RawArray* MakeServiceControlMessage(Dart_Port port_id, intptr_t code, |
| 123 const String& name) { |
| 124 const Array& list = Array::Handle(Array::New(4)); |
| 125 ASSERT(!list.IsNull()); |
| 126 const Integer& code_int = Integer::Handle(Integer::New(code)); |
| 127 const Integer& port_int = Integer::Handle(Integer::New(port_id)); |
| 128 const SendPort& send_port = SendPort::Handle(SendPort::New(port_id)); |
| 129 list.SetAt(0, code_int); |
| 130 list.SetAt(1, port_int); |
| 131 list.SetAt(2, send_port); |
| 132 list.SetAt(3, name); |
| 133 return list.raw(); |
| 134 } |
| 135 |
| 136 |
| 137 const char* ServiceIsolate::kName = "vm-service"; |
| 138 Isolate* ServiceIsolate::isolate_ = NULL; |
| 139 Dart_Port ServiceIsolate::port_ = ILLEGAL_PORT; |
| 140 Dart_Port ServiceIsolate::load_port_ = ILLEGAL_PORT; |
| 141 Dart_IsolateCreateCallback ServiceIsolate::create_callback_ = NULL; |
| 142 Monitor* ServiceIsolate::monitor_ = NULL; |
| 143 bool ServiceIsolate::initializing_ = true; |
| 144 |
| 145 |
| 146 class RegisterRunningIsolatesVisitor : public IsolateVisitor { |
| 147 public: |
| 148 explicit RegisterRunningIsolatesVisitor(Isolate* service_isolate) |
| 149 : IsolateVisitor(), |
| 150 register_function_(Function::Handle(service_isolate)), |
| 151 service_isolate_(service_isolate) { |
| 152 ASSERT(ServiceIsolate::IsServiceIsolate(Isolate::Current())); |
| 153 // Get library. |
| 154 const String& library_url = Symbols::DartVMService(); |
| 155 ASSERT(!library_url.IsNull()); |
| 156 const Library& library = |
| 157 Library::Handle(Library::LookupLibrary(library_url)); |
| 158 ASSERT(!library.IsNull()); |
| 159 // Get function. |
| 160 const String& function_name = |
| 161 String::Handle(String::New("_registerIsolate")); |
| 162 ASSERT(!function_name.IsNull()); |
| 163 register_function_ = library.LookupFunctionAllowPrivate(function_name); |
| 164 ASSERT(!register_function_.IsNull()); |
| 165 } |
| 166 |
| 167 virtual void VisitIsolate(Isolate* isolate) { |
| 168 ASSERT(ServiceIsolate::IsServiceIsolate(Isolate::Current())); |
| 169 if (ServiceIsolate::IsServiceIsolate(isolate) || |
| 170 (isolate == Dart::vm_isolate())) { |
| 171 // We do not register the service or vm isolate. |
| 172 return; |
| 173 } |
| 174 // Setup arguments for call. |
| 175 Dart_Port port_id = isolate->main_port(); |
| 176 const Integer& port_int = Integer::Handle(Integer::New(port_id)); |
| 177 ASSERT(!port_int.IsNull()); |
| 178 const SendPort& send_port = SendPort::Handle(SendPort::New(port_id)); |
| 179 const String& name = String::Handle(String::New(isolate->name())); |
| 180 ASSERT(!name.IsNull()); |
| 181 const Array& args = Array::Handle(Array::New(3)); |
| 182 ASSERT(!args.IsNull()); |
| 183 args.SetAt(0, port_int); |
| 184 args.SetAt(1, send_port); |
| 185 args.SetAt(2, name); |
| 186 Object& r = Object::Handle(service_isolate_); |
| 187 r = DartEntry::InvokeFunction(register_function_, args); |
| 188 if (FLAG_trace_service) { |
| 189 OS::Print("vm-service: Isolate %s %" Pd64 " registered.\n", |
| 190 name.ToCString(), |
| 191 port_id); |
| 192 } |
| 193 ASSERT(!r.IsError()); |
| 194 } |
| 195 |
| 196 private: |
| 197 Function& register_function_; |
| 198 Isolate* service_isolate_; |
| 199 }; |
| 200 |
| 201 |
| 202 |
| 203 class ServiceIsolateNatives : public AllStatic { |
| 204 public: |
| 205 static void SendIsolateServiceMessage(Dart_NativeArguments args) { |
| 206 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); |
| 207 Isolate* isolate = arguments->isolate(); |
| 208 StackZone zone(isolate); |
| 209 HANDLESCOPE(isolate); |
| 210 GET_NON_NULL_NATIVE_ARGUMENT(SendPort, sp, arguments->NativeArgAt(0)); |
| 211 GET_NON_NULL_NATIVE_ARGUMENT(Array, message, arguments->NativeArgAt(1)); |
| 212 |
| 213 // Set the type of the OOB message. |
| 214 message.SetAt(0, Smi::Handle(isolate, Smi::New(Message::kServiceOOBMsg))); |
| 215 |
| 216 // Serialize message. |
| 217 uint8_t* data = NULL; |
| 218 MessageWriter writer(&data, &allocator, false); |
| 219 writer.WriteMessage(message); |
| 220 |
| 221 // TODO(turnidge): Throw an exception when the return value is false? |
| 222 PortMap::PostMessage(new Message(sp.Id(), data, writer.BytesWritten(), |
| 223 Message::kOOBPriority)); |
| 224 } |
| 225 |
| 226 static void SendRootServiceMessage(Dart_NativeArguments args) { |
| 227 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); |
| 228 Isolate* isolate = arguments->isolate(); |
| 229 StackZone zone(isolate); |
| 230 HANDLESCOPE(isolate); |
| 231 GET_NON_NULL_NATIVE_ARGUMENT(Array, message, arguments->NativeArgAt(0)); |
| 232 Service::HandleRootMessage(message); |
| 233 } |
| 234 |
| 235 static void SetEventMask(Dart_NativeArguments args) { |
| 236 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); |
| 237 Isolate* isolate = arguments->isolate(); |
| 238 StackZone zone(isolate); |
| 239 HANDLESCOPE(isolate); |
| 240 GET_NON_NULL_NATIVE_ARGUMENT(Integer, mask, arguments->NativeArgAt(0)); |
| 241 Service::SetEventMask(mask.AsTruncatedUint32Value()); |
| 242 } |
| 243 |
| 244 static void OnStart(Dart_NativeArguments args) { |
| 245 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); |
| 246 Isolate* isolate = arguments->isolate(); |
| 247 StackZone zone(isolate); |
| 248 HANDLESCOPE(isolate); |
| 249 { |
| 250 if (FLAG_trace_service) { |
| 251 OS::Print("vm-service: Booting dart:vmservice library.\n"); |
| 252 } |
| 253 // Boot the dart:vmservice library. |
| 254 Dart_EnterScope(); |
| 255 Dart_Handle url_str = |
| 256 Dart_NewStringFromCString(Symbols::Name(Symbols::kDartVMServiceId)); |
| 257 Dart_Handle library = Dart_LookupLibrary(url_str); |
| 258 ASSERT(Dart_IsLibrary(library)); |
| 259 Dart_Handle result = |
| 260 Dart_Invoke(library, Dart_NewStringFromCString("boot"), 0, NULL); |
| 261 ASSERT(!Dart_IsError(result)); |
| 262 Dart_Port port = ExtractPort(isolate, result); |
| 263 ASSERT(port != ILLEGAL_PORT); |
| 264 ServiceIsolate::SetServicePort(port); |
| 265 Dart_ExitScope(); |
| 266 } |
| 267 |
| 268 { |
| 269 if (FLAG_trace_service) { |
| 270 OS::Print("vm-service: Registering running isolates.\n"); |
| 271 } |
| 272 // Register running isolates with service. |
| 273 RegisterRunningIsolatesVisitor register_isolates(isolate); |
| 274 Isolate::VisitIsolates(®ister_isolates); |
| 275 } |
| 276 } |
| 277 }; |
| 278 |
| 279 |
| 280 struct ServiceNativeEntry { |
| 281 const char* name; |
| 282 int num_arguments; |
| 283 Dart_NativeFunction function; |
| 284 }; |
| 285 |
| 286 |
| 287 static ServiceNativeEntry _ServiceNativeEntries[] = { |
| 288 {"VMService_SendIsolateServiceMessage", 2, |
| 289 ServiceIsolateNatives::SendIsolateServiceMessage}, |
| 290 {"VMService_SendRootServiceMessage", 1, |
| 291 ServiceIsolateNatives::SendRootServiceMessage}, |
| 292 {"VMService_SetEventMask", 1, |
| 293 ServiceIsolateNatives::SetEventMask}, |
| 294 {"VMService_OnStart", 0, |
| 295 ServiceIsolateNatives::OnStart }, |
| 296 }; |
| 297 |
| 298 |
| 299 static Dart_NativeFunction ServiceNativeResolver(Dart_Handle name, |
| 300 int num_arguments, |
| 301 bool* auto_setup_scope) { |
| 302 const Object& obj = Object::Handle(Api::UnwrapHandle(name)); |
| 303 if (!obj.IsString()) { |
| 304 return NULL; |
| 305 } |
| 306 const char* function_name = obj.ToCString(); |
| 307 ASSERT(function_name != NULL); |
| 308 ASSERT(auto_setup_scope != NULL); |
| 309 *auto_setup_scope = true; |
| 310 intptr_t n = sizeof(_ServiceNativeEntries) / |
| 311 sizeof(_ServiceNativeEntries[0]); |
| 312 for (intptr_t i = 0; i < n; i++) { |
| 313 ServiceNativeEntry entry = _ServiceNativeEntries[i]; |
| 314 if ((strcmp(function_name, entry.name) == 0) && |
| 315 (num_arguments == entry.num_arguments)) { |
| 316 return entry.function; |
| 317 } |
| 318 } |
| 319 return NULL; |
| 320 } |
| 321 |
| 322 |
| 323 bool ServiceIsolate::NameEquals(const char* name) { |
| 324 ASSERT(name != NULL); |
| 325 return strcmp(name, kName) == 0; |
| 326 } |
| 327 |
| 328 |
| 329 bool ServiceIsolate::Exists() { |
| 330 MonitorLocker ml(monitor_); |
| 331 return isolate_ != NULL; |
| 332 } |
| 333 |
| 334 |
| 335 bool ServiceIsolate::IsRunning() { |
| 336 MonitorLocker ml(monitor_); |
| 337 return (port_ != ILLEGAL_PORT) && (isolate_ != NULL); |
| 338 } |
| 339 |
| 340 |
| 341 bool ServiceIsolate::IsServiceIsolate(Isolate* isolate) { |
| 342 MonitorLocker ml(monitor_); |
| 343 return isolate == isolate_; |
| 344 } |
| 345 |
| 346 |
| 347 Dart_Port ServiceIsolate::Port() { |
| 348 MonitorLocker ml(monitor_); |
| 349 return port_; |
| 350 } |
| 351 |
| 352 |
| 353 Dart_Port ServiceIsolate::WaitForLoadPort() { |
| 354 MonitorLocker ml(monitor_); |
| 355 |
| 356 while (initializing_ && (load_port_ == ILLEGAL_PORT)) { |
| 357 ml.Wait(); |
| 358 } |
| 359 |
| 360 return load_port_; |
| 361 } |
| 362 |
| 363 |
| 364 Dart_Port ServiceIsolate::LoadPort() { |
| 365 MonitorLocker ml(monitor_); |
| 366 return load_port_; |
| 367 } |
| 368 |
| 369 |
| 370 bool ServiceIsolate::SendIsolateStartupMessage() { |
| 371 if (!IsRunning()) { |
| 372 return false; |
| 373 } |
| 374 Isolate* isolate = Isolate::Current(); |
| 375 if (IsServiceIsolate(isolate)) { |
| 376 return false; |
| 377 } |
| 378 ASSERT(isolate != NULL); |
| 379 HANDLESCOPE(isolate); |
| 380 const String& name = String::Handle(String::New(isolate->name())); |
| 381 ASSERT(!name.IsNull()); |
| 382 const Array& list = Array::Handle( |
| 383 MakeServiceControlMessage(Dart_GetMainPortId(), |
| 384 VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID, |
| 385 name)); |
| 386 ASSERT(!list.IsNull()); |
| 387 uint8_t* data = NULL; |
| 388 MessageWriter writer(&data, &allocator, false); |
| 389 writer.WriteMessage(list); |
| 390 intptr_t len = writer.BytesWritten(); |
| 391 if (FLAG_trace_service) { |
| 392 OS::Print("vm-service: Isolate %s %" Pd64 " registered.\n", |
| 393 name.ToCString(), |
| 394 Dart_GetMainPortId()); |
| 395 } |
| 396 return PortMap::PostMessage( |
| 397 new Message(port_, data, len, Message::kNormalPriority)); |
| 398 } |
| 399 |
| 400 |
| 401 bool ServiceIsolate::SendIsolateShutdownMessage() { |
| 402 if (!IsRunning()) { |
| 403 return false; |
| 404 } |
| 405 Isolate* isolate = Isolate::Current(); |
| 406 if (IsServiceIsolate(isolate)) { |
| 407 return false; |
| 408 } |
| 409 ASSERT(isolate != NULL); |
| 410 HANDLESCOPE(isolate); |
| 411 const String& name = String::Handle(String::New(isolate->name())); |
| 412 ASSERT(!name.IsNull()); |
| 413 const Array& list = Array::Handle( |
| 414 MakeServiceControlMessage(Dart_GetMainPortId(), |
| 415 VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID, |
| 416 name)); |
| 417 ASSERT(!list.IsNull()); |
| 418 uint8_t* data = NULL; |
| 419 MessageWriter writer(&data, &allocator, false); |
| 420 writer.WriteMessage(list); |
| 421 intptr_t len = writer.BytesWritten(); |
| 422 if (FLAG_trace_service) { |
| 423 OS::Print("vm-service: Isolate %s %" Pd64 " deregistered.\n", |
| 424 name.ToCString(), |
| 425 Dart_GetMainPortId()); |
| 426 } |
| 427 return PortMap::PostMessage( |
| 428 new Message(port_, data, len, Message::kNormalPriority)); |
| 429 } |
| 430 |
| 431 |
| 432 void ServiceIsolate::SetServicePort(Dart_Port port) { |
| 433 MonitorLocker ml(monitor_); |
| 434 port_ = port; |
| 435 } |
| 436 |
| 437 |
| 438 void ServiceIsolate::SetServiceIsolate(Isolate* isolate) { |
| 439 MonitorLocker ml(monitor_); |
| 440 isolate_ = isolate; |
| 441 if (isolate_ != NULL) { |
| 442 isolate_->is_service_isolate_ = true; |
| 443 } |
| 444 } |
| 445 |
| 446 void ServiceIsolate::SetLoadPort(Dart_Port port) { |
| 447 MonitorLocker ml(monitor_); |
| 448 load_port_ = port; |
| 449 } |
| 450 |
| 451 |
| 452 void ServiceIsolate::MaybeInjectVMServiceLibrary(Isolate* isolate) { |
| 453 ASSERT(isolate != NULL); |
| 454 ASSERT(isolate->name() != NULL); |
| 455 if (!ServiceIsolate::NameEquals(isolate->name())) { |
| 456 // Not service isolate. |
| 457 return; |
| 458 } |
| 459 if (Exists()) { |
| 460 // Service isolate already exists. |
| 461 return; |
| 462 } |
| 463 SetServiceIsolate(isolate); |
| 464 |
| 465 StackZone zone(isolate); |
| 466 HANDLESCOPE(isolate); |
| 467 |
| 468 // Register dart:vmservice library. |
| 469 const String& url_str = String::Handle(Symbols::DartVMService().raw()); |
| 470 const Library& library = Library::Handle(Library::New(url_str)); |
| 471 library.Register(); |
| 472 library.set_native_entry_resolver(ServiceNativeResolver); |
| 473 |
| 474 // Temporarily install our library tag handler. |
| 475 isolate->set_library_tag_handler(LibraryTagHandler); |
| 476 |
| 477 // Get script source. |
| 478 const char* resource = NULL; |
| 479 const char* path = "/vmservice.dart"; |
| 480 intptr_t r = Resources::ResourceLookup(path, &resource); |
| 481 ASSERT(r != Resources::kNoSuchInstance); |
| 482 ASSERT(resource != NULL); |
| 483 const String& source_str = String::Handle( |
| 484 String::FromUTF8(reinterpret_cast<const uint8_t*>(resource), r)); |
| 485 ASSERT(!source_str.IsNull()); |
| 486 const Script& script = Script::Handle( |
| 487 isolate, Script::New(url_str, source_str, RawScript::kLibraryTag)); |
| 488 |
| 489 // Compile script. |
| 490 Dart_EnterScope(); // Need to enter scope for tag handler. |
| 491 library.SetLoadInProgress(); |
| 492 const Error& error = Error::Handle(isolate, |
| 493 Compiler::Compile(library, script)); |
| 494 ASSERT(error.IsNull()); |
| 495 Dart_Handle result = Dart_FinalizeLoading(false); |
| 496 ASSERT(!Dart_IsError(result)); |
| 497 Dart_ExitScope(); |
| 498 |
| 499 // Uninstall our library tag handler. |
| 500 isolate->set_library_tag_handler(NULL); |
| 501 } |
| 502 |
| 503 |
| 504 void ServiceIsolate::FinishedInitializing() { |
| 505 MonitorLocker ml(monitor_); |
| 506 initializing_ = false; |
| 507 ml.NotifyAll(); |
| 508 } |
| 509 |
| 510 |
| 511 class RunServiceTask : public ThreadPool::Task { |
| 512 public: |
| 513 virtual void Run() { |
| 514 ASSERT(Isolate::Current() == NULL); |
| 515 char* error = NULL; |
| 516 Isolate* isolate = NULL; |
| 517 |
| 518 Dart_IsolateCreateCallback create_callback = |
| 519 ServiceIsolate::create_callback(); |
| 520 // TODO(johnmccutchan): Support starting up service isolate without embedder |
| 521 // provided isolate creation callback. |
| 522 if (create_callback == NULL) { |
| 523 ServiceIsolate::FinishedInitializing(); |
| 524 return; |
| 525 } |
| 526 |
| 527 isolate = |
| 528 reinterpret_cast<Isolate*>(create_callback(ServiceIsolate::kName, |
| 529 NULL, |
| 530 NULL, |
| 531 NULL, |
| 532 &error)); |
| 533 if (isolate == NULL) { |
| 534 OS::PrintErr("vm-service: Isolate creation error: %s\n", error); |
| 535 ServiceIsolate::FinishedInitializing(); |
| 536 return; |
| 537 } |
| 538 |
| 539 Isolate::SetCurrent(NULL); |
| 540 |
| 541 RunMain(isolate); |
| 542 |
| 543 ServiceIsolate::FinishedInitializing(); |
| 544 |
| 545 isolate->message_handler()->Run(Dart::thread_pool(), |
| 546 NULL, |
| 547 ShutdownIsolate, |
| 548 reinterpret_cast<uword>(isolate)); |
| 549 } |
| 550 |
| 551 protected: |
| 552 static void ShutdownIsolate(uword parameter) { |
| 553 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); |
| 554 ASSERT(ServiceIsolate::IsServiceIsolate(isolate)); |
| 555 { |
| 556 // Print the error if there is one. This may execute dart code to |
| 557 // print the exception object, so we need to use a StartIsolateScope. |
| 558 StartIsolateScope start_scope(isolate); |
| 559 StackZone zone(isolate); |
| 560 HandleScope handle_scope(isolate); |
| 561 Error& error = Error::Handle(); |
| 562 error = isolate->object_store()->sticky_error(); |
| 563 if (!error.IsNull()) { |
| 564 OS::PrintErr("vm-service: Error: %s\n", error.ToErrorCString()); |
| 565 } |
| 566 Dart::RunShutdownCallback(); |
| 567 } |
| 568 { |
| 569 // Shut the isolate down. |
| 570 SwitchIsolateScope switch_scope(isolate); |
| 571 Dart::ShutdownIsolate(); |
| 572 } |
| 573 ServiceIsolate::SetServiceIsolate(NULL); |
| 574 ServiceIsolate::SetServicePort(ILLEGAL_PORT); |
| 575 if (FLAG_trace_service) { |
| 576 OS::Print("vm-service: Shutdown.\n"); |
| 577 } |
| 578 } |
| 579 |
| 580 void RunMain(Isolate* isolate) { |
| 581 StartIsolateScope iso_scope(isolate); |
| 582 StackZone zone(isolate); |
| 583 HANDLESCOPE(isolate); |
| 584 // Invoke main which will return the loadScriptPort. |
| 585 const Library& root_library = |
| 586 Library::Handle(isolate, isolate->object_store()->root_library()); |
| 587 if (root_library.IsNull()) { |
| 588 if (FLAG_trace_service) { |
| 589 OS::Print("vm-service: Embedder did not install a script."); |
| 590 } |
| 591 // Service isolate is not supported by embedder. |
| 592 return; |
| 593 } |
| 594 ASSERT(!root_library.IsNull()); |
| 595 const String& entry_name = String::Handle(isolate, String::New("main")); |
| 596 ASSERT(!entry_name.IsNull()); |
| 597 const Function& entry = |
| 598 Function::Handle(isolate, |
| 599 root_library.LookupFunctionAllowPrivate(entry_name)); |
| 600 if (entry.IsNull()) { |
| 601 // Service isolate is not supported by embedder. |
| 602 if (FLAG_trace_service) { |
| 603 OS::Print("vm-service: Embedder did not provide a main function."); |
| 604 } |
| 605 return; |
| 606 } |
| 607 ASSERT(!entry.IsNull()); |
| 608 const Object& result = |
| 609 Object::Handle(isolate, |
| 610 DartEntry::InvokeFunction(entry, |
| 611 Object::empty_array())); |
| 612 ASSERT(!result.IsNull()); |
| 613 if (result.IsError()) { |
| 614 // Service isolate did not initialize properly. |
| 615 if (FLAG_trace_service) { |
| 616 const Error& error = Error::Cast(result); |
| 617 OS::Print("vm-service: Calling main resulted in an error: %s", |
| 618 error.ToErrorCString()); |
| 619 } |
| 620 return; |
| 621 } |
| 622 ASSERT(result.IsReceivePort()); |
| 623 const ReceivePort& rp = ReceivePort::Cast(result); |
| 624 ServiceIsolate::SetLoadPort(rp.Id()); |
| 625 } |
| 626 }; |
| 627 |
| 628 |
| 629 void ServiceIsolate::Run() { |
| 630 ASSERT(monitor_ == NULL); |
| 631 monitor_ = new Monitor(); |
| 632 ASSERT(monitor_ != NULL); |
| 633 // Grab the isolate create callback here to avoid race conditions with tests |
| 634 // that change this after Dart_Initialize returns. |
| 635 create_callback_ = Isolate::CreateCallback(); |
| 636 Dart::thread_pool()->Run(new RunServiceTask()); |
| 637 } |
| 638 |
| 639 |
| 640 Dart_Handle ServiceIsolate::GetSource(const char* name) { |
| 641 ASSERT(name != NULL); |
| 642 int i = 0; |
| 643 while (true) { |
| 644 const char* path = Resources::Path(i); |
| 645 if (path == NULL) { |
| 646 break; |
| 647 } |
| 648 ASSERT(*path != '\0'); |
| 649 // Skip the '/'. |
| 650 path++; |
| 651 if (strcmp(name, path) == 0) { |
| 652 const uint8_t* str = Resources::Resource(i); |
| 653 intptr_t length = Resources::Length(i); |
| 654 return Dart_NewStringFromUTF8(str, length); |
| 655 } |
| 656 i++; |
| 657 } |
| 658 return Dart_Null(); |
| 659 } |
| 660 |
| 661 |
| 662 Dart_Handle ServiceIsolate::LibraryTagHandler(Dart_LibraryTag tag, |
| 663 Dart_Handle library, |
| 664 Dart_Handle url) { |
| 665 if (tag == Dart_kCanonicalizeUrl) { |
| 666 // url is already canonicalized. |
| 667 return url; |
| 668 } |
| 669 if (tag != Dart_kSourceTag) { |
| 670 FATAL("ServiceIsolate::LibraryTagHandler encountered an unexpected tag."); |
| 671 } |
| 672 ASSERT(tag == Dart_kSourceTag); |
| 673 const char* url_string = NULL; |
| 674 Dart_Handle result = Dart_StringToCString(url, &url_string); |
| 675 if (Dart_IsError(result)) { |
| 676 return result; |
| 677 } |
| 678 Dart_Handle source = GetSource(url_string); |
| 679 if (Dart_IsError(source)) { |
| 680 return source; |
| 681 } |
| 682 return Dart_LoadSource(library, url, source, 0, 0); |
| 683 } |
| 684 |
| 685 } // namespace dart |
OLD | NEW |