Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: runtime/vm/service.cc

Issue 125103004: Move service into VM (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698