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 |