Index: runtime/lib/isolate.cc |
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc |
index d62bb2bfc0d1193c33e89f43722ef3d1d5adb35f..00efcae7aa2ad97b274024283927df9e1b524589 100644 |
--- a/runtime/lib/isolate.cc |
+++ b/runtime/lib/isolate.cc |
@@ -2,6 +2,7 @@ |
// for details. All rights reserved. Use of this source code is governed by a |
// BSD-style license that can be found in the LICENSE file. |
+#include "include/dart_native_api.h" |
#include "platform/assert.h" |
#include "vm/bootstrap_natives.h" |
#include "vm/class_finalizer.h" |
@@ -125,60 +126,70 @@ static void ThrowIsolateSpawnException(const String& message) { |
} |
-static bool CreateIsolate(Isolate* parent_isolate, |
- IsolateSpawnState* state, |
- char** error) { |
- Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); |
- if (callback == NULL) { |
- *error = strdup("Null callback specified for isolate creation\n"); |
- return false; |
- } |
+class SpawnIsolateTask : public ThreadPool::Task { |
+ public: |
+ explicit SpawnIsolateTask(IsolateSpawnState* state) : state_(state) {} |
+ |
+ virtual void Run() { |
+ // Create a new isolate. |
+ char* error = NULL; |
+ Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); |
+ if (callback == NULL) { |
+ ReportError( |
+ "Isolate spawn is not supported by this Dart implementation\n"); |
+ delete state_; |
+ state_ = NULL; |
+ return; |
+ } |
+ |
+ Dart_IsolateFlags api_flags; |
+ state_->isolate_flags()->CopyTo(&api_flags); |
+ |
+ Isolate* isolate = reinterpret_cast<Isolate*>( |
+ (callback)(state_->script_url(), |
+ state_->function_name(), |
+ state_->package_root(), |
+ state_->package_map(), |
+ &api_flags, |
+ state_->init_data(), |
+ &error)); |
+ if (isolate == NULL) { |
+ ReportError(error); |
+ delete state_; |
+ state_ = NULL; |
+ free(error); |
+ return; |
+ } |
- Dart_IsolateFlags api_flags; |
- state->isolate_flags()->CopyTo(&api_flags); |
- |
- void* init_data = parent_isolate->init_callback_data(); |
- Isolate* child_isolate = reinterpret_cast<Isolate*>( |
- (callback)(state->script_url(), |
- state->function_name(), |
- state->package_root(), |
- state->package_map(), |
- &api_flags, |
- init_data, |
- error)); |
- if (child_isolate == NULL) { |
- return false; |
+ if (state_->origin_id() != ILLEGAL_PORT) { |
+ // For isolates spawned using spawnFunction we set the origin_id |
+ // to the origin_id of the parent isolate. |
+ isolate->set_origin_id(state_->origin_id()); |
+ } |
+ MutexLocker ml(isolate->mutex()); |
+ state_->set_isolate(reinterpret_cast<Isolate*>(isolate)); |
+ isolate->set_spawn_state(state_); |
+ state_ = NULL; |
+ if (isolate->is_runnable()) { |
+ isolate->Run(); |
+ } |
} |
- if (!state->is_spawn_uri()) { |
- // For isolates spawned using the spawn semantics we set |
- // the origin_id to the origin_id of the parent isolate. |
- child_isolate->set_origin_id(parent_isolate->origin_id()); |
+ |
+ private: |
+ void ReportError(const char* error) { |
+ Dart_CObject error_cobj; |
+ error_cobj.type = Dart_CObject_kString; |
+ error_cobj.value.as_string = const_cast<char*>(error); |
+ if (!Dart_PostCObject(state_->parent_port(), &error_cobj)) { |
+ // Perhaps the parent isolate died or closed the port before we |
+ // could report the error. Ignore. |
+ } |
} |
- state->set_isolate(reinterpret_cast<Isolate*>(child_isolate)); |
- return true; |
-} |
+ IsolateSpawnState* state_; |
-static void Spawn(Isolate* parent_isolate, IsolateSpawnState* state) { |
- Thread::ExitIsolate(); |
- // Create a new isolate. |
- char* error = NULL; |
- if (!CreateIsolate(parent_isolate, state, &error)) { |
- Thread::EnterIsolate(parent_isolate); |
- delete state; |
- const String& msg = String::Handle(String::New(error)); |
- free(error); |
- ThrowIsolateSpawnException(msg); |
- } |
- Thread::EnterIsolate(parent_isolate); |
- // Start the new isolate if it is already marked as runnable. |
- Isolate* spawned_isolate = state->isolate(); |
- MutexLocker ml(spawned_isolate->mutex()); |
- spawned_isolate->set_spawn_state(state); |
- if (spawned_isolate->is_runnable()) { |
- spawned_isolate->Run(); |
- } |
-} |
+ DISALLOW_COPY_AND_ASSIGN(SpawnIsolateTask); |
+}; |
DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 7) { |
@@ -206,13 +217,16 @@ DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 7) { |
Dart_Port on_exit_port = onExit.IsNull() ? ILLEGAL_PORT : onExit.Id(); |
Dart_Port on_error_port = onError.IsNull() ? ILLEGAL_PORT : onError.Id(); |
- Spawn(isolate, new IsolateSpawnState(port.Id(), |
- func, |
- message, |
- paused.value(), |
- fatal_errors, |
- on_exit_port, |
- on_error_port)); |
+ Dart::thread_pool()->Run(new SpawnIsolateTask( |
+ new IsolateSpawnState(port.Id(), |
+ isolate->origin_id(), |
+ isolate->init_callback_data(), |
+ func, |
+ message, |
+ paused.value(), |
+ fatal_errors, |
+ on_exit_port, |
+ on_error_port))); |
return Object::null(); |
} |
} |
@@ -327,6 +341,7 @@ DEFINE_NATIVE_ENTRY(Isolate_spawnUri, 12) { |
IsolateSpawnState* state = new IsolateSpawnState( |
port.Id(), |
+ isolate->init_callback_data(), |
canonical_uri, |
utf8_package_root, |
const_cast<const char**>(utf8_package_map), |
@@ -342,7 +357,7 @@ DEFINE_NATIVE_ENTRY(Isolate_spawnUri, 12) { |
state->isolate_flags()->set_checked(checked.value()); |
} |
- Spawn(isolate, state); |
+ Dart::thread_pool()->Run(new SpawnIsolateTask(state)); |
return Object::null(); |
} |