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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
46 | 46 |
47 static uint8_t* SerializeObject(const Instance& obj) { | 47 static uint8_t* SerializeObject(const Instance& obj) { |
48 uint8_t* result = NULL; | 48 uint8_t* result = NULL; |
49 SnapshotWriter writer(Snapshot::kMessage, &result, &allocator); | 49 SnapshotWriter writer(Snapshot::kMessage, &result, &allocator); |
50 writer.WriteObject(obj.raw()); | 50 writer.WriteObject(obj.raw()); |
51 writer.FinalizeBuffer(); | 51 writer.FinalizeBuffer(); |
52 return result; | 52 return result; |
53 } | 53 } |
54 | 54 |
55 | 55 |
56 // TODO(turnidge): Taking down the whole vm when an isolate fails is | |
57 // bad. Change this. | |
56 static void ProcessError(const Object& obj) { | 58 static void ProcessError(const Object& obj) { |
57 ASSERT(obj.IsError()); | 59 ASSERT(obj.IsError()); |
58 Error& error = Error::Handle(); | 60 Error& error = Error::Handle(); |
59 error ^= obj.raw(); | 61 error ^= obj.raw(); |
60 OS::PrintErr("%s\n", error.ToErrorCString()); | 62 OS::PrintErr("%s\n", error.ToErrorCString()); |
61 exit(255); | 63 exit(255); |
62 } | 64 } |
63 | 65 |
64 | 66 |
65 static void ThrowErrorException(Exceptions::ExceptionType type, | 67 static void ThrowErrorException(Exceptions::ExceptionType type, |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
376 intptr_t send_id = Smi::CheckedHandle(arguments->At(0)).Value(); | 378 intptr_t send_id = Smi::CheckedHandle(arguments->At(0)).Value(); |
377 intptr_t reply_id = Smi::CheckedHandle(arguments->At(1)).Value(); | 379 intptr_t reply_id = Smi::CheckedHandle(arguments->At(1)).Value(); |
378 // TODO(iposva): Allow for arbitrary messages to be sent. | 380 // TODO(iposva): Allow for arbitrary messages to be sent. |
379 uint8_t* data = SerializeObject(Instance::CheckedHandle(arguments->At(2))); | 381 uint8_t* data = SerializeObject(Instance::CheckedHandle(arguments->At(2))); |
380 | 382 |
381 // TODO(turnidge): Throw an exception when the return value is false? | 383 // TODO(turnidge): Throw an exception when the return value is false? |
382 PortMap::PostMessage(new Message( | 384 PortMap::PostMessage(new Message( |
383 send_id, reply_id, data, Message::kNormalPriority)); | 385 send_id, reply_id, data, Message::kNormalPriority)); |
384 } | 386 } |
385 | 387 |
388 | |
389 static void ThrowIllegalArgException(const char* message) { | |
390 const String& message_str = String::Handle(String::New(message)); | |
391 GrowableArray<const Object*> args(1); | |
392 args.Add(&message_str); | |
393 Exceptions::ThrowByType(Exceptions::kIllegalArgument, args); | |
394 } | |
395 | |
396 | |
397 class SpawnState { | |
398 public: | |
399 explicit SpawnState(const Function& func) | |
400 : isolate_(NULL), | |
401 library_url_(NULL), | |
402 function_name_(NULL) { | |
403 const Class& cls = Class::Handle(func.owner()); | |
404 const Library& lib = Library::Handle(cls.library()); | |
siva
2012/03/12 23:25:41
Assert cls represents implicit top level in 'lib'
turnidge
2012/03/13 18:13:48
Added an assert that cls.IsTopLevel().
| |
405 const String& lib_url = String::Handle(lib.url()); | |
406 library_url_ = strdup(lib_url.ToCString()); | |
407 | |
408 const String& func_name = String::Handle(func.name()); | |
409 function_name_ = strdup(func_name.ToCString()); | |
410 } | |
411 | |
412 ~SpawnState() { | |
413 free(library_url_); | |
414 free(function_name_); | |
415 } | |
416 | |
417 Isolate* isolate() const { return isolate_; } | |
418 void set_isolate(Isolate* value) { isolate_ = value; } | |
419 char* library_url() const { return library_url_; } | |
420 char* function_name() const { return function_name_; } | |
421 | |
422 private: | |
423 Isolate* isolate_; | |
424 char* library_url_; | |
425 char* function_name_; | |
426 }; | |
427 | |
428 | |
429 static bool CreateIsolate(SpawnState* state, char** error) { | |
430 Isolate* parent_isolate = Isolate::Current(); | |
431 | |
432 Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); | |
433 ASSERT(callback); | |
434 const char* isolate_name = BuildIsolateName(state->library_url(), | |
435 "", | |
436 state->function_name()); | |
437 void* init_data = parent_isolate->init_callback_data(); | |
438 bool retval = (callback)(isolate_name, init_data, error); | |
439 if (retval) { | |
440 Isolate* child_isolate = Isolate::Current(); | |
441 ASSERT(child_isolate); | |
442 state->set_isolate(child_isolate); | |
siva
2012/03/12 23:25:41
We are assuming that the callback will load up the
turnidge
2012/03/13 18:13:48
It seems to me that if this occurs, it is an inter
siva
2012/03/13 19:45:21
Since the callback is something that the embedder
| |
443 } else { | |
444 Dart::ShutdownIsolate(); | |
445 } | |
446 Isolate::SetCurrent(parent_isolate); | |
447 return retval; | |
448 } | |
449 | |
450 | |
451 static void RunIsolate2(uword parameter) { | |
452 SpawnState* state = reinterpret_cast<SpawnState*>(parameter); | |
453 Isolate* isolate = state->isolate(); | |
454 | |
455 Isolate::SetCurrent(isolate); | |
456 // Intialize stack limit in case we are running isolate in a | |
457 // different thread than in which it was initialized. | |
458 isolate->SetStackLimitFromCurrentTOS(reinterpret_cast<uword>(&isolate)); | |
459 | |
460 { | |
461 Zone zone(isolate); | |
462 HandleScope handle_scope(isolate); | |
463 ASSERT(ClassFinalizer::FinalizePendingClasses()); | |
464 Object& result = Object::Handle(); | |
465 | |
466 const String& lib_url = | |
467 String::Handle(String::NewSymbol(state->library_url())); | |
468 const String& func_name = | |
469 String::Handle(String::NewSymbol(state->function_name())); | |
470 delete state; | |
471 state = NULL; | |
472 | |
473 const Library& lib = Library::Handle(Library::LookupLibrary(lib_url)); | |
474 ASSERT(!lib.IsNull() && !lib.IsError()); | |
475 GrowableArray<const Object*> args(0); | |
476 const Function& func = | |
477 Function::Handle(lib.LookupLocalFunction(func_name)); | |
siva
2012/03/12 23:25:41
ASSERT(!func.IsNull());
turnidge
2012/03/13 18:13:48
Done.
| |
478 const Array& kNoArgNames = Array::Handle(); | |
479 result = DartEntry::InvokeStatic(func, args, kNoArgNames); | |
480 if (result.IsError()) { | |
481 ProcessError(result); | |
482 } | |
483 | |
484 result = isolate->StandardRunLoop(); | |
485 if (result.IsError()) { | |
486 ProcessError(result); | |
487 } | |
488 ASSERT(result.IsNull()); | |
489 } | |
490 Dart::ShutdownIsolate(); | |
491 } | |
492 | |
493 | |
494 DEFINE_NATIVE_ENTRY(isolate_spawnFunction, 1) { | |
495 const Closure& closure = Closure::CheckedHandle(arguments->At(0)); | |
siva
2012/03/12 23:25:41
This should be
GET_NATIVE_ARGUMENT(Closure, closur
turnidge
2012/03/13 18:13:48
Done.
| |
496 const Function& func = Function::Handle(closure.function()); | |
497 const Context& ctx = Context::Handle(closure.context()); | |
498 | |
499 if (!func.IsClosureFunction() || !func.is_static()) { | |
500 ThrowIllegalArgException( | |
501 "spawnFunction expects to be passed a closure to a static function"); | |
502 } | |
siva
2012/03/12 23:25:41
Don't we also have to check that it is a top level
turnidge
2012/03/13 18:13:48
Done.
| |
503 if (ctx.num_variables() > 0) { | |
Siggi Cherem (dart-lang)
2012/03/12 22:57:44
is this check redundant with the check above for i
turnidge
2012/03/13 18:13:48
I believe it is. Made it an ASSERT.
| |
504 ThrowIllegalArgException( | |
505 "spawnFunction expects to be passed a closure with no bound variables"); | |
506 } | |
507 | |
508 // Create a new isolate. | |
509 char* error = NULL; | |
510 SpawnState* state = new SpawnState(func); | |
511 if (!CreateIsolate(state, &error)) { | |
512 // TODO(turnidge): Throw a different exception type here. | |
turnidge
2012/03/12 22:38:48
Siggi -- what type of exception do we want to thro
Siggi Cherem (dart-lang)
2012/03/12 22:57:44
How about we introduce 'IsolateSpawnException' (ma
turnidge
2012/03/13 18:13:48
I've added IsolateSpawnException as part of this c
| |
513 delete state; | |
514 ThrowIllegalArgException(error); | |
515 } | |
516 | |
517 // Try to create a SendPort for the new isolate. | |
518 const Object& port = | |
519 Object::Handle(SendPortCreate(state->isolate()->main_port())); | |
520 if (port.IsError()) { | |
521 Isolate* saved = Isolate::Current(); | |
522 Isolate::SetCurrent(state->isolate()); | |
523 Dart::ShutdownIsolate(); | |
524 Isolate::SetCurrent(saved); | |
525 delete state; | |
526 Exceptions::PropagateError(port); | |
527 } | |
528 | |
529 // Start the new isolate. | |
530 int result = Thread::Start(RunIsolate2, reinterpret_cast<uword>(state)); | |
531 if (result != 0) { | |
532 FATAL1("Failed to start isolate thread: error %d", result); | |
Siggi Cherem (dart-lang)
2012/03/12 22:57:44
should this be fatal or also throw the IsolateSpaw
siva
2012/03/12 23:25:41
Why does this have to be a Fatal and not an except
turnidge
2012/03/13 18:13:48
I was just cribbing from the existing code. Chang
| |
533 } | |
534 | |
535 arguments->SetReturn(port); | |
536 } | |
537 | |
538 | |
539 DEFINE_NATIVE_ENTRY(isolate_getPortInternal, 0) { | |
540 const Object& port = Object::Handle(ReceivePortCreate(isolate->main_port())); | |
541 if (port.IsError()) { | |
542 Exceptions::PropagateError(port); | |
543 } | |
544 arguments->SetReturn(port); | |
545 } | |
546 | |
386 } // namespace dart | 547 } // namespace dart |
OLD | NEW |