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 "bin/vmservice_impl.h" | 5 #include "bin/vmservice_impl.h" |
6 | 6 |
7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
8 | 8 |
9 #include "bin/builtin.h" | 9 #include "bin/builtin.h" |
10 #include "bin/dartutils.h" | 10 #include "bin/dartutils.h" |
11 #include "bin/isolate_data.h" | 11 #include "bin/isolate_data.h" |
12 #include "bin/resources.h" | |
13 #include "bin/thread.h" | 12 #include "bin/thread.h" |
14 | 13 |
15 #include "vm/dart_api_impl.h" | |
16 #include "vm/dart_entry.h" | |
17 #include "vm/isolate.h" | |
18 #include "vm/message.h" | |
19 #include "vm/native_entry.h" | |
20 #include "vm/native_arguments.h" | |
21 #include "vm/object.h" | |
22 #include "vm/port.h" | |
23 #include "vm/snapshot.h" | |
24 | |
25 namespace dart { | 14 namespace dart { |
26 namespace bin { | 15 namespace bin { |
27 | 16 |
28 // snapshot_buffer points to a snapshot if we link in a snapshot otherwise | |
29 // it is initialized to NULL. | |
30 extern const uint8_t* snapshot_buffer; | |
31 #define RETURN_ERROR_HANDLE(handle) \ | 17 #define RETURN_ERROR_HANDLE(handle) \ |
32 if (Dart_IsError(handle)) { \ | 18 if (Dart_IsError(handle)) { \ |
33 return handle; \ | 19 return handle; \ |
34 } | 20 } |
35 | 21 |
36 #define SHUTDOWN_ON_ERROR(handle) \ | 22 #define SHUTDOWN_ON_ERROR(handle) \ |
37 if (Dart_IsError(handle)) { \ | 23 if (Dart_IsError(handle)) { \ |
38 error_msg_ = strdup(Dart_GetError(handle)); \ | 24 error_msg_ = strdup(Dart_GetError(handle)); \ |
39 Dart_ExitScope(); \ | 25 Dart_ExitScope(); \ |
40 Dart_ShutdownIsolate(); \ | 26 Dart_ShutdownIsolate(); \ |
41 return false; \ | 27 return false; \ |
42 } | 28 } |
43 | 29 |
44 #define kLibraryResourceNamePrefix "/vmservice" | 30 #define kLibrarySourceNamePrefix "/vmservice" |
45 static const char* kVMServiceIOLibraryScriptResourceName = | 31 static const char* kVMServiceIOLibraryScriptResourceName = "vmservice_io.dart"; |
46 kLibraryResourceNamePrefix "/vmservice_io.dart"; | |
47 static const char* kVMServiceLibraryName = | |
48 kLibraryResourceNamePrefix "/vmservice.dart"; | |
49 | |
50 #define kClientResourceNamePrefix "/vmservice/client/deployed/web" | 32 #define kClientResourceNamePrefix "/vmservice/client/deployed/web" |
51 | 33 |
52 Dart_Isolate VmService::isolate_ = NULL; | 34 struct ResourcesEntry { |
53 Dart_Port VmService::port_ = ILLEGAL_PORT; | 35 const char* path_; |
54 dart::Monitor* VmService::monitor_ = NULL; | 36 const char* resource_; |
| 37 int length_; |
| 38 }; |
| 39 |
| 40 extern ResourcesEntry __service_bin_resources_[]; |
| 41 |
| 42 class Resources { |
| 43 public: |
| 44 static const int kNoSuchInstance = -1; |
| 45 static int ResourceLookup(const char* path, const char** resource) { |
| 46 ResourcesEntry* table = ResourcesTable(); |
| 47 for (int i = 0; table[i].path_ != NULL; i++) { |
| 48 const ResourcesEntry& entry = table[i]; |
| 49 if (strcmp(path, entry.path_) == 0) { |
| 50 *resource = entry.resource_; |
| 51 ASSERT(entry.length_ > 0); |
| 52 return entry.length_; |
| 53 } |
| 54 } |
| 55 return kNoSuchInstance; |
| 56 } |
| 57 |
| 58 static const char* Path(int idx) { |
| 59 ASSERT(idx >= 0); |
| 60 ResourcesEntry* entry = At(idx); |
| 61 if (entry == NULL) { |
| 62 return NULL; |
| 63 } |
| 64 ASSERT(entry->path_ != NULL); |
| 65 return entry->path_; |
| 66 } |
| 67 |
| 68 private: |
| 69 static ResourcesEntry* At(int idx) { |
| 70 ASSERT(idx >= 0); |
| 71 ResourcesEntry* table = ResourcesTable(); |
| 72 for (int i = 0; table[i].path_ != NULL; i++) { |
| 73 if (idx == i) { |
| 74 return &table[i]; |
| 75 } |
| 76 } |
| 77 return NULL; |
| 78 } |
| 79 static ResourcesEntry* ResourcesTable() { |
| 80 return &__service_bin_resources_[0]; |
| 81 } |
| 82 |
| 83 DISALLOW_ALLOCATION(); |
| 84 DISALLOW_IMPLICIT_CONSTRUCTORS(Resources); |
| 85 }; |
| 86 |
55 const char* VmService::error_msg_ = NULL; | 87 const char* VmService::error_msg_ = NULL; |
56 | 88 |
57 // These must be kept in sync with vmservice/constants.dart | |
58 #define VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID 1 | |
59 #define VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID 2 | |
60 | |
61 | |
62 static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name, | |
63 int num_arguments, | |
64 bool* auto_setup_scope); | |
65 | |
66 | |
67 bool VmService::Start(intptr_t server_port) { | 89 bool VmService::Start(intptr_t server_port) { |
68 monitor_ = new dart::Monitor(); | 90 bool r = _Start(server_port); |
69 ASSERT(monitor_ != NULL); | 91 if (!r) { |
70 error_msg_ = NULL; | 92 return r; |
71 | |
72 | |
73 { | |
74 // Take lock before spawning new thread. | |
75 MonitorLocker ml(monitor_); | |
76 // Spawn new thread. | |
77 dart::Thread::Start(ThreadMain, server_port); | |
78 // Wait until service is running on spawned thread. | |
79 ml.Wait(); | |
80 } | 93 } |
81 return port_ != ILLEGAL_PORT; | 94 // Start processing messages in a new thread. |
| 95 dart::Thread::Start(ThreadMain, NULL); |
| 96 return true; |
82 } | 97 } |
83 | 98 |
84 | 99 |
85 bool VmService::_Start(intptr_t server_port) { | 100 bool VmService::_Start(intptr_t server_port) { |
86 ASSERT(isolate_ == NULL); | 101 ASSERT(Dart_CurrentIsolate() == NULL); |
87 char* error = NULL; | 102 Dart_Isolate isolate = Dart_GetServiceIsolate(NULL); |
88 const char* script_uri = "vmservice:"; | 103 if (isolate == NULL) { |
89 IsolateData* isolate_data = new IsolateData(script_uri); | 104 error_msg_ = "Internal error."; |
90 isolate_ = Dart_CreateIsolate(script_uri, "main", snapshot_buffer, | |
91 isolate_data, | |
92 &error); | |
93 if (isolate_ == NULL) { | |
94 error_msg_ = error; | |
95 return false; | 105 return false; |
96 } | 106 } |
97 | 107 Dart_EnterIsolate(isolate); |
98 Dart_EnterScope(); | 108 Dart_EnterScope(); |
99 | 109 // Install our own library tag handler. |
100 if (snapshot_buffer != NULL) { | 110 Dart_SetLibraryTagHandler(LibraryTagHandler); |
101 // Setup the native resolver as the snapshot does not carry it. | 111 Dart_Handle result; |
102 Builtin::SetNativeResolver(Builtin::kBuiltinLibrary); | 112 Dart_Handle library = LoadScript(kVMServiceIOLibraryScriptResourceName); |
103 Builtin::SetNativeResolver(Builtin::kIOLibrary); | 113 // Expect a library. |
104 } | 114 ASSERT(library != Dart_Null()); |
105 | 115 SHUTDOWN_ON_ERROR(library); |
106 // Set up the library tag handler for this isolate. | |
107 Dart_Handle result = Dart_SetLibraryTagHandler(LibraryTagHandler); | |
108 SHUTDOWN_ON_ERROR(result); | |
109 | |
110 // Load the specified application script into the newly created isolate. | |
111 | |
112 // Prepare builtin and its dependent libraries for use to resolve URIs. | |
113 // The builtin library is part of the core snapshot and would already be | |
114 // available here in the case of script snapshot loading. | |
115 Dart_Handle builtin_lib = | |
116 Builtin::LoadAndCheckLibrary(Builtin::kBuiltinLibrary); | |
117 SHUTDOWN_ON_ERROR(builtin_lib); | |
118 | |
119 // Prepare for script loading by setting up the 'print' and 'timer' | |
120 // closures and setting up 'package root' for URI resolution. | |
121 result = DartUtils::PrepareForScriptLoading("", builtin_lib); | |
122 SHUTDOWN_ON_ERROR(result); | |
123 | |
124 { | |
125 // Load source into service isolate. | |
126 Dart_Handle library = LoadScript(kVMServiceIOLibraryScriptResourceName); | |
127 SHUTDOWN_ON_ERROR(library); | |
128 } | |
129 | |
130 // Make the isolate runnable so that it is ready to handle messages. | |
131 Dart_ExitScope(); | 116 Dart_ExitScope(); |
132 Dart_ExitIsolate(); | 117 Dart_ExitIsolate(); |
133 | 118 bool retval = Dart_IsolateMakeRunnable(isolate); |
134 bool retval = Dart_IsolateMakeRunnable(isolate_); | |
135 if (!retval) { | 119 if (!retval) { |
136 Dart_EnterIsolate(isolate_); | 120 Dart_EnterIsolate(isolate); |
137 Dart_ShutdownIsolate(); | 121 Dart_ShutdownIsolate(); |
138 error_msg_ = "Invalid isolate state - Unable to make it runnable."; | 122 error_msg_ = "Invalid isolate state - Unable to make it runnable."; |
139 return false; | 123 return false; |
140 } | 124 } |
141 | 125 |
142 Dart_EnterIsolate(isolate_); | 126 Dart_EnterIsolate(isolate); |
143 Dart_EnterScope(); | 127 Dart_EnterScope(); |
144 | 128 library = Dart_RootLibrary(); |
145 | |
146 Dart_Handle library = Dart_RootLibrary(); | |
147 // Set requested TCP port. | 129 // Set requested TCP port. |
148 DartUtils::SetIntegerField(library, "_port", server_port); | 130 DartUtils::SetIntegerField(library, "_port", server_port); |
149 result = Dart_Invoke(library, DartUtils::NewString("main"), 0, NULL); | 131 result = Dart_Invoke(library, DartUtils::NewString("main"), 0, NULL); |
150 SHUTDOWN_ON_ERROR(result); | 132 SHUTDOWN_ON_ERROR(result); |
151 | 133 // Load resources. |
152 // Retrieve the ReceivePort that the service is waiting on. The _receivePort | |
153 // variable is setup in the call to main. | |
154 Dart_Handle receivePort = Dart_GetField(library, | |
155 DartUtils::NewString("_receivePort")); | |
156 SHUTDOWN_ON_ERROR(receivePort); | |
157 | |
158 { | |
159 // Extract the Dart_Port from the receive port. | |
160 HANDLESCOPE(Isolate::Current()); | |
161 const Object& unwrapped_rp = Object::Handle(Api::UnwrapHandle(receivePort)); | |
162 const Instance& rp = Instance::Cast(unwrapped_rp); | |
163 // Extract ReceivePort port id. | |
164 const Object& rp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(rp)); | |
165 if (rp_id_obj.IsError()) { | |
166 const Error& error = Error::Cast(rp_id_obj); | |
167 error_msg_ = strdup(error.ToErrorCString()); | |
168 Dart_ExitScope(); | |
169 Dart_ShutdownIsolate(); | |
170 return false; | |
171 } | |
172 ASSERT(rp_id_obj.IsSmi() || rp_id_obj.IsMint()); | |
173 Integer& id = Integer::Handle(); | |
174 id ^= rp_id_obj.raw(); | |
175 port_ = static_cast<Dart_Port>(id.AsInt64Value()); | |
176 } | |
177 | |
178 Dart_Handle library_name = Dart_NewStringFromCString(kVMServiceLibraryName); | |
179 library = Dart_LookupLibrary(library_name); | |
180 SHUTDOWN_ON_ERROR(library); | |
181 result = LoadResources(library); | 134 result = LoadResources(library); |
182 SHUTDOWN_ON_ERROR(result); | 135 SHUTDOWN_ON_ERROR(result); |
183 | 136 |
184 Dart_ExitScope(); | 137 Dart_ExitScope(); |
185 Dart_ExitIsolate(); | 138 Dart_ExitIsolate(); |
186 | 139 |
187 return true; | 140 return true; |
188 } | 141 } |
189 | 142 |
190 | 143 |
191 void VmService::_Stop() { | |
192 port_ = ILLEGAL_PORT; | |
193 } | |
194 | |
195 | |
196 const char* VmService::GetErrorMessage() { | 144 const char* VmService::GetErrorMessage() { |
197 return error_msg_ == NULL ? "No error." : error_msg_; | 145 return error_msg_ == NULL ? "No error." : error_msg_; |
198 } | 146 } |
199 | 147 |
200 | 148 |
201 Dart_Port VmService::port() { | |
202 return port_; | |
203 } | |
204 | |
205 | |
206 bool VmService::IsRunning() { | |
207 return port_ != ILLEGAL_PORT; | |
208 } | |
209 | |
210 | |
211 Dart_Handle VmService::GetSource(const char* name) { | 149 Dart_Handle VmService::GetSource(const char* name) { |
| 150 const intptr_t kBufferSize = 512; |
| 151 char buffer[kBufferSize]; |
| 152 snprintf(&buffer[0], kBufferSize-1, "%s/%s", kLibrarySourceNamePrefix, name); |
212 const char* vmservice_source = NULL; | 153 const char* vmservice_source = NULL; |
213 int r = Resources::ResourceLookup(name, &vmservice_source); | 154 int r = Resources::ResourceLookup(buffer, &vmservice_source); |
214 ASSERT(r != Resources::kNoSuchInstance); | 155 ASSERT(r != Resources::kNoSuchInstance); |
215 return Dart_NewStringFromCString(vmservice_source); | 156 return Dart_NewStringFromCString(vmservice_source); |
216 } | 157 } |
217 | 158 |
218 | 159 |
219 Dart_Handle VmService::LoadScript(const char* name) { | 160 Dart_Handle VmService::LoadScript(const char* name) { |
220 Dart_Handle url = Dart_NewStringFromCString(name); | 161 Dart_Handle url = Dart_NewStringFromCString("dart:vmservice_io"); |
221 Dart_Handle source = GetSource(name); | 162 Dart_Handle source = GetSource(name); |
222 return Dart_LoadScript(url, source, 0, 0); | 163 return Dart_LoadScript(url, source, 0, 0); |
223 } | 164 } |
224 | 165 |
225 | 166 |
226 Dart_Handle VmService::LoadSource(Dart_Handle library, const char* name) { | 167 Dart_Handle VmService::LoadSource(Dart_Handle library, const char* name) { |
227 Dart_Handle url = Dart_NewStringFromCString(name); | 168 Dart_Handle url = Dart_NewStringFromCString(name); |
228 Dart_Handle source = GetSource(name); | 169 Dart_Handle source = GetSource(name); |
229 return Dart_LoadSource(library, url, source); | 170 return Dart_LoadSource(library, url, source); |
230 } | 171 } |
231 | 172 |
232 | 173 |
233 Dart_Handle VmService::LoadSources(Dart_Handle library, const char* names[]) { | |
234 Dart_Handle result = Dart_Null(); | |
235 for (int i = 0; names[i] != NULL; i++) { | |
236 result = LoadSource(library, names[i]); | |
237 if (Dart_IsError(result)) { | |
238 break; | |
239 } | |
240 } | |
241 return result; | |
242 } | |
243 | |
244 | |
245 Dart_Handle VmService::LoadResource(Dart_Handle library, | 174 Dart_Handle VmService::LoadResource(Dart_Handle library, |
246 const char* resource_name, | 175 const char* resource_name, |
247 const char* prefix) { | 176 const char* prefix) { |
248 intptr_t prefix_len = strlen(prefix); | 177 intptr_t prefix_len = strlen(prefix); |
249 // Prepare for invoke call. | 178 // Prepare for invoke call. |
250 Dart_Handle name = Dart_NewStringFromCString(resource_name+prefix_len); | 179 Dart_Handle name = Dart_NewStringFromCString(resource_name+prefix_len); |
251 RETURN_ERROR_HANDLE(name); | 180 RETURN_ERROR_HANDLE(name); |
252 const char* data_buffer = NULL; | 181 const char* data_buffer = NULL; |
253 int data_buffer_length = Resources::ResourceLookup(resource_name, | 182 int data_buffer_length = Resources::ResourceLookup(resource_name, |
254 &data_buffer); | 183 &data_buffer); |
(...skipping 23 matching lines...) Expand all Loading... |
278 Dart_Handle args[kNumArgs] = { name, data_list }; | 207 Dart_Handle args[kNumArgs] = { name, data_list }; |
279 result = Dart_Invoke(library, Dart_NewStringFromCString("_addResource"), | 208 result = Dart_Invoke(library, Dart_NewStringFromCString("_addResource"), |
280 kNumArgs, args); | 209 kNumArgs, args); |
281 return result; | 210 return result; |
282 } | 211 } |
283 | 212 |
284 | 213 |
285 Dart_Handle VmService::LoadResources(Dart_Handle library) { | 214 Dart_Handle VmService::LoadResources(Dart_Handle library) { |
286 Dart_Handle result = Dart_Null(); | 215 Dart_Handle result = Dart_Null(); |
287 intptr_t prefixLen = strlen(kClientResourceNamePrefix); | 216 intptr_t prefixLen = strlen(kClientResourceNamePrefix); |
288 for (intptr_t i = 0; i < Resources::get_resource_count(); i++) { | 217 for (intptr_t i = 0; Resources::Path(i) != NULL; i++) { |
289 const char* path = Resources::get_resource_path(i); | 218 const char* path = Resources::Path(i); |
290 if (!strncmp(path, kClientResourceNamePrefix, prefixLen)) { | 219 if (!strncmp(path, kClientResourceNamePrefix, prefixLen)) { |
291 result = LoadResource(library, path, kClientResourceNamePrefix); | 220 result = LoadResource(library, path, kClientResourceNamePrefix); |
292 if (Dart_IsError(result)) { | 221 if (Dart_IsError(result)) { |
293 break; | 222 break; |
294 } | 223 } |
295 } | 224 } |
296 } | 225 } |
297 return result; | 226 return result; |
298 } | 227 } |
299 | 228 |
300 | 229 |
301 static bool IsVMServiceURL(const char* url) { | |
302 static const intptr_t kLibraryResourceNamePrefixLen = | |
303 strlen(kLibraryResourceNamePrefix); | |
304 return 0 == strncmp(kLibraryResourceNamePrefix, url, | |
305 kLibraryResourceNamePrefixLen); | |
306 } | |
307 | |
308 | |
309 static bool IsVMServiceLibrary(const char* url) { | |
310 return 0 == strcmp(kVMServiceLibraryName, url); | |
311 } | |
312 | |
313 | |
314 Dart_Handle VmService::LibraryTagHandler(Dart_LibraryTag tag, | 230 Dart_Handle VmService::LibraryTagHandler(Dart_LibraryTag tag, |
315 Dart_Handle library, | 231 Dart_Handle library, |
316 Dart_Handle url) { | 232 Dart_Handle url) { |
317 if (!Dart_IsLibrary(library)) { | 233 if (!Dart_IsLibrary(library)) { |
318 return Dart_NewApiError("not a library"); | 234 return Dart_NewApiError("not a library"); |
319 } | 235 } |
320 if (!Dart_IsString(url)) { | 236 if (!Dart_IsString(url)) { |
321 return Dart_NewApiError("url is not a string"); | 237 return Dart_NewApiError("url is not a string"); |
322 } | 238 } |
323 const char* url_string = NULL; | 239 const char* url_string = NULL; |
324 Dart_Handle result = Dart_StringToCString(url, &url_string); | 240 Dart_Handle result = Dart_StringToCString(url, &url_string); |
325 if (Dart_IsError(result)) { | 241 if (Dart_IsError(result)) { |
326 return result; | 242 return result; |
327 } | 243 } |
328 Dart_Handle library_url = Dart_LibraryUrl(library); | 244 Dart_Handle library_url = Dart_LibraryUrl(library); |
329 const char* library_url_string = NULL; | 245 const char* library_url_string = NULL; |
330 result = Dart_StringToCString(library_url, &library_url_string); | 246 result = Dart_StringToCString(library_url, &library_url_string); |
331 if (Dart_IsError(result)) { | 247 if (Dart_IsError(result)) { |
332 return result; | 248 return result; |
333 } | 249 } |
334 bool is_vm_service_url = IsVMServiceURL(url_string); | 250 if (tag == Dart_kImportTag) { |
335 if (!is_vm_service_url) { | 251 // Embedder handles all requests for external libraries. |
336 // Pass to DartUtils. | |
337 return DartUtils::LibraryTagHandler(tag, library, url); | 252 return DartUtils::LibraryTagHandler(tag, library, url); |
338 } | 253 } |
339 switch (tag) { | 254 ASSERT((tag == Dart_kSourceTag) || (tag == Dart_kCanonicalizeUrl)); |
340 case Dart_kCanonicalizeUrl: | 255 if (tag == Dart_kCanonicalizeUrl) { |
341 // The URL is already canonicalized. | 256 // url is already canonicalized. |
342 return url; | 257 return url; |
343 break; | |
344 case Dart_kImportTag: { | |
345 Dart_Handle source = GetSource(url_string); | |
346 if (Dart_IsError(source)) { | |
347 return source; | |
348 } | |
349 Dart_Handle lib = Dart_LoadLibrary(url, source); | |
350 if (Dart_IsError(lib)) { | |
351 return lib; | |
352 } | |
353 if (IsVMServiceLibrary(url_string)) { | |
354 // Install native resolver for this library. | |
355 result = Dart_SetNativeResolver(lib, VmServiceNativeResolver); | |
356 if (Dart_IsError(result)) { | |
357 return result; | |
358 } | |
359 } | |
360 return lib; | |
361 } | |
362 break; | |
363 case Dart_kSourceTag: { | |
364 Dart_Handle source = GetSource(url_string); | |
365 if (Dart_IsError(source)) { | |
366 return source; | |
367 } | |
368 return Dart_LoadSource(library, url, source); | |
369 } | |
370 break; | |
371 default: | |
372 UNIMPLEMENTED(); | |
373 break; | |
374 } | 258 } |
375 UNREACHABLE(); | 259 Dart_Handle source = GetSource(url_string); |
376 return result; | 260 if (Dart_IsError(source)) { |
| 261 return source; |
| 262 } |
| 263 return Dart_LoadSource(library, url, source); |
377 } | 264 } |
378 | 265 |
379 | 266 |
380 void VmService::ThreadMain(uword parameters) { | 267 void VmService::ThreadMain(uword parameters) { |
381 ASSERT(Dart_CurrentIsolate() == NULL); | 268 ASSERT(Dart_CurrentIsolate() == NULL); |
382 ASSERT(isolate_ == NULL); | 269 Dart_Isolate service_isolate = Dart_GetServiceIsolate(NULL); |
383 | 270 Dart_EnterIsolate(service_isolate); |
384 intptr_t server_port = static_cast<intptr_t>(parameters); | 271 Dart_EnterScope(); |
385 ASSERT(server_port >= 0); | |
386 | |
387 // Lock scope. | |
388 { | |
389 MonitorLocker ml(monitor_); | |
390 bool r = _Start(server_port); | |
391 if (!r) { | |
392 port_ = ILLEGAL_PORT; | |
393 monitor_->Notify(); | |
394 return; | |
395 } | |
396 | |
397 Dart_EnterIsolate(isolate_); | |
398 Dart_EnterScope(); | |
399 | |
400 Dart_Handle receievePort = Dart_GetReceivePort(port_); | |
401 ASSERT(!Dart_IsError(receievePort)); | |
402 monitor_->Notify(); | |
403 } | |
404 | |
405 // Keep handling messages until the last active receive port is closed. | |
406 Dart_Handle result = Dart_RunLoop(); | 272 Dart_Handle result = Dart_RunLoop(); |
407 if (Dart_IsError(result)) { | 273 if (Dart_IsError(result)) { |
408 printf("VmService has exited with an error:\n%s\n", Dart_GetError(result)); | 274 printf("Service exited with an error:\n%s\n", Dart_GetError(result)); |
409 } | 275 } |
410 | |
411 _Stop(); | |
412 | |
413 Dart_ExitScope(); | 276 Dart_ExitScope(); |
414 Dart_ExitIsolate(); | 277 Dart_ExitIsolate(); |
415 } | 278 } |
416 | 279 |
417 | 280 |
418 static Dart_Handle MakeServiceControlMessage(Dart_Port port_id, intptr_t code, | |
419 Dart_Handle name) { | |
420 Dart_Handle result; | |
421 Dart_Handle list = Dart_NewList(4); | |
422 ASSERT(!Dart_IsError(list)); | |
423 Dart_Handle code_handle = Dart_NewInteger(code); | |
424 ASSERT(!Dart_IsError(code_handle)); | |
425 result = Dart_ListSetAt(list, 0, code_handle); | |
426 ASSERT(!Dart_IsError(result)); | |
427 Dart_Handle port_id_handle = Dart_NewInteger(port_id); | |
428 ASSERT(!Dart_IsError(port_id_handle)); | |
429 result = Dart_ListSetAt(list, 1, port_id_handle); | |
430 ASSERT(!Dart_IsError(result)); | |
431 Dart_Handle sendPort = Dart_NewSendPort(port_id); | |
432 ASSERT(!Dart_IsError(sendPort)); | |
433 result = Dart_ListSetAt(list, 2, sendPort); | |
434 ASSERT(!Dart_IsError(result)); | |
435 result = Dart_ListSetAt(list, 3, name); | |
436 ASSERT(!Dart_IsError(result)); | |
437 return list; | |
438 } | |
439 | |
440 | |
441 bool VmService::SendIsolateStartupMessage() { | |
442 if (!IsRunning()) { | |
443 return false; | |
444 } | |
445 Isolate* isolate = Isolate::Current(); | |
446 ASSERT(isolate != NULL); | |
447 HANDLESCOPE(isolate); | |
448 Dart_Handle name = Api::NewHandle(isolate, String::New(isolate->name())); | |
449 ASSERT(!Dart_IsError(name)); | |
450 Dart_Handle list = | |
451 MakeServiceControlMessage(Dart_GetMainPortId(), | |
452 VM_SERVICE_ISOLATE_STARTUP_MESSAGE_ID, | |
453 name); | |
454 ASSERT(!Dart_IsError(list)); | |
455 return Dart_Post(port_, list); | |
456 } | |
457 | |
458 | |
459 bool VmService::SendIsolateShutdownMessage() { | |
460 if (!IsRunning()) { | |
461 return false; | |
462 } | |
463 Isolate* isolate = Isolate::Current(); | |
464 ASSERT(isolate != NULL); | |
465 HANDLESCOPE(isolate); | |
466 Dart_Handle list = | |
467 MakeServiceControlMessage(Dart_GetMainPortId(), | |
468 VM_SERVICE_ISOLATE_SHUTDOWN_MESSAGE_ID, | |
469 Dart_Null()); | |
470 ASSERT(!Dart_IsError(list)); | |
471 return Dart_Post(port_, list); | |
472 } | |
473 | |
474 | |
475 void VmService::VmServiceShutdownCallback(void* callback_data) { | |
476 ASSERT(Dart_CurrentIsolate() != NULL); | |
477 Dart_EnterScope(); | |
478 VmService::SendIsolateShutdownMessage(); | |
479 Dart_ExitScope(); | |
480 } | |
481 | |
482 | |
483 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { | |
484 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); | |
485 return reinterpret_cast<uint8_t*>(new_ptr); | |
486 } | |
487 | |
488 | |
489 static void SendServiceMessage(Dart_NativeArguments args) { | |
490 NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args); | |
491 Isolate* isolate = arguments->isolate(); | |
492 StackZone zone(isolate); | |
493 HANDLESCOPE(isolate); | |
494 GET_NON_NULL_NATIVE_ARGUMENT(Instance, sp, arguments->NativeArgAt(0)); | |
495 GET_NON_NULL_NATIVE_ARGUMENT(Instance, message, arguments->NativeArgAt(1)); | |
496 | |
497 // Extract SendPort port id. | |
498 const Object& sp_id_obj = Object::Handle(DartLibraryCalls::PortGetId(sp)); | |
499 if (sp_id_obj.IsError()) { | |
500 Exceptions::PropagateError(Error::Cast(sp_id_obj)); | |
501 } | |
502 Integer& id = Integer::Handle(); | |
503 id ^= sp_id_obj.raw(); | |
504 Dart_Port sp_id = static_cast<Dart_Port>(id.AsInt64Value()); | |
505 ASSERT(sp_id != ILLEGAL_PORT); | |
506 | |
507 // Serialize message. | |
508 uint8_t* data = NULL; | |
509 MessageWriter writer(&data, &allocator); | |
510 writer.WriteMessage(message); | |
511 | |
512 // TODO(turnidge): Throw an exception when the return value is false? | |
513 PortMap::PostMessage(new Message(sp_id, data, writer.BytesWritten(), | |
514 Message::kOOBPriority)); | |
515 } | |
516 | |
517 | |
518 struct VmServiceNativeEntry { | |
519 const char* name; | |
520 int num_arguments; | |
521 Dart_NativeFunction function; | |
522 }; | |
523 | |
524 | |
525 static VmServiceNativeEntry _VmServiceNativeEntries[] = { | |
526 {"VMService_SendServiceMessage", 2, SendServiceMessage} | |
527 }; | |
528 | |
529 | |
530 static Dart_NativeFunction VmServiceNativeResolver(Dart_Handle name, | |
531 int num_arguments, | |
532 bool* auto_setup_scope) { | |
533 const Object& obj = Object::Handle(Api::UnwrapHandle(name)); | |
534 if (!obj.IsString()) { | |
535 return NULL; | |
536 } | |
537 const char* function_name = obj.ToCString(); | |
538 ASSERT(function_name != NULL); | |
539 ASSERT(auto_setup_scope != NULL); | |
540 *auto_setup_scope = true; | |
541 intptr_t n = | |
542 sizeof(_VmServiceNativeEntries) / sizeof(_VmServiceNativeEntries[0]); | |
543 for (intptr_t i = 0; i < n; i++) { | |
544 VmServiceNativeEntry entry = _VmServiceNativeEntries[i]; | |
545 if (!strcmp(function_name, entry.name) && | |
546 (num_arguments == entry.num_arguments)) { | |
547 return entry.function; | |
548 } | |
549 } | |
550 return NULL; | |
551 } | |
552 | 281 |
553 } // namespace bin | 282 } // namespace bin |
554 } // namespace dart | 283 } // namespace dart |
OLD | NEW |