| 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 19 matching lines...) Expand all Loading... |
| 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 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) { |
| 35 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); | 35 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); |
| 36 return reinterpret_cast<uint8_t*>(new_ptr); | 36 return reinterpret_cast<uint8_t*>(new_ptr); |
| 37 } | 37 } |
| 38 | 38 |
| 39 | 39 |
| 40 static Dart_Port ExtractPort(Isolate* isolate, Dart_Handle receivePort) { | |
| 41 const ReceivePort& rp = Api::UnwrapReceivePortHandle(isolate, receivePort); | |
| 42 if (rp.IsNull()) { | |
| 43 return ILLEGAL_PORT; | |
| 44 } | |
| 45 return rp.Id(); | |
| 46 } | |
| 47 | |
| 48 | |
| 49 // These must be kept in sync with service/constants.dart | 40 // These must be kept in sync with service/constants.dart |
| 50 #define VM_SERVICE_ISOLATE_EXIT_MESSAGE_ID 0 | 41 #define VM_SERVICE_ISOLATE_EXIT_MESSAGE_ID 0 |
| 51 #define VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID 1 | 42 #define VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID 1 |
| 52 #define VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID 2 | 43 #define VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID 2 |
| 53 | 44 |
| 54 static RawArray* MakeServiceControlMessage(Dart_Port port_id, intptr_t code, | 45 static RawArray* MakeServiceControlMessage(Dart_Port port_id, intptr_t code, |
| 55 const String& name) { | 46 const String& name) { |
| 56 const Array& list = Array::Handle(Array::New(4)); | 47 const Array& list = Array::Handle(Array::New(4)); |
| 57 ASSERT(!list.IsNull()); | 48 ASSERT(!list.IsNull()); |
| 58 const Integer& code_int = Integer::Handle(Integer::New(code)); | 49 const Integer& code_int = Integer::Handle(Integer::New(code)); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 82 Dart_Port ServiceIsolate::load_port_ = ILLEGAL_PORT; | 73 Dart_Port ServiceIsolate::load_port_ = ILLEGAL_PORT; |
| 83 Dart_Port ServiceIsolate::origin_ = ILLEGAL_PORT; | 74 Dart_Port ServiceIsolate::origin_ = ILLEGAL_PORT; |
| 84 Dart_IsolateCreateCallback ServiceIsolate::create_callback_ = NULL; | 75 Dart_IsolateCreateCallback ServiceIsolate::create_callback_ = NULL; |
| 85 uint8_t* ServiceIsolate::exit_message_ = NULL; | 76 uint8_t* ServiceIsolate::exit_message_ = NULL; |
| 86 intptr_t ServiceIsolate::exit_message_length_ = 0; | 77 intptr_t ServiceIsolate::exit_message_length_ = 0; |
| 87 Monitor* ServiceIsolate::monitor_ = NULL; | 78 Monitor* ServiceIsolate::monitor_ = NULL; |
| 88 bool ServiceIsolate::initializing_ = true; | 79 bool ServiceIsolate::initializing_ = true; |
| 89 bool ServiceIsolate::shutting_down_ = false; | 80 bool ServiceIsolate::shutting_down_ = false; |
| 90 | 81 |
| 91 | 82 |
| 92 class RegisterRunningIsolatesVisitor : public IsolateVisitor { | |
| 93 public: | |
| 94 explicit RegisterRunningIsolatesVisitor(Isolate* service_isolate) | |
| 95 : IsolateVisitor(), | |
| 96 register_function_(Function::Handle(service_isolate)), | |
| 97 service_isolate_(service_isolate) { | |
| 98 ASSERT(ServiceIsolate::IsServiceIsolate(Isolate::Current())); | |
| 99 // Get library. | |
| 100 const String& library_url = Symbols::DartVMService(); | |
| 101 ASSERT(!library_url.IsNull()); | |
| 102 const Library& library = | |
| 103 Library::Handle(Library::LookupLibrary(library_url)); | |
| 104 ASSERT(!library.IsNull()); | |
| 105 // Get function. | |
| 106 const String& function_name = | |
| 107 String::Handle(String::New("_registerIsolate")); | |
| 108 ASSERT(!function_name.IsNull()); | |
| 109 register_function_ = library.LookupFunctionAllowPrivate(function_name); | |
| 110 ASSERT(!register_function_.IsNull()); | |
| 111 } | |
| 112 | |
| 113 virtual void VisitIsolate(Isolate* isolate) { | |
| 114 ASSERT(ServiceIsolate::IsServiceIsolate(Isolate::Current())); | |
| 115 if (ServiceIsolate::IsServiceIsolateDescendant(isolate) || | |
| 116 (isolate == Dart::vm_isolate())) { | |
| 117 // We do not register the service (and descendants) or the vm-isolate. | |
| 118 return; | |
| 119 } | |
| 120 // Setup arguments for call. | |
| 121 Dart_Port port_id = isolate->main_port(); | |
| 122 const Integer& port_int = Integer::Handle(Integer::New(port_id)); | |
| 123 ASSERT(!port_int.IsNull()); | |
| 124 const SendPort& send_port = SendPort::Handle(SendPort::New(port_id)); | |
| 125 const String& name = String::Handle(String::New(isolate->name())); | |
| 126 ASSERT(!name.IsNull()); | |
| 127 const Array& args = Array::Handle(Array::New(3)); | |
| 128 ASSERT(!args.IsNull()); | |
| 129 args.SetAt(0, port_int); | |
| 130 args.SetAt(1, send_port); | |
| 131 args.SetAt(2, name); | |
| 132 Object& r = Object::Handle(service_isolate_); | |
| 133 r = DartEntry::InvokeFunction(register_function_, args); | |
| 134 if (FLAG_trace_service) { | |
| 135 OS::Print("vm-service: Isolate %s %" Pd64 " registered.\n", | |
| 136 name.ToCString(), | |
| 137 port_id); | |
| 138 } | |
| 139 ASSERT(!r.IsError()); | |
| 140 } | |
| 141 | |
| 142 private: | |
| 143 Function& register_function_; | |
| 144 Isolate* service_isolate_; | |
| 145 }; | |
| 146 | |
| 147 | |
| 148 | |
| 149 class ServiceIsolateNatives : public AllStatic { | |
| 150 public: | |
| 151 static void SendIsolateServiceMessage(Dart_NativeArguments args) { | |
| 152 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | |
| 153 Thread* thread = arguments->thread(); | |
| 154 StackZone stack_zone(thread); | |
| 155 Zone* zone = stack_zone.GetZone(); // Used by GET_NON_NULL_NATIVE_ARGUMENT. | |
| 156 HANDLESCOPE(thread); | |
| 157 GET_NON_NULL_NATIVE_ARGUMENT(SendPort, sp, arguments->NativeArgAt(0)); | |
| 158 GET_NON_NULL_NATIVE_ARGUMENT(Array, message, arguments->NativeArgAt(1)); | |
| 159 | |
| 160 // Set the type of the OOB message. | |
| 161 message.SetAt(0, Smi::Handle(thread->zone(), | |
| 162 Smi::New(Message::kServiceOOBMsg))); | |
| 163 | |
| 164 // Serialize message. | |
| 165 uint8_t* data = NULL; | |
| 166 MessageWriter writer(&data, &allocator, false); | |
| 167 writer.WriteMessage(message); | |
| 168 | |
| 169 // TODO(turnidge): Throw an exception when the return value is false? | |
| 170 bool result = PortMap::PostMessage( | |
| 171 new Message(sp.Id(), data, writer.BytesWritten(), | |
| 172 Message::kOOBPriority)); | |
| 173 arguments->SetReturn(Bool::Get(result)); | |
| 174 } | |
| 175 | |
| 176 static void SendRootServiceMessage(Dart_NativeArguments args) { | |
| 177 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | |
| 178 Thread* thread = arguments->thread(); | |
| 179 StackZone stack_zone(thread); | |
| 180 Zone* zone = stack_zone.GetZone(); // Used by GET_NON_NULL_NATIVE_ARGUMENT. | |
| 181 HANDLESCOPE(thread); | |
| 182 GET_NON_NULL_NATIVE_ARGUMENT(Array, message, arguments->NativeArgAt(0)); | |
| 183 Service::HandleRootMessage(message); | |
| 184 } | |
| 185 | |
| 186 static void OnStart(Dart_NativeArguments args) { | |
| 187 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | |
| 188 Thread* thread = arguments->thread(); | |
| 189 Isolate* isolate = thread->isolate(); | |
| 190 StackZone zone(thread); | |
| 191 HANDLESCOPE(thread); | |
| 192 { | |
| 193 if (FLAG_trace_service) { | |
| 194 OS::Print("vm-service: Booting dart:vmservice library.\n"); | |
| 195 } | |
| 196 // Boot the dart:vmservice library. | |
| 197 Dart_EnterScope(); | |
| 198 Dart_Handle url_str = | |
| 199 Dart_NewStringFromCString(Symbols::Name(Symbols::kDartVMServiceId)); | |
| 200 Dart_Handle library = Dart_LookupLibrary(url_str); | |
| 201 ASSERT(Dart_IsLibrary(library)); | |
| 202 Dart_Handle result = | |
| 203 Dart_Invoke(library, Dart_NewStringFromCString("boot"), 0, NULL); | |
| 204 ASSERT(!Dart_IsError(result)); | |
| 205 Dart_Port port = ExtractPort(isolate, result); | |
| 206 ASSERT(port != ILLEGAL_PORT); | |
| 207 ServiceIsolate::SetServicePort(port); | |
| 208 Dart_ExitScope(); | |
| 209 } | |
| 210 | |
| 211 { | |
| 212 if (FLAG_trace_service) { | |
| 213 OS::Print("vm-service: Registering running isolates.\n"); | |
| 214 } | |
| 215 // Register running isolates with service. | |
| 216 RegisterRunningIsolatesVisitor register_isolates(isolate); | |
| 217 Isolate::VisitIsolates(®ister_isolates); | |
| 218 } | |
| 219 } | |
| 220 | |
| 221 static void OnExit(Dart_NativeArguments args) { | |
| 222 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | |
| 223 Thread* thread = arguments->thread(); | |
| 224 StackZone zone(thread); | |
| 225 HANDLESCOPE(thread); | |
| 226 { | |
| 227 if (FLAG_trace_service) { | |
| 228 OS::Print("vm-service: processed exit message.\n"); | |
| 229 } | |
| 230 } | |
| 231 } | |
| 232 | |
| 233 static void ListenStream(Dart_NativeArguments args) { | |
| 234 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | |
| 235 Thread* thread = arguments->thread(); | |
| 236 StackZone stack_zone(thread); | |
| 237 Zone* zone = stack_zone.GetZone(); // Used by GET_NON_NULL_NATIVE_ARGUMENT. | |
| 238 HANDLESCOPE(thread); | |
| 239 GET_NON_NULL_NATIVE_ARGUMENT(String, stream_id, arguments->NativeArgAt(0)); | |
| 240 bool result = Service::ListenStream(stream_id.ToCString()); | |
| 241 arguments->SetReturn(Bool::Get(result)); | |
| 242 } | |
| 243 | |
| 244 static void CancelStream(Dart_NativeArguments args) { | |
| 245 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | |
| 246 Thread* thread = arguments->thread(); | |
| 247 StackZone stack_zone(thread); | |
| 248 Zone* zone = stack_zone.GetZone(); // Used by GET_NON_NULL_NATIVE_ARGUMENT. | |
| 249 HANDLESCOPE(thread); | |
| 250 GET_NON_NULL_NATIVE_ARGUMENT(String, stream_id, arguments->NativeArgAt(0)); | |
| 251 Service::CancelStream(stream_id.ToCString()); | |
| 252 } | |
| 253 }; | |
| 254 | |
| 255 | |
| 256 struct ServiceNativeEntry { | |
| 257 const char* name; | |
| 258 int num_arguments; | |
| 259 Dart_NativeFunction function; | |
| 260 }; | |
| 261 | |
| 262 | |
| 263 static ServiceNativeEntry _ServiceNativeEntries[] = { | |
| 264 {"VMService_SendIsolateServiceMessage", 2, | |
| 265 ServiceIsolateNatives::SendIsolateServiceMessage}, | |
| 266 {"VMService_SendRootServiceMessage", 1, | |
| 267 ServiceIsolateNatives::SendRootServiceMessage}, | |
| 268 {"VMService_OnStart", 0, | |
| 269 ServiceIsolateNatives::OnStart }, | |
| 270 {"VMService_OnExit", 0, | |
| 271 ServiceIsolateNatives::OnExit }, | |
| 272 {"VMService_ListenStream", 1, | |
| 273 ServiceIsolateNatives::ListenStream }, | |
| 274 {"VMService_CancelStream", 1, | |
| 275 ServiceIsolateNatives::CancelStream }, | |
| 276 }; | |
| 277 | |
| 278 | |
| 279 Dart_NativeFunction ServiceIsolate::NativeResolver(Dart_Handle name, | |
| 280 int num_arguments, | |
| 281 bool* auto_setup_scope) { | |
| 282 const Object& obj = Object::Handle(Api::UnwrapHandle(name)); | |
| 283 if (!obj.IsString()) { | |
| 284 return NULL; | |
| 285 } | |
| 286 const char* function_name = obj.ToCString(); | |
| 287 ASSERT(function_name != NULL); | |
| 288 ASSERT(auto_setup_scope != NULL); | |
| 289 *auto_setup_scope = true; | |
| 290 intptr_t n = sizeof(_ServiceNativeEntries) / | |
| 291 sizeof(_ServiceNativeEntries[0]); | |
| 292 for (intptr_t i = 0; i < n; i++) { | |
| 293 ServiceNativeEntry entry = _ServiceNativeEntries[i]; | |
| 294 if ((strcmp(function_name, entry.name) == 0) && | |
| 295 (num_arguments == entry.num_arguments)) { | |
| 296 return entry.function; | |
| 297 } | |
| 298 } | |
| 299 return NULL; | |
| 300 } | |
| 301 | |
| 302 | |
| 303 bool ServiceIsolate::NameEquals(const char* name) { | 83 bool ServiceIsolate::NameEquals(const char* name) { |
| 304 ASSERT(name != NULL); | 84 ASSERT(name != NULL); |
| 305 return strcmp(name, kName) == 0; | 85 return strcmp(name, kName) == 0; |
| 306 } | 86 } |
| 307 | 87 |
| 308 | 88 |
| 309 bool ServiceIsolate::Exists() { | 89 bool ServiceIsolate::Exists() { |
| 310 MonitorLocker ml(monitor_); | 90 MonitorLocker ml(monitor_); |
| 311 return isolate_ != NULL; | 91 return isolate_ != NULL; |
| 312 } | 92 } |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 683 } | 463 } |
| 684 SendServiceExitMessage(); | 464 SendServiceExitMessage(); |
| 685 { | 465 { |
| 686 MonitorLocker ml(monitor_); | 466 MonitorLocker ml(monitor_); |
| 687 while (shutting_down_ && (port_ != ILLEGAL_PORT)) { | 467 while (shutting_down_ && (port_ != ILLEGAL_PORT)) { |
| 688 ml.Wait(); | 468 ml.Wait(); |
| 689 } | 469 } |
| 690 } | 470 } |
| 691 } | 471 } |
| 692 | 472 |
| 473 |
| 474 void ServiceIsolate::BootVmServiceLibrary() { |
| 475 const Library& vmservice_library = |
| 476 Library::Handle(Library::LookupLibrary(Symbols::DartVMService())); |
| 477 ASSERT(!vmservice_library.IsNull()); |
| 478 const String& boot_function_name = String::Handle(String::New("boot")); |
| 479 const Function& boot_function = |
| 480 Function::Handle( |
| 481 vmservice_library.LookupFunctionAllowPrivate(boot_function_name)); |
| 482 ASSERT(!boot_function.IsNull()); |
| 483 const Object& result = |
| 484 Object::Handle( |
| 485 DartEntry::InvokeFunction(boot_function, Object::empty_array())); |
| 486 ASSERT(!result.IsNull()); |
| 487 Dart_Port port = ILLEGAL_PORT; |
| 488 if (result.IsReceivePort()) { |
| 489 port = ReceivePort::Cast(result).Id(); |
| 490 } |
| 491 ASSERT(port != ILLEGAL_PORT); |
| 492 ServiceIsolate::SetServicePort(port); |
| 493 } |
| 494 |
| 693 } // namespace dart | 495 } // namespace dart |
| OLD | NEW |