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

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 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 266
265 static char* BuildIsolateName(const char* script_name, 267 static char* BuildIsolateName(const char* script_name,
266 const char* class_name, 268 const char* class_name,
267 const char* func_name) { 269 const char* func_name) {
268 // Skip past any slashes in the script name. 270 // Skip past any slashes in the script name.
269 const char* last_slash = strrchr(script_name, '/'); 271 const char* last_slash = strrchr(script_name, '/');
270 if (last_slash != NULL) { 272 if (last_slash != NULL) {
271 script_name = last_slash + 1; 273 script_name = last_slash + 1;
272 } 274 }
273 275
274 const char* kFormat = "%s/%s.%s"; 276 char* chars = NULL;
275 intptr_t len = OS::SNPrint(NULL, 0, kFormat, script_name, class_name, 277 if (class_name && class_name[0] != '\0') {
276 func_name) + 1; 278 const char* kFormat = "%s/%s.%s";
277 char* chars = reinterpret_cast<char*>( 279 intptr_t len = OS::SNPrint(NULL, 0, kFormat, script_name, class_name,
278 Isolate::Current()->current_zone()->Allocate(len)); 280 func_name) + 1;
279 OS::SNPrint(chars, len, kFormat, script_name, class_name, func_name); 281 chars = reinterpret_cast<char*>(
282 Isolate::Current()->current_zone()->Allocate(len));
283 OS::SNPrint(chars, len, kFormat, script_name, class_name, func_name);
284 } else {
285 const char* kFormat = "%s/%s";
286 intptr_t len = OS::SNPrint(NULL, 0, kFormat, script_name, func_name) + 1;
287 chars = reinterpret_cast<char*>(
288 Isolate::Current()->current_zone()->Allocate(len));
289 OS::SNPrint(chars, len, kFormat, script_name, func_name);
290 }
280 return chars; 291 return chars;
281 } 292 }
282 293
283 294
284 DEFINE_NATIVE_ENTRY(IsolateNatives_start, 2) { 295 DEFINE_NATIVE_ENTRY(IsolateNatives_start, 2) {
285 Isolate* preserved_isolate = Isolate::Current(); 296 Isolate* preserved_isolate = Isolate::Current();
286 const Instance& runnable = Instance::CheckedHandle(arguments->At(0)); 297 const Instance& runnable = Instance::CheckedHandle(arguments->At(0));
287 const Class& runnable_class = Class::Handle(runnable.clazz()); 298 const Class& runnable_class = Class::Handle(runnable.clazz());
288 const char* class_name = String::Handle(runnable_class.Name()).ToCString(); 299 const char* class_name = String::Handle(runnable_class.Name()).ToCString();
289 const Library& library = Library::Handle(runnable_class.library()); 300 const Library& library = Library::Handle(runnable_class.library());
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 intptr_t send_id = Smi::CheckedHandle(arguments->At(0)).Value(); 387 intptr_t send_id = Smi::CheckedHandle(arguments->At(0)).Value();
377 intptr_t reply_id = Smi::CheckedHandle(arguments->At(1)).Value(); 388 intptr_t reply_id = Smi::CheckedHandle(arguments->At(1)).Value();
378 // TODO(iposva): Allow for arbitrary messages to be sent. 389 // TODO(iposva): Allow for arbitrary messages to be sent.
379 uint8_t* data = SerializeObject(Instance::CheckedHandle(arguments->At(2))); 390 uint8_t* data = SerializeObject(Instance::CheckedHandle(arguments->At(2)));
380 391
381 // TODO(turnidge): Throw an exception when the return value is false? 392 // TODO(turnidge): Throw an exception when the return value is false?
382 PortMap::PostMessage(new Message( 393 PortMap::PostMessage(new Message(
383 send_id, reply_id, data, Message::kNormalPriority)); 394 send_id, reply_id, data, Message::kNormalPriority));
384 } 395 }
385 396
397
398 static void ThrowIllegalArgException(const String& message) {
399 GrowableArray<const Object*> args(1);
400 args.Add(&message);
401 Exceptions::ThrowByType(Exceptions::kIllegalArgument, args);
402 }
403
404
405 static void ThrowIsolateSpawnException(const String& message) {
406 GrowableArray<const Object*> args(1);
407 args.Add(&message);
408 Exceptions::ThrowByType(Exceptions::kIsolateSpawn, args);
409 }
410
411
412 class SpawnState {
413 public:
414 explicit SpawnState(const Function& func)
415 : isolate_(NULL),
416 library_url_(NULL),
417 function_name_(NULL) {
418 const Class& cls = Class::Handle(func.owner());
419 ASSERT(cls.IsTopLevel());
420 const Library& lib = Library::Handle(cls.library());
421 const String& lib_url = String::Handle(lib.url());
422 library_url_ = strdup(lib_url.ToCString());
423
424 const String& func_name = String::Handle(func.name());
425 function_name_ = strdup(func_name.ToCString());
426 }
427
428 ~SpawnState() {
429 free(library_url_);
430 free(function_name_);
431 }
432
433 Isolate* isolate() const { return isolate_; }
434 void set_isolate(Isolate* value) { isolate_ = value; }
435 char* library_url() const { return library_url_; }
436 char* function_name() const { return function_name_; }
437
438 RawFunction* ResolveFunction() {
439 const String& lib_url =
440 String::Handle(String::NewSymbol(library_url()));
441 const String& func_name =
442 String::Handle(String::NewSymbol(function_name()));
443
444 const Library& lib = Library::Handle(Library::LookupLibrary(lib_url));
445 if (lib.IsNull() || lib.IsError()) {
446 return Function::null();
447 }
448 return lib.LookupLocalFunction(func_name);
449 }
450
451 void Cleanup() {
452 Isolate* saved = Isolate::Current();
453 Isolate::SetCurrent(isolate());
454 Dart::ShutdownIsolate();
455 Isolate::SetCurrent(saved);
456 }
457
458 private:
459 Isolate* isolate_;
460 char* library_url_;
461 char* function_name_;
462 };
463
464
465 static bool CreateIsolate(SpawnState* state, char** error) {
466 Isolate* parent_isolate = Isolate::Current();
467
468 Dart_IsolateCreateCallback callback = Isolate::CreateCallback();
469 ASSERT(callback);
470 const char* isolate_name = BuildIsolateName(state->library_url(),
471 "",
472 state->function_name());
473 void* init_data = parent_isolate->init_callback_data();
474 bool retval = (callback)(isolate_name, init_data, error);
475 if (retval) {
476 Isolate* child_isolate = Isolate::Current();
477 ASSERT(child_isolate);
478 state->set_isolate(child_isolate);
479
480 // Attempt to resolve the entry function now, so that we fail fast
481 // in the case that the embedder's isolate create callback is
482 // violating its contract.
483 {
484 Zone zone(child_isolate);
485 HandleScope handle_scope(child_isolate);
486 const Function& func = Function::Handle(state->ResolveFunction());
487 if (func.IsNull()) {
488 *error = strdup(zone.PrintToString(
489 "Internal error while starting isolate '%s': "
490 "unable to resolve entry function '%s'.",
491 child_isolate->name(), state->function_name()));
492 retval = false;
493 }
494 }
495 }
496 if (!retval) {
497 Dart::ShutdownIsolate();
498 }
499 Isolate::SetCurrent(parent_isolate);
500 return retval;
501 }
502
503
504 static void RunIsolate2(uword parameter) {
505 SpawnState* state = reinterpret_cast<SpawnState*>(parameter);
506 Isolate* isolate = state->isolate();
507
508 Isolate::SetCurrent(isolate);
509 // Intialize stack limit in case we are running isolate in a
510 // different thread than in which it was initialized.
511 isolate->SetStackLimitFromCurrentTOS(reinterpret_cast<uword>(&isolate));
512
513 {
514 Zone zone(isolate);
515 HandleScope handle_scope(isolate);
516 ASSERT(ClassFinalizer::FinalizePendingClasses());
517 Object& result = Object::Handle();
518
519 const Function& func = Function::Handle(state->ResolveFunction());
520 delete state;
521 state = NULL;
522 ASSERT(!func.IsNull());
523
524 GrowableArray<const Object*> args(0);
525 const Array& kNoArgNames = Array::Handle();
526 result = DartEntry::InvokeStatic(func, args, kNoArgNames);
527 if (result.IsError()) {
528 ProcessError(result);
529 }
530
531 result = isolate->StandardRunLoop();
532 if (result.IsError()) {
533 ProcessError(result);
534 }
535 ASSERT(result.IsNull());
536 }
537 Dart::ShutdownIsolate();
538 }
539
540
541 DEFINE_NATIVE_ENTRY(isolate_spawnFunction, 1) {
542 GET_NATIVE_ARGUMENT(Closure, closure, arguments->At(0));
543 const Function& func = Function::Handle(closure.function());
544 const Class& cls = Class::Handle(func.owner());
545 if (!func.IsClosureFunction() || !func.is_static() || !cls.IsTopLevel()) {
546 const String& msg = String::Handle(String::New(
547 "spawnFunction expects to be passed a closure to a top-level static "
548 "function"));
549 ThrowIllegalArgException(msg);
550 }
551
552 #if defined(DEBUG)
553 const Context& ctx = Context::Handle(closure.context());
554 ASSERT(ctx.num_variables() == 0);
555 #endif
556
557 // Create a new isolate.
558 char* error = NULL;
559 SpawnState* state = new SpawnState(func);
560 if (!CreateIsolate(state, &error)) {
561 delete state;
562 const String& msg = String::Handle(String::New(error));
563 ThrowIsolateSpawnException(msg);
564 }
565
566 // Try to create a SendPort for the new isolate.
567 const Object& port =
568 Object::Handle(SendPortCreate(state->isolate()->main_port()));
569 if (port.IsError()) {
570 state->Cleanup();
571 delete state;
572 Exceptions::PropagateError(port);
573 }
574
575 // Start the new isolate.
576 int result = Thread::Start(RunIsolate2, reinterpret_cast<uword>(state));
577 if (result != 0) {
578 const String& msg = String::Handle(String::NewFormatted(
579 "Failed to start thread for isolate '%s'. Error code '%d'.",
580 state->isolate()->name(), result));
581 state->Cleanup();
582 delete state;
583 ThrowIsolateSpawnException(msg);
584 }
585
586 arguments->SetReturn(port);
587 }
588
589
590 DEFINE_NATIVE_ENTRY(isolate_getPortInternal, 0) {
591 const Object& port = Object::Handle(ReceivePortCreate(isolate->main_port()));
592 if (port.IsError()) {
593 Exceptions::PropagateError(port);
594 }
595 arguments->SetReturn(port);
596 }
597
386 } // namespace dart 598 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698