OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 "platform/assert.h" | 5 #include "platform/assert.h" |
6 #include "vm/bootstrap_natives.h" | 6 #include "vm/bootstrap_natives.h" |
7 #include "vm/class_finalizer.h" | 7 #include "vm/class_finalizer.h" |
8 #include "vm/dart.h" | 8 #include "vm/dart.h" |
9 #include "vm/dart_api_impl.h" | 9 #include "vm/dart_api_impl.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 24 matching lines...) Expand all Loading... |
35 intptr_t port_id_; | 35 intptr_t port_id_; |
36 }; | 36 }; |
37 | 37 |
38 | 38 |
39 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { | 39 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { |
40 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); | 40 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); |
41 return reinterpret_cast<uint8_t*>(new_ptr); | 41 return reinterpret_cast<uint8_t*>(new_ptr); |
42 } | 42 } |
43 | 43 |
44 | 44 |
45 static void StoreError(Isolate* isolate, const Object& obj) { | |
46 ASSERT(obj.IsError()); | |
47 isolate->object_store()->set_sticky_error(Error::Cast(obj)); | |
48 } | |
49 | |
50 | |
51 // TODO(turnidge): Move to DartLibraryCalls. | 45 // TODO(turnidge): Move to DartLibraryCalls. |
52 static RawObject* ReceivePortCreate(intptr_t port_id) { | 46 static RawObject* ReceivePortCreate(intptr_t port_id) { |
53 Isolate* isolate = Isolate::Current(); | 47 Isolate* isolate = Isolate::Current(); |
54 Function& func = | 48 Function& func = |
55 Function::Handle(isolate, | 49 Function::Handle(isolate, |
56 isolate->object_store()->receive_port_create_function()); | 50 isolate->object_store()->receive_port_create_function()); |
57 const int kNumArguments = 1; | 51 const int kNumArguments = 1; |
58 if (func.IsNull()) { | 52 if (func.IsNull()) { |
59 Library& isolate_lib = Library::Handle(Library::IsolateLibrary()); | 53 Library& isolate_lib = Library::Handle(Library::IsolateLibrary()); |
60 ASSERT(!isolate_lib.IsNull()); | 54 ASSERT(!isolate_lib.IsNull()); |
(...skipping 14 matching lines...) Expand all Loading... |
75 args.SetAt(0, Integer::Handle(isolate, Integer::New(port_id))); | 69 args.SetAt(0, Integer::Handle(isolate, Integer::New(port_id))); |
76 const Object& result = | 70 const Object& result = |
77 Object::Handle(isolate, DartEntry::InvokeFunction(func, args)); | 71 Object::Handle(isolate, DartEntry::InvokeFunction(func, args)); |
78 if (!result.IsError()) { | 72 if (!result.IsError()) { |
79 PortMap::SetLive(port_id); | 73 PortMap::SetLive(port_id); |
80 } | 74 } |
81 return result.raw(); | 75 return result.raw(); |
82 } | 76 } |
83 | 77 |
84 | 78 |
85 static void ShutdownIsolate(uword parameter) { | |
86 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); | |
87 { | |
88 // Print the error if there is one. This may execute dart code to | |
89 // print the exception object, so we need to use a StartIsolateScope. | |
90 StartIsolateScope start_scope(isolate); | |
91 StackZone zone(isolate); | |
92 HandleScope handle_scope(isolate); | |
93 Error& error = Error::Handle(); | |
94 error = isolate->object_store()->sticky_error(); | |
95 if (!error.IsNull()) { | |
96 OS::PrintErr("in ShutdownIsolate: %s\n", error.ToErrorCString()); | |
97 } | |
98 } | |
99 { | |
100 // Shut the isolate down. | |
101 SwitchIsolateScope switch_scope(isolate); | |
102 Dart::ShutdownIsolate(); | |
103 } | |
104 } | |
105 | |
106 | |
107 static char* GetRootScriptUri(Isolate* isolate) { | |
108 const Library& library = | |
109 Library::Handle(isolate->object_store()->root_library()); | |
110 ASSERT(!library.IsNull()); | |
111 const String& script_name = String::Handle(library.url()); | |
112 return isolate->current_zone()->MakeCopyOfString(script_name.ToCString()); | |
113 } | |
114 | |
115 | |
116 DEFINE_NATIVE_ENTRY(ReceivePortImpl_factory, 1) { | 79 DEFINE_NATIVE_ENTRY(ReceivePortImpl_factory, 1) { |
117 ASSERT(AbstractTypeArguments::CheckedHandle( | 80 ASSERT(AbstractTypeArguments::CheckedHandle( |
118 arguments->NativeArgAt(0)).IsNull()); | 81 arguments->NativeArgAt(0)).IsNull()); |
119 intptr_t port_id = | 82 intptr_t port_id = |
120 PortMap::CreatePort(arguments->isolate()->message_handler()); | 83 PortMap::CreatePort(arguments->isolate()->message_handler()); |
121 const Object& port = Object::Handle(ReceivePortCreate(port_id)); | 84 const Object& port = Object::Handle(ReceivePortCreate(port_id)); |
122 if (port.IsError()) { | 85 if (port.IsError()) { |
123 Exceptions::PropagateError(Error::Cast(port)); | 86 Exceptions::PropagateError(Error::Cast(port)); |
124 } | 87 } |
125 return port.raw(); | 88 return port.raw(); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 Dart_ExitScope(); | 158 Dart_ExitScope(); |
196 } else { | 159 } else { |
197 *error = zone->PrintToString( | 160 *error = zone->PrintToString( |
198 "Unable to canonicalize uri '%s': no library tag handler found.", | 161 "Unable to canonicalize uri '%s': no library tag handler found.", |
199 uri.ToCString()); | 162 uri.ToCString()); |
200 } | 163 } |
201 return retval; | 164 return retval; |
202 } | 165 } |
203 | 166 |
204 | 167 |
205 class SpawnState { | 168 static bool CreateIsolate(IsolateSpawnState* state, char** error) { |
206 public: | |
207 SpawnState(const Function& func, const Function& callback_func) | |
208 : isolate_(NULL), | |
209 script_url_(NULL), | |
210 library_url_(NULL), | |
211 function_name_(NULL), | |
212 exception_callback_name_(NULL) { | |
213 script_url_ = strdup(GetRootScriptUri(Isolate::Current())); | |
214 const Class& cls = Class::Handle(func.Owner()); | |
215 ASSERT(cls.IsTopLevel()); | |
216 const Library& lib = Library::Handle(cls.library()); | |
217 const String& lib_url = String::Handle(lib.url()); | |
218 library_url_ = strdup(lib_url.ToCString()); | |
219 | |
220 const String& func_name = String::Handle(func.name()); | |
221 function_name_ = strdup(func_name.ToCString()); | |
222 if (!callback_func.IsNull()) { | |
223 const String& callback_name = String::Handle(callback_func.name()); | |
224 exception_callback_name_ = strdup(callback_name.ToCString()); | |
225 } else { | |
226 exception_callback_name_ = strdup("_unhandledExceptionCallback"); | |
227 } | |
228 } | |
229 | |
230 explicit SpawnState(const char* script_url) | |
231 : isolate_(NULL), | |
232 library_url_(NULL), | |
233 function_name_(NULL), | |
234 exception_callback_name_(NULL) { | |
235 script_url_ = strdup(script_url); | |
236 library_url_ = NULL; | |
237 function_name_ = strdup("main"); | |
238 exception_callback_name_ = strdup("_unhandledExceptionCallback"); | |
239 } | |
240 | |
241 ~SpawnState() { | |
242 free(script_url_); | |
243 free(library_url_); | |
244 free(function_name_); | |
245 free(exception_callback_name_); | |
246 } | |
247 | |
248 Isolate* isolate() const { return isolate_; } | |
249 void set_isolate(Isolate* value) { isolate_ = value; } | |
250 char* script_url() const { return script_url_; } | |
251 char* library_url() const { return library_url_; } | |
252 char* function_name() const { return function_name_; } | |
253 char* exception_callback_name() const { return exception_callback_name_; } | |
254 | |
255 RawObject* ResolveFunction() { | |
256 // Resolve the library. | |
257 Library& lib = Library::Handle(); | |
258 if (library_url()) { | |
259 const String& lib_url = String::Handle(String::New(library_url())); | |
260 lib = Library::LookupLibrary(lib_url); | |
261 if (lib.IsNull() || lib.IsError()) { | |
262 const String& msg = String::Handle(String::NewFormatted( | |
263 "Unable to find library '%s'.", library_url())); | |
264 return LanguageError::New(msg); | |
265 } | |
266 } else { | |
267 lib = isolate()->object_store()->root_library(); | |
268 } | |
269 ASSERT(!lib.IsNull()); | |
270 | |
271 // Resolve the function. | |
272 const String& func_name = | |
273 String::Handle(String::New(function_name())); | |
274 const Function& func = Function::Handle(lib.LookupLocalFunction(func_name)); | |
275 if (func.IsNull()) { | |
276 const String& msg = String::Handle(String::NewFormatted( | |
277 "Unable to resolve function '%s' in library '%s'.", | |
278 function_name(), (library_url() ? library_url() : script_url()))); | |
279 return LanguageError::New(msg); | |
280 } | |
281 return func.raw(); | |
282 } | |
283 | |
284 void Cleanup() { | |
285 SwitchIsolateScope switch_scope(isolate()); | |
286 Dart::ShutdownIsolate(); | |
287 } | |
288 | |
289 private: | |
290 Isolate* isolate_; | |
291 char* script_url_; | |
292 char* library_url_; | |
293 char* function_name_; | |
294 char* exception_callback_name_; | |
295 }; | |
296 | |
297 | |
298 static bool CreateIsolate(SpawnState* state, char** error) { | |
299 Isolate* parent_isolate = Isolate::Current(); | 169 Isolate* parent_isolate = Isolate::Current(); |
300 | 170 |
301 Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); | 171 Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); |
302 if (callback == NULL) { | 172 if (callback == NULL) { |
303 *error = strdup("Null callback specified for isolate creation\n"); | 173 *error = strdup("Null callback specified for isolate creation\n"); |
304 Isolate::SetCurrent(parent_isolate); | 174 Isolate::SetCurrent(parent_isolate); |
305 return false; | 175 return false; |
306 } | 176 } |
307 | 177 |
308 void* init_data = parent_isolate->init_callback_data(); | 178 void* init_data = parent_isolate->init_callback_data(); |
309 bool retval = (callback)(state->script_url(), | 179 Isolate* child_isolate = reinterpret_cast<Isolate*>( |
310 state->function_name(), | 180 (callback)(state->script_url(), |
311 init_data, | 181 state->function_name(), |
312 error); | 182 init_data, |
313 if (!retval) { | 183 error)); |
| 184 if (child_isolate == NULL) { |
314 Isolate::SetCurrent(parent_isolate); | 185 Isolate::SetCurrent(parent_isolate); |
315 return false; | 186 return false; |
316 } | 187 } |
317 | 188 state->set_isolate(reinterpret_cast<Isolate*>(child_isolate)); |
318 Isolate* child_isolate = Isolate::Current(); | |
319 ASSERT(child_isolate); | |
320 state->set_isolate(child_isolate); | |
321 | |
322 // Attempt to resolve the entry function now, so that we fail fast | |
323 // in the case that the function cannot be resolved. | |
324 // | |
325 // TODO(turnidge): Revisit this once we have an isolate death api. | |
326 bool resolve_error = false; | |
327 { | |
328 StackZone zone(child_isolate); | |
329 HandleScope handle_scope(child_isolate); | |
330 const Object& result = Object::Handle(state->ResolveFunction()); | |
331 if (result.IsError()) { | |
332 Error& errobj = Error::Handle(); | |
333 errobj ^= result.raw(); | |
334 *error = strdup(errobj.ToErrorCString()); | |
335 resolve_error = true; | |
336 } else { | |
337 const String& callback_name = | |
338 String::Handle(child_isolate, | |
339 String::New(state->exception_callback_name())); | |
340 child_isolate->object_store()-> | |
341 set_unhandled_exception_handler(callback_name); | |
342 } | |
343 } | |
344 if (resolve_error) { | |
345 Dart::ShutdownIsolate(); | |
346 Isolate::SetCurrent(parent_isolate); | |
347 return false; | |
348 } | |
349 | 189 |
350 Isolate::SetCurrent(parent_isolate); | 190 Isolate::SetCurrent(parent_isolate); |
351 return true; | 191 return true; |
352 } | 192 } |
353 | 193 |
354 | 194 |
355 static bool RunIsolate(uword parameter) { | 195 static RawObject* Spawn(NativeArguments* arguments, IsolateSpawnState* state) { |
356 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); | |
357 SpawnState* state = reinterpret_cast<SpawnState*>(isolate->spawn_data()); | |
358 isolate->set_spawn_data(0); | |
359 { | |
360 StartIsolateScope start_scope(isolate); | |
361 StackZone zone(isolate); | |
362 HandleScope handle_scope(isolate); | |
363 if (!ClassFinalizer::FinalizePendingClasses()) { | |
364 // Error is in sticky error already. | |
365 return false; | |
366 } | |
367 | |
368 Object& result = Object::Handle(); | |
369 result = state->ResolveFunction(); | |
370 delete state; | |
371 state = NULL; | |
372 if (result.IsError()) { | |
373 StoreError(isolate, result); | |
374 return false; | |
375 } | |
376 ASSERT(result.IsFunction()); | |
377 Function& func = Function::Handle(isolate); | |
378 func ^= result.raw(); | |
379 result = DartEntry::InvokeFunction(func, Object::empty_array()); | |
380 if (result.IsError()) { | |
381 StoreError(isolate, result); | |
382 return false; | |
383 } | |
384 } | |
385 return true; | |
386 } | |
387 | |
388 | |
389 static RawObject* Spawn(NativeArguments* arguments, SpawnState* state) { | |
390 // Create a new isolate. | 196 // Create a new isolate. |
391 char* error = NULL; | 197 char* error = NULL; |
392 if (!CreateIsolate(state, &error)) { | 198 if (!CreateIsolate(state, &error)) { |
393 delete state; | 199 delete state; |
394 const String& msg = String::Handle(String::New(error)); | 200 const String& msg = String::Handle(String::New(error)); |
395 free(error); | 201 free(error); |
396 ThrowIsolateSpawnException(msg); | 202 ThrowIsolateSpawnException(msg); |
397 } | 203 } |
398 | 204 |
399 // Try to create a SendPort for the new isolate. | 205 // Try to create a SendPort for the new isolate. |
400 const Object& port = Object::Handle( | 206 const Object& port = Object::Handle( |
401 DartLibraryCalls::NewSendPort(state->isolate()->main_port())); | 207 DartLibraryCalls::NewSendPort(state->isolate()->main_port())); |
402 if (port.IsError()) { | 208 if (port.IsError()) { |
403 state->Cleanup(); | 209 state->Cleanup(); |
404 delete state; | 210 delete state; |
405 Exceptions::PropagateError(Error::Cast(port)); | 211 Exceptions::PropagateError(Error::Cast(port)); |
406 } | 212 } |
407 | 213 |
408 // Start the new isolate. | 214 // Start the new isolate if it is already marked as runnable. |
| 215 MutexLocker ml(state->isolate()->mutex()); |
409 state->isolate()->set_spawn_data(reinterpret_cast<uword>(state)); | 216 state->isolate()->set_spawn_data(reinterpret_cast<uword>(state)); |
410 state->isolate()->message_handler()->Run( | 217 if (state->isolate()->is_runnable()) { |
411 Dart::thread_pool(), RunIsolate, ShutdownIsolate, | 218 state->isolate()->Run(); |
412 reinterpret_cast<uword>(state->isolate())); | 219 } |
413 | 220 |
414 return port.raw(); | 221 return port.raw(); |
415 } | 222 } |
416 | 223 |
417 | 224 |
418 DEFINE_NATIVE_ENTRY(isolate_spawnFunction, 2) { | 225 DEFINE_NATIVE_ENTRY(isolate_spawnFunction, 2) { |
419 GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0)); | 226 GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0)); |
420 bool throw_exception = false; | 227 bool throw_exception = false; |
421 Function& func = Function::Handle(); | 228 Function& func = Function::Handle(); |
422 if (closure.IsClosure()) { | 229 if (closure.IsClosure()) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 #if defined(DEBUG) | 264 #if defined(DEBUG) |
458 Context& ctx = Context::Handle(); | 265 Context& ctx = Context::Handle(); |
459 ctx = Closure::context(closure); | 266 ctx = Closure::context(closure); |
460 ASSERT(ctx.num_variables() == 0); | 267 ASSERT(ctx.num_variables() == 0); |
461 if (!callback.IsNull()) { | 268 if (!callback.IsNull()) { |
462 ctx = Closure::context(callback); | 269 ctx = Closure::context(callback); |
463 ASSERT(ctx.num_variables() == 0); | 270 ASSERT(ctx.num_variables() == 0); |
464 } | 271 } |
465 #endif | 272 #endif |
466 | 273 |
467 return Spawn(arguments, new SpawnState(func, callback_func)); | 274 return Spawn(arguments, new IsolateSpawnState(func, callback_func)); |
468 } | 275 } |
469 | 276 |
470 | 277 |
471 DEFINE_NATIVE_ENTRY(isolate_spawnUri, 1) { | 278 DEFINE_NATIVE_ENTRY(isolate_spawnUri, 1) { |
472 GET_NON_NULL_NATIVE_ARGUMENT(String, uri, arguments->NativeArgAt(0)); | 279 GET_NON_NULL_NATIVE_ARGUMENT(String, uri, arguments->NativeArgAt(0)); |
473 | 280 |
474 // Canonicalize the uri with respect to the current isolate. | 281 // Canonicalize the uri with respect to the current isolate. |
475 char* error = NULL; | 282 char* error = NULL; |
476 char* canonical_uri = NULL; | 283 char* canonical_uri = NULL; |
477 const Library& root_lib = | 284 const Library& root_lib = |
478 Library::Handle(arguments->isolate()->object_store()->root_library()); | 285 Library::Handle(arguments->isolate()->object_store()->root_library()); |
479 if (!CanonicalizeUri(arguments->isolate(), root_lib, uri, | 286 if (!CanonicalizeUri(arguments->isolate(), root_lib, uri, |
480 &canonical_uri, &error)) { | 287 &canonical_uri, &error)) { |
481 const String& msg = String::Handle(String::New(error)); | 288 const String& msg = String::Handle(String::New(error)); |
482 ThrowIsolateSpawnException(msg); | 289 ThrowIsolateSpawnException(msg); |
483 } | 290 } |
484 | 291 |
485 return Spawn(arguments, new SpawnState(canonical_uri)); | 292 return Spawn(arguments, new IsolateSpawnState(canonical_uri)); |
486 } | 293 } |
487 | 294 |
488 | 295 |
489 DEFINE_NATIVE_ENTRY(isolate_getPortInternal, 0) { | 296 DEFINE_NATIVE_ENTRY(isolate_getPortInternal, 0) { |
490 const Object& port = Object::Handle(ReceivePortCreate(isolate->main_port())); | 297 const Object& port = Object::Handle(ReceivePortCreate(isolate->main_port())); |
491 if (port.IsError()) { | 298 if (port.IsError()) { |
492 Exceptions::PropagateError(Error::Cast(port)); | 299 Exceptions::PropagateError(Error::Cast(port)); |
493 } | 300 } |
494 return port.raw(); | 301 return port.raw(); |
495 } | 302 } |
496 | 303 |
497 } // namespace dart | 304 } // namespace dart |
OLD | NEW |