OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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.h" | 5 #include "vm/service.h" |
6 | 6 |
7 #include "include/dart_api.h" | |
8 | |
7 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
10 #include "vm/dart_api_impl.h" | |
8 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
9 #include "vm/debugger.h" | 12 #include "vm/debugger.h" |
10 #include "vm/heap_histogram.h" | 13 #include "vm/heap_histogram.h" |
11 #include "vm/isolate.h" | 14 #include "vm/isolate.h" |
12 #include "vm/message.h" | 15 #include "vm/message.h" |
16 #include "vm/native_entry.h" | |
17 #include "vm/native_arguments.h" | |
13 #include "vm/object.h" | 18 #include "vm/object.h" |
14 #include "vm/object_id_ring.h" | 19 #include "vm/object_id_ring.h" |
15 #include "vm/object_store.h" | 20 #include "vm/object_store.h" |
16 #include "vm/port.h" | 21 #include "vm/port.h" |
17 #include "vm/profiler.h" | 22 #include "vm/profiler.h" |
18 | 23 |
24 | |
19 namespace dart { | 25 namespace dart { |
20 | 26 |
21 typedef void (*ServiceMessageHandler)(Isolate* isolate, JSONStream* stream); | 27 struct ResourcesEntry { |
22 | 28 const char* path_; |
23 struct ServiceMessageHandlerEntry { | 29 const char* resource_; |
24 const char* command; | 30 int length_; |
25 ServiceMessageHandler handler; | |
26 }; | 31 }; |
27 | 32 |
28 static ServiceMessageHandler FindServiceMessageHandler(const char* command); | 33 extern ResourcesEntry __service_resources_[]; |
34 | |
35 class Resources { | |
36 public: | |
37 static const int kNoSuchInstance = -1; | |
38 static int ResourceLookup(const char* path, const char** resource) { | |
39 ResourcesEntry* table = ResourceTable(); | |
40 for (int i = 0; table[i].path_ != NULL; i++) { | |
41 const ResourcesEntry& entry = table[i]; | |
42 if (strcmp(path, entry.path_) == 0) { | |
43 *resource = entry.resource_; | |
44 ASSERT(entry.length_ > 0); | |
45 return entry.length_; | |
46 } | |
47 } | |
48 return kNoSuchInstance; | |
49 } | |
50 | |
51 static const char* Path(int idx) { | |
52 ASSERT(idx >= 0); | |
53 ResourcesEntry* entry = At(idx); | |
54 if (entry == NULL) { | |
55 return NULL; | |
56 } | |
57 ASSERT(entry->path_ != NULL); | |
58 return entry->path_; | |
59 } | |
60 | |
61 static const char* Resource(int idx) { | |
62 ASSERT(idx >= 0); | |
63 ResourcesEntry* entry = At(idx); | |
64 if (entry == NULL) { | |
65 return NULL; | |
66 } | |
67 return entry->resource_; | |
68 } | |
69 | |
70 private: | |
71 static ResourcesEntry* At(int idx) { | |
72 ASSERT(idx >= 0); | |
73 ResourcesEntry* table = ResourceTable(); | |
74 for (int i = 0; table[i].path_ != NULL; i++) { | |
75 if (idx == i) { | |
76 return &table[i]; | |
77 } | |
78 } | |
79 return NULL; | |
80 } | |
81 | |
82 static ResourcesEntry* ResourceTable() { | |
83 return &__service_resources_[0]; | |
84 } | |
85 | |
86 DISALLOW_ALLOCATION(); | |
87 DISALLOW_IMPLICIT_CONSTRUCTORS(Resources); | |
88 }; | |
29 | 89 |
30 | 90 |
31 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { | 91 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { |
32 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); | 92 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); |
33 return reinterpret_cast<uint8_t*>(new_ptr); | 93 return reinterpret_cast<uint8_t*>(new_ptr); |
34 } | 94 } |
35 | 95 |
36 | 96 |
97 static void SendServiceMessage(Dart_NativeArguments args) { | |
98 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | |
99 Isolate* isolate = arguments->isolate(); | |
100 StackZone zone(isolate); | |
101 HANDLESCOPE(isolate); | |
102 GET_NON_NULL_NATIVE_ARGUMENT(Instance, sp, arguments->NativeArgAt(0)); | |
103 GET_NON_NULL_NATIVE_ARGUMENT(Instance, message, arguments->NativeArgAt(1)); | |
104 | |
105 // Extract SendPort port id. | |
106 const Object& sp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(sp)); | |
107 if (sp_id_obj.IsError()) { | |
108 Exceptions::PropagateError(Error::Cast(sp_id_obj)); | |
109 } | |
110 Integer& id = Integer::Handle(); | |
111 id ^= sp_id_obj.raw(); | |
112 Dart_Port sp_id = static_cast<Dart_Port>(id.AsInt64Value()); | |
113 ASSERT(sp_id != ILLEGAL_PORT); | |
114 | |
115 // Serialize message. | |
116 uint8_t* data = NULL; | |
117 MessageWriter writer(&data, &allocator); | |
118 writer.WriteMessage(message); | |
119 | |
120 // TODO(turnidge): Throw an exception when the return value is false? | |
121 PortMap::PostMessage(new Message(sp_id, data, writer.BytesWritten(), | |
122 Message::kOOBPriority)); | |
123 } | |
124 | |
125 | |
126 struct VmServiceNativeEntry { | |
127 const char* name; | |
128 int num_arguments; | |
129 Dart_NativeFunction function; | |
130 }; | |
131 | |
132 | |
133 static VmServiceNativeEntry _VmServiceNativeEntries[] = { | |
134 {"VMService_SendServiceMessage", 2, SendServiceMessage} | |
135 }; | |
136 | |
137 | |
138 static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name, | |
139 int num_arguments, | |
140 bool* auto_setup_scope) { | |
141 const Object& obj = Object::Handle(Api::UnwrapHandle(name)); | |
142 if (!obj.IsString()) { | |
143 return NULL; | |
144 } | |
145 const char* function_name = obj.ToCString(); | |
146 ASSERT(function_name != NULL); | |
147 ASSERT(auto_setup_scope != NULL); | |
148 *auto_setup_scope = true; | |
149 intptr_t n = | |
150 sizeof(_VmServiceNativeEntries) / sizeof(_VmServiceNativeEntries[0]); | |
151 for (intptr_t i = 0; i < n; i++) { | |
152 VmServiceNativeEntry entry = _VmServiceNativeEntries[i]; | |
153 if (!strcmp(function_name, entry.name) && | |
154 (num_arguments == entry.num_arguments)) { | |
155 return entry.function; | |
156 } | |
157 } | |
158 return NULL; | |
159 } | |
160 | |
161 #define SHUTDOWN(error_msg) \ | |
162 printf("Service Isolate Error: %s\n", error_msg); \ | |
163 Dart_ExitScope(); \ | |
164 Dart_ShutdownIsolate(); \ | |
165 return NULL | |
166 | |
167 #define SHUTDOWN_ON_ERROR(handle) \ | |
168 if (Dart_IsError(handle)) { \ | |
169 SHUTDOWN(Dart_GetError(handle)); \ | |
170 } | |
171 | |
172 Isolate* Service::service_isolate_ = NULL; | |
173 Dart_LibraryTagHandler Service::default_handler_ = NULL; | |
174 Dart_Port Service::port_ = ILLEGAL_PORT; | |
175 | |
176 Isolate* Service::GetServiceIsolate(void* callback_data) { | |
siva
2014/01/14 18:19:00
I am wondering if we should split this into
Servic
| |
177 if (service_isolate_ != NULL) { | |
178 // Already initialized, return service isolate. | |
179 return service_isolate_; | |
180 } | |
181 Dart_ServiceIsolateCreateCalback create_callback = | |
182 Isolate::ServiceCreateCallback(); | |
183 if (create_callback == NULL) { | |
184 return NULL; | |
185 } | |
186 if (Dart_CurrentIsolate() != NULL) { | |
187 // Clear current isolate. | |
188 Dart_ExitIsolate(); | |
189 } | |
190 char* error = NULL; | |
191 Dart_Isolate isolate = create_callback(callback_data, &error); | |
192 if (isolate == NULL) { | |
193 printf("Service Isolate Error: %s\n", error); | |
194 return NULL; | |
195 } | |
196 Dart_EnterIsolate(isolate); | |
197 Dart_EnterScope(); | |
198 Dart_Handle result; | |
199 Dart_Handle root_library = Dart_RootLibrary(); | |
200 SHUTDOWN_ON_ERROR(root_library); | |
201 ASSERT(root_library == Dart_Null()); | |
202 // Retrieve the embedder default library tag handler. | |
203 default_handler_ = reinterpret_cast<Isolate*>(isolate)->library_tag_handler(); | |
204 ASSERT(default_handler_ != NULL); | |
205 // Temporarily install our own. | |
206 Dart_SetLibraryTagHandler(LibraryTagHandler); | |
207 // Load VM service library. | |
208 Dart_Handle library; | |
209 { | |
210 const char* resource = NULL; | |
211 const char* path = "/vmservice.dart"; | |
212 int r = Resources::ResourceLookup(path, &resource); | |
213 ASSERT(r != Resources::kNoSuchInstance); | |
214 ASSERT(resource != NULL); | |
215 Dart_Handle url = Dart_NewStringFromCString("dart:vmservice"); | |
siva
2014/01/14 18:19:00
We have made symbols of other core dart libraries
| |
216 SHUTDOWN_ON_ERROR(url); | |
217 Dart_Handle source = Dart_NewStringFromCString(resource); | |
siva
2014/01/14 18:19:00
I think this may not be right to treat the dart:vm
| |
218 SHUTDOWN_ON_ERROR(source); | |
219 library = Dart_LoadLibrary(url, source); | |
220 SHUTDOWN_ON_ERROR(library); | |
221 result = Dart_SetNativeResolver(library, VmServiceNativeResolver); | |
222 SHUTDOWN_ON_ERROR(result); | |
223 } | |
224 // Install embedder default library tag handler again. | |
225 Dart_SetLibraryTagHandler(default_handler_); | |
226 default_handler_ = NULL; | |
227 // Boot the service. | |
228 { | |
229 result = Dart_Invoke(library, Dart_NewStringFromCString("boot"), 0, NULL); | |
230 SHUTDOWN_ON_ERROR(result); | |
231 HANDLESCOPE(Isolate::Current()); | |
232 const Object& unwrapped_rp = Object::Handle(Api::UnwrapHandle(result)); | |
233 const Instance& rp = Instance::Cast(unwrapped_rp); | |
234 // Extract RawReceivePort port id. | |
235 const Object& rp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(rp)); | |
236 if (rp_id_obj.IsError()) { | |
237 const Error& error = Error::Cast(rp_id_obj); | |
238 SHUTDOWN(error.ToErrorCString()); | |
239 } | |
240 ASSERT(rp_id_obj.IsSmi() || rp_id_obj.IsMint()); | |
241 const Integer& id = Integer::Cast(rp_id_obj); | |
242 port_ = static_cast<Dart_Port>(id.AsInt64Value()); | |
243 } | |
244 Dart_ExitScope(); | |
245 Dart_ExitIsolate(); | |
246 service_isolate_ = reinterpret_cast<Isolate*>(isolate); | |
247 return service_isolate_; | |
siva
2014/01/14 18:19:00
one general comment about this function, we are in
Cutch
2014/01/14 19:53:26
Done.
| |
248 } | |
249 | |
250 | |
251 // These must be kept in sync with service/constants.dart | |
252 #define VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID 1 | |
253 #define VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID 2 | |
254 | |
255 | |
256 static Dart_Handle MakeServiceControlMessage(Dart_Port port_id, intptr_t code, | |
257 Dart_Handle name) { | |
258 Dart_Handle result; | |
259 Dart_Handle list = Dart_NewList(4); | |
260 ASSERT(!Dart_IsError(list)); | |
261 Dart_Handle code_handle = Dart_NewInteger(code); | |
262 ASSERT(!Dart_IsError(code_handle)); | |
263 result = Dart_ListSetAt(list, 0, code_handle); | |
264 ASSERT(!Dart_IsError(result)); | |
265 Dart_Handle port_id_handle = Dart_NewInteger(port_id); | |
266 ASSERT(!Dart_IsError(port_id_handle)); | |
267 result = Dart_ListSetAt(list, 1, port_id_handle); | |
268 ASSERT(!Dart_IsError(result)); | |
269 Dart_Handle sendPort = Dart_NewSendPort(port_id); | |
270 ASSERT(!Dart_IsError(sendPort)); | |
271 result = Dart_ListSetAt(list, 2, sendPort); | |
272 ASSERT(!Dart_IsError(result)); | |
273 result = Dart_ListSetAt(list, 3, name); | |
274 ASSERT(!Dart_IsError(result)); | |
275 return list; | |
siva
2014/01/14 18:19:00
Same comment about this function it could be plain
Cutch
2014/01/14 19:53:26
Done.
| |
276 } | |
277 | |
278 | |
279 bool Service::SendIsolateStartupMessage() { | |
280 if (!IsRunning()) { | |
281 return false; | |
282 } | |
283 Isolate* isolate = Isolate::Current(); | |
284 ASSERT(isolate != NULL); | |
285 HANDLESCOPE(isolate); | |
286 Dart_EnterScope(); | |
287 Dart_Handle name = Api::NewHandle(isolate, String::New(isolate->name())); | |
288 ASSERT(!Dart_IsError(name)); | |
289 Dart_Handle list = | |
290 MakeServiceControlMessage(Dart_GetMainPortId(), | |
291 VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID, | |
292 name); | |
293 ASSERT(!Dart_IsError(list)); | |
294 bool r = Dart_Post(port_, list); | |
295 Dart_ExitScope(); | |
296 return r; | |
297 } | |
298 | |
299 | |
300 bool Service::SendIsolateShutdownMessage() { | |
301 if (!IsRunning()) { | |
302 return false; | |
303 } | |
304 Isolate* isolate = Isolate::Current(); | |
305 ASSERT(isolate != NULL); | |
306 HANDLESCOPE(isolate); | |
307 Dart_EnterScope(); | |
308 Dart_Handle list = | |
309 MakeServiceControlMessage(Dart_GetMainPortId(), | |
310 VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID, | |
311 Dart_Null()); | |
312 ASSERT(!Dart_IsError(list)); | |
313 bool r = Dart_Post(port_, list); | |
314 Dart_ExitScope(); | |
315 return r; | |
316 } | |
317 | |
318 | |
319 bool Service::IsRunning() { | |
320 return port_ != ILLEGAL_PORT; | |
321 } | |
322 | |
323 | |
324 Dart_Handle Service::GetSource(const char* name) { | |
325 ASSERT(name != NULL); | |
326 int i = 0; | |
327 while (true) { | |
328 const char* path = Resources::Path(i); | |
329 if (path == NULL) { | |
330 break; | |
331 } | |
332 ASSERT(*path != '\0'); | |
333 // Skip the '/'. | |
334 path++; | |
335 if (strcmp(name, path) == 0) { | |
336 return Dart_NewStringFromCString(Resources::Resource(i)); | |
337 } | |
338 i++; | |
339 } | |
340 return Dart_Null(); | |
341 } | |
342 | |
343 | |
344 Dart_Handle Service::LibraryTagHandler(Dart_LibraryTag tag, Dart_Handle library, | |
345 Dart_Handle url) { | |
346 if (!Dart_IsLibrary(library)) { | |
347 return Dart_NewApiError("not a library"); | |
348 } | |
349 if (!Dart_IsString(url)) { | |
350 return Dart_NewApiError("url is not a string"); | |
351 } | |
352 const char* url_string = NULL; | |
353 Dart_Handle result = Dart_StringToCString(url, &url_string); | |
354 if (Dart_IsError(result)) { | |
355 return result; | |
356 } | |
357 if (tag == Dart_kImportTag) { | |
358 // Embedder handles all requests for external libraries. | |
359 ASSERT(default_handler_ != NULL); | |
360 return default_handler_(tag, library, url); | |
361 } | |
362 ASSERT((tag == Dart_kSourceTag) || (tag == Dart_kCanonicalizeUrl)); | |
363 if (tag == Dart_kCanonicalizeUrl) { | |
364 // url is already canonicalized. | |
365 return url; | |
366 } | |
367 Dart_Handle source = GetSource(url_string); | |
368 if (Dart_IsError(source)) { | |
369 return source; | |
370 } | |
371 return Dart_LoadSource(library, url, source); | |
372 } | |
373 | |
374 | |
375 typedef void (*ServiceMessageHandler)(Isolate* isolate, JSONStream* stream); | |
376 | |
377 struct ServiceMessageHandlerEntry { | |
378 const char* command; | |
379 ServiceMessageHandler handler; | |
380 }; | |
381 | |
382 static ServiceMessageHandler FindServiceMessageHandler(const char* command); | |
383 | |
37 static void PostReply(const String& reply, const Instance& reply_port) { | 384 static void PostReply(const String& reply, const Instance& reply_port) { |
38 const Object& id_obj = Object::Handle( | 385 const Object& id_obj = Object::Handle( |
39 DartLibraryCalls::PortGetId(reply_port)); | 386 DartLibraryCalls::PortGetId(reply_port)); |
40 if (id_obj.IsError()) { | 387 if (id_obj.IsError()) { |
41 Exceptions::PropagateError(Error::Cast(id_obj)); | 388 Exceptions::PropagateError(Error::Cast(id_obj)); |
42 } | 389 } |
43 const Integer& id = Integer::Cast(id_obj); | 390 const Integer& id = Integer::Cast(id_obj); |
44 Dart_Port port = static_cast<Dart_Port>(id.AsInt64Value()); | 391 Dart_Port port = static_cast<Dart_Port>(id.AsInt64Value()); |
45 ASSERT(port != ILLEGAL_PORT); | 392 ASSERT(port != ILLEGAL_PORT); |
46 | 393 |
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
649 for (intptr_t i = 0; i < num_message_handlers; i++) { | 996 for (intptr_t i = 0; i < num_message_handlers; i++) { |
650 const ServiceMessageHandlerEntry& entry = __message_handlers[i]; | 997 const ServiceMessageHandlerEntry& entry = __message_handlers[i]; |
651 if (!strcmp(command, entry.command)) { | 998 if (!strcmp(command, entry.command)) { |
652 return entry.handler; | 999 return entry.handler; |
653 } | 1000 } |
654 } | 1001 } |
655 return HandleFallthrough; | 1002 return HandleFallthrough; |
656 } | 1003 } |
657 | 1004 |
658 } // namespace dart | 1005 } // namespace dart |
OLD | NEW |