Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Side by Side Diff: runtime/lib/isolate.cc

Issue 9691005: Implement spawnFunction from the new isolate api. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698