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 = get_resources_table(); | |
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* get_resource_path(int idx) { | |
siva
2014/01/10 00:01:54
ditto comments about the function names as they ar
Cutch
2014/01/10 21:01:42
Done.
| |
52 ASSERT(idx >= 0); | |
53 ResourcesEntry* entry = get_resource_entry(idx); | |
54 if (entry == NULL) { | |
55 return NULL; | |
56 } | |
57 return entry->path_; | |
58 } | |
59 | |
60 static const char* get_resource_resource(int idx) { | |
61 ASSERT(idx >= 0); | |
62 ResourcesEntry* entry = get_resource_entry(idx); | |
63 if (entry == NULL) { | |
64 return NULL; | |
65 } | |
66 return entry->resource_; | |
67 } | |
68 | |
69 private: | |
70 static ResourcesEntry* get_resource_entry(int idx) { | |
71 ASSERT(idx >= 0); | |
72 ResourcesEntry* table = get_resources_table(); | |
73 for (int i = 0; table[i].path_ != NULL; i++) { | |
74 if (idx == i) { | |
75 return &table[i]; | |
76 } | |
77 } | |
78 return NULL; | |
79 } | |
80 | |
81 static ResourcesEntry* get_resources_table() { | |
82 return &__service_resources_[0]; | |
83 } | |
84 | |
85 DISALLOW_ALLOCATION(); | |
86 DISALLOW_IMPLICIT_CONSTRUCTORS(Resources); | |
87 }; | |
29 | 88 |
30 | 89 |
31 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { | 90 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); | 91 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); |
33 return reinterpret_cast<uint8_t*>(new_ptr); | 92 return reinterpret_cast<uint8_t*>(new_ptr); |
34 } | 93 } |
35 | 94 |
36 | 95 |
96 static void SendServiceMessage(Dart_NativeArguments args) { | |
97 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | |
98 Isolate* isolate = arguments->isolate(); | |
99 StackZone zone(isolate); | |
100 HANDLESCOPE(isolate); | |
101 GET_NON_NULL_NATIVE_ARGUMENT(Instance, sp, arguments->NativeArgAt(0)); | |
102 GET_NON_NULL_NATIVE_ARGUMENT(Instance, message, arguments->NativeArgAt(1)); | |
103 | |
104 // Extract SendPort port id. | |
105 const Object& sp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(sp)); | |
106 if (sp_id_obj.IsError()) { | |
107 Exceptions::PropagateError(Error::Cast(sp_id_obj)); | |
108 } | |
109 Integer& id = Integer::Handle(); | |
110 id ^= sp_id_obj.raw(); | |
111 Dart_Port sp_id = static_cast<Dart_Port>(id.AsInt64Value()); | |
112 ASSERT(sp_id != ILLEGAL_PORT); | |
113 | |
114 // Serialize message. | |
115 uint8_t* data = NULL; | |
116 MessageWriter writer(&data, &allocator); | |
117 writer.WriteMessage(message); | |
118 | |
119 // TODO(turnidge): Throw an exception when the return value is false? | |
120 PortMap::PostMessage(new Message(sp_id, data, writer.BytesWritten(), | |
121 Message::kOOBPriority)); | |
122 } | |
123 | |
124 | |
125 struct VmServiceNativeEntry { | |
126 const char* name; | |
127 int num_arguments; | |
128 Dart_NativeFunction function; | |
129 }; | |
130 | |
131 | |
132 static VmServiceNativeEntry _VmServiceNativeEntries[] = { | |
133 {"VMService_SendServiceMessage", 2, SendServiceMessage} | |
134 }; | |
135 | |
136 | |
137 static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name, | |
138 int num_arguments, | |
139 bool* auto_setup_scope) { | |
140 const Object& obj = Object::Handle(Api::UnwrapHandle(name)); | |
141 if (!obj.IsString()) { | |
142 return NULL; | |
143 } | |
144 const char* function_name = obj.ToCString(); | |
145 ASSERT(function_name != NULL); | |
146 ASSERT(auto_setup_scope != NULL); | |
147 *auto_setup_scope = true; | |
148 intptr_t n = | |
149 sizeof(_VmServiceNativeEntries) / sizeof(_VmServiceNativeEntries[0]); | |
150 for (intptr_t i = 0; i < n; i++) { | |
151 VmServiceNativeEntry entry = _VmServiceNativeEntries[i]; | |
152 if (!strcmp(function_name, entry.name) && | |
153 (num_arguments == entry.num_arguments)) { | |
154 return entry.function; | |
155 } | |
156 } | |
siva
2014/01/10 00:01:54
There is only one entry in the table does it need
Cutch
2014/01/10 21:01:42
There will be more natives later. Todd has a CL wh
| |
157 return NULL; | |
158 } | |
159 | |
160 #define SHUTDOWN(error_msg) \ | |
161 printf("Service Isolate Error: %s\n", error_msg); \ | |
162 Dart_ExitScope(); \ | |
163 Dart_ShutdownIsolate(); \ | |
164 return NULL | |
165 | |
166 #define SHUTDOWN_ON_ERROR(handle) \ | |
167 if (Dart_IsError(handle)) { \ | |
168 SHUTDOWN(Dart_GetError(handle)); \ | |
169 } | |
170 | |
171 Isolate* Service::service_isolate_ = NULL; | |
172 Dart_LibraryTagHandler Service::default_handler_ = NULL; | |
173 Dart_Port Service::port_ = ILLEGAL_PORT; | |
174 | |
175 Isolate* Service::GetServiceIsolate(void* callback_data) { | |
176 if (service_isolate_ != NULL) { | |
177 // Already initialized, return service isolate. | |
178 return service_isolate_; | |
179 } | |
siva
2014/01/10 00:01:54
What happens if multiple threads from the embedder
Cutch
2014/01/10 21:01:42
Good point. Do we make thread safety guarantees ab
| |
180 Dart_ServiceIsolateCreateCallback create_callback = | |
181 Isolate::ServiceCreateCallback(); | |
182 if (create_callback == NULL) { | |
183 return NULL; | |
184 } | |
185 if (Dart_CurrentIsolate() != NULL) { | |
186 // Clear current isolate. | |
187 Dart_ExitIsolate(); | |
188 } | |
189 char* error = NULL; | |
190 Dart_Isolate isolate = create_callback(callback_data, &error); | |
191 if (isolate == NULL) { | |
192 printf("Service Isolate Error: %s\n", error); | |
193 return NULL; | |
194 } | |
195 Dart_EnterIsolate(isolate); | |
196 Dart_EnterScope(); | |
197 Dart_Handle result; | |
198 Dart_Handle root_library = Dart_RootLibrary(); | |
199 SHUTDOWN_ON_ERROR(root_library); | |
200 ASSERT(root_library == Dart_Null()); | |
201 // Retrieve the embedder default library tag handler. | |
202 default_handler_ = reinterpret_cast<Isolate*>(isolate)->library_tag_handler(); | |
203 ASSERT(default_handler_ != NULL); | |
204 // Temporarily install our own. | |
205 Dart_SetLibraryTagHandler(LibraryTagHandler); | |
206 // Load VM service library. | |
207 Dart_Handle library; | |
208 { | |
209 const char* resource = NULL; | |
210 const char* path = "/vmservice.dart"; | |
211 int r = Resources::ResourceLookup(path, &resource); | |
212 ASSERT(r != Resources::kNoSuchInstance); | |
213 ASSERT(resource != NULL); | |
214 Dart_Handle url = Dart_NewStringFromCString("dart:vmservice"); | |
215 SHUTDOWN_ON_ERROR(url); | |
216 Dart_Handle source = Dart_NewStringFromCString(resource); | |
217 SHUTDOWN_ON_ERROR(source); | |
218 library = Dart_LoadLibrary(url, source); | |
219 SHUTDOWN_ON_ERROR(library); | |
220 result = Dart_SetNativeResolver(library, VmServiceNativeResolver); | |
221 SHUTDOWN_ON_ERROR(result); | |
222 } | |
223 // Install embedder default library tag handler again. | |
224 Dart_SetLibraryTagHandler(default_handler_); | |
225 default_handler_ = NULL; | |
226 // Boot the service. | |
227 { | |
228 result = Dart_Invoke(library, Dart_NewStringFromCString("boot"), 0, NULL); | |
229 SHUTDOWN_ON_ERROR(result); | |
230 HANDLESCOPE(Isolate::Current()); | |
231 const Object& unwrapped_rp = Object::Handle(Api::UnwrapHandle(result)); | |
232 const Instance& rp = Instance::Cast(unwrapped_rp); | |
233 // Extract RawReceivePort port id. | |
234 const Object& rp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(rp)); | |
235 if (rp_id_obj.IsError()) { | |
236 const Error& error = Error::Cast(rp_id_obj); | |
237 SHUTDOWN(error.ToErrorCString()); | |
238 } | |
239 ASSERT(rp_id_obj.IsSmi() || rp_id_obj.IsMint()); | |
240 Integer& id = Integer::Handle(); | |
241 id ^= rp_id_obj.raw(); | |
siva
2014/01/10 00:01:54
Since you are asserting that rp_id_obj is a Smi or
Cutch
2014/01/10 21:01:42
Done.
| |
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_; | |
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; | |
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::get_resource_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::get_resource_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 Dart_Handle library_url = Dart_LibraryUrl(library); | |
358 const char* library_url_string = NULL; | |
359 result = Dart_StringToCString(library_url, &library_url_string); | |
360 if (Dart_IsError(result)) { | |
361 return result; | |
362 } | |
siva
2014/01/10 00:01:54
What is the conversion to C string library_url_str
Cutch
2014/01/10 21:01:42
Done.
| |
363 if (tag == Dart_kImportTag) { | |
364 // Embedder handles all requests for external libraries. | |
365 ASSERT(default_handler_ != NULL); | |
366 return default_handler_(tag, library, url); | |
367 } | |
368 ASSERT((tag == Dart_kSourceTag) || (tag == Dart_kCanonicalizeUrl)); | |
369 if (tag == Dart_kCanonicalizeUrl) { | |
370 // url is already canonicalized. | |
371 return url; | |
372 } | |
373 Dart_Handle source = GetSource(url_string); | |
374 if (Dart_IsError(source)) { | |
375 return source; | |
376 } | |
377 return Dart_LoadSource(library, url, source); | |
378 } | |
379 | |
380 | |
381 typedef void (*ServiceMessageHandler)(Isolate* isolate, JSONStream* stream); | |
382 | |
383 struct ServiceMessageHandlerEntry { | |
384 const char* command; | |
385 ServiceMessageHandler handler; | |
386 }; | |
387 | |
388 static ServiceMessageHandler FindServiceMessageHandler(const char* command); | |
389 | |
37 static void PostReply(const String& reply, const Instance& reply_port) { | 390 static void PostReply(const String& reply, const Instance& reply_port) { |
38 const Object& id_obj = Object::Handle( | 391 const Object& id_obj = Object::Handle( |
39 DartLibraryCalls::PortGetId(reply_port)); | 392 DartLibraryCalls::PortGetId(reply_port)); |
40 if (id_obj.IsError()) { | 393 if (id_obj.IsError()) { |
41 Exceptions::PropagateError(Error::Cast(id_obj)); | 394 Exceptions::PropagateError(Error::Cast(id_obj)); |
42 } | 395 } |
43 const Integer& id = Integer::Cast(id_obj); | 396 const Integer& id = Integer::Cast(id_obj); |
44 Dart_Port port = static_cast<Dart_Port>(id.AsInt64Value()); | 397 Dart_Port port = static_cast<Dart_Port>(id.AsInt64Value()); |
45 ASSERT(port != ILLEGAL_PORT); | 398 ASSERT(port != ILLEGAL_PORT); |
46 | 399 |
(...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
649 for (intptr_t i = 0; i < num_message_handlers; i++) { | 1002 for (intptr_t i = 0; i < num_message_handlers; i++) { |
650 const ServiceMessageHandlerEntry& entry = __message_handlers[i]; | 1003 const ServiceMessageHandlerEntry& entry = __message_handlers[i]; |
651 if (!strcmp(command, entry.command)) { | 1004 if (!strcmp(command, entry.command)) { |
652 return entry.handler; | 1005 return entry.handler; |
653 } | 1006 } |
654 } | 1007 } |
655 return HandleFallthrough; | 1008 return HandleFallthrough; |
656 } | 1009 } |
657 | 1010 |
658 } // namespace dart | 1011 } // namespace dart |
OLD | NEW |