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 "include/dart_native_api.h" |
5 #include "platform/assert.h" | 6 #include "platform/assert.h" |
6 #include "vm/bootstrap_natives.h" | 7 #include "vm/bootstrap_natives.h" |
7 #include "vm/class_finalizer.h" | 8 #include "vm/class_finalizer.h" |
8 #include "vm/dart.h" | 9 #include "vm/dart.h" |
9 #include "vm/dart_api_impl.h" | 10 #include "vm/dart_api_impl.h" |
10 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
11 #include "vm/exceptions.h" | 12 #include "vm/exceptions.h" |
12 #include "vm/lockers.h" | 13 #include "vm/lockers.h" |
13 #include "vm/longjump.h" | 14 #include "vm/longjump.h" |
14 #include "vm/message_handler.h" | 15 #include "vm/message_handler.h" |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 } | 119 } |
119 | 120 |
120 | 121 |
121 static void ThrowIsolateSpawnException(const String& message) { | 122 static void ThrowIsolateSpawnException(const String& message) { |
122 const Array& args = Array::Handle(Array::New(1)); | 123 const Array& args = Array::Handle(Array::New(1)); |
123 args.SetAt(0, message); | 124 args.SetAt(0, message); |
124 Exceptions::ThrowByType(Exceptions::kIsolateSpawn, args); | 125 Exceptions::ThrowByType(Exceptions::kIsolateSpawn, args); |
125 } | 126 } |
126 | 127 |
127 | 128 |
128 static bool CreateIsolate(Isolate* parent_isolate, | 129 class SpawnIsolateTask : public ThreadPool::Task { |
129 IsolateSpawnState* state, | 130 public: |
130 char** error) { | 131 explicit SpawnIsolateTask(IsolateSpawnState* state) : state_(state) {} |
131 Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); | 132 |
132 if (callback == NULL) { | 133 virtual void Run() { |
133 *error = strdup("Null callback specified for isolate creation\n"); | 134 // Create a new isolate. |
134 return false; | 135 char* error = NULL; |
| 136 Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); |
| 137 if (callback == NULL) { |
| 138 ReportError( |
| 139 "Isolate spawn is not supported by this Dart implementation\n"); |
| 140 delete state_; |
| 141 state_ = NULL; |
| 142 return; |
| 143 } |
| 144 |
| 145 Dart_IsolateFlags api_flags; |
| 146 state_->isolate_flags()->CopyTo(&api_flags); |
| 147 |
| 148 Isolate* isolate = reinterpret_cast<Isolate*>( |
| 149 (callback)(state_->script_url(), |
| 150 state_->function_name(), |
| 151 state_->package_root(), |
| 152 state_->package_map(), |
| 153 &api_flags, |
| 154 state_->init_data(), |
| 155 &error)); |
| 156 if (isolate == NULL) { |
| 157 ReportError(error); |
| 158 delete state_; |
| 159 state_ = NULL; |
| 160 free(error); |
| 161 return; |
| 162 } |
| 163 |
| 164 if (state_->origin_id() != ILLEGAL_PORT) { |
| 165 // For isolates spawned using spawnFunction we set the origin_id |
| 166 // to the origin_id of the parent isolate. |
| 167 isolate->set_origin_id(state_->origin_id()); |
| 168 } |
| 169 MutexLocker ml(isolate->mutex()); |
| 170 state_->set_isolate(reinterpret_cast<Isolate*>(isolate)); |
| 171 isolate->set_spawn_state(state_); |
| 172 state_ = NULL; |
| 173 if (isolate->is_runnable()) { |
| 174 isolate->Run(); |
| 175 } |
135 } | 176 } |
136 | 177 |
137 Dart_IsolateFlags api_flags; | 178 private: |
138 state->isolate_flags()->CopyTo(&api_flags); | 179 void ReportError(const char* error) { |
| 180 Dart_CObject error_cobj; |
| 181 error_cobj.type = Dart_CObject_kString; |
| 182 error_cobj.value.as_string = const_cast<char*>(error); |
| 183 if (!Dart_PostCObject(state_->parent_port(), &error_cobj)) { |
| 184 // Perhaps the parent isolate died or closed the port before we |
| 185 // could report the error. Ignore. |
| 186 } |
| 187 } |
139 | 188 |
140 void* init_data = parent_isolate->init_callback_data(); | 189 IsolateSpawnState* state_; |
141 Isolate* child_isolate = reinterpret_cast<Isolate*>( | |
142 (callback)(state->script_url(), | |
143 state->function_name(), | |
144 state->package_root(), | |
145 state->package_map(), | |
146 &api_flags, | |
147 init_data, | |
148 error)); | |
149 if (child_isolate == NULL) { | |
150 return false; | |
151 } | |
152 if (!state->is_spawn_uri()) { | |
153 // For isolates spawned using the spawn semantics we set | |
154 // the origin_id to the origin_id of the parent isolate. | |
155 child_isolate->set_origin_id(parent_isolate->origin_id()); | |
156 } | |
157 state->set_isolate(reinterpret_cast<Isolate*>(child_isolate)); | |
158 return true; | |
159 } | |
160 | 190 |
161 | 191 DISALLOW_COPY_AND_ASSIGN(SpawnIsolateTask); |
162 static void Spawn(Isolate* parent_isolate, IsolateSpawnState* state) { | 192 }; |
163 Thread::ExitIsolate(); | |
164 // Create a new isolate. | |
165 char* error = NULL; | |
166 if (!CreateIsolate(parent_isolate, state, &error)) { | |
167 Thread::EnterIsolate(parent_isolate); | |
168 delete state; | |
169 const String& msg = String::Handle(String::New(error)); | |
170 free(error); | |
171 ThrowIsolateSpawnException(msg); | |
172 } | |
173 Thread::EnterIsolate(parent_isolate); | |
174 // Start the new isolate if it is already marked as runnable. | |
175 Isolate* spawned_isolate = state->isolate(); | |
176 MutexLocker ml(spawned_isolate->mutex()); | |
177 spawned_isolate->set_spawn_state(state); | |
178 if (spawned_isolate->is_runnable()) { | |
179 spawned_isolate->Run(); | |
180 } | |
181 } | |
182 | 193 |
183 | 194 |
184 DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 7) { | 195 DEFINE_NATIVE_ENTRY(Isolate_spawnFunction, 7) { |
185 GET_NON_NULL_NATIVE_ARGUMENT(SendPort, port, arguments->NativeArgAt(0)); | 196 GET_NON_NULL_NATIVE_ARGUMENT(SendPort, port, arguments->NativeArgAt(0)); |
186 GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(1)); | 197 GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(1)); |
187 GET_NON_NULL_NATIVE_ARGUMENT(Instance, message, arguments->NativeArgAt(2)); | 198 GET_NON_NULL_NATIVE_ARGUMENT(Instance, message, arguments->NativeArgAt(2)); |
188 GET_NON_NULL_NATIVE_ARGUMENT(Bool, paused, arguments->NativeArgAt(3)); | 199 GET_NON_NULL_NATIVE_ARGUMENT(Bool, paused, arguments->NativeArgAt(3)); |
189 GET_NATIVE_ARGUMENT(Bool, fatalErrors, arguments->NativeArgAt(4)); | 200 GET_NATIVE_ARGUMENT(Bool, fatalErrors, arguments->NativeArgAt(4)); |
190 GET_NATIVE_ARGUMENT(SendPort, onExit, arguments->NativeArgAt(5)); | 201 GET_NATIVE_ARGUMENT(SendPort, onExit, arguments->NativeArgAt(5)); |
191 GET_NATIVE_ARGUMENT(SendPort, onError, arguments->NativeArgAt(6)); | 202 GET_NATIVE_ARGUMENT(SendPort, onError, arguments->NativeArgAt(6)); |
192 | 203 |
193 if (closure.IsClosure()) { | 204 if (closure.IsClosure()) { |
194 Function& func = Function::Handle(); | 205 Function& func = Function::Handle(); |
195 func = Closure::function(closure); | 206 func = Closure::function(closure); |
196 if (func.IsImplicitClosureFunction() && func.is_static()) { | 207 if (func.IsImplicitClosureFunction() && func.is_static()) { |
197 #if defined(DEBUG) | 208 #if defined(DEBUG) |
198 Context& ctx = Context::Handle(); | 209 Context& ctx = Context::Handle(); |
199 ctx = Closure::context(closure); | 210 ctx = Closure::context(closure); |
200 ASSERT(ctx.num_variables() == 0); | 211 ASSERT(ctx.num_variables() == 0); |
201 #endif | 212 #endif |
202 // Get the parent function so that we get the right function name. | 213 // Get the parent function so that we get the right function name. |
203 func = func.parent_function(); | 214 func = func.parent_function(); |
204 | 215 |
205 bool fatal_errors = fatalErrors.IsNull() ? true : fatalErrors.value(); | 216 bool fatal_errors = fatalErrors.IsNull() ? true : fatalErrors.value(); |
206 Dart_Port on_exit_port = onExit.IsNull() ? ILLEGAL_PORT : onExit.Id(); | 217 Dart_Port on_exit_port = onExit.IsNull() ? ILLEGAL_PORT : onExit.Id(); |
207 Dart_Port on_error_port = onError.IsNull() ? ILLEGAL_PORT : onError.Id(); | 218 Dart_Port on_error_port = onError.IsNull() ? ILLEGAL_PORT : onError.Id(); |
208 | 219 |
209 Spawn(isolate, new IsolateSpawnState(port.Id(), | 220 Dart::thread_pool()->Run(new SpawnIsolateTask( |
210 func, | 221 new IsolateSpawnState(port.Id(), |
211 message, | 222 isolate->origin_id(), |
212 paused.value(), | 223 isolate->init_callback_data(), |
213 fatal_errors, | 224 func, |
214 on_exit_port, | 225 message, |
215 on_error_port)); | 226 paused.value(), |
| 227 fatal_errors, |
| 228 on_exit_port, |
| 229 on_error_port))); |
216 return Object::null(); | 230 return Object::null(); |
217 } | 231 } |
218 } | 232 } |
219 const String& msg = String::Handle(String::New( | 233 const String& msg = String::Handle(String::New( |
220 "Isolate.spawn expects to be passed a static or top-level function")); | 234 "Isolate.spawn expects to be passed a static or top-level function")); |
221 Exceptions::ThrowArgumentError(msg); | 235 Exceptions::ThrowArgumentError(msg); |
222 return Object::null(); | 236 return Object::null(); |
223 } | 237 } |
224 | 238 |
225 | 239 |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 // NULL terminated array. | 334 // NULL terminated array. |
321 utf8_package_map[len] = NULL; | 335 utf8_package_map[len] = NULL; |
322 } | 336 } |
323 | 337 |
324 bool fatal_errors = fatalErrors.IsNull() ? true : fatalErrors.value(); | 338 bool fatal_errors = fatalErrors.IsNull() ? true : fatalErrors.value(); |
325 Dart_Port on_exit_port = onExit.IsNull() ? ILLEGAL_PORT : onExit.Id(); | 339 Dart_Port on_exit_port = onExit.IsNull() ? ILLEGAL_PORT : onExit.Id(); |
326 Dart_Port on_error_port = onError.IsNull() ? ILLEGAL_PORT : onError.Id(); | 340 Dart_Port on_error_port = onError.IsNull() ? ILLEGAL_PORT : onError.Id(); |
327 | 341 |
328 IsolateSpawnState* state = new IsolateSpawnState( | 342 IsolateSpawnState* state = new IsolateSpawnState( |
329 port.Id(), | 343 port.Id(), |
| 344 isolate->init_callback_data(), |
330 canonical_uri, | 345 canonical_uri, |
331 utf8_package_root, | 346 utf8_package_root, |
332 const_cast<const char**>(utf8_package_map), | 347 const_cast<const char**>(utf8_package_map), |
333 args, | 348 args, |
334 message, | 349 message, |
335 paused.value(), | 350 paused.value(), |
336 fatal_errors, | 351 fatal_errors, |
337 on_exit_port, | 352 on_exit_port, |
338 on_error_port); | 353 on_error_port); |
339 // If we were passed a value then override the default flags state for | 354 // If we were passed a value then override the default flags state for |
340 // checked mode. | 355 // checked mode. |
341 if (!checked.IsNull()) { | 356 if (!checked.IsNull()) { |
342 state->isolate_flags()->set_checked(checked.value()); | 357 state->isolate_flags()->set_checked(checked.value()); |
343 } | 358 } |
344 | 359 |
345 Spawn(isolate, state); | 360 Dart::thread_pool()->Run(new SpawnIsolateTask(state)); |
346 return Object::null(); | 361 return Object::null(); |
347 } | 362 } |
348 | 363 |
349 | 364 |
350 DEFINE_NATIVE_ENTRY(Isolate_getPortAndCapabilitiesOfCurrentIsolate, 0) { | 365 DEFINE_NATIVE_ENTRY(Isolate_getPortAndCapabilitiesOfCurrentIsolate, 0) { |
351 const Array& result = Array::Handle(Array::New(3)); | 366 const Array& result = Array::Handle(Array::New(3)); |
352 result.SetAt(0, SendPort::Handle(SendPort::New(isolate->main_port()))); | 367 result.SetAt(0, SendPort::Handle(SendPort::New(isolate->main_port()))); |
353 result.SetAt(1, Capability::Handle( | 368 result.SetAt(1, Capability::Handle( |
354 Capability::New(isolate->pause_capability()))); | 369 Capability::New(isolate->pause_capability()))); |
355 result.SetAt(2, Capability::Handle( | 370 result.SetAt(2, Capability::Handle( |
(...skipping 13 matching lines...) Expand all Loading... |
369 MessageWriter writer(&data, &allocator, false); | 384 MessageWriter writer(&data, &allocator, false); |
370 writer.WriteMessage(msg); | 385 writer.WriteMessage(msg); |
371 | 386 |
372 PortMap::PostMessage(new Message(port.Id(), | 387 PortMap::PostMessage(new Message(port.Id(), |
373 data, writer.BytesWritten(), | 388 data, writer.BytesWritten(), |
374 Message::kOOBPriority)); | 389 Message::kOOBPriority)); |
375 return Object::null(); | 390 return Object::null(); |
376 } | 391 } |
377 | 392 |
378 } // namespace dart | 393 } // namespace dart |
OLD | NEW |