| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 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 | 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 "vm/service_isolate.h" | 5 #include "vm/service_isolate.h" |
| 6 | 6 |
| 7 #include "vm/compiler.h" | 7 #include "vm/compiler.h" |
| 8 #include "vm/dart_api_impl.h" | 8 #include "vm/dart_api_impl.h" |
| 9 #include "vm/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/isolate.h" | 10 #include "vm/isolate.h" |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 | 24 |
| 25 DECLARE_FLAG(bool, shutdown); | 25 DECLARE_FLAG(bool, shutdown); |
| 26 | 26 |
| 27 #define Z (T->zone()) | 27 #define Z (T->zone()) |
| 28 | 28 |
| 29 | 29 |
| 30 DEFINE_FLAG(bool, trace_service, false, "Trace VM service requests."); | 30 DEFINE_FLAG(bool, trace_service, false, "Trace VM service requests."); |
| 31 DEFINE_FLAG(bool, trace_service_pause_events, false, | 31 DEFINE_FLAG(bool, trace_service_pause_events, false, |
| 32 "Trace VM service isolate pause events."); | 32 "Trace VM service isolate pause events."); |
| 33 | 33 |
| 34 struct ResourcesEntry { | |
| 35 const char* path_; | |
| 36 const char* resource_; | |
| 37 int length_; | |
| 38 }; | |
| 39 | |
| 40 extern ResourcesEntry __service_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 = ResourceTable(); | |
| 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 static int Length(int idx) { | |
| 69 ASSERT(idx >= 0); | |
| 70 ResourcesEntry* entry = At(idx); | |
| 71 if (entry == NULL) { | |
| 72 return kNoSuchInstance; | |
| 73 } | |
| 74 ASSERT(entry->path_ != NULL); | |
| 75 return entry->length_; | |
| 76 } | |
| 77 | |
| 78 static const uint8_t* Resource(int idx) { | |
| 79 ASSERT(idx >= 0); | |
| 80 ResourcesEntry* entry = At(idx); | |
| 81 if (entry == NULL) { | |
| 82 return NULL; | |
| 83 } | |
| 84 return reinterpret_cast<const uint8_t*>(entry->resource_); | |
| 85 } | |
| 86 | |
| 87 private: | |
| 88 static ResourcesEntry* At(int idx) { | |
| 89 ASSERT(idx >= 0); | |
| 90 ResourcesEntry* table = ResourceTable(); | |
| 91 for (int i = 0; table[i].path_ != NULL; i++) { | |
| 92 if (idx == i) { | |
| 93 return &table[i]; | |
| 94 } | |
| 95 } | |
| 96 return NULL; | |
| 97 } | |
| 98 | |
| 99 static ResourcesEntry* ResourceTable() { | |
| 100 return &__service_resources_[0]; | |
| 101 } | |
| 102 | |
| 103 DISALLOW_ALLOCATION(); | |
| 104 DISALLOW_IMPLICIT_CONSTRUCTORS(Resources); | |
| 105 }; | |
| 106 | |
| 107 | |
| 108 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { | 34 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { |
| 109 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); | 35 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); |
| 110 return reinterpret_cast<uint8_t*>(new_ptr); | 36 return reinterpret_cast<uint8_t*>(new_ptr); |
| 111 } | 37 } |
| 112 | 38 |
| 113 | 39 |
| 114 static Dart_Port ExtractPort(Isolate* isolate, Dart_Handle receivePort) { | 40 static Dart_Port ExtractPort(Isolate* isolate, Dart_Handle receivePort) { |
| 115 const ReceivePort& rp = Api::UnwrapReceivePortHandle(isolate, receivePort); | 41 const ReceivePort& rp = Api::UnwrapReceivePortHandle(isolate, receivePort); |
| 116 if (rp.IsNull()) { | 42 if (rp.IsNull()) { |
| 117 return ILLEGAL_PORT; | 43 return ILLEGAL_PORT; |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 ServiceIsolateNatives::OnStart }, | 269 ServiceIsolateNatives::OnStart }, |
| 344 {"VMService_OnExit", 0, | 270 {"VMService_OnExit", 0, |
| 345 ServiceIsolateNatives::OnExit }, | 271 ServiceIsolateNatives::OnExit }, |
| 346 {"VMService_ListenStream", 1, | 272 {"VMService_ListenStream", 1, |
| 347 ServiceIsolateNatives::ListenStream }, | 273 ServiceIsolateNatives::ListenStream }, |
| 348 {"VMService_CancelStream", 1, | 274 {"VMService_CancelStream", 1, |
| 349 ServiceIsolateNatives::CancelStream }, | 275 ServiceIsolateNatives::CancelStream }, |
| 350 }; | 276 }; |
| 351 | 277 |
| 352 | 278 |
| 353 static Dart_NativeFunction ServiceNativeResolver(Dart_Handle name, | 279 Dart_NativeFunction ServiceIsolate::NativeResolver(Dart_Handle name, |
| 354 int num_arguments, | 280 int num_arguments, |
| 355 bool* auto_setup_scope) { | 281 bool* auto_setup_scope) { |
| 356 const Object& obj = Object::Handle(Api::UnwrapHandle(name)); | 282 const Object& obj = Object::Handle(Api::UnwrapHandle(name)); |
| 357 if (!obj.IsString()) { | 283 if (!obj.IsString()) { |
| 358 return NULL; | 284 return NULL; |
| 359 } | 285 } |
| 360 const char* function_name = obj.ToCString(); | 286 const char* function_name = obj.ToCString(); |
| 361 ASSERT(function_name != NULL); | 287 ASSERT(function_name != NULL); |
| 362 ASSERT(auto_setup_scope != NULL); | 288 ASSERT(auto_setup_scope != NULL); |
| 363 *auto_setup_scope = true; | 289 *auto_setup_scope = true; |
| 364 intptr_t n = sizeof(_ServiceNativeEntries) / | 290 intptr_t n = sizeof(_ServiceNativeEntries) / |
| 365 sizeof(_ServiceNativeEntries[0]); | 291 sizeof(_ServiceNativeEntries[0]); |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 origin_ = isolate_->origin_id(); | 448 origin_ = isolate_->origin_id(); |
| 523 } | 449 } |
| 524 } | 450 } |
| 525 | 451 |
| 526 void ServiceIsolate::SetLoadPort(Dart_Port port) { | 452 void ServiceIsolate::SetLoadPort(Dart_Port port) { |
| 527 MonitorLocker ml(monitor_); | 453 MonitorLocker ml(monitor_); |
| 528 load_port_ = port; | 454 load_port_ = port; |
| 529 } | 455 } |
| 530 | 456 |
| 531 | 457 |
| 532 void ServiceIsolate::MaybeInjectVMServiceLibrary(Isolate* I) { | 458 void ServiceIsolate::MaybeMakeServiceIsolate(Isolate* I) { |
| 533 Thread* T = Thread::Current(); | 459 Thread* T = Thread::Current(); |
| 534 ASSERT(I == T->isolate()); | 460 ASSERT(I == T->isolate()); |
| 535 ASSERT(I != NULL); | 461 ASSERT(I != NULL); |
| 536 ASSERT(I->name() != NULL); | 462 ASSERT(I->name() != NULL); |
| 537 if (!ServiceIsolate::NameEquals(I->name())) { | 463 if (!ServiceIsolate::NameEquals(I->name())) { |
| 538 // Not service isolate. | 464 // Not service isolate. |
| 539 return; | 465 return; |
| 540 } | 466 } |
| 541 if (Exists()) { | 467 if (Exists()) { |
| 542 // Service isolate already exists. | 468 // Service isolate already exists. |
| 543 return; | 469 return; |
| 544 } | 470 } |
| 545 SetServiceIsolate(I); | 471 SetServiceIsolate(I); |
| 546 | |
| 547 StackZone zone(T); | |
| 548 HANDLESCOPE(T); | |
| 549 | |
| 550 // Register dart:vmservice library. | |
| 551 const String& url_str = String::Handle(Z, Symbols::DartVMService().raw()); | |
| 552 const Library& library = Library::Handle(Z, Library::New(url_str)); | |
| 553 library.Register(); | |
| 554 library.set_native_entry_resolver(ServiceNativeResolver); | |
| 555 | |
| 556 // Temporarily install our library tag handler. | |
| 557 I->set_library_tag_handler(LibraryTagHandler); | |
| 558 | |
| 559 // Get script source. | |
| 560 const char* resource = NULL; | |
| 561 const char* path = "/vmservice.dart"; | |
| 562 intptr_t r = Resources::ResourceLookup(path, &resource); | |
| 563 ASSERT(r != Resources::kNoSuchInstance); | |
| 564 ASSERT(resource != NULL); | |
| 565 const String& source_str = String::Handle(Z, | |
| 566 String::FromUTF8(reinterpret_cast<const uint8_t*>(resource), r)); | |
| 567 ASSERT(!source_str.IsNull()); | |
| 568 const Script& script = Script::Handle(Z, | |
| 569 Script::New(url_str, source_str, RawScript::kLibraryTag)); | |
| 570 | |
| 571 // Compile script. | |
| 572 Dart_EnterScope(); // Need to enter scope for tag handler. | |
| 573 library.SetLoadInProgress(); | |
| 574 const Error& error = Error::Handle(Z, Compiler::Compile(library, script)); | |
| 575 if (!error.IsNull()) { | |
| 576 OS::PrintErr("vm-service: Isolate creation error: %s\n", | |
| 577 error.ToErrorCString()); | |
| 578 } | |
| 579 ASSERT(error.IsNull()); | |
| 580 Dart_Handle result = Dart_FinalizeLoading(false); | |
| 581 ASSERT(!Dart_IsError(result)); | |
| 582 Dart_ExitScope(); | |
| 583 | |
| 584 // Uninstall our library tag handler. | |
| 585 I->set_library_tag_handler(NULL); | |
| 586 } | 472 } |
| 587 | 473 |
| 588 | 474 |
| 589 void ServiceIsolate::ConstructExitMessageAndCache(Isolate* I) { | 475 void ServiceIsolate::ConstructExitMessageAndCache(Isolate* I) { |
| 590 // Construct and cache exit message here so we can send it without needing an | 476 // Construct and cache exit message here so we can send it without needing an |
| 591 // isolate. | 477 // isolate. |
| 592 StartIsolateScope iso_scope(I); | 478 StartIsolateScope iso_scope(I); |
| 593 Thread* T = Thread::Current(); | 479 Thread* T = Thread::Current(); |
| 594 ASSERT(I == T->isolate()); | 480 ASSERT(I == T->isolate()); |
| 595 ASSERT(I != NULL); | 481 ASSERT(I != NULL); |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 797 } | 683 } |
| 798 SendServiceExitMessage(); | 684 SendServiceExitMessage(); |
| 799 { | 685 { |
| 800 MonitorLocker ml(monitor_); | 686 MonitorLocker ml(monitor_); |
| 801 while (shutting_down_ && (port_ != ILLEGAL_PORT)) { | 687 while (shutting_down_ && (port_ != ILLEGAL_PORT)) { |
| 802 ml.Wait(); | 688 ml.Wait(); |
| 803 } | 689 } |
| 804 } | 690 } |
| 805 } | 691 } |
| 806 | 692 |
| 807 | |
| 808 Dart_Handle ServiceIsolate::GetSource(const char* name) { | |
| 809 ASSERT(name != NULL); | |
| 810 int i = 0; | |
| 811 while (true) { | |
| 812 const char* path = Resources::Path(i); | |
| 813 if (path == NULL) { | |
| 814 break; | |
| 815 } | |
| 816 ASSERT(*path != '\0'); | |
| 817 // Skip the '/'. | |
| 818 path++; | |
| 819 if (strcmp(name, path) == 0) { | |
| 820 const uint8_t* str = Resources::Resource(i); | |
| 821 intptr_t length = Resources::Length(i); | |
| 822 return Dart_NewStringFromUTF8(str, length); | |
| 823 } | |
| 824 i++; | |
| 825 } | |
| 826 FATAL1("vm-service: Could not find embedded source file: %s ", name); | |
| 827 return Dart_Null(); | |
| 828 } | |
| 829 | |
| 830 | |
| 831 Dart_Handle ServiceIsolate::LibraryTagHandler(Dart_LibraryTag tag, | |
| 832 Dart_Handle library, | |
| 833 Dart_Handle url) { | |
| 834 if (tag == Dart_kCanonicalizeUrl) { | |
| 835 // url is already canonicalized. | |
| 836 return url; | |
| 837 } | |
| 838 if (tag != Dart_kSourceTag) { | |
| 839 FATAL("ServiceIsolate::LibraryTagHandler encountered an unexpected tag."); | |
| 840 } | |
| 841 ASSERT(tag == Dart_kSourceTag); | |
| 842 const char* url_string = NULL; | |
| 843 Dart_Handle result = Dart_StringToCString(url, &url_string); | |
| 844 if (Dart_IsError(result)) { | |
| 845 return result; | |
| 846 } | |
| 847 Dart_Handle source = GetSource(url_string); | |
| 848 if (Dart_IsError(source)) { | |
| 849 return source; | |
| 850 } | |
| 851 return Dart_LoadSource(library, url, source, 0, 0); | |
| 852 } | |
| 853 | |
| 854 } // namespace dart | 693 } // namespace dart |
| OLD | NEW |