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 = get_resources_table(); | |
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* get_resource_path(int idx) { | |
siva
2014/01/10 00:01:54
These are not strictly accessors so you probably n
| |
59 ASSERT(idx >= 0); | |
60 ResourcesEntry* entry = get_resource_entry(idx); | |
61 if (entry == NULL) { | |
62 return NULL; | |
63 } | |
64 return entry->path_; | |
siva
2014/01/10 00:01:54
should we assert that entry_path_ is not NULL ?
| |
65 } | |
66 | |
67 static const char* get_resource_resource(int idx) { | |
siva
2014/01/10 00:01:54
How about Resource for this.
Cutch
2014/01/10 21:01:42
Killed it.
| |
68 ASSERT(idx >= 0); | |
69 ResourcesEntry* entry = get_resource_entry(idx); | |
70 if (entry == NULL) { | |
71 return NULL; | |
72 } | |
73 return entry->resource_; | |
74 } | |
75 | |
76 private: | |
77 static ResourcesEntry* get_resource_entry(int idx) { | |
siva
2014/01/10 00:01:54
Ditto Entry?
Cutch
2014/01/10 21:01:42
Renamed to "At".
| |
78 ASSERT(idx >= 0); | |
79 ResourcesEntry* table = get_resources_table(); | |
80 for (int i = 0; table[i].path_ != NULL; i++) { | |
81 if (idx == i) { | |
82 return &table[i]; | |
83 } | |
84 } | |
85 return NULL; | |
86 } | |
87 static ResourcesEntry* get_resources_table() { | |
siva
2014/01/10 00:01:54
service_bin_resources() or ResourcesTable for this
Cutch
2014/01/10 21:01:42
Done.
| |
88 return &__service_bin_resources_[0]; | |
89 } | |
90 | |
91 DISALLOW_ALLOCATION(); | |
92 DISALLOW_IMPLICIT_CONSTRUCTORS(Resources); | |
93 }; | |
94 | |
55 const char* VmService::error_msg_ = NULL; | 95 const char* VmService::error_msg_ = NULL; |
56 | 96 |
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) { | 97 bool VmService::Start(intptr_t server_port) { |
68 monitor_ = new dart::Monitor(); | 98 bool r = _Start(server_port); |
69 ASSERT(monitor_ != NULL); | 99 if (!r) { |
70 error_msg_ = NULL; | 100 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 } | 101 } |
81 return port_ != ILLEGAL_PORT; | 102 // Start processing messages in a new thread. |
103 dart::Thread::Start(ThreadMain, NULL); | |
104 return true; | |
82 } | 105 } |
83 | 106 |
84 | 107 |
85 bool VmService::_Start(intptr_t server_port) { | 108 bool VmService::_Start(intptr_t server_port) { |
86 ASSERT(isolate_ == NULL); | 109 ASSERT(Dart_CurrentIsolate() == NULL); |
87 char* error = NULL; | 110 Dart_Isolate isolate = Dart_GetServiceIsolate(); |
siva
2014/01/10 00:01:54
As discussed offline it would be great if we just
Cutch
2014/01/10 21:01:42
Agree that I should follow this cleanup with anoth
| |
88 const char* script_uri = "vmservice:"; | 111 if (isolate == NULL) { |
89 IsolateData* isolate_data = new IsolateData(script_uri); | 112 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; | 113 return false; |
96 } | 114 } |
97 | 115 Dart_EnterIsolate(isolate); |
98 Dart_EnterScope(); | 116 Dart_EnterScope(); |
99 | 117 // Install our own library tag handler. |
100 if (snapshot_buffer != NULL) { | 118 Dart_SetLibraryTagHandler(LibraryTagHandler); |
101 // Setup the native resolver as the snapshot does not carry it. | 119 Dart_Handle result; |
102 Builtin::SetNativeResolver(Builtin::kBuiltinLibrary); | 120 Dart_Handle library = LoadScript(kVMServiceIOLibraryScriptResourceName); |
103 Builtin::SetNativeResolver(Builtin::kIOLibrary); | 121 // Expect a library. |
104 } | 122 ASSERT(library != Dart_Null()); |
105 | 123 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(); | 124 Dart_ExitScope(); |
132 Dart_ExitIsolate(); | 125 Dart_ExitIsolate(); |
133 | 126 bool retval = Dart_IsolateMakeRunnable(isolate); |
134 bool retval = Dart_IsolateMakeRunnable(isolate_); | |
135 if (!retval) { | 127 if (!retval) { |
136 Dart_EnterIsolate(isolate_); | 128 Dart_EnterIsolate(isolate); |
137 Dart_ShutdownIsolate(); | 129 Dart_ShutdownIsolate(); |
138 error_msg_ = "Invalid isolate state - Unable to make it runnable."; | 130 error_msg_ = "Invalid isolate state - Unable to make it runnable."; |
139 return false; | 131 return false; |
140 } | 132 } |
141 | 133 |
142 Dart_EnterIsolate(isolate_); | 134 Dart_EnterIsolate(isolate); |
143 Dart_EnterScope(); | 135 Dart_EnterScope(); |
144 | 136 library = Dart_RootLibrary(); |
145 | |
146 Dart_Handle library = Dart_RootLibrary(); | |
147 // Set requested TCP port. | 137 // Set requested TCP port. |
148 DartUtils::SetIntegerField(library, "_port", server_port); | 138 DartUtils::SetIntegerField(library, "_port", server_port); |
149 result = Dart_Invoke(library, DartUtils::NewString("main"), 0, NULL); | 139 result = Dart_Invoke(library, DartUtils::NewString("main"), 0, NULL); |
150 SHUTDOWN_ON_ERROR(result); | 140 SHUTDOWN_ON_ERROR(result); |
151 | 141 // 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); | 142 result = LoadResources(library); |
182 SHUTDOWN_ON_ERROR(result); | 143 SHUTDOWN_ON_ERROR(result); |
183 | 144 |
184 Dart_ExitScope(); | 145 Dart_ExitScope(); |
185 Dart_ExitIsolate(); | 146 Dart_ExitIsolate(); |
186 | 147 |
187 return true; | 148 return true; |
188 } | 149 } |
189 | 150 |
190 | 151 |
191 void VmService::_Stop() { | |
192 port_ = ILLEGAL_PORT; | |
193 } | |
194 | |
195 | |
196 const char* VmService::GetErrorMessage() { | 152 const char* VmService::GetErrorMessage() { |
197 return error_msg_ == NULL ? "No error." : error_msg_; | 153 return error_msg_ == NULL ? "No error." : error_msg_; |
198 } | 154 } |
199 | 155 |
200 | 156 |
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) { | 157 Dart_Handle VmService::GetSource(const char* name) { |
158 const intptr_t kBufferSize = 512; | |
159 char buffer[kBufferSize]; | |
160 snprintf(&buffer[0], kBufferSize-1, "%s/%s", kLibrarySourceNamePrefix, name); | |
212 const char* vmservice_source = NULL; | 161 const char* vmservice_source = NULL; |
213 int r = Resources::ResourceLookup(name, &vmservice_source); | 162 int r = Resources::ResourceLookup(buffer, &vmservice_source); |
214 ASSERT(r != Resources::kNoSuchInstance); | 163 ASSERT(r != Resources::kNoSuchInstance); |
215 return Dart_NewStringFromCString(vmservice_source); | 164 return Dart_NewStringFromCString(vmservice_source); |
216 } | 165 } |
217 | 166 |
218 | 167 |
219 Dart_Handle VmService::LoadScript(const char* name) { | 168 Dart_Handle VmService::LoadScript(const char* name) { |
220 Dart_Handle url = Dart_NewStringFromCString(name); | 169 Dart_Handle url = Dart_NewStringFromCString("dart:vmservice_io"); |
221 Dart_Handle source = GetSource(name); | 170 Dart_Handle source = GetSource(name); |
222 return Dart_LoadScript(url, source, 0, 0); | 171 return Dart_LoadScript(url, source, 0, 0); |
223 } | 172 } |
224 | 173 |
225 | 174 |
226 Dart_Handle VmService::LoadSource(Dart_Handle library, const char* name) { | 175 Dart_Handle VmService::LoadSource(Dart_Handle library, const char* name) { |
227 Dart_Handle url = Dart_NewStringFromCString(name); | 176 Dart_Handle url = Dart_NewStringFromCString(name); |
228 Dart_Handle source = GetSource(name); | 177 Dart_Handle source = GetSource(name); |
229 return Dart_LoadSource(library, url, source); | 178 return Dart_LoadSource(library, url, source); |
230 } | 179 } |
231 | 180 |
232 | 181 |
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, | 182 Dart_Handle VmService::LoadResource(Dart_Handle library, |
246 const char* resource_name, | 183 const char* resource_name, |
247 const char* prefix) { | 184 const char* prefix) { |
248 intptr_t prefix_len = strlen(prefix); | 185 intptr_t prefix_len = strlen(prefix); |
249 // Prepare for invoke call. | 186 // Prepare for invoke call. |
250 Dart_Handle name = Dart_NewStringFromCString(resource_name+prefix_len); | 187 Dart_Handle name = Dart_NewStringFromCString(resource_name+prefix_len); |
251 RETURN_ERROR_HANDLE(name); | 188 RETURN_ERROR_HANDLE(name); |
252 const char* data_buffer = NULL; | 189 const char* data_buffer = NULL; |
253 int data_buffer_length = Resources::ResourceLookup(resource_name, | 190 int data_buffer_length = Resources::ResourceLookup(resource_name, |
254 &data_buffer); | 191 &data_buffer); |
(...skipping 23 matching lines...) Expand all Loading... | |
278 Dart_Handle args[kNumArgs] = { name, data_list }; | 215 Dart_Handle args[kNumArgs] = { name, data_list }; |
279 result = Dart_Invoke(library, Dart_NewStringFromCString("_addResource"), | 216 result = Dart_Invoke(library, Dart_NewStringFromCString("_addResource"), |
280 kNumArgs, args); | 217 kNumArgs, args); |
281 return result; | 218 return result; |
282 } | 219 } |
283 | 220 |
284 | 221 |
285 Dart_Handle VmService::LoadResources(Dart_Handle library) { | 222 Dart_Handle VmService::LoadResources(Dart_Handle library) { |
286 Dart_Handle result = Dart_Null(); | 223 Dart_Handle result = Dart_Null(); |
287 intptr_t prefixLen = strlen(kClientResourceNamePrefix); | 224 intptr_t prefixLen = strlen(kClientResourceNamePrefix); |
288 for (intptr_t i = 0; i < Resources::get_resource_count(); i++) { | 225 for (intptr_t i = 0; Resources::get_resource_path(i) != NULL; i++) { |
289 const char* path = Resources::get_resource_path(i); | 226 const char* path = Resources::get_resource_path(i); |
290 if (!strncmp(path, kClientResourceNamePrefix, prefixLen)) { | 227 if (!strncmp(path, kClientResourceNamePrefix, prefixLen)) { |
291 result = LoadResource(library, path, kClientResourceNamePrefix); | 228 result = LoadResource(library, path, kClientResourceNamePrefix); |
292 if (Dart_IsError(result)) { | 229 if (Dart_IsError(result)) { |
293 break; | 230 break; |
294 } | 231 } |
295 } | 232 } |
296 } | 233 } |
297 return result; | 234 return result; |
298 } | 235 } |
299 | 236 |
300 | 237 |
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, | 238 Dart_Handle VmService::LibraryTagHandler(Dart_LibraryTag tag, |
315 Dart_Handle library, | 239 Dart_Handle library, |
316 Dart_Handle url) { | 240 Dart_Handle url) { |
317 if (!Dart_IsLibrary(library)) { | 241 if (!Dart_IsLibrary(library)) { |
318 return Dart_NewApiError("not a library"); | 242 return Dart_NewApiError("not a library"); |
319 } | 243 } |
320 if (!Dart_IsString(url)) { | 244 if (!Dart_IsString(url)) { |
321 return Dart_NewApiError("url is not a string"); | 245 return Dart_NewApiError("url is not a string"); |
322 } | 246 } |
323 const char* url_string = NULL; | 247 const char* url_string = NULL; |
324 Dart_Handle result = Dart_StringToCString(url, &url_string); | 248 Dart_Handle result = Dart_StringToCString(url, &url_string); |
325 if (Dart_IsError(result)) { | 249 if (Dart_IsError(result)) { |
326 return result; | 250 return result; |
327 } | 251 } |
328 Dart_Handle library_url = Dart_LibraryUrl(library); | 252 Dart_Handle library_url = Dart_LibraryUrl(library); |
329 const char* library_url_string = NULL; | 253 const char* library_url_string = NULL; |
330 result = Dart_StringToCString(library_url, &library_url_string); | 254 result = Dart_StringToCString(library_url, &library_url_string); |
331 if (Dart_IsError(result)) { | 255 if (Dart_IsError(result)) { |
332 return result; | 256 return result; |
333 } | 257 } |
334 bool is_vm_service_url = IsVMServiceURL(url_string); | 258 if (tag == Dart_kImportTag) { |
335 if (!is_vm_service_url) { | 259 // Embedder handles all requests for external libraries. |
336 // Pass to DartUtils. | |
337 return DartUtils::LibraryTagHandler(tag, library, url); | 260 return DartUtils::LibraryTagHandler(tag, library, url); |
338 } | 261 } |
339 switch (tag) { | 262 ASSERT((tag == Dart_kSourceTag) || (tag == Dart_kCanonicalizeUrl)); |
340 case Dart_kCanonicalizeUrl: | 263 if (tag == Dart_kCanonicalizeUrl) { |
341 // The URL is already canonicalized. | 264 // url is already canonicalized. |
342 return url; | 265 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 } | 266 } |
375 UNREACHABLE(); | 267 Dart_Handle source = GetSource(url_string); |
376 return result; | 268 if (Dart_IsError(source)) { |
269 return source; | |
270 } | |
271 return Dart_LoadSource(library, url, source); | |
377 } | 272 } |
378 | 273 |
379 | 274 |
380 void VmService::ThreadMain(uword parameters) { | 275 void VmService::ThreadMain(uword parameters) { |
381 ASSERT(Dart_CurrentIsolate() == NULL); | 276 ASSERT(Dart_CurrentIsolate() == NULL); |
382 ASSERT(isolate_ == NULL); | 277 Dart_Isolate service_isolate = Dart_GetServiceIsolate(); |
383 | 278 Dart_EnterIsolate(service_isolate); |
384 intptr_t server_port = static_cast<intptr_t>(parameters); | 279 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(); | 280 Dart_Handle result = Dart_RunLoop(); |
407 if (Dart_IsError(result)) { | 281 if (Dart_IsError(result)) { |
408 printf("VmService has exited with an error:\n%s\n", Dart_GetError(result)); | 282 printf("Service exited with an error:\n%s\n", Dart_GetError(result)); |
409 } | 283 } |
410 | |
411 _Stop(); | |
412 | |
413 Dart_ExitScope(); | 284 Dart_ExitScope(); |
414 Dart_ExitIsolate(); | 285 Dart_ExitIsolate(); |
415 } | 286 } |
416 | 287 |
417 | 288 |
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 | 289 |
553 } // namespace bin | 290 } // namespace bin |
554 } // namespace dart | 291 } // namespace dart |
OLD | NEW |