| 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 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 52 | 52 |
| 53 | 53 |
| 54 static void StoreError(Isolate* isolate, const Object& obj) { | 54 static void StoreError(Isolate* isolate, const Object& obj) { |
| 55 ASSERT(obj.IsError()); | 55 ASSERT(obj.IsError()); |
| 56 Error& error = Error::Handle(); | 56 Error& error = Error::Handle(); |
| 57 error ^= obj.raw(); | 57 error ^= obj.raw(); |
| 58 isolate->object_store()->set_sticky_error(error); | 58 isolate->object_store()->set_sticky_error(error); |
| 59 } | 59 } |
| 60 | 60 |
| 61 | 61 |
| 62 static void ThrowErrorException(Exceptions::ExceptionType type, | |
| 63 const char* error_msg, | |
| 64 const char* library_url, | |
| 65 const char* class_name) { | |
| 66 String& str = String::Handle(); | |
| 67 String& name = String::Handle(); | |
| 68 str ^= String::New(error_msg); | |
| 69 name ^= Symbols::New(library_url); | |
| 70 str ^= String::Concat(str, name); | |
| 71 name ^= String::New(":"); | |
| 72 str ^= String::Concat(str, name); | |
| 73 name ^= Symbols::New(class_name); | |
| 74 str ^= String::Concat(str, name); | |
| 75 GrowableArray<const Object*> arguments(1); | |
| 76 arguments.Add(&str); | |
| 77 Exceptions::ThrowByType(type, arguments); | |
| 78 } | |
| 79 | |
| 80 | |
| 81 // TODO(turnidge): Move to DartLibraryCalls. | 62 // TODO(turnidge): Move to DartLibraryCalls. |
| 82 RawObject* ReceivePortCreate(intptr_t port_id) { | 63 RawObject* ReceivePortCreate(intptr_t port_id) { |
| 83 Library& isolate_lib = Library::Handle(Library::IsolateLibrary()); | 64 Library& isolate_lib = Library::Handle(Library::IsolateLibrary()); |
| 84 ASSERT(!isolate_lib.IsNull()); | 65 ASSERT(!isolate_lib.IsNull()); |
| 85 const String& public_class_name = | 66 const String& public_class_name = |
| 86 String::Handle(Symbols::New("_ReceivePortImpl")); | 67 String::Handle(Symbols::New("_ReceivePortImpl")); |
| 87 const String& class_name = | 68 const String& class_name = |
| 88 String::Handle(isolate_lib.PrivateName(public_class_name)); | 69 String::Handle(isolate_lib.PrivateName(public_class_name)); |
| 89 const String& function_name = | 70 const String& function_name = |
| 90 String::Handle(Symbols::New("_get_or_create")); | 71 String::Handle(Symbols::New("_get_or_create")); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 101 arguments.Add(&Integer::Handle(Integer::New(port_id))); | 82 arguments.Add(&Integer::Handle(Integer::New(port_id))); |
| 102 const Object& result = Object::Handle( | 83 const Object& result = Object::Handle( |
| 103 DartEntry::InvokeStatic(function, arguments, kNoArgumentNames)); | 84 DartEntry::InvokeStatic(function, arguments, kNoArgumentNames)); |
| 104 if (!result.IsError()) { | 85 if (!result.IsError()) { |
| 105 PortMap::SetLive(port_id); | 86 PortMap::SetLive(port_id); |
| 106 } | 87 } |
| 107 return result.raw(); | 88 return result.raw(); |
| 108 } | 89 } |
| 109 | 90 |
| 110 | 91 |
| 111 static bool RunIsolate(uword parameter) { | |
| 112 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); | |
| 113 IsolateStartData* data = | |
| 114 reinterpret_cast<IsolateStartData*>(isolate->spawn_data()); | |
| 115 isolate->set_spawn_data(NULL); | |
| 116 char* library_url = data->library_url_; | |
| 117 char* class_name = data->class_name_; | |
| 118 intptr_t port_id = data->port_id_; | |
| 119 delete data; | |
| 120 | |
| 121 { | |
| 122 StartIsolateScope start_scope(isolate); | |
| 123 Zone zone(isolate); | |
| 124 HandleScope handle_scope(isolate); | |
| 125 ASSERT(ClassFinalizer::AllClassesFinalized()); | |
| 126 // Lookup the target class by name, create an instance and call the run | |
| 127 // method. | |
| 128 const String& lib_name = String::Handle(Symbols::New(library_url)); | |
| 129 free(library_url); | |
| 130 const Library& lib = Library::Handle(Library::LookupLibrary(lib_name)); | |
| 131 ASSERT(!lib.IsNull()); | |
| 132 const String& cls_name = String::Handle(Symbols::New(class_name)); | |
| 133 free(class_name); | |
| 134 const Class& target_class = Class::Handle(lib.LookupClass(cls_name)); | |
| 135 // TODO(iposva): Deserialize or call the constructor after allocating. | |
| 136 // For now, we only support a non-parameterized or raw target class. | |
| 137 const Instance& target = Instance::Handle(Instance::New(target_class)); | |
| 138 Object& result = Object::Handle(); | |
| 139 | |
| 140 // Invoke the default constructor. | |
| 141 const String& period = String::Handle(String::New(".")); | |
| 142 String& constructor_name = String::Handle(String::Concat(cls_name, period)); | |
| 143 const Function& default_constructor = | |
| 144 Function::Handle(target_class.LookupConstructor(constructor_name)); | |
| 145 if (!default_constructor.IsNull()) { | |
| 146 GrowableArray<const Object*> arguments(1); | |
| 147 arguments.Add(&target); | |
| 148 arguments.Add(&Smi::Handle(Smi::New(Function::kCtorPhaseAll))); | |
| 149 const Array& kNoArgumentNames = Array::Handle(); | |
| 150 result = DartEntry::InvokeStatic(default_constructor, | |
| 151 arguments, | |
| 152 kNoArgumentNames); | |
| 153 if (result.IsError()) { | |
| 154 StoreError(isolate, result); | |
| 155 return false; | |
| 156 } | |
| 157 ASSERT(result.IsNull()); | |
| 158 } | |
| 159 | |
| 160 // Invoke the "_run" method. | |
| 161 const Function& target_function = Function::Handle(Resolver::ResolveDynamic( | |
| 162 target, String::Handle(Symbols::New("_run")), 2, 0)); | |
| 163 // TODO(iposva): Proper error checking here. | |
| 164 ASSERT(!target_function.IsNull()); | |
| 165 // TODO(iposva): Allocate the proper port number here. | |
| 166 const Object& local_port = Object::Handle(ReceivePortCreate(port_id)); | |
| 167 if (local_port.IsError()) { | |
| 168 StoreError(isolate, local_port); | |
| 169 return false; | |
| 170 } | |
| 171 GrowableArray<const Object*> arguments(1); | |
| 172 arguments.Add(&local_port); | |
| 173 const Array& kNoArgumentNames = Array::Handle(); | |
| 174 result = DartEntry::InvokeDynamic(target, | |
| 175 target_function, | |
| 176 arguments, | |
| 177 kNoArgumentNames); | |
| 178 if (result.IsError()) { | |
| 179 StoreError(isolate, result); | |
| 180 return false; | |
| 181 } | |
| 182 ASSERT(result.IsNull()); | |
| 183 } | |
| 184 return true; | |
| 185 } | |
| 186 | |
| 187 | |
| 188 static void ShutdownIsolate(uword parameter) { | 92 static void ShutdownIsolate(uword parameter) { |
| 189 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); | 93 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); |
| 190 { | 94 { |
| 191 // Print the error if there is one. This may execute dart code to | 95 // Print the error if there is one. This may execute dart code to |
| 192 // print the exception object, so we need to use a StartIsolateScope. | 96 // print the exception object, so we need to use a StartIsolateScope. |
| 193 StartIsolateScope start_scope(isolate); | 97 StartIsolateScope start_scope(isolate); |
| 194 Zone zone(isolate); | 98 Zone zone(isolate); |
| 195 HandleScope handle_scope(isolate); | 99 HandleScope handle_scope(isolate); |
| 196 Error& error = Error::Handle(); | 100 Error& error = Error::Handle(); |
| 197 error = isolate->object_store()->sticky_error(); | 101 error = isolate->object_store()->sticky_error(); |
| 198 if (!error.IsNull()) { | 102 if (!error.IsNull()) { |
| 199 OS::PrintErr("%s\n", error.ToErrorCString()); | 103 OS::PrintErr("%s\n", error.ToErrorCString()); |
| 200 exit(255); | 104 exit(255); |
| 201 } | 105 } |
| 202 } | 106 } |
| 203 { | 107 { |
| 204 // Shut the isolate down. | 108 // Shut the isolate down. |
| 205 SwitchIsolateScope switch_scope(isolate); | 109 SwitchIsolateScope switch_scope(isolate); |
| 206 Dart::ShutdownIsolate(); | 110 Dart::ShutdownIsolate(); |
| 207 } | 111 } |
| 208 } | 112 } |
| 209 | 113 |
| 210 | 114 |
| 211 static bool CheckArguments(const char* library_url, const char* class_name) { | |
| 212 Isolate* isolate = Isolate::Current(); | |
| 213 Zone zone(isolate); | |
| 214 HandleScope handle_scope(isolate); | |
| 215 String& name = String::Handle(); | |
| 216 if (!ClassFinalizer::FinalizePendingClasses()) { | |
| 217 return false; | |
| 218 } | |
| 219 // Lookup the target class by name, create an instance and call the run | |
| 220 // method. | |
| 221 name ^= Symbols::New(library_url); | |
| 222 const Library& lib = Library::Handle(Library::LookupLibrary(name)); | |
| 223 if (lib.IsNull()) { | |
| 224 const String& error_str = String::Handle( | |
| 225 String::New("Error starting Isolate, library not loaded : ")); | |
| 226 const Error& error = Error::Handle(LanguageError::New(error_str)); | |
| 227 Isolate::Current()->object_store()->set_sticky_error(error); | |
| 228 return false; | |
| 229 } | |
| 230 name ^= Symbols::New(class_name); | |
| 231 const Class& target_class = Class::Handle(lib.LookupClass(name)); | |
| 232 if (target_class.IsNull()) { | |
| 233 const String& error_str = String::Handle( | |
| 234 String::New("Error starting Isolate, class not loaded : ")); | |
| 235 const Error& error = Error::Handle(LanguageError::New(error_str)); | |
| 236 Isolate::Current()->object_store()->set_sticky_error(error); | |
| 237 return false; | |
| 238 } | |
| 239 return true; // No errors. | |
| 240 } | |
| 241 | |
| 242 | |
| 243 static char* GetRootScriptUri(Isolate* isolate) { | 115 static char* GetRootScriptUri(Isolate* isolate) { |
| 244 const Library& library = | 116 const Library& library = |
| 245 Library::Handle(isolate->object_store()->root_library()); | 117 Library::Handle(isolate->object_store()->root_library()); |
| 246 ASSERT(!library.IsNull()); | 118 ASSERT(!library.IsNull()); |
| 247 const String& script_name = String::Handle(library.url()); | 119 const String& script_name = String::Handle(library.url()); |
| 248 return isolate->current_zone()->MakeCopyOfString(script_name.ToCString()); | 120 return isolate->current_zone()->MakeCopyOfString(script_name.ToCString()); |
| 249 } | 121 } |
| 250 | 122 |
| 251 | 123 |
| 252 static char* BuildMainName(const char* class_name) { | |
| 253 intptr_t len = OS::SNPrint(NULL, 0, "%s.main", class_name) + 1; | |
| 254 char* chars = reinterpret_cast<char*>( | |
| 255 Isolate::Current()->current_zone()->Allocate(len)); | |
| 256 OS::SNPrint(chars, len, "%s.main", class_name); | |
| 257 return chars; | |
| 258 } | |
| 259 | |
| 260 | |
| 261 DEFINE_NATIVE_ENTRY(IsolateNatives_start, 2) { | |
| 262 Isolate* preserved_isolate = Isolate::Current(); | |
| 263 GET_NATIVE_ARGUMENT(Instance, runnable, arguments->At(0)); | |
| 264 // arguments->At(1) unused. | |
| 265 const Class& runnable_class = Class::Handle(runnable.clazz()); | |
| 266 const char* class_name = String::Handle(runnable_class.Name()).ToCString(); | |
| 267 const Library& library = Library::Handle(runnable_class.library()); | |
| 268 ASSERT(!library.IsNull()); | |
| 269 const char* library_url = String::Handle(library.url()).ToCString(); | |
| 270 intptr_t port_id = 0; | |
| 271 LongJump jump; | |
| 272 bool init_successful = true; | |
| 273 Isolate* spawned_isolate = NULL; | |
| 274 void* callback_data = preserved_isolate->init_callback_data(); | |
| 275 char* error = NULL; | |
| 276 Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); | |
| 277 const char* root_script_uri = GetRootScriptUri(preserved_isolate); | |
| 278 const char* main = BuildMainName(class_name); | |
| 279 if (callback == NULL) { | |
| 280 error = strdup("Null callback specified for isolate creation\n"); | |
| 281 } else if (callback(root_script_uri, main, callback_data, &error)) { | |
| 282 spawned_isolate = Isolate::Current(); | |
| 283 ASSERT(spawned_isolate != NULL); | |
| 284 // Check arguments to see if the specified library and classes are | |
| 285 // loaded, this check will throw an exception if they are not loaded. | |
| 286 if (init_successful && CheckArguments(library_url, class_name)) { | |
| 287 port_id = spawned_isolate->main_port(); | |
| 288 spawned_isolate->set_spawn_data( | |
| 289 reinterpret_cast<uword>( | |
| 290 new IsolateStartData(strdup(library_url), | |
| 291 strdup(class_name), | |
| 292 port_id))); | |
| 293 Isolate::SetCurrent(NULL); | |
| 294 spawned_isolate->message_handler()->Run( | |
| 295 Dart::thread_pool(), RunIsolate, ShutdownIsolate, | |
| 296 reinterpret_cast<uword>(spawned_isolate)); | |
| 297 } else { | |
| 298 // Error spawning the isolate, maybe due to initialization errors or | |
| 299 // errors while loading the application into spawned isolate, shut | |
| 300 // it down and report error. | |
| 301 // Make sure to grab the error message out of the isolate before it has | |
| 302 // been shutdown and to allocate it in the preserved isolates zone. | |
| 303 { | |
| 304 Zone zone(spawned_isolate); | |
| 305 HandleScope scope(spawned_isolate); | |
| 306 const Error& err_obj = Error::Handle( | |
| 307 spawned_isolate->object_store()->sticky_error()); | |
| 308 error = strdup(err_obj.ToErrorCString()); | |
| 309 } | |
| 310 Dart::ShutdownIsolate(); | |
| 311 spawned_isolate = NULL; | |
| 312 } | |
| 313 } | |
| 314 | |
| 315 // Switch back to the original isolate and return. | |
| 316 Isolate::SetCurrent(preserved_isolate); | |
| 317 if (spawned_isolate == NULL) { | |
| 318 // Unable to spawn isolate correctly, throw exception. | |
| 319 ThrowErrorException(Exceptions::kIllegalArgument, | |
| 320 error, | |
| 321 library_url, | |
| 322 class_name); | |
| 323 } | |
| 324 | |
| 325 // TODO(turnidge): Move this code up before we launch the new | |
| 326 // thread. That way we won't have a thread hanging around that we | |
| 327 // can't talk to. | |
| 328 const Object& port = Object::Handle(DartLibraryCalls::NewSendPort(port_id)); | |
| 329 if (port.IsError()) { | |
| 330 Exceptions::PropagateError(Error::Cast(port)); | |
| 331 } | |
| 332 arguments->SetReturn(port); | |
| 333 } | |
| 334 | |
| 335 | |
| 336 DEFINE_NATIVE_ENTRY(ReceivePortImpl_factory, 1) { | 124 DEFINE_NATIVE_ENTRY(ReceivePortImpl_factory, 1) { |
| 337 ASSERT(AbstractTypeArguments::CheckedHandle(arguments->At(0)).IsNull()); | 125 ASSERT(AbstractTypeArguments::CheckedHandle(arguments->At(0)).IsNull()); |
| 338 intptr_t port_id = | 126 intptr_t port_id = |
| 339 PortMap::CreatePort(arguments->isolate()->message_handler()); | 127 PortMap::CreatePort(arguments->isolate()->message_handler()); |
| 340 const Object& port = Object::Handle(ReceivePortCreate(port_id)); | 128 const Object& port = Object::Handle(ReceivePortCreate(port_id)); |
| 341 if (port.IsError()) { | 129 if (port.IsError()) { |
| 342 Exceptions::PropagateError(Error::Cast(port)); | 130 Exceptions::PropagateError(Error::Cast(port)); |
| 343 } | 131 } |
| 344 arguments->SetReturn(port); | 132 arguments->SetReturn(port); |
| 345 } | 133 } |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 char* script_url_; | 281 char* script_url_; |
| 494 char* library_url_; | 282 char* library_url_; |
| 495 char* function_name_; | 283 char* function_name_; |
| 496 }; | 284 }; |
| 497 | 285 |
| 498 | 286 |
| 499 static bool CreateIsolate(SpawnState* state, char** error) { | 287 static bool CreateIsolate(SpawnState* state, char** error) { |
| 500 Isolate* parent_isolate = Isolate::Current(); | 288 Isolate* parent_isolate = Isolate::Current(); |
| 501 | 289 |
| 502 Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); | 290 Dart_IsolateCreateCallback callback = Isolate::CreateCallback(); |
| 503 ASSERT(callback != NULL); | 291 if (callback == NULL) { |
| 292 *error = strdup("Null callback specified for isolate creation\n"); |
| 293 Isolate::SetCurrent(parent_isolate); |
| 294 return false; |
| 295 } |
| 296 |
| 504 void* init_data = parent_isolate->init_callback_data(); | 297 void* init_data = parent_isolate->init_callback_data(); |
| 505 bool retval = (callback)(state->script_url(), | 298 bool retval = (callback)(state->script_url(), |
| 506 state->function_name(), | 299 state->function_name(), |
| 507 init_data, | 300 init_data, |
| 508 error); | 301 error); |
| 509 if (!retval) { | 302 if (!retval) { |
| 510 Isolate::SetCurrent(parent_isolate); | 303 Isolate::SetCurrent(parent_isolate); |
| 511 return false; | 304 return false; |
| 512 } | 305 } |
| 513 | 306 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 535 Dart::ShutdownIsolate(); | 328 Dart::ShutdownIsolate(); |
| 536 Isolate::SetCurrent(parent_isolate); | 329 Isolate::SetCurrent(parent_isolate); |
| 537 return false; | 330 return false; |
| 538 } | 331 } |
| 539 | 332 |
| 540 Isolate::SetCurrent(parent_isolate); | 333 Isolate::SetCurrent(parent_isolate); |
| 541 return true; | 334 return true; |
| 542 } | 335 } |
| 543 | 336 |
| 544 | 337 |
| 545 static bool RunIsolate2(uword parameter) { | 338 static bool RunIsolate(uword parameter) { |
| 546 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); | 339 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); |
| 547 SpawnState* state = reinterpret_cast<SpawnState*>(isolate->spawn_data()); | 340 SpawnState* state = reinterpret_cast<SpawnState*>(isolate->spawn_data()); |
| 548 isolate->set_spawn_data(NULL); | 341 isolate->set_spawn_data(NULL); |
| 549 { | 342 { |
| 550 StartIsolateScope start_scope(isolate); | 343 StartIsolateScope start_scope(isolate); |
| 551 Zone zone(isolate); | 344 Zone zone(isolate); |
| 552 HandleScope handle_scope(isolate); | 345 HandleScope handle_scope(isolate); |
| 553 if (!ClassFinalizer::FinalizePendingClasses()) { | 346 if (!ClassFinalizer::FinalizePendingClasses()) { |
| 554 // Error is in sticky error already. | 347 // Error is in sticky error already. |
| 555 return false; | 348 return false; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 DartLibraryCalls::NewSendPort(state->isolate()->main_port())); | 386 DartLibraryCalls::NewSendPort(state->isolate()->main_port())); |
| 594 if (port.IsError()) { | 387 if (port.IsError()) { |
| 595 state->Cleanup(); | 388 state->Cleanup(); |
| 596 delete state; | 389 delete state; |
| 597 Exceptions::PropagateError(Error::Cast(port)); | 390 Exceptions::PropagateError(Error::Cast(port)); |
| 598 } | 391 } |
| 599 | 392 |
| 600 // Start the new isolate. | 393 // Start the new isolate. |
| 601 state->isolate()->set_spawn_data(reinterpret_cast<uword>(state)); | 394 state->isolate()->set_spawn_data(reinterpret_cast<uword>(state)); |
| 602 state->isolate()->message_handler()->Run( | 395 state->isolate()->message_handler()->Run( |
| 603 Dart::thread_pool(), RunIsolate2, ShutdownIsolate, | 396 Dart::thread_pool(), RunIsolate, ShutdownIsolate, |
| 604 reinterpret_cast<uword>(state->isolate())); | 397 reinterpret_cast<uword>(state->isolate())); |
| 605 | 398 |
| 606 arguments->SetReturn(port); | 399 arguments->SetReturn(port); |
| 607 } | 400 } |
| 608 | 401 |
| 609 | 402 |
| 610 DEFINE_NATIVE_ENTRY(isolate_spawnFunction, 1) { | 403 DEFINE_NATIVE_ENTRY(isolate_spawnFunction, 1) { |
| 611 GET_NATIVE_ARGUMENT(Closure, closure, arguments->At(0)); | 404 GET_NATIVE_ARGUMENT(Closure, closure, arguments->At(0)); |
| 612 const Function& func = Function::Handle(closure.function()); | 405 const Function& func = Function::Handle(closure.function()); |
| 613 const Class& cls = Class::Handle(func.owner()); | 406 const Class& cls = Class::Handle(func.owner()); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 648 | 441 |
| 649 DEFINE_NATIVE_ENTRY(isolate_getPortInternal, 0) { | 442 DEFINE_NATIVE_ENTRY(isolate_getPortInternal, 0) { |
| 650 const Object& port = Object::Handle(ReceivePortCreate(isolate->main_port())); | 443 const Object& port = Object::Handle(ReceivePortCreate(isolate->main_port())); |
| 651 if (port.IsError()) { | 444 if (port.IsError()) { |
| 652 Exceptions::PropagateError(Error::Cast(port)); | 445 Exceptions::PropagateError(Error::Cast(port)); |
| 653 } | 446 } |
| 654 arguments->SetReturn(port); | 447 arguments->SetReturn(port); |
| 655 } | 448 } |
| 656 | 449 |
| 657 } // namespace dart | 450 } // namespace dart |
| OLD | NEW |