| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 "vm/isolate.h" | 5 #include "vm/deferred_objects.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "vm/deopt_instructions.h" |
| 8 #include "platform/assert.h" | 8 #include "vm/flags.h" |
| 9 #include "platform/json.h" | 9 #include "vm/object.h" |
| 10 #include "lib/mirrors.h" | |
| 11 #include "vm/code_observers.h" | |
| 12 #include "vm/compiler_stats.h" | |
| 13 #include "vm/coverage.h" | |
| 14 #include "vm/dart_api_state.h" | |
| 15 #include "vm/dart_entry.h" | |
| 16 #include "vm/debugger.h" | |
| 17 #include "vm/heap.h" | |
| 18 #include "vm/heap_histogram.h" | |
| 19 #include "vm/message_handler.h" | |
| 20 #include "vm/object_id_ring.h" | |
| 21 #include "vm/object_store.h" | |
| 22 #include "vm/parser.h" | |
| 23 #include "vm/port.h" | |
| 24 #include "vm/reusable_handles.h" | |
| 25 #include "vm/service.h" | |
| 26 #include "vm/simulator.h" | |
| 27 #include "vm/stack_frame.h" | |
| 28 #include "vm/stub_code.h" | |
| 29 #include "vm/symbols.h" | |
| 30 #include "vm/thread.h" | |
| 31 #include "vm/timer.h" | |
| 32 #include "vm/visitor.h" | |
| 33 | |
| 34 | 10 |
| 35 namespace dart { | 11 namespace dart { |
| 36 | 12 |
| 37 DEFINE_FLAG(bool, report_usage_count, false, | |
| 38 "Track function usage and report."); | |
| 39 DEFINE_FLAG(bool, trace_isolates, false, | |
| 40 "Trace isolate creation and shut down."); | |
| 41 DECLARE_FLAG(bool, trace_deoptimization_verbose); | 13 DECLARE_FLAG(bool, trace_deoptimization_verbose); |
| 42 | 14 |
| 43 | 15 |
| 44 void Isolate::RegisterClass(const Class& cls) { | |
| 45 class_table()->Register(cls); | |
| 46 if (object_histogram() != NULL) object_histogram()->RegisterClass(cls); | |
| 47 } | |
| 48 | |
| 49 | |
| 50 class IsolateMessageHandler : public MessageHandler { | |
| 51 public: | |
| 52 explicit IsolateMessageHandler(Isolate* isolate); | |
| 53 ~IsolateMessageHandler(); | |
| 54 | |
| 55 const char* name() const; | |
| 56 void MessageNotify(Message::Priority priority); | |
| 57 bool HandleMessage(Message* message); | |
| 58 | |
| 59 #if defined(DEBUG) | |
| 60 // Check that it is safe to access this handler. | |
| 61 void CheckAccess(); | |
| 62 #endif | |
| 63 bool IsCurrentIsolate() const; | |
| 64 virtual Isolate* GetIsolate() const { return isolate_; } | |
| 65 bool UnhandledExceptionCallbackHandler(const Object& message, | |
| 66 const UnhandledException& error); | |
| 67 | |
| 68 private: | |
| 69 bool ProcessUnhandledException(const Object& message, const Error& result); | |
| 70 RawFunction* ResolveCallbackFunction(); | |
| 71 Isolate* isolate_; | |
| 72 }; | |
| 73 | |
| 74 | |
| 75 IsolateMessageHandler::IsolateMessageHandler(Isolate* isolate) | |
| 76 : isolate_(isolate) { | |
| 77 } | |
| 78 | |
| 79 | |
| 80 IsolateMessageHandler::~IsolateMessageHandler() { | |
| 81 } | |
| 82 | |
| 83 const char* IsolateMessageHandler::name() const { | |
| 84 return isolate_->name(); | |
| 85 } | |
| 86 | |
| 87 | |
| 88 void IsolateMessageHandler::MessageNotify(Message::Priority priority) { | |
| 89 if (priority >= Message::kOOBPriority) { | |
| 90 // Handle out of band messages even if the isolate is busy. | |
| 91 isolate_->ScheduleInterrupts(Isolate::kMessageInterrupt); | |
| 92 } | |
| 93 Dart_MessageNotifyCallback callback = isolate_->message_notify_callback(); | |
| 94 if (callback) { | |
| 95 // Allow the embedder to handle message notification. | |
| 96 (*callback)(Api::CastIsolate(isolate_)); | |
| 97 } | |
| 98 } | |
| 99 | |
| 100 | |
| 101 bool IsolateMessageHandler::HandleMessage(Message* message) { | |
| 102 StartIsolateScope start_scope(isolate_); | |
| 103 StackZone zone(isolate_); | |
| 104 HandleScope handle_scope(isolate_); | |
| 105 | |
| 106 // If the message is in band we lookup the receive port to dispatch to. If | |
| 107 // the receive port is closed, we drop the message without deserializing it. | |
| 108 Object& receive_port = Object::Handle(); | |
| 109 if (!message->IsOOB()) { | |
| 110 receive_port = DartLibraryCalls::LookupReceivePort(message->dest_port()); | |
| 111 if (receive_port.IsError()) { | |
| 112 return ProcessUnhandledException(Object::null_instance(), | |
| 113 Error::Cast(receive_port)); | |
| 114 } | |
| 115 if (receive_port.IsNull()) { | |
| 116 delete message; | |
| 117 return true; | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 // Parse the message. | |
| 122 SnapshotReader reader(message->data(), message->len(), | |
| 123 Snapshot::kMessage, Isolate::Current()); | |
| 124 const Object& msg_obj = Object::Handle(reader.ReadObject()); | |
| 125 if (msg_obj.IsError()) { | |
| 126 // An error occurred while reading the message. | |
| 127 return ProcessUnhandledException(Object::null_instance(), | |
| 128 Error::Cast(msg_obj)); | |
| 129 } | |
| 130 if (!msg_obj.IsNull() && !msg_obj.IsInstance()) { | |
| 131 // TODO(turnidge): We need to decide what an isolate does with | |
| 132 // malformed messages. If they (eventually) come from a remote | |
| 133 // machine, then it might make sense to drop the message entirely. | |
| 134 // In the case that the message originated locally, which is | |
| 135 // always true for now, then this should never occur. | |
| 136 UNREACHABLE(); | |
| 137 } | |
| 138 | |
| 139 Instance& msg = Instance::Handle(); | |
| 140 msg ^= msg_obj.raw(); // Can't use Instance::Cast because may be null. | |
| 141 | |
| 142 bool success = true; | |
| 143 if (message->IsOOB()) { | |
| 144 Service::HandleServiceMessage(isolate_, message->reply_port(), msg); | |
| 145 } else { | |
| 146 const Object& result = Object::Handle( | |
| 147 DartLibraryCalls::HandleMessage( | |
| 148 receive_port, message->reply_port(), msg)); | |
| 149 if (result.IsError()) { | |
| 150 success = ProcessUnhandledException(msg, Error::Cast(result)); | |
| 151 } else { | |
| 152 ASSERT(result.IsNull()); | |
| 153 } | |
| 154 } | |
| 155 delete message; | |
| 156 return success; | |
| 157 } | |
| 158 | |
| 159 | |
| 160 RawFunction* IsolateMessageHandler::ResolveCallbackFunction() { | |
| 161 ASSERT(isolate_->object_store()->unhandled_exception_handler() != NULL); | |
| 162 String& callback_name = String::Handle(isolate_); | |
| 163 if (isolate_->object_store()->unhandled_exception_handler() != | |
| 164 String::null()) { | |
| 165 callback_name = isolate_->object_store()->unhandled_exception_handler(); | |
| 166 } else { | |
| 167 callback_name = String::New("_unhandledExceptionCallback"); | |
| 168 } | |
| 169 Library& lib = | |
| 170 Library::Handle(isolate_, isolate_->object_store()->isolate_library()); | |
| 171 Function& func = | |
| 172 Function::Handle(isolate_, lib.LookupLocalFunction(callback_name)); | |
| 173 if (func.IsNull()) { | |
| 174 lib = isolate_->object_store()->root_library(); | |
| 175 func = lib.LookupLocalFunction(callback_name); | |
| 176 } | |
| 177 return func.raw(); | |
| 178 } | |
| 179 | |
| 180 | |
| 181 bool IsolateMessageHandler::UnhandledExceptionCallbackHandler( | |
| 182 const Object& message, const UnhandledException& error) { | |
| 183 const Instance& cause = Instance::Handle(isolate_, error.exception()); | |
| 184 const Instance& stacktrace = | |
| 185 Instance::Handle(isolate_, error.stacktrace()); | |
| 186 | |
| 187 // Wrap these args into an IsolateUncaughtException object. | |
| 188 const Array& exception_args = Array::Handle(Array::New(3)); | |
| 189 exception_args.SetAt(0, message); | |
| 190 exception_args.SetAt(1, cause); | |
| 191 exception_args.SetAt(2, stacktrace); | |
| 192 const Object& exception = | |
| 193 Object::Handle(isolate_, | |
| 194 Exceptions::Create(Exceptions::kIsolateUnhandledException, | |
| 195 exception_args)); | |
| 196 if (exception.IsError()) { | |
| 197 return false; | |
| 198 } | |
| 199 ASSERT(exception.IsInstance()); | |
| 200 | |
| 201 // Invoke script's callback function. | |
| 202 Object& function = Object::Handle(isolate_, ResolveCallbackFunction()); | |
| 203 if (function.IsNull() || function.IsError()) { | |
| 204 return false; | |
| 205 } | |
| 206 const Array& callback_args = Array::Handle(Array::New(1)); | |
| 207 callback_args.SetAt(0, exception); | |
| 208 const Object& result = | |
| 209 Object::Handle(DartEntry::InvokeFunction(Function::Cast(function), | |
| 210 callback_args)); | |
| 211 if (result.IsError()) { | |
| 212 const Error& err = Error::Cast(result); | |
| 213 OS::PrintErr("failed calling unhandled exception callback: %s\n", | |
| 214 err.ToErrorCString()); | |
| 215 return false; | |
| 216 } | |
| 217 | |
| 218 ASSERT(result.IsBool()); | |
| 219 bool continue_from_exception = Bool::Cast(result).value(); | |
| 220 if (continue_from_exception) { | |
| 221 isolate_->object_store()->clear_sticky_error(); | |
| 222 } | |
| 223 return continue_from_exception; | |
| 224 } | |
| 225 | |
| 226 #if defined(DEBUG) | |
| 227 void IsolateMessageHandler::CheckAccess() { | |
| 228 ASSERT(IsCurrentIsolate()); | |
| 229 } | |
| 230 #endif | |
| 231 | |
| 232 | |
| 233 bool IsolateMessageHandler::IsCurrentIsolate() const { | |
| 234 return (isolate_ == Isolate::Current()); | |
| 235 } | |
| 236 | |
| 237 | |
| 238 bool IsolateMessageHandler::ProcessUnhandledException( | |
| 239 const Object& message, const Error& result) { | |
| 240 if (result.IsUnhandledException()) { | |
| 241 // Invoke the isolate's uncaught exception handler, if it exists. | |
| 242 const UnhandledException& error = UnhandledException::Cast(result); | |
| 243 RawInstance* exception = error.exception(); | |
| 244 if ((exception != isolate_->object_store()->out_of_memory()) && | |
| 245 (exception != isolate_->object_store()->stack_overflow())) { | |
| 246 if (UnhandledExceptionCallbackHandler(message, error)) { | |
| 247 return true; | |
| 248 } | |
| 249 } | |
| 250 } | |
| 251 | |
| 252 // Invoke the isolate's unhandled exception callback if there is one. | |
| 253 if (Isolate::UnhandledExceptionCallback() != NULL) { | |
| 254 Dart_EnterScope(); | |
| 255 Dart_Handle error = Api::NewHandle(isolate_, result.raw()); | |
| 256 (Isolate::UnhandledExceptionCallback())(error); | |
| 257 Dart_ExitScope(); | |
| 258 } | |
| 259 | |
| 260 isolate_->object_store()->set_sticky_error(result); | |
| 261 return false; | |
| 262 } | |
| 263 | |
| 264 | |
| 265 #if defined(DEBUG) | |
| 266 // static | |
| 267 void BaseIsolate::AssertCurrent(BaseIsolate* isolate) { | |
| 268 ASSERT(isolate == Isolate::Current()); | |
| 269 } | |
| 270 #endif | |
| 271 | |
| 272 | |
| 273 void DeferredDouble::Materialize() { | 16 void DeferredDouble::Materialize() { |
| 274 RawDouble** double_slot = reinterpret_cast<RawDouble**>(slot()); | 17 RawDouble** double_slot = reinterpret_cast<RawDouble**>(slot()); |
| 275 *double_slot = Double::New(value()); | 18 *double_slot = Double::New(value()); |
| 276 | 19 |
| 277 if (FLAG_trace_deoptimization_verbose) { | 20 if (FLAG_trace_deoptimization_verbose) { |
| 278 OS::PrintErr("materializing double at %" Px ": %g\n", | 21 OS::PrintErr("materializing double at %" Px ": %g\n", |
| 279 reinterpret_cast<uword>(slot()), value()); | 22 reinterpret_cast<uword>(slot()), value()); |
| 280 } | 23 } |
| 281 } | 24 } |
| 282 | 25 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 uint32_t y = raw_uint32x4->y(); | 64 uint32_t y = raw_uint32x4->y(); |
| 322 uint32_t z = raw_uint32x4->z(); | 65 uint32_t z = raw_uint32x4->z(); |
| 323 uint32_t w = raw_uint32x4->w(); | 66 uint32_t w = raw_uint32x4->w(); |
| 324 OS::PrintErr("materializing Uint32x4 at %" Px ": %x,%x,%x,%x\n", | 67 OS::PrintErr("materializing Uint32x4 at %" Px ": %x,%x,%x,%x\n", |
| 325 reinterpret_cast<uword>(slot()), x, y, z, w); | 68 reinterpret_cast<uword>(slot()), x, y, z, w); |
| 326 } | 69 } |
| 327 } | 70 } |
| 328 | 71 |
| 329 | 72 |
| 330 void DeferredObjectRef::Materialize() { | 73 void DeferredObjectRef::Materialize() { |
| 331 DeferredObject* obj = Isolate::Current()->GetDeferredObject(index()); | 74 // TODO(turnidge): Consider passing the deopt_context to materialize |
| 75 // instead of accessing it through the current isolate. It would |
| 76 // make it easier to test deferred object materialization in a unit |
| 77 // test eventually. |
| 78 DeferredObject* obj = |
| 79 Isolate::Current()->deopt_context()->GetDeferredObject(index()); |
| 332 *slot() = obj->object(); | 80 *slot() = obj->object(); |
| 333 if (FLAG_trace_deoptimization_verbose) { | 81 if (FLAG_trace_deoptimization_verbose) { |
| 334 OS::PrintErr("writing instance ref at %" Px ": %s\n", | 82 OS::PrintErr("writing instance ref at %" Px ": %s\n", |
| 335 reinterpret_cast<uword>(slot()), | 83 reinterpret_cast<uword>(slot()), |
| 336 Instance::Handle(obj->object()).ToCString()); | 84 Instance::Handle(obj->object()).ToCString()); |
| 337 } | 85 } |
| 338 } | 86 } |
| 339 | 87 |
| 340 | 88 |
| 341 RawInstance* DeferredObject::object() { | 89 RawInstance* DeferredObject::object() { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 369 if (FLAG_trace_deoptimization_verbose) { | 117 if (FLAG_trace_deoptimization_verbose) { |
| 370 OS::PrintErr(" %s <- %s\n", | 118 OS::PrintErr(" %s <- %s\n", |
| 371 String::Handle(field.name()).ToCString(), | 119 String::Handle(field.name()).ToCString(), |
| 372 value.ToCString()); | 120 value.ToCString()); |
| 373 } | 121 } |
| 374 } | 122 } |
| 375 | 123 |
| 376 object_ = &obj; | 124 object_ = &obj; |
| 377 } | 125 } |
| 378 | 126 |
| 379 | |
| 380 #define REUSABLE_HANDLE_INITIALIZERS(object) \ | |
| 381 object##_handle_(NULL), | |
| 382 | |
| 383 Isolate::Isolate() | |
| 384 : store_buffer_(), | |
| 385 message_notify_callback_(NULL), | |
| 386 name_(NULL), | |
| 387 start_time_(OS::GetCurrentTimeMicros()), | |
| 388 main_port_(0), | |
| 389 heap_(NULL), | |
| 390 object_store_(NULL), | |
| 391 top_context_(Context::null()), | |
| 392 top_exit_frame_info_(0), | |
| 393 init_callback_data_(NULL), | |
| 394 library_tag_handler_(NULL), | |
| 395 api_state_(NULL), | |
| 396 stub_code_(NULL), | |
| 397 debugger_(NULL), | |
| 398 single_step_(false), | |
| 399 simulator_(NULL), | |
| 400 long_jump_base_(NULL), | |
| 401 timer_list_(), | |
| 402 deopt_id_(0), | |
| 403 mutex_(new Mutex()), | |
| 404 stack_limit_(0), | |
| 405 saved_stack_limit_(0), | |
| 406 message_handler_(NULL), | |
| 407 spawn_data_(0), | |
| 408 is_runnable_(false), | |
| 409 gc_prologue_callbacks_(), | |
| 410 gc_epilogue_callbacks_(), | |
| 411 defer_finalization_count_(0), | |
| 412 deopt_cpu_registers_copy_(NULL), | |
| 413 deopt_fpu_registers_copy_(NULL), | |
| 414 deopt_frame_copy_(NULL), | |
| 415 deopt_frame_copy_size_(0), | |
| 416 deferred_boxes_(NULL), | |
| 417 deferred_object_refs_(NULL), | |
| 418 deferred_objects_count_(0), | |
| 419 deferred_objects_(NULL), | |
| 420 stacktrace_(NULL), | |
| 421 stack_frame_index_(-1), | |
| 422 object_histogram_(NULL), | |
| 423 object_id_ring_(NULL), | |
| 424 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS) | |
| 425 reusable_handles_() { | |
| 426 if (FLAG_print_object_histogram && (Dart::vm_isolate() != NULL)) { | |
| 427 object_histogram_ = new ObjectHistogram(this); | |
| 428 } | |
| 429 } | |
| 430 #undef REUSABLE_HANDLE_INITIALIZERS | |
| 431 | |
| 432 | |
| 433 Isolate::~Isolate() { | |
| 434 delete [] name_; | |
| 435 delete heap_; | |
| 436 delete object_store_; | |
| 437 delete api_state_; | |
| 438 delete stub_code_; | |
| 439 delete debugger_; | |
| 440 #if defined(USING_SIMULATOR) | |
| 441 delete simulator_; | |
| 442 #endif | |
| 443 delete mutex_; | |
| 444 mutex_ = NULL; // Fail fast if interrupts are scheduled on a dead isolate. | |
| 445 delete message_handler_; | |
| 446 message_handler_ = NULL; // Fail fast if we send messages to a dead isolate. | |
| 447 delete object_histogram_; | |
| 448 } | |
| 449 | |
| 450 void Isolate::SetCurrent(Isolate* current) { | |
| 451 Thread::SetThreadLocal(isolate_key, reinterpret_cast<uword>(current)); | |
| 452 } | |
| 453 | |
| 454 | |
| 455 // The single thread local key which stores all the thread local data | |
| 456 // for a thread. Since an Isolate is the central repository for | |
| 457 // storing all isolate specific information a single thread local key | |
| 458 // is sufficient. | |
| 459 ThreadLocalKey Isolate::isolate_key = Thread::kUnsetThreadLocalKey; | |
| 460 | |
| 461 | |
| 462 void Isolate::InitOnce() { | |
| 463 ASSERT(isolate_key == Thread::kUnsetThreadLocalKey); | |
| 464 isolate_key = Thread::CreateThreadLocal(); | |
| 465 ASSERT(isolate_key != Thread::kUnsetThreadLocalKey); | |
| 466 create_callback_ = NULL; | |
| 467 } | |
| 468 | |
| 469 | |
| 470 Isolate* Isolate::Init(const char* name_prefix) { | |
| 471 Isolate* result = new Isolate(); | |
| 472 ASSERT(result != NULL); | |
| 473 | |
| 474 // TODO(5411455): For now just set the recently created isolate as | |
| 475 // the current isolate. | |
| 476 SetCurrent(result); | |
| 477 | |
| 478 // Setup the isolate specific resuable handles. | |
| 479 #define REUSABLE_HANDLE_ALLOCATION(object) \ | |
| 480 result->object##_handle_ = result->AllocateReusableHandle<object>(); \ | |
| 481 | |
| 482 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_ALLOCATION) | |
| 483 #undef REUSABLE_HANDLE_ALLOCATION | |
| 484 | |
| 485 // Setup the isolate message handler. | |
| 486 MessageHandler* handler = new IsolateMessageHandler(result); | |
| 487 ASSERT(handler != NULL); | |
| 488 result->set_message_handler(handler); | |
| 489 | |
| 490 // Setup the Dart API state. | |
| 491 ApiState* state = new ApiState(); | |
| 492 ASSERT(state != NULL); | |
| 493 result->set_api_state(state); | |
| 494 | |
| 495 // Initialize stack top and limit in case we are running the isolate in the | |
| 496 // main thread. | |
| 497 // TODO(5411455): Need to figure out how to set the stack limit for the | |
| 498 // main thread. | |
| 499 result->SetStackLimitFromCurrentTOS(reinterpret_cast<uword>(&result)); | |
| 500 result->set_main_port(PortMap::CreatePort(result->message_handler())); | |
| 501 result->BuildName(name_prefix); | |
| 502 | |
| 503 result->debugger_ = new Debugger(); | |
| 504 result->debugger_->Initialize(result); | |
| 505 if (FLAG_trace_isolates) { | |
| 506 if (name_prefix == NULL || strcmp(name_prefix, "vm-isolate") != 0) { | |
| 507 OS::Print("[+] Starting isolate:\n" | |
| 508 "\tisolate: %s\n", result->name()); | |
| 509 } | |
| 510 } | |
| 511 return result; | |
| 512 } | |
| 513 | |
| 514 | |
| 515 void Isolate::BuildName(const char* name_prefix) { | |
| 516 ASSERT(name_ == NULL); | |
| 517 if (name_prefix == NULL) { | |
| 518 name_prefix = "isolate"; | |
| 519 } | |
| 520 const char* kFormat = "%s-%lld"; | |
| 521 intptr_t len = OS::SNPrint(NULL, 0, kFormat, name_prefix, main_port()) + 1; | |
| 522 name_ = new char[len]; | |
| 523 OS::SNPrint(name_, len, kFormat, name_prefix, main_port()); | |
| 524 } | |
| 525 | |
| 526 | |
| 527 // TODO(5411455): Use flag to override default value and Validate the | |
| 528 // stack size by querying OS. | |
| 529 uword Isolate::GetSpecifiedStackSize() { | |
| 530 ASSERT(Isolate::kStackSizeBuffer < Thread::GetMaxStackSize()); | |
| 531 uword stack_size = Thread::GetMaxStackSize() - Isolate::kStackSizeBuffer; | |
| 532 return stack_size; | |
| 533 } | |
| 534 | |
| 535 | |
| 536 void Isolate::SetStackLimitFromCurrentTOS(uword stack_top_value) { | |
| 537 #if defined(USING_SIMULATOR) | |
| 538 // Ignore passed-in native stack top and use Simulator stack top. | |
| 539 Simulator* sim = Simulator::Current(); // May allocate a simulator. | |
| 540 ASSERT(simulator() == sim); // This isolate's simulator is the current one. | |
| 541 stack_top_value = sim->StackTop(); | |
| 542 // The overflow area is accounted for by the simulator. | |
| 543 #endif | |
| 544 SetStackLimit(stack_top_value - GetSpecifiedStackSize()); | |
| 545 } | |
| 546 | |
| 547 | |
| 548 void Isolate::SetStackLimit(uword limit) { | |
| 549 MutexLocker ml(mutex_); | |
| 550 if (stack_limit_ == saved_stack_limit_) { | |
| 551 // No interrupt pending, set stack_limit_ too. | |
| 552 stack_limit_ = limit; | |
| 553 } | |
| 554 saved_stack_limit_ = limit; | |
| 555 } | |
| 556 | |
| 557 | |
| 558 void Isolate::ScheduleInterrupts(uword interrupt_bits) { | |
| 559 // TODO(turnidge): Can't use MutexLocker here because MutexLocker is | |
| 560 // a StackResource, which requires a current isolate. Should | |
| 561 // MutexLocker really be a StackResource? | |
| 562 mutex_->Lock(); | |
| 563 ASSERT((interrupt_bits & ~kInterruptsMask) == 0); // Must fit in mask. | |
| 564 if (stack_limit_ == saved_stack_limit_) { | |
| 565 stack_limit_ = (~static_cast<uword>(0)) & ~kInterruptsMask; | |
| 566 } | |
| 567 stack_limit_ |= interrupt_bits; | |
| 568 mutex_->Unlock(); | |
| 569 } | |
| 570 | |
| 571 | |
| 572 bool Isolate::MakeRunnable() { | |
| 573 ASSERT(Isolate::Current() == NULL); | |
| 574 // Can't use MutexLocker here because MutexLocker is | |
| 575 // a StackResource, which requires a current isolate. | |
| 576 mutex_->Lock(); | |
| 577 // Check if we are in a valid state to make the isolate runnable. | |
| 578 if (is_runnable_ == true) { | |
| 579 mutex_->Unlock(); | |
| 580 return false; // Already runnable. | |
| 581 } | |
| 582 // Set the isolate as runnable and if we are being spawned schedule | |
| 583 // isolate on thread pool for execution. | |
| 584 is_runnable_ = true; | |
| 585 IsolateSpawnState* state = reinterpret_cast<IsolateSpawnState*>(spawn_data()); | |
| 586 if (state != NULL) { | |
| 587 ASSERT(this == state->isolate()); | |
| 588 Run(); | |
| 589 } | |
| 590 mutex_->Unlock(); | |
| 591 return true; | |
| 592 } | |
| 593 | |
| 594 | |
| 595 static void StoreError(Isolate* isolate, const Object& obj) { | |
| 596 ASSERT(obj.IsError()); | |
| 597 isolate->object_store()->set_sticky_error(Error::Cast(obj)); | |
| 598 } | |
| 599 | |
| 600 | |
| 601 static bool RunIsolate(uword parameter) { | |
| 602 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); | |
| 603 IsolateSpawnState* state = NULL; | |
| 604 { | |
| 605 MutexLocker ml(isolate->mutex()); | |
| 606 state = reinterpret_cast<IsolateSpawnState*>(isolate->spawn_data()); | |
| 607 isolate->set_spawn_data(0); | |
| 608 } | |
| 609 { | |
| 610 StartIsolateScope start_scope(isolate); | |
| 611 StackZone zone(isolate); | |
| 612 HandleScope handle_scope(isolate); | |
| 613 if (!ClassFinalizer::FinalizePendingClasses()) { | |
| 614 // Error is in sticky error already. | |
| 615 return false; | |
| 616 } | |
| 617 | |
| 618 // Set up specific unhandled exception handler. | |
| 619 const String& callback_name = String::Handle( | |
| 620 isolate, String::New(state->exception_callback_name())); | |
| 621 isolate->object_store()-> | |
| 622 set_unhandled_exception_handler(callback_name); | |
| 623 | |
| 624 Object& result = Object::Handle(); | |
| 625 result = state->ResolveFunction(); | |
| 626 delete state; | |
| 627 state = NULL; | |
| 628 if (result.IsError()) { | |
| 629 StoreError(isolate, result); | |
| 630 return false; | |
| 631 } | |
| 632 ASSERT(result.IsFunction()); | |
| 633 Function& func = Function::Handle(isolate); | |
| 634 func ^= result.raw(); | |
| 635 result = DartEntry::InvokeFunction(func, Object::empty_array()); | |
| 636 if (result.IsError()) { | |
| 637 StoreError(isolate, result); | |
| 638 return false; | |
| 639 } | |
| 640 } | |
| 641 return true; | |
| 642 } | |
| 643 | |
| 644 | |
| 645 static void ShutdownIsolate(uword parameter) { | |
| 646 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); | |
| 647 { | |
| 648 // Print the error if there is one. This may execute dart code to | |
| 649 // print the exception object, so we need to use a StartIsolateScope. | |
| 650 StartIsolateScope start_scope(isolate); | |
| 651 StackZone zone(isolate); | |
| 652 HandleScope handle_scope(isolate); | |
| 653 Error& error = Error::Handle(); | |
| 654 error = isolate->object_store()->sticky_error(); | |
| 655 if (!error.IsNull()) { | |
| 656 OS::PrintErr("in ShutdownIsolate: %s\n", error.ToErrorCString()); | |
| 657 } | |
| 658 Dart::RunShutdownCallback(); | |
| 659 } | |
| 660 { | |
| 661 // Shut the isolate down. | |
| 662 SwitchIsolateScope switch_scope(isolate); | |
| 663 Dart::ShutdownIsolate(); | |
| 664 } | |
| 665 } | |
| 666 | |
| 667 | |
| 668 void Isolate::Run() { | |
| 669 message_handler()->Run(Dart::thread_pool(), | |
| 670 RunIsolate, | |
| 671 ShutdownIsolate, | |
| 672 reinterpret_cast<uword>(this)); | |
| 673 } | |
| 674 | |
| 675 | |
| 676 uword Isolate::GetAndClearInterrupts() { | |
| 677 MutexLocker ml(mutex_); | |
| 678 if (stack_limit_ == saved_stack_limit_) { | |
| 679 return 0; // No interrupt was requested. | |
| 680 } | |
| 681 uword interrupt_bits = stack_limit_ & kInterruptsMask; | |
| 682 stack_limit_ = saved_stack_limit_; | |
| 683 return interrupt_bits; | |
| 684 } | |
| 685 | |
| 686 | |
| 687 static int MostUsedFunctionFirst(const Function* const* a, | |
| 688 const Function* const* b) { | |
| 689 if ((*a)->usage_counter() > (*b)->usage_counter()) { | |
| 690 return -1; | |
| 691 } else if ((*a)->usage_counter() < (*b)->usage_counter()) { | |
| 692 return 1; | |
| 693 } else { | |
| 694 return 0; | |
| 695 } | |
| 696 } | |
| 697 | |
| 698 | |
| 699 static void AddFunctionsFromClass(const Class& cls, | |
| 700 GrowableArray<const Function*>* functions) { | |
| 701 const Array& class_functions = Array::Handle(cls.functions()); | |
| 702 // Class 'dynamic' is allocated/initialized in a special way, leaving | |
| 703 // the functions field NULL instead of empty. | |
| 704 const int func_len = class_functions.IsNull() ? 0 : class_functions.Length(); | |
| 705 for (int j = 0; j < func_len; j++) { | |
| 706 Function& function = Function::Handle(); | |
| 707 function ^= class_functions.At(j); | |
| 708 if (function.usage_counter() > 0) { | |
| 709 functions->Add(&function); | |
| 710 } | |
| 711 } | |
| 712 } | |
| 713 | |
| 714 | |
| 715 void Isolate::PrintInvokedFunctions() { | |
| 716 ASSERT(this == Isolate::Current()); | |
| 717 const GrowableObjectArray& libraries = | |
| 718 GrowableObjectArray::Handle(object_store()->libraries()); | |
| 719 Library& library = Library::Handle(); | |
| 720 GrowableArray<const Function*> invoked_functions; | |
| 721 for (int i = 0; i < libraries.Length(); i++) { | |
| 722 library ^= libraries.At(i); | |
| 723 Class& cls = Class::Handle(); | |
| 724 ClassDictionaryIterator iter(library, | |
| 725 ClassDictionaryIterator::kIteratePrivate); | |
| 726 while (iter.HasNext()) { | |
| 727 cls = iter.GetNextClass(); | |
| 728 AddFunctionsFromClass(cls, &invoked_functions); | |
| 729 } | |
| 730 } | |
| 731 invoked_functions.Sort(MostUsedFunctionFirst); | |
| 732 for (int i = 0; i < invoked_functions.length(); i++) { | |
| 733 OS::Print("%10" Pd " x %s\n", | |
| 734 invoked_functions[i]->usage_counter(), | |
| 735 invoked_functions[i]->ToFullyQualifiedCString()); | |
| 736 } | |
| 737 } | |
| 738 | |
| 739 | |
| 740 class FinalizeWeakPersistentHandlesVisitor : public HandleVisitor { | |
| 741 public: | |
| 742 FinalizeWeakPersistentHandlesVisitor() { | |
| 743 } | |
| 744 | |
| 745 void VisitHandle(uword addr) { | |
| 746 FinalizablePersistentHandle* handle = | |
| 747 reinterpret_cast<FinalizablePersistentHandle*>(addr); | |
| 748 FinalizablePersistentHandle::Finalize(handle); | |
| 749 } | |
| 750 | |
| 751 private: | |
| 752 DISALLOW_COPY_AND_ASSIGN(FinalizeWeakPersistentHandlesVisitor); | |
| 753 }; | |
| 754 | |
| 755 | |
| 756 void Isolate::Shutdown() { | |
| 757 ASSERT(this == Isolate::Current()); | |
| 758 ASSERT(top_resource() == NULL); | |
| 759 ASSERT((heap_ == NULL) || heap_->Verify()); | |
| 760 | |
| 761 // Create an area where we do have a zone and a handle scope so that we can | |
| 762 // call VM functions while tearing this isolate down. | |
| 763 { | |
| 764 StackZone stack_zone(this); | |
| 765 HandleScope handle_scope(this); | |
| 766 | |
| 767 if (FLAG_print_object_histogram) { | |
| 768 heap()->CollectAllGarbage(); | |
| 769 object_histogram()->Print(); | |
| 770 } | |
| 771 | |
| 772 // Clean up debugger resources. | |
| 773 debugger()->Shutdown(); | |
| 774 | |
| 775 // Close all the ports owned by this isolate. | |
| 776 PortMap::ClosePorts(message_handler()); | |
| 777 | |
| 778 // Fail fast if anybody tries to post any more messsages to this isolate. | |
| 779 delete message_handler(); | |
| 780 set_message_handler(NULL); | |
| 781 | |
| 782 // Dump all accumalated timer data for the isolate. | |
| 783 timer_list_.ReportTimers(); | |
| 784 if (FLAG_report_usage_count) { | |
| 785 PrintInvokedFunctions(); | |
| 786 } | |
| 787 | |
| 788 // Write out the coverage data if collection has been enabled. | |
| 789 CodeCoverage::Write(this); | |
| 790 | |
| 791 // Finalize any weak persistent handles with a non-null referent. | |
| 792 FinalizeWeakPersistentHandlesVisitor visitor; | |
| 793 api_state()->weak_persistent_handles().VisitHandles(&visitor); | |
| 794 | |
| 795 CompilerStats::Print(); | |
| 796 // TODO(asiva): Move this code to Dart::Cleanup when we have that method | |
| 797 // as the cleanup for Dart::InitOnce. | |
| 798 CodeObservers::DeleteAll(); | |
| 799 if (FLAG_trace_isolates) { | |
| 800 heap()->PrintSizes(); | |
| 801 megamorphic_cache_table()->PrintSizes(); | |
| 802 Symbols::DumpStats(); | |
| 803 OS::Print("[-] Stopping isolate:\n" | |
| 804 "\tisolate: %s\n", name()); | |
| 805 } | |
| 806 } | |
| 807 | |
| 808 // TODO(5411455): For now just make sure there are no current isolates | |
| 809 // as we are shutting down the isolate. | |
| 810 SetCurrent(NULL); | |
| 811 } | |
| 812 | |
| 813 | |
| 814 Dart_IsolateCreateCallback Isolate::create_callback_ = NULL; | |
| 815 Dart_IsolateInterruptCallback Isolate::interrupt_callback_ = NULL; | |
| 816 Dart_IsolateUnhandledExceptionCallback | |
| 817 Isolate::unhandled_exception_callback_ = NULL; | |
| 818 Dart_IsolateShutdownCallback Isolate::shutdown_callback_ = NULL; | |
| 819 Dart_FileOpenCallback Isolate::file_open_callback_ = NULL; | |
| 820 Dart_FileReadCallback Isolate::file_read_callback_ = NULL; | |
| 821 Dart_FileWriteCallback Isolate::file_write_callback_ = NULL; | |
| 822 Dart_FileCloseCallback Isolate::file_close_callback_ = NULL; | |
| 823 Dart_IsolateInterruptCallback Isolate::vmstats_callback_ = NULL; | |
| 824 | |
| 825 | |
| 826 void Isolate::VisitObjectPointers(ObjectPointerVisitor* visitor, | |
| 827 bool visit_prologue_weak_handles, | |
| 828 bool validate_frames) { | |
| 829 ASSERT(visitor != NULL); | |
| 830 | |
| 831 // Visit objects in the object store. | |
| 832 object_store()->VisitObjectPointers(visitor); | |
| 833 | |
| 834 // Visit objects in the class table. | |
| 835 class_table()->VisitObjectPointers(visitor); | |
| 836 | |
| 837 // Visit objects in the megamorphic cache. | |
| 838 megamorphic_cache_table()->VisitObjectPointers(visitor); | |
| 839 | |
| 840 // Visit objects in per isolate stubs. | |
| 841 StubCode::VisitObjectPointers(visitor); | |
| 842 | |
| 843 // Visit objects in zones. | |
| 844 current_zone()->VisitObjectPointers(visitor); | |
| 845 | |
| 846 // Visit objects in isolate specific handles area. | |
| 847 reusable_handles_.VisitObjectPointers(visitor); | |
| 848 | |
| 849 // Iterate over all the stack frames and visit objects on the stack. | |
| 850 StackFrameIterator frames_iterator(validate_frames); | |
| 851 StackFrame* frame = frames_iterator.NextFrame(); | |
| 852 while (frame != NULL) { | |
| 853 frame->VisitObjectPointers(visitor); | |
| 854 frame = frames_iterator.NextFrame(); | |
| 855 } | |
| 856 | |
| 857 // Visit the dart api state for all local and persistent handles. | |
| 858 if (api_state() != NULL) { | |
| 859 api_state()->VisitObjectPointers(visitor, visit_prologue_weak_handles); | |
| 860 } | |
| 861 | |
| 862 // Visit the top context which is stored in the isolate. | |
| 863 visitor->VisitPointer(reinterpret_cast<RawObject**>(&top_context_)); | |
| 864 | |
| 865 // Visit objects in the debugger. | |
| 866 debugger()->VisitObjectPointers(visitor); | |
| 867 } | |
| 868 | |
| 869 | |
| 870 void Isolate::VisitWeakPersistentHandles(HandleVisitor* visitor, | |
| 871 bool visit_prologue_weak_handles) { | |
| 872 if (api_state() != NULL) { | |
| 873 api_state()->VisitWeakHandles(visitor, visit_prologue_weak_handles); | |
| 874 } | |
| 875 } | |
| 876 | |
| 877 | |
| 878 static Monitor* status_sync = NULL; | |
| 879 | |
| 880 | |
| 881 bool Isolate::FetchStacktrace() { | |
| 882 Isolate* isolate = Isolate::Current(); | |
| 883 MonitorLocker ml(status_sync); | |
| 884 DebuggerStackTrace* stack = Debugger::CollectStackTrace(); | |
| 885 TextBuffer buffer(256); | |
| 886 buffer.Printf("{ \"handle\": \"0x%" Px64 "\", \"stacktrace\": [ ", | |
| 887 reinterpret_cast<int64_t>(isolate)); | |
| 888 intptr_t n_frames = stack->Length(); | |
| 889 String& url = String::Handle(); | |
| 890 String& function = String::Handle(); | |
| 891 for (int i = 0; i < n_frames; i++) { | |
| 892 if (i > 0) { | |
| 893 buffer.Printf(", "); | |
| 894 } | |
| 895 ActivationFrame* frame = stack->FrameAt(i); | |
| 896 url ^= frame->SourceUrl(); | |
| 897 function ^= frame->function().UserVisibleName(); | |
| 898 buffer.Printf("{ \"url\": \"%s\", ", url.ToCString()); | |
| 899 buffer.Printf("\"line\": %" Pd ", ", frame->LineNumber()); | |
| 900 buffer.Printf("\"function\": \"%s\", ", function.ToCString()); | |
| 901 | |
| 902 const Code& code = frame->code(); | |
| 903 buffer.Printf("\"code\": { "); | |
| 904 buffer.Printf("\"alive\": %s, ", code.is_alive() ? "false" : "true"); | |
| 905 buffer.Printf("\"optimized\": %s }}", | |
| 906 code.is_optimized() ? "false" : "true"); | |
| 907 } | |
| 908 buffer.Printf("]}"); | |
| 909 isolate->stacktrace_ = OS::StrNDup(buffer.buf(), buffer.length()); | |
| 910 ml.Notify(); | |
| 911 return true; | |
| 912 } | |
| 913 | |
| 914 | |
| 915 bool Isolate::FetchStackFrameDetails() { | |
| 916 Isolate* isolate = Isolate::Current(); | |
| 917 ASSERT(isolate->stack_frame_index_ >= 0); | |
| 918 MonitorLocker ml(status_sync); | |
| 919 DebuggerStackTrace* stack = Debugger::CollectStackTrace(); | |
| 920 intptr_t frame_index = isolate->stack_frame_index_; | |
| 921 if (frame_index >= stack->Length()) { | |
| 922 // Frame no longer available. | |
| 923 return false; | |
| 924 } | |
| 925 ActivationFrame* frame = stack->FrameAt(frame_index); | |
| 926 TextBuffer buffer(256); | |
| 927 buffer.Printf("{ \"handle\": \"0x%" Px64 "\", \"frame_index\": %" Pd ", ", | |
| 928 reinterpret_cast<int64_t>(isolate), frame_index); | |
| 929 | |
| 930 const Code& code = frame->code(); | |
| 931 buffer.Printf("\"code\": { \"size\": %" Pd ", ", code.Size()); | |
| 932 buffer.Printf("\"alive\": %s, ", code.is_alive() ? "false" : "true"); | |
| 933 buffer.Printf("\"optimized\": %s }, ", | |
| 934 code.is_optimized() ? "false" : "true"); | |
| 935 // TODO(tball): add compilation stats (time, etc.), when available. | |
| 936 | |
| 937 buffer.Printf("\"local_vars\": [ "); | |
| 938 intptr_t n_local_vars = frame->NumLocalVariables(); | |
| 939 String& var_name = String::Handle(); | |
| 940 Instance& value = Instance::Handle(); | |
| 941 for (int i = 0; i < n_local_vars; i++) { | |
| 942 if (i > 0) { | |
| 943 buffer.Printf(", "); | |
| 944 } | |
| 945 intptr_t token_pos, end_pos; | |
| 946 frame->VariableAt(i, &var_name, &token_pos, &end_pos, &value); | |
| 947 buffer.Printf( | |
| 948 "{ \"name\": \"%s\", \"pos\": %" Pd ", \"end_pos\": %" Pd ", " | |
| 949 "\"value\": \"%s\" }", | |
| 950 var_name.ToCString(), token_pos, end_pos, value.ToCString()); | |
| 951 } | |
| 952 buffer.Printf("]}"); | |
| 953 isolate->stacktrace_ = OS::StrNDup(buffer.buf(), buffer.length()); | |
| 954 ml.Notify(); | |
| 955 return true; | |
| 956 } | |
| 957 | |
| 958 | |
| 959 char* Isolate::DoStacktraceInterrupt(Dart_IsolateInterruptCallback cb) { | |
| 960 ASSERT(stacktrace_ == NULL); | |
| 961 SetVmStatsCallback(cb); | |
| 962 if (status_sync == NULL) { | |
| 963 status_sync = new Monitor(); | |
| 964 } | |
| 965 if (is_runnable()) { | |
| 966 ScheduleInterrupts(Isolate::kVmStatusInterrupt); | |
| 967 { | |
| 968 MonitorLocker ml(status_sync); | |
| 969 if (stacktrace_ == NULL) { // It may already be available. | |
| 970 ml.Wait(1000); | |
| 971 } | |
| 972 } | |
| 973 SetVmStatsCallback(NULL); | |
| 974 } | |
| 975 char* result = stacktrace_; | |
| 976 stacktrace_ = NULL; | |
| 977 if (result == NULL) { | |
| 978 // Return empty stack. | |
| 979 TextBuffer buffer(256); | |
| 980 buffer.Printf("{ \"handle\": \"0x%" Px64 "\", \"stacktrace\": []}", | |
| 981 reinterpret_cast<int64_t>(this)); | |
| 982 | |
| 983 result = OS::StrNDup(buffer.buf(), buffer.length()); | |
| 984 } | |
| 985 ASSERT(result != NULL); | |
| 986 // result is freed by VmStats::WebServer(). | |
| 987 return result; | |
| 988 } | |
| 989 | |
| 990 | |
| 991 char* Isolate::GetStatusStacktrace() { | |
| 992 return DoStacktraceInterrupt(&FetchStacktrace); | |
| 993 } | |
| 994 | |
| 995 char* Isolate::GetStatusStackFrame(intptr_t index) { | |
| 996 ASSERT(index >= 0); | |
| 997 stack_frame_index_ = index; | |
| 998 char* result = DoStacktraceInterrupt(&FetchStackFrameDetails); | |
| 999 stack_frame_index_ = -1; | |
| 1000 return result; | |
| 1001 } | |
| 1002 | |
| 1003 | |
| 1004 // Returns the isolate's general detail information. | |
| 1005 char* Isolate::GetStatusDetails() { | |
| 1006 const char* format = "{\n" | |
| 1007 " \"handle\": \"0x%" Px64 "\",\n" | |
| 1008 " \"name\": \"%s\",\n" | |
| 1009 " \"port\": %" Pd ",\n" | |
| 1010 " \"starttime\": %" Pd ",\n" | |
| 1011 " \"stacklimit\": %" Pd ",\n" | |
| 1012 " \"newspace\": {\n" | |
| 1013 " \"used\": %" Pd ",\n" | |
| 1014 " \"capacity\": %" Pd "\n" | |
| 1015 " },\n" | |
| 1016 " \"oldspace\": {\n" | |
| 1017 " \"used\": %" Pd ",\n" | |
| 1018 " \"capacity\": %" Pd "\n" | |
| 1019 " }\n" | |
| 1020 "}"; | |
| 1021 char buffer[300]; | |
| 1022 int64_t address = reinterpret_cast<int64_t>(this); | |
| 1023 int n = OS::SNPrint(buffer, 300, format, address, name(), main_port(), | |
| 1024 (start_time() / 1000L), saved_stack_limit(), | |
| 1025 heap()->Used(Heap::kNew) / KB, | |
| 1026 heap()->Capacity(Heap::kNew) / KB, | |
| 1027 heap()->Used(Heap::kOld) / KB, | |
| 1028 heap()->Capacity(Heap::kOld) / KB); | |
| 1029 ASSERT(n < 300); | |
| 1030 return strdup(buffer); | |
| 1031 } | |
| 1032 | |
| 1033 | |
| 1034 char* Isolate::GetStatus(const char* request) { | |
| 1035 char* p = const_cast<char*>(request); | |
| 1036 const char* service_type = "/isolate/"; | |
| 1037 ASSERT(!strncmp(p, service_type, strlen(service_type))); | |
| 1038 p += strlen(service_type); | |
| 1039 | |
| 1040 // Extract isolate handle. | |
| 1041 int64_t addr; | |
| 1042 OS::StringToInt64(p, &addr); | |
| 1043 // TODO(tball): add validity check when issue 9600 is fixed. | |
| 1044 Isolate* isolate = reinterpret_cast<Isolate*>(addr); | |
| 1045 p += strcspn(p, "/"); | |
| 1046 | |
| 1047 // Query "/isolate/<handle>". | |
| 1048 if (strlen(p) == 0) { | |
| 1049 return isolate->GetStatusDetails(); | |
| 1050 } | |
| 1051 | |
| 1052 // Query "/isolate/<handle>/stacktrace" | |
| 1053 if (!strcmp(p, "/stacktrace")) { | |
| 1054 return isolate->GetStatusStacktrace(); | |
| 1055 } | |
| 1056 | |
| 1057 // Query "/isolate/<handle>/stacktrace/<frame-index>" | |
| 1058 const char* stacktrace_query = "/stacktrace/"; | |
| 1059 int64_t frame_index = -1; | |
| 1060 if (!strncmp(p, stacktrace_query, strlen(stacktrace_query))) { | |
| 1061 p += strlen(stacktrace_query); | |
| 1062 OS::StringToInt64(p, &frame_index); | |
| 1063 if (frame_index >= 0) { | |
| 1064 return isolate->GetStatusStackFrame(frame_index); | |
| 1065 } | |
| 1066 } | |
| 1067 | |
| 1068 // TODO(tball): "/isolate/<handle>/stacktrace/<frame-index>"/disassemble" | |
| 1069 | |
| 1070 return NULL; // Unimplemented query. | |
| 1071 } | |
| 1072 | |
| 1073 | |
| 1074 template<class T> | |
| 1075 T* Isolate::AllocateReusableHandle() { | |
| 1076 T* handle = reinterpret_cast<T*>(reusable_handles_.AllocateScopedHandle()); | |
| 1077 T::initializeHandle(handle, T::null()); | |
| 1078 return handle; | |
| 1079 } | |
| 1080 | |
| 1081 | |
| 1082 static void FillDeferredSlots(DeferredSlot** slot_list) { | |
| 1083 DeferredSlot* slot = *slot_list; | |
| 1084 *slot_list = NULL; | |
| 1085 | |
| 1086 while (slot != NULL) { | |
| 1087 DeferredSlot* current = slot; | |
| 1088 slot = slot->next(); | |
| 1089 | |
| 1090 current->Materialize(); | |
| 1091 | |
| 1092 delete current; | |
| 1093 } | |
| 1094 } | |
| 1095 | |
| 1096 | |
| 1097 void Isolate::MaterializeDeferredBoxes() { | |
| 1098 FillDeferredSlots(&deferred_boxes_); | |
| 1099 } | |
| 1100 | |
| 1101 | |
| 1102 void Isolate::MaterializeDeferredObjects() { | |
| 1103 FillDeferredSlots(&deferred_object_refs_); | |
| 1104 } | |
| 1105 | |
| 1106 | |
| 1107 static char* GetRootScriptUri(Isolate* isolate) { | |
| 1108 const Library& library = | |
| 1109 Library::Handle(isolate->object_store()->root_library()); | |
| 1110 ASSERT(!library.IsNull()); | |
| 1111 const String& script_name = String::Handle(library.url()); | |
| 1112 return isolate->current_zone()->MakeCopyOfString(script_name.ToCString()); | |
| 1113 } | |
| 1114 | |
| 1115 | |
| 1116 IsolateSpawnState::IsolateSpawnState(const Function& func, | |
| 1117 const Function& callback_func) | |
| 1118 : isolate_(NULL), | |
| 1119 script_url_(NULL), | |
| 1120 library_url_(NULL), | |
| 1121 function_name_(NULL), | |
| 1122 exception_callback_name_(NULL) { | |
| 1123 script_url_ = strdup(GetRootScriptUri(Isolate::Current())); | |
| 1124 const Class& cls = Class::Handle(func.Owner()); | |
| 1125 ASSERT(cls.IsTopLevel()); | |
| 1126 const Library& lib = Library::Handle(cls.library()); | |
| 1127 const String& lib_url = String::Handle(lib.url()); | |
| 1128 library_url_ = strdup(lib_url.ToCString()); | |
| 1129 | |
| 1130 const String& func_name = String::Handle(func.name()); | |
| 1131 function_name_ = strdup(func_name.ToCString()); | |
| 1132 if (!callback_func.IsNull()) { | |
| 1133 const String& callback_name = String::Handle(callback_func.name()); | |
| 1134 exception_callback_name_ = strdup(callback_name.ToCString()); | |
| 1135 } else { | |
| 1136 exception_callback_name_ = strdup("_unhandledExceptionCallback"); | |
| 1137 } | |
| 1138 } | |
| 1139 | |
| 1140 | |
| 1141 IsolateSpawnState::IsolateSpawnState(const char* script_url) | |
| 1142 : isolate_(NULL), | |
| 1143 library_url_(NULL), | |
| 1144 function_name_(NULL), | |
| 1145 exception_callback_name_(NULL) { | |
| 1146 script_url_ = strdup(script_url); | |
| 1147 library_url_ = NULL; | |
| 1148 function_name_ = strdup("main"); | |
| 1149 exception_callback_name_ = strdup("_unhandledExceptionCallback"); | |
| 1150 } | |
| 1151 | |
| 1152 | |
| 1153 IsolateSpawnState::~IsolateSpawnState() { | |
| 1154 free(script_url_); | |
| 1155 free(library_url_); | |
| 1156 free(function_name_); | |
| 1157 free(exception_callback_name_); | |
| 1158 } | |
| 1159 | |
| 1160 | |
| 1161 RawObject* IsolateSpawnState::ResolveFunction() { | |
| 1162 // Resolve the library. | |
| 1163 Library& lib = Library::Handle(); | |
| 1164 if (library_url()) { | |
| 1165 const String& lib_url = String::Handle(String::New(library_url())); | |
| 1166 lib = Library::LookupLibrary(lib_url); | |
| 1167 if (lib.IsNull() || lib.IsError()) { | |
| 1168 const String& msg = String::Handle(String::NewFormatted( | |
| 1169 "Unable to find library '%s'.", library_url())); | |
| 1170 return LanguageError::New(msg); | |
| 1171 } | |
| 1172 } else { | |
| 1173 lib = isolate()->object_store()->root_library(); | |
| 1174 } | |
| 1175 ASSERT(!lib.IsNull()); | |
| 1176 | |
| 1177 // Resolve the function. | |
| 1178 const String& func_name = | |
| 1179 String::Handle(String::New(function_name())); | |
| 1180 const Function& func = Function::Handle(lib.LookupLocalFunction(func_name)); | |
| 1181 if (func.IsNull()) { | |
| 1182 const String& msg = String::Handle(String::NewFormatted( | |
| 1183 "Unable to resolve function '%s' in library '%s'.", | |
| 1184 function_name(), (library_url() ? library_url() : script_url()))); | |
| 1185 return LanguageError::New(msg); | |
| 1186 } | |
| 1187 return func.raw(); | |
| 1188 } | |
| 1189 | |
| 1190 | |
| 1191 void IsolateSpawnState::Cleanup() { | |
| 1192 SwitchIsolateScope switch_scope(isolate()); | |
| 1193 Dart::ShutdownIsolate(); | |
| 1194 } | |
| 1195 | |
| 1196 } // namespace dart | 127 } // namespace dart |
| OLD | NEW |