| 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 24 matching lines...) Expand all Loading... |
| 35 intptr_t port_id_; | 35 intptr_t port_id_; |
| 36 }; | 36 }; |
| 37 | 37 |
| 38 | 38 |
| 39 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { | 39 static uint8_t* allocator(uint8_t* ptr, intptr_t old_size, intptr_t new_size) { |
| 40 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); | 40 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size); |
| 41 return reinterpret_cast<uint8_t*>(new_ptr); | 41 return reinterpret_cast<uint8_t*>(new_ptr); |
| 42 } | 42 } |
| 43 | 43 |
| 44 | 44 |
| 45 static void StoreError(Isolate* isolate, const Object& obj) { | |
| 46 ASSERT(obj.IsError()); | |
| 47 isolate->object_store()->set_sticky_error(Error::Cast(obj)); | |
| 48 } | |
| 49 | |
| 50 | |
| 51 // TODO(turnidge): Move to DartLibraryCalls. | 45 // TODO(turnidge): Move to DartLibraryCalls. |
| 52 static RawObject* ReceivePortCreate(intptr_t port_id) { | 46 static RawObject* ReceivePortCreate(intptr_t port_id) { |
| 53 Isolate* isolate = Isolate::Current(); | 47 Isolate* isolate = Isolate::Current(); |
| 54 Function& func = | 48 Function& func = |
| 55 Function::Handle(isolate, | 49 Function::Handle(isolate, |
| 56 isolate->object_store()->receive_port_create_function()); | 50 isolate->object_store()->receive_port_create_function()); |
| 57 const int kNumArguments = 1; | 51 const int kNumArguments = 1; |
| 58 if (func.IsNull()) { | 52 if (func.IsNull()) { |
| 59 Library& isolate_lib = Library::Handle(Library::IsolateLibrary()); | 53 Library& isolate_lib = Library::Handle(Library::IsolateLibrary()); |
| 60 ASSERT(!isolate_lib.IsNull()); | 54 ASSERT(!isolate_lib.IsNull()); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 75 args.SetAt(0, Integer::Handle(isolate, Integer::New(port_id))); | 69 args.SetAt(0, Integer::Handle(isolate, Integer::New(port_id))); |
| 76 const Object& result = | 70 const Object& result = |
| 77 Object::Handle(isolate, DartEntry::InvokeFunction(func, args)); | 71 Object::Handle(isolate, DartEntry::InvokeFunction(func, args)); |
| 78 if (!result.IsError()) { | 72 if (!result.IsError()) { |
| 79 PortMap::SetLive(port_id); | 73 PortMap::SetLive(port_id); |
| 80 } | 74 } |
| 81 return result.raw(); | 75 return result.raw(); |
| 82 } | 76 } |
| 83 | 77 |
| 84 | 78 |
| 85 static void ShutdownIsolate(uword parameter) { | |
| 86 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); | |
| 87 { | |
| 88 // Print the error if there is one. This may execute dart code to | |
| 89 // print the exception object, so we need to use a StartIsolateScope. | |
| 90 StartIsolateScope start_scope(isolate); | |
| 91 StackZone zone(isolate); | |
| 92 HandleScope handle_scope(isolate); | |
| 93 Error& error = Error::Handle(); | |
| 94 error = isolate->object_store()->sticky_error(); | |
| 95 if (!error.IsNull()) { | |
| 96 OS::PrintErr("in ShutdownIsolate: %s\n", error.ToErrorCString()); | |
| 97 } | |
| 98 } | |
| 99 { | |
| 100 // Shut the isolate down. | |
| 101 SwitchIsolateScope switch_scope(isolate); | |
| 102 Dart::ShutdownIsolate(); | |
| 103 } | |
| 104 } | |
| 105 | |
| 106 | |
| 107 static char* GetRootScriptUri(Isolate* isolate) { | |
| 108 const Library& library = | |
| 109 Library::Handle(isolate->object_store()->root_library()); | |
| 110 ASSERT(!library.IsNull()); | |
| 111 const String& script_name = String::Handle(library.url()); | |
| 112 return isolate->current_zone()->MakeCopyOfString(script_name.ToCString()); | |
| 113 } | |
| 114 | |
| 115 | |
| 116 DEFINE_NATIVE_ENTRY(ReceivePortImpl_factory, 1) { | 79 DEFINE_NATIVE_ENTRY(ReceivePortImpl_factory, 1) { |
| 117 ASSERT(AbstractTypeArguments::CheckedHandle( | 80 ASSERT(AbstractTypeArguments::CheckedHandle( |
| 118 arguments->NativeArgAt(0)).IsNull()); | 81 arguments->NativeArgAt(0)).IsNull()); |
| 119 intptr_t port_id = | 82 intptr_t port_id = |
| 120 PortMap::CreatePort(arguments->isolate()->message_handler()); | 83 PortMap::CreatePort(arguments->isolate()->message_handler()); |
| 121 const Object& port = Object::Handle(ReceivePortCreate(port_id)); | 84 const Object& port = Object::Handle(ReceivePortCreate(port_id)); |
| 122 if (port.IsError()) { | 85 if (port.IsError()) { |
| 123 Exceptions::PropagateError(Error::Cast(port)); | 86 Exceptions::PropagateError(Error::Cast(port)); |
| 124 } | 87 } |
| 125 return port.raw(); | 88 return port.raw(); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 Dart_ExitScope(); | 158 Dart_ExitScope(); |
| 196 } else { | 159 } else { |
| 197 *error = zone->PrintToString( | 160 *error = zone->PrintToString( |
| 198 "Unable to canonicalize uri '%s': no library tag handler found.", | 161 "Unable to canonicalize uri '%s': no library tag handler found.", |
| 199 uri.ToCString()); | 162 uri.ToCString()); |
| 200 } | 163 } |
| 201 return retval; | 164 return retval; |
| 202 } | 165 } |
| 203 | 166 |
| 204 | 167 |
| 205 class SpawnState { | 168 static bool CreateIsolate(IsolateSpawnState* state, char** error) { |
| 206 public: | |
| 207 SpawnState(const Function& func, const Function& callback_func) | |
| 208 : isolate_(NULL), | |
| 209 script_url_(NULL), | |
| 210 library_url_(NULL), | |
| 211 function_name_(NULL), | |
| 212 exception_callback_name_(NULL) { | |
| 213 script_url_ = strdup(GetRootScriptUri(Isolate::Current())); | |
| 214 const Class& cls = Class::Handle(func.Owner()); | |
| 215 ASSERT(cls.IsTopLevel()); | |
| 216 const Library& lib = Library::Handle(cls.library()); | |
| 217 const String& lib_url = String::Handle(lib.url()); | |
| 218 library_url_ = strdup(lib_url.ToCString()); | |
| 219 | |
| 220 const String& func_name = String::Handle(func.name()); | |
| 221 function_name_ = strdup(func_name.ToCString()); | |
| 222 if (!callback_func.IsNull()) { | |
| 223 const String& callback_name = String::Handle(callback_func.name()); | |
| 224 exception_callback_name_ = strdup(callback_name.ToCString()); | |
| 225 } else { | |
| 226 exception_callback_name_ = strdup("_unhandledExceptionCallback"); | |
| 227 } | |
| 228 } | |
| 229 | |
| 230 explicit SpawnState(const char* script_url) | |
| 231 : isolate_(NULL), | |
| 232 library_url_(NULL), | |
| 233 function_name_(NULL), | |
| 234 exception_callback_name_(NULL) { | |
| 235 script_url_ = strdup(script_url); | |
| 236 library_url_ = NULL; | |
| 237 function_name_ = strdup("main"); | |
| 238 exception_callback_name_ = strdup("_unhandledExceptionCallback"); | |
| 239 } | |
| 240 | |
| 241 ~SpawnState() { | |
| 242 free(script_url_); | |
| 243 free(library_url_); | |
| 244 free(function_name_); | |
| 245 free(exception_callback_name_); | |
| 246 } | |
| 247 | |
| 248 Isolate* isolate() const { return isolate_; } | |
| 249 void set_isolate(Isolate* value) { isolate_ = value; } | |
| 250 char* script_url() const { return script_url_; } | |
| 251 char* library_url() const { return library_url_; } | |
| 252 char* function_name() const { return function_name_; } | |
| 253 char* exception_callback_name() const { return exception_callback_name_; } | |
| 254 | |
| 255 RawObject* ResolveFunction() { | |
| 256 // Resolve the library. | |
| 257 Library& lib = Library::Handle(); | |
| 258 if (library_url()) { | |
| 259 const String& lib_url = String::Handle(String::New(library_url())); | |
| 260 lib = Library::LookupLibrary(lib_url); | |
| 261 if (lib.IsNull() || lib.IsError()) { | |
| 262 const String& msg = String::Handle(String::NewFormatted( | |
| 263 "Unable to find library '%s'.", library_url())); | |
| 264 return LanguageError::New(msg); | |
| 265 } | |
| 266 } else { | |
| 267 lib = isolate()->object_store()->root_library(); | |
| 268 } | |
| 269 ASSERT(!lib.IsNull()); | |
| 270 | |
| 271 // Resolve the function. | |
| 272 const String& func_name = | |
| 273 String::Handle(String::New(function_name())); | |
| 274 const Function& func = Function::Handle(lib.LookupLocalFunction(func_name)); | |
| 275 if (func.IsNull()) { | |
| 276 const String& msg = String::Handle(String::NewFormatted( | |
| 277 "Unable to resolve function '%s' in library '%s'.", | |
| 278 function_name(), (library_url() ? library_url() : script_url()))); | |
| 279 return LanguageError::New(msg); | |
| 280 } | |
| 281 return func.raw(); | |
| 282 } | |
| 283 | |
| 284 void Cleanup() { | |
| 285 SwitchIsolateScope switch_scope(isolate()); | |
| 286 Dart::ShutdownIsolate(); | |
| 287 } | |
| 288 | |
| 289 private: | |
| 290 Isolate* isolate_; | |
| 291 char* script_url_; | |
| 292 char* library_url_; | |
| 293 char* function_name_; | |
| 294 char* exception_callback_name_; | |
| 295 }; | |
| 296 | |
| 297 | |
| 298 static bool CreateIsolate(SpawnState* state, char** error) { | |
| 299 Isolate* parent_isolate = Isolate::Current(); | 169 Isolate* parent_isolate = Isolate::Current(); |
| 300 | 170 |
| 301 Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); | 171 Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); |
| 302 if (callback == NULL) { | 172 if (callback == NULL) { |
| 303 *error = strdup("Null callback specified for isolate creation\n"); | 173 *error = strdup("Null callback specified for isolate creation\n"); |
| 304 Isolate::SetCurrent(parent_isolate); | 174 Isolate::SetCurrent(parent_isolate); |
| 305 return false; | 175 return false; |
| 306 } | 176 } |
| 307 | 177 |
| 308 void* init_data = parent_isolate->init_callback_data(); | 178 void* init_data = parent_isolate->init_callback_data(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 child_isolate->object_store()-> | 210 child_isolate->object_store()-> |
| 341 set_unhandled_exception_handler(callback_name); | 211 set_unhandled_exception_handler(callback_name); |
| 342 } | 212 } |
| 343 } | 213 } |
| 344 if (resolve_error) { | 214 if (resolve_error) { |
| 345 Dart::ShutdownIsolate(); | 215 Dart::ShutdownIsolate(); |
| 346 Isolate::SetCurrent(parent_isolate); | 216 Isolate::SetCurrent(parent_isolate); |
| 347 return false; | 217 return false; |
| 348 } | 218 } |
| 349 | 219 |
| 220 child_isolate->set_spawn_data(reinterpret_cast<uword>(state)); |
| 350 Isolate::SetCurrent(parent_isolate); | 221 Isolate::SetCurrent(parent_isolate); |
| 351 return true; | 222 return true; |
| 352 } | 223 } |
| 353 | 224 |
| 354 | 225 |
| 355 static bool RunIsolate(uword parameter) { | 226 static RawObject* Spawn(NativeArguments* arguments, IsolateSpawnState* state) { |
| 356 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); | |
| 357 SpawnState* state = reinterpret_cast<SpawnState*>(isolate->spawn_data()); | |
| 358 isolate->set_spawn_data(0); | |
| 359 { | |
| 360 StartIsolateScope start_scope(isolate); | |
| 361 StackZone zone(isolate); | |
| 362 HandleScope handle_scope(isolate); | |
| 363 if (!ClassFinalizer::FinalizePendingClasses()) { | |
| 364 // Error is in sticky error already. | |
| 365 return false; | |
| 366 } | |
| 367 | |
| 368 Object& result = Object::Handle(); | |
| 369 result = state->ResolveFunction(); | |
| 370 delete state; | |
| 371 state = NULL; | |
| 372 if (result.IsError()) { | |
| 373 StoreError(isolate, result); | |
| 374 return false; | |
| 375 } | |
| 376 ASSERT(result.IsFunction()); | |
| 377 Function& func = Function::Handle(isolate); | |
| 378 func ^= result.raw(); | |
| 379 result = DartEntry::InvokeFunction(func, Object::empty_array()); | |
| 380 if (result.IsError()) { | |
| 381 StoreError(isolate, result); | |
| 382 return false; | |
| 383 } | |
| 384 } | |
| 385 return true; | |
| 386 } | |
| 387 | |
| 388 | |
| 389 static RawObject* Spawn(NativeArguments* arguments, SpawnState* state) { | |
| 390 // Create a new isolate. | 227 // Create a new isolate. |
| 391 char* error = NULL; | 228 char* error = NULL; |
| 392 if (!CreateIsolate(state, &error)) { | 229 if (!CreateIsolate(state, &error)) { |
| 393 delete state; | 230 delete state; |
| 394 const String& msg = String::Handle(String::New(error)); | 231 const String& msg = String::Handle(String::New(error)); |
| 395 free(error); | 232 free(error); |
| 396 ThrowIsolateSpawnException(msg); | 233 ThrowIsolateSpawnException(msg); |
| 397 } | 234 } |
| 398 | 235 |
| 399 // Try to create a SendPort for the new isolate. | 236 // Try to create a SendPort for the new isolate. |
| 400 const Object& port = Object::Handle( | 237 const Object& port = Object::Handle( |
| 401 DartLibraryCalls::NewSendPort(state->isolate()->main_port())); | 238 DartLibraryCalls::NewSendPort(state->isolate()->main_port())); |
| 402 if (port.IsError()) { | 239 if (port.IsError()) { |
| 403 state->Cleanup(); | 240 state->Cleanup(); |
| 404 delete state; | 241 delete state; |
| 405 Exceptions::PropagateError(Error::Cast(port)); | 242 Exceptions::PropagateError(Error::Cast(port)); |
| 406 } | 243 } |
| 407 | 244 |
| 408 // Start the new isolate. | 245 // Start the new isolate if it is already marked as runnable. |
| 409 state->isolate()->set_spawn_data(reinterpret_cast<uword>(state)); | 246 if (state->isolate()->is_runnable()) { |
| 410 state->isolate()->message_handler()->Run( | 247 state->isolate()->Run(); |
| 411 Dart::thread_pool(), RunIsolate, ShutdownIsolate, | 248 } |
| 412 reinterpret_cast<uword>(state->isolate())); | |
| 413 | 249 |
| 414 return port.raw(); | 250 return port.raw(); |
| 415 } | 251 } |
| 416 | 252 |
| 417 | 253 |
| 418 DEFINE_NATIVE_ENTRY(isolate_spawnFunction, 2) { | 254 DEFINE_NATIVE_ENTRY(isolate_spawnFunction, 2) { |
| 419 GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0)); | 255 GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0)); |
| 420 bool throw_exception = false; | 256 bool throw_exception = false; |
| 421 Function& func = Function::Handle(); | 257 Function& func = Function::Handle(); |
| 422 if (closure.IsClosure()) { | 258 if (closure.IsClosure()) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 #if defined(DEBUG) | 293 #if defined(DEBUG) |
| 458 Context& ctx = Context::Handle(); | 294 Context& ctx = Context::Handle(); |
| 459 ctx = Closure::context(closure); | 295 ctx = Closure::context(closure); |
| 460 ASSERT(ctx.num_variables() == 0); | 296 ASSERT(ctx.num_variables() == 0); |
| 461 if (!callback.IsNull()) { | 297 if (!callback.IsNull()) { |
| 462 ctx = Closure::context(callback); | 298 ctx = Closure::context(callback); |
| 463 ASSERT(ctx.num_variables() == 0); | 299 ASSERT(ctx.num_variables() == 0); |
| 464 } | 300 } |
| 465 #endif | 301 #endif |
| 466 | 302 |
| 467 return Spawn(arguments, new SpawnState(func, callback_func)); | 303 return Spawn(arguments, new IsolateSpawnState(func, callback_func)); |
| 468 } | 304 } |
| 469 | 305 |
| 470 | 306 |
| 471 DEFINE_NATIVE_ENTRY(isolate_spawnUri, 1) { | 307 DEFINE_NATIVE_ENTRY(isolate_spawnUri, 1) { |
| 472 GET_NON_NULL_NATIVE_ARGUMENT(String, uri, arguments->NativeArgAt(0)); | 308 GET_NON_NULL_NATIVE_ARGUMENT(String, uri, arguments->NativeArgAt(0)); |
| 473 | 309 |
| 474 // Canonicalize the uri with respect to the current isolate. | 310 // Canonicalize the uri with respect to the current isolate. |
| 475 char* error = NULL; | 311 char* error = NULL; |
| 476 char* canonical_uri = NULL; | 312 char* canonical_uri = NULL; |
| 477 const Library& root_lib = | 313 const Library& root_lib = |
| 478 Library::Handle(arguments->isolate()->object_store()->root_library()); | 314 Library::Handle(arguments->isolate()->object_store()->root_library()); |
| 479 if (!CanonicalizeUri(arguments->isolate(), root_lib, uri, | 315 if (!CanonicalizeUri(arguments->isolate(), root_lib, uri, |
| 480 &canonical_uri, &error)) { | 316 &canonical_uri, &error)) { |
| 481 const String& msg = String::Handle(String::New(error)); | 317 const String& msg = String::Handle(String::New(error)); |
| 482 ThrowIsolateSpawnException(msg); | 318 ThrowIsolateSpawnException(msg); |
| 483 } | 319 } |
| 484 | 320 |
| 485 return Spawn(arguments, new SpawnState(canonical_uri)); | 321 return Spawn(arguments, new IsolateSpawnState(canonical_uri)); |
| 486 } | 322 } |
| 487 | 323 |
| 488 | 324 |
| 489 DEFINE_NATIVE_ENTRY(isolate_getPortInternal, 0) { | 325 DEFINE_NATIVE_ENTRY(isolate_getPortInternal, 0) { |
| 490 const Object& port = Object::Handle(ReceivePortCreate(isolate->main_port())); | 326 const Object& port = Object::Handle(ReceivePortCreate(isolate->main_port())); |
| 491 if (port.IsError()) { | 327 if (port.IsError()) { |
| 492 Exceptions::PropagateError(Error::Cast(port)); | 328 Exceptions::PropagateError(Error::Cast(port)); |
| 493 } | 329 } |
| 494 return port.raw(); | 330 return port.raw(); |
| 495 } | 331 } |
| 496 | 332 |
| 497 } // namespace dart | 333 } // namespace dart |
| OLD | NEW |