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 |