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 String& message) { |
| 390 GrowableArray<const Object*> args(1); |
| 391 args.Add(&message); |
| 392 Exceptions::ThrowByType(Exceptions::kIllegalArgument, args); |
| 393 } |
| 394 |
| 395 |
| 396 static void ThrowIsolateSpawnException(const String& message) { |
| 397 GrowableArray<const Object*> args(1); |
| 398 args.Add(&message); |
| 399 Exceptions::ThrowByType(Exceptions::kIsolateSpawn, args); |
| 400 } |
| 401 |
| 402 |
| 403 class SpawnState { |
| 404 public: |
| 405 explicit SpawnState(const Function& func) |
| 406 : isolate_(NULL), |
| 407 library_url_(NULL), |
| 408 function_name_(NULL) { |
| 409 const Class& cls = Class::Handle(func.owner()); |
| 410 ASSERT(cls.IsTopLevel()); |
| 411 const Library& lib = Library::Handle(cls.library()); |
| 412 const String& lib_url = String::Handle(lib.url()); |
| 413 library_url_ = strdup(lib_url.ToCString()); |
| 414 |
| 415 const String& func_name = String::Handle(func.name()); |
| 416 function_name_ = strdup(func_name.ToCString()); |
| 417 } |
| 418 |
| 419 ~SpawnState() { |
| 420 free(library_url_); |
| 421 free(function_name_); |
| 422 } |
| 423 |
| 424 Isolate* isolate() const { return isolate_; } |
| 425 void set_isolate(Isolate* value) { isolate_ = value; } |
| 426 char* library_url() const { return library_url_; } |
| 427 char* function_name() const { return function_name_; } |
| 428 |
| 429 RawFunction* ResolveFunction() { |
| 430 const String& lib_url = |
| 431 String::Handle(String::NewSymbol(library_url())); |
| 432 const String& func_name = |
| 433 String::Handle(String::NewSymbol(function_name())); |
| 434 |
| 435 const Library& lib = Library::Handle(Library::LookupLibrary(lib_url)); |
| 436 if (lib.IsNull() || lib.IsError()) { |
| 437 return Function::null(); |
| 438 } |
| 439 return lib.LookupLocalFunction(func_name); |
| 440 } |
| 441 |
| 442 void Cleanup() { |
| 443 Isolate* saved = Isolate::Current(); |
| 444 Isolate::SetCurrent(isolate()); |
| 445 Dart::ShutdownIsolate(); |
| 446 Isolate::SetCurrent(saved); |
| 447 } |
| 448 |
| 449 private: |
| 450 Isolate* isolate_; |
| 451 char* library_url_; |
| 452 char* function_name_; |
| 453 }; |
| 454 |
| 455 |
| 456 static bool CreateIsolate(SpawnState* state, char** error) { |
| 457 Isolate* parent_isolate = Isolate::Current(); |
| 458 |
| 459 Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); |
| 460 ASSERT(callback); |
| 461 const char* isolate_name = BuildIsolateName(state->library_url(), |
| 462 "", |
| 463 state->function_name()); |
| 464 void* init_data = parent_isolate->init_callback_data(); |
| 465 bool retval = (callback)(isolate_name, init_data, error); |
| 466 if (retval) { |
| 467 Isolate* child_isolate = Isolate::Current(); |
| 468 ASSERT(child_isolate); |
| 469 state->set_isolate(child_isolate); |
| 470 } else { |
| 471 Dart::ShutdownIsolate(); |
| 472 } |
| 473 Isolate::SetCurrent(parent_isolate); |
| 474 return retval; |
| 475 } |
| 476 |
| 477 |
| 478 static void RunIsolate2(uword parameter) { |
| 479 SpawnState* state = reinterpret_cast<SpawnState*>(parameter); |
| 480 Isolate* isolate = state->isolate(); |
| 481 |
| 482 Isolate::SetCurrent(isolate); |
| 483 // Intialize stack limit in case we are running isolate in a |
| 484 // different thread than in which it was initialized. |
| 485 isolate->SetStackLimitFromCurrentTOS(reinterpret_cast<uword>(&isolate)); |
| 486 |
| 487 { |
| 488 Zone zone(isolate); |
| 489 HandleScope handle_scope(isolate); |
| 490 ASSERT(ClassFinalizer::FinalizePendingClasses()); |
| 491 Object& result = Object::Handle(); |
| 492 |
| 493 const Function& func = Function::Handle(state->ResolveFunction()); |
| 494 delete state; |
| 495 state = NULL; |
| 496 ASSERT(!func.IsNull()); |
| 497 |
| 498 GrowableArray<const Object*> args(0); |
| 499 const Array& kNoArgNames = Array::Handle(); |
| 500 result = DartEntry::InvokeStatic(func, args, kNoArgNames); |
| 501 if (result.IsError()) { |
| 502 ProcessError(result); |
| 503 } |
| 504 |
| 505 result = isolate->StandardRunLoop(); |
| 506 if (result.IsError()) { |
| 507 ProcessError(result); |
| 508 } |
| 509 ASSERT(result.IsNull()); |
| 510 } |
| 511 Dart::ShutdownIsolate(); |
| 512 } |
| 513 |
| 514 |
| 515 DEFINE_NATIVE_ENTRY(isolate_spawnFunction, 1) { |
| 516 GET_NATIVE_ARGUMENT(Closure, closure, arguments->At(0)); |
| 517 const Function& func = Function::Handle(closure.function()); |
| 518 const Class& cls = Class::Handle(func.owner()); |
| 519 if (!func.IsClosureFunction() || !func.is_static() || !cls.IsTopLevel()) { |
| 520 const String& msg = String::Handle(String::New( |
| 521 "spawnFunction expects to be passed a closure to a top-level static " |
| 522 "function")); |
| 523 ThrowIllegalArgException(msg); |
| 524 } |
| 525 |
| 526 #if defined(DEBUG) |
| 527 const Context& ctx = Context::Handle(closure.context()); |
| 528 ASSERT(ctx.num_variables() == 0); |
| 529 #endif |
| 530 |
| 531 // Create a new isolate. |
| 532 char* error = NULL; |
| 533 SpawnState* state = new SpawnState(func); |
| 534 if (!CreateIsolate(state, &error)) { |
| 535 delete state; |
| 536 const String& msg = String::Handle(String::New(msg)); |
| 537 ThrowIsolateSpawnException(msg); |
| 538 } |
| 539 |
| 540 // Try to create a SendPort for the new isolate. |
| 541 const Object& port = |
| 542 Object::Handle(SendPortCreate(state->isolate()->main_port())); |
| 543 if (port.IsError()) { |
| 544 state->Cleanup(); |
| 545 delete state; |
| 546 Exceptions::PropagateError(port); |
| 547 } |
| 548 |
| 549 // Start the new isolate. |
| 550 int result = Thread::Start(RunIsolate2, reinterpret_cast<uword>(state)); |
| 551 if (result != 0) { |
| 552 const String& msg = String::Handle(String::NewFormat( |
| 553 "Failed to start thread for isolate '%s'. Error code '%d'.", |
| 554 state->isolate()->name(), result)); |
| 555 state->Cleanup(); |
| 556 delete state; |
| 557 ThrowIsolateSpawnException(msg); |
| 558 } |
| 559 |
| 560 arguments->SetReturn(port); |
| 561 } |
| 562 |
| 563 |
| 564 DEFINE_NATIVE_ENTRY(isolate_getPortInternal, 0) { |
| 565 const Object& port = Object::Handle(ReceivePortCreate(isolate->main_port())); |
| 566 if (port.IsError()) { |
| 567 Exceptions::PropagateError(port); |
| 568 } |
| 569 arguments->SetReturn(port); |
| 570 } |
| 571 |
386 } // namespace dart | 572 } // namespace dart |
OLD | NEW |