| 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/isolate.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 #include "include/dart_native_api.h" | 8 #include "include/dart_native_api.h" |
| 9 #include "platform/assert.h" | 9 #include "platform/assert.h" |
| 10 #include "platform/json.h" | 10 #include "platform/json.h" |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 } | 171 } |
| 172 | 172 |
| 173 | 173 |
| 174 class IsolateMessageHandler : public MessageHandler { | 174 class IsolateMessageHandler : public MessageHandler { |
| 175 public: | 175 public: |
| 176 explicit IsolateMessageHandler(Isolate* isolate); | 176 explicit IsolateMessageHandler(Isolate* isolate); |
| 177 ~IsolateMessageHandler(); | 177 ~IsolateMessageHandler(); |
| 178 | 178 |
| 179 const char* name() const; | 179 const char* name() const; |
| 180 void MessageNotify(Message::Priority priority); | 180 void MessageNotify(Message::Priority priority); |
| 181 bool HandleMessage(Message* message); | 181 MessageStatus HandleMessage(Message* message); |
| 182 void NotifyPauseOnStart(); | 182 void NotifyPauseOnStart(); |
| 183 void NotifyPauseOnExit(); | 183 void NotifyPauseOnExit(); |
| 184 | 184 |
| 185 #if defined(DEBUG) | 185 #if defined(DEBUG) |
| 186 // Check that it is safe to access this handler. | 186 // Check that it is safe to access this handler. |
| 187 void CheckAccess(); | 187 void CheckAccess(); |
| 188 #endif | 188 #endif |
| 189 bool IsCurrentIsolate() const; | 189 bool IsCurrentIsolate() const; |
| 190 virtual Isolate* isolate() const { return isolate_; } | 190 virtual Isolate* isolate() const { return isolate_; } |
| 191 | 191 |
| 192 private: | 192 private: |
| 193 // A result of false indicates that the isolate should terminate the | 193 // A result of false indicates that the isolate should terminate the |
| 194 // processing of further events. | 194 // processing of further events. |
| 195 RawError* HandleLibMessage(const Array& message); | 195 RawError* HandleLibMessage(const Array& message); |
| 196 | 196 |
| 197 bool ProcessUnhandledException(const Error& result); | 197 MessageStatus ProcessUnhandledException(const Error& result); |
| 198 Isolate* isolate_; | 198 Isolate* isolate_; |
| 199 }; | 199 }; |
| 200 | 200 |
| 201 | 201 |
| 202 IsolateMessageHandler::IsolateMessageHandler(Isolate* isolate) | 202 IsolateMessageHandler::IsolateMessageHandler(Isolate* isolate) |
| 203 : isolate_(isolate) { | 203 : isolate_(isolate) { |
| 204 } | 204 } |
| 205 | 205 |
| 206 | 206 |
| 207 IsolateMessageHandler::~IsolateMessageHandler() { | 207 IsolateMessageHandler::~IsolateMessageHandler() { |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 SerializeObject(message, &data, &len, false); | 278 SerializeObject(message, &data, &len, false); |
| 279 this->PostMessage( | 279 this->PostMessage( |
| 280 new Message(Message::kIllegalPort, | 280 new Message(Message::kIllegalPort, |
| 281 data, len, | 281 data, len, |
| 282 Message::kNormalPriority), | 282 Message::kNormalPriority), |
| 283 priority == Isolate::kBeforeNextEventAction /* at_head */); | 283 priority == Isolate::kBeforeNextEventAction /* at_head */); |
| 284 } | 284 } |
| 285 break; | 285 break; |
| 286 } | 286 } |
| 287 case Isolate::kKillMsg: | 287 case Isolate::kKillMsg: |
| 288 case Isolate::kInternalKillMsg: { | 288 case Isolate::kInternalKillMsg: |
| 289 case Isolate::kVMRestartMsg: { |
| 289 // [ OOB, kKillMsg, terminate capability, priority ] | 290 // [ OOB, kKillMsg, terminate capability, priority ] |
| 290 if (message.Length() != 4) return Error::null(); | 291 if (message.Length() != 4) return Error::null(); |
| 291 Object& obj = Object::Handle(I, message.At(3)); | 292 Object& obj = Object::Handle(I, message.At(3)); |
| 292 if (!obj.IsSmi()) return Error::null(); | 293 if (!obj.IsSmi()) return Error::null(); |
| 293 const intptr_t priority = Smi::Cast(obj).Value(); | 294 const intptr_t priority = Smi::Cast(obj).Value(); |
| 294 if (priority == Isolate::kImmediateAction) { | 295 if (priority == Isolate::kImmediateAction) { |
| 295 obj = message.At(2); | 296 obj = message.At(2); |
| 296 // Signal that the isolate should stop execution. | |
| 297 if (I->VerifyTerminateCapability(obj)) { | 297 if (I->VerifyTerminateCapability(obj)) { |
| 298 // We will kill the current isolate by returning an UnwindError. |
| 298 if (msg_type == Isolate::kKillMsg) { | 299 if (msg_type == Isolate::kKillMsg) { |
| 299 const String& msg = String::Handle(String::New( | 300 const String& msg = String::Handle(String::New( |
| 300 "isolate terminated by Isolate.kill")); | 301 "isolate terminated by Isolate.kill")); |
| 301 const UnwindError& error = | 302 const UnwindError& error = |
| 302 UnwindError::Handle(UnwindError::New(msg)); | 303 UnwindError::Handle(UnwindError::New(msg)); |
| 303 error.set_is_user_initiated(true); | 304 error.set_is_user_initiated(true); |
| 304 return error.raw(); | 305 return error.raw(); |
| 305 } else { | 306 } else if (msg_type == Isolate::kInternalKillMsg) { |
| 306 // TODO(turnidge): We should give the message handler a way | |
| 307 // to detect when an isolate is unwinding. | |
| 308 I->message_handler()->set_pause_on_start(false); | |
| 309 I->message_handler()->set_pause_on_exit(false); | |
| 310 const String& msg = String::Handle(String::New( | 307 const String& msg = String::Handle(String::New( |
| 311 "isolate terminated by vm")); | 308 "isolate terminated by vm")); |
| 312 return UnwindError::New(msg); | 309 return UnwindError::New(msg); |
| 310 } else if (msg_type == Isolate::kVMRestartMsg) { |
| 311 // If this is the main isolate, this request to restart |
| 312 // will be caught and handled in the embedder. Otherwise |
| 313 // this unwind error will cause the isolate to exit. |
| 314 const String& msg = String::Handle(String::New( |
| 315 "isolate terminated for vm restart")); |
| 316 const UnwindError& error = |
| 317 UnwindError::Handle(UnwindError::New(msg)); |
| 318 error.set_is_vm_restart(true); |
| 319 return error.raw(); |
| 320 } else { |
| 321 UNREACHABLE(); |
| 313 } | 322 } |
| 314 } else { | 323 } else { |
| 315 return Error::null(); | 324 return Error::null(); |
| 316 } | 325 } |
| 317 } else { | 326 } else { |
| 318 ASSERT((priority == Isolate::kBeforeNextEventAction) || | 327 ASSERT((priority == Isolate::kBeforeNextEventAction) || |
| 319 (priority == Isolate::kAsEventAction)); | 328 (priority == Isolate::kAsEventAction)); |
| 320 // Update the message so that it will be handled immediately when it | 329 // Update the message so that it will be handled immediately when it |
| 321 // is picked up from the message queue the next time. | 330 // is picked up from the message queue the next time. |
| 322 message.SetAt( | 331 message.SetAt( |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 I->ScheduleInterrupts(Isolate::kMessageInterrupt); | 423 I->ScheduleInterrupts(Isolate::kMessageInterrupt); |
| 415 } | 424 } |
| 416 Dart_MessageNotifyCallback callback = I->message_notify_callback(); | 425 Dart_MessageNotifyCallback callback = I->message_notify_callback(); |
| 417 if (callback) { | 426 if (callback) { |
| 418 // Allow the embedder to handle message notification. | 427 // Allow the embedder to handle message notification. |
| 419 (*callback)(Api::CastIsolate(I)); | 428 (*callback)(Api::CastIsolate(I)); |
| 420 } | 429 } |
| 421 } | 430 } |
| 422 | 431 |
| 423 | 432 |
| 424 bool IsolateMessageHandler::HandleMessage(Message* message) { | 433 MessageHandler::MessageStatus IsolateMessageHandler::HandleMessage( |
| 434 Message* message) { |
| 425 ASSERT(IsCurrentIsolate()); | 435 ASSERT(IsCurrentIsolate()); |
| 426 Thread* thread = Thread::Current(); | 436 Thread* thread = Thread::Current(); |
| 427 StackZone stack_zone(thread); | 437 StackZone stack_zone(thread); |
| 428 Zone* zone = stack_zone.GetZone(); | 438 Zone* zone = stack_zone.GetZone(); |
| 429 HandleScope handle_scope(thread); | 439 HandleScope handle_scope(thread); |
| 430 TimelineDurationScope tds(thread, I->GetIsolateStream(), "HandleMessage"); | 440 TimelineDurationScope tds(thread, I->GetIsolateStream(), "HandleMessage"); |
| 431 tds.SetNumArguments(1); | 441 tds.SetNumArguments(1); |
| 432 tds.CopyArgument(0, "isolateName", I->name()); | 442 tds.CopyArgument(0, "isolateName", I->name()); |
| 433 | 443 |
| 434 // If the message is in band we lookup the handler to dispatch to. If the | 444 // If the message is in band we lookup the handler to dispatch to. If the |
| 435 // receive port was closed, we drop the message without deserializing it. | 445 // receive port was closed, we drop the message without deserializing it. |
| 436 // Illegal port is a special case for artificially enqueued isolate library | 446 // Illegal port is a special case for artificially enqueued isolate library |
| 437 // messages which are handled in C++ code below. | 447 // messages which are handled in C++ code below. |
| 438 Object& msg_handler = Object::Handle(zone); | 448 Object& msg_handler = Object::Handle(zone); |
| 439 if (!message->IsOOB() && (message->dest_port() != Message::kIllegalPort)) { | 449 if (!message->IsOOB() && (message->dest_port() != Message::kIllegalPort)) { |
| 440 msg_handler = DartLibraryCalls::LookupHandler(message->dest_port()); | 450 msg_handler = DartLibraryCalls::LookupHandler(message->dest_port()); |
| 441 if (msg_handler.IsError()) { | 451 if (msg_handler.IsError()) { |
| 442 delete message; | 452 delete message; |
| 443 return ProcessUnhandledException(Error::Cast(msg_handler)); | 453 return ProcessUnhandledException(Error::Cast(msg_handler)); |
| 444 } | 454 } |
| 445 if (msg_handler.IsNull()) { | 455 if (msg_handler.IsNull()) { |
| 446 // If the port has been closed then the message will be dropped at this | 456 // If the port has been closed then the message will be dropped at this |
| 447 // point. Make sure to post to the delivery failure port in that case. | 457 // point. Make sure to post to the delivery failure port in that case. |
| 448 if (message->RedirectToDeliveryFailurePort()) { | 458 if (message->RedirectToDeliveryFailurePort()) { |
| 449 PortMap::PostMessage(message); | 459 PortMap::PostMessage(message); |
| 450 } else { | 460 } else { |
| 451 delete message; | 461 delete message; |
| 452 } | 462 } |
| 453 return true; | 463 return kOK; |
| 454 } | 464 } |
| 455 } | 465 } |
| 456 | 466 |
| 457 // Parse the message. | 467 // Parse the message. |
| 458 MessageSnapshotReader reader(message->data(), message->len(), thread); | 468 MessageSnapshotReader reader(message->data(), message->len(), thread); |
| 459 const Object& msg_obj = Object::Handle(zone, reader.ReadObject()); | 469 const Object& msg_obj = Object::Handle(zone, reader.ReadObject()); |
| 460 if (msg_obj.IsError()) { | 470 if (msg_obj.IsError()) { |
| 461 // An error occurred while reading the message. | 471 // An error occurred while reading the message. |
| 462 delete message; | 472 delete message; |
| 463 return ProcessUnhandledException(Error::Cast(msg_obj)); | 473 return ProcessUnhandledException(Error::Cast(msg_obj)); |
| 464 } | 474 } |
| 465 if (!msg_obj.IsNull() && !msg_obj.IsInstance()) { | 475 if (!msg_obj.IsNull() && !msg_obj.IsInstance()) { |
| 466 // TODO(turnidge): We need to decide what an isolate does with | 476 // TODO(turnidge): We need to decide what an isolate does with |
| 467 // malformed messages. If they (eventually) come from a remote | 477 // malformed messages. If they (eventually) come from a remote |
| 468 // machine, then it might make sense to drop the message entirely. | 478 // machine, then it might make sense to drop the message entirely. |
| 469 // In the case that the message originated locally, which is | 479 // In the case that the message originated locally, which is |
| 470 // always true for now, then this should never occur. | 480 // always true for now, then this should never occur. |
| 471 UNREACHABLE(); | 481 UNREACHABLE(); |
| 472 } | 482 } |
| 473 | 483 |
| 474 Instance& msg = Instance::Handle(zone); | 484 Instance& msg = Instance::Handle(zone); |
| 475 msg ^= msg_obj.raw(); // Can't use Instance::Cast because may be null. | 485 msg ^= msg_obj.raw(); // Can't use Instance::Cast because may be null. |
| 476 | 486 |
| 477 bool success = true; | 487 MessageStatus status = kOK; |
| 478 if (message->IsOOB()) { | 488 if (message->IsOOB()) { |
| 479 // OOB messages are expected to be fixed length arrays where the first | 489 // OOB messages are expected to be fixed length arrays where the first |
| 480 // element is a Smi describing the OOB destination. Messages that do not | 490 // element is a Smi describing the OOB destination. Messages that do not |
| 481 // confirm to this layout are silently ignored. | 491 // confirm to this layout are silently ignored. |
| 482 if (msg.IsArray()) { | 492 if (msg.IsArray()) { |
| 483 const Array& oob_msg = Array::Cast(msg); | 493 const Array& oob_msg = Array::Cast(msg); |
| 484 if (oob_msg.Length() > 0) { | 494 if (oob_msg.Length() > 0) { |
| 485 const Object& oob_tag = Object::Handle(zone, oob_msg.At(0)); | 495 const Object& oob_tag = Object::Handle(zone, oob_msg.At(0)); |
| 486 if (oob_tag.IsSmi()) { | 496 if (oob_tag.IsSmi()) { |
| 487 switch (Smi::Cast(oob_tag).Value()) { | 497 switch (Smi::Cast(oob_tag).Value()) { |
| 488 case Message::kServiceOOBMsg: { | 498 case Message::kServiceOOBMsg: { |
| 489 Service::HandleIsolateMessage(I, oob_msg); | 499 Service::HandleIsolateMessage(I, oob_msg); |
| 490 break; | 500 break; |
| 491 } | 501 } |
| 492 case Message::kIsolateLibOOBMsg: { | 502 case Message::kIsolateLibOOBMsg: { |
| 493 const Error& error = Error::Handle(HandleLibMessage(oob_msg)); | 503 const Error& error = Error::Handle(HandleLibMessage(oob_msg)); |
| 494 if (!error.IsNull()) { | 504 if (!error.IsNull()) { |
| 495 success = ProcessUnhandledException(error); | 505 status = ProcessUnhandledException(error); |
| 496 } | 506 } |
| 497 break; | 507 break; |
| 498 } | 508 } |
| 499 #if defined(DEBUG) | 509 #if defined(DEBUG) |
| 500 // Malformed OOB messages are silently ignored in release builds. | 510 // Malformed OOB messages are silently ignored in release builds. |
| 501 default: { | 511 default: { |
| 502 UNREACHABLE(); | 512 UNREACHABLE(); |
| 503 break; | 513 break; |
| 504 } | 514 } |
| 505 #endif // defined(DEBUG) | 515 #endif // defined(DEBUG) |
| 506 } | 516 } |
| 507 } | 517 } |
| 508 } | 518 } |
| 509 } | 519 } |
| 510 } else if (message->dest_port() == Message::kIllegalPort) { | 520 } else if (message->dest_port() == Message::kIllegalPort) { |
| 511 // Check whether this is a delayed OOB message which needed handling as | 521 // Check whether this is a delayed OOB message which needed handling as |
| 512 // part of the regular message dispatch. All other messages are dropped on | 522 // part of the regular message dispatch. All other messages are dropped on |
| 513 // the floor. | 523 // the floor. |
| 514 if (msg.IsArray()) { | 524 if (msg.IsArray()) { |
| 515 const Array& msg_arr = Array::Cast(msg); | 525 const Array& msg_arr = Array::Cast(msg); |
| 516 if (msg_arr.Length() > 0) { | 526 if (msg_arr.Length() > 0) { |
| 517 const Object& oob_tag = Object::Handle(zone, msg_arr.At(0)); | 527 const Object& oob_tag = Object::Handle(zone, msg_arr.At(0)); |
| 518 if (oob_tag.IsSmi() && | 528 if (oob_tag.IsSmi() && |
| 519 (Smi::Cast(oob_tag).Value() == Message::kDelayedIsolateLibOOBMsg)) { | 529 (Smi::Cast(oob_tag).Value() == Message::kDelayedIsolateLibOOBMsg)) { |
| 520 const Error& error = Error::Handle(HandleLibMessage(msg_arr)); | 530 const Error& error = Error::Handle(HandleLibMessage(msg_arr)); |
| 521 if (!error.IsNull()) { | 531 if (!error.IsNull()) { |
| 522 success = ProcessUnhandledException(error); | 532 status = ProcessUnhandledException(error); |
| 523 } | 533 } |
| 524 } | 534 } |
| 525 } | 535 } |
| 526 } | 536 } |
| 527 } else { | 537 } else { |
| 528 const Object& result = Object::Handle(zone, | 538 const Object& result = Object::Handle(zone, |
| 529 DartLibraryCalls::HandleMessage(msg_handler, msg)); | 539 DartLibraryCalls::HandleMessage(msg_handler, msg)); |
| 530 if (result.IsError()) { | 540 if (result.IsError()) { |
| 531 success = ProcessUnhandledException(Error::Cast(result)); | 541 status = ProcessUnhandledException(Error::Cast(result)); |
| 532 } else { | 542 } else { |
| 533 ASSERT(result.IsNull()); | 543 ASSERT(result.IsNull()); |
| 534 } | 544 } |
| 535 } | 545 } |
| 536 delete message; | 546 delete message; |
| 537 if (success) { | 547 if (status == kOK) { |
| 538 const Object& result = | 548 const Object& result = |
| 539 Object::Handle(zone, I->InvokePendingServiceExtensionCalls()); | 549 Object::Handle(zone, I->InvokePendingServiceExtensionCalls()); |
| 540 if (result.IsError()) { | 550 if (result.IsError()) { |
| 541 success = ProcessUnhandledException(Error::Cast(result)); | 551 status = ProcessUnhandledException(Error::Cast(result)); |
| 542 } else { | 552 } else { |
| 543 ASSERT(result.IsNull()); | 553 ASSERT(result.IsNull()); |
| 544 } | 554 } |
| 545 } | 555 } |
| 546 return success; | 556 return status; |
| 547 } | 557 } |
| 548 | 558 |
| 549 | 559 |
| 550 void IsolateMessageHandler::NotifyPauseOnStart() { | 560 void IsolateMessageHandler::NotifyPauseOnStart() { |
| 551 if (Service::debug_stream.enabled()) { | 561 if (Service::debug_stream.enabled()) { |
| 552 StartIsolateScope start_isolate(I); | 562 StartIsolateScope start_isolate(I); |
| 553 StackZone zone(T); | 563 StackZone zone(T); |
| 554 HandleScope handle_scope(T); | 564 HandleScope handle_scope(T); |
| 555 ServiceEvent pause_event(I, ServiceEvent::kPauseStart); | 565 ServiceEvent pause_event(I, ServiceEvent::kPauseStart); |
| 556 Service::HandleEvent(&pause_event); | 566 Service::HandleEvent(&pause_event); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 580 ASSERT(IsCurrentIsolate()); | 590 ASSERT(IsCurrentIsolate()); |
| 581 } | 591 } |
| 582 #endif | 592 #endif |
| 583 | 593 |
| 584 | 594 |
| 585 bool IsolateMessageHandler::IsCurrentIsolate() const { | 595 bool IsolateMessageHandler::IsCurrentIsolate() const { |
| 586 return (I == Isolate::Current()); | 596 return (I == Isolate::Current()); |
| 587 } | 597 } |
| 588 | 598 |
| 589 | 599 |
| 590 bool IsolateMessageHandler::ProcessUnhandledException(const Error& result) { | 600 static MessageHandler::MessageStatus StoreError(Isolate* isolate, |
| 601 const Error& error) { |
| 602 isolate->object_store()->set_sticky_error(error); |
| 603 if (error.IsUnwindError()) { |
| 604 const UnwindError& unwind = UnwindError::Cast(error); |
| 605 if (!unwind.is_user_initiated()) { |
| 606 if (unwind.is_vm_restart()) { |
| 607 return MessageHandler::kRestart; |
| 608 } else { |
| 609 return MessageHandler::kShutdown; |
| 610 } |
| 611 } |
| 612 } |
| 613 return MessageHandler::kError; |
| 614 } |
| 615 |
| 616 |
| 617 MessageHandler::MessageStatus IsolateMessageHandler::ProcessUnhandledException( |
| 618 const Error& result) { |
| 591 // Notify the debugger about specific unhandled exceptions which are withheld | 619 // Notify the debugger about specific unhandled exceptions which are withheld |
| 592 // when being thrown. | 620 // when being thrown. |
| 593 if (result.IsUnhandledException()) { | 621 if (result.IsUnhandledException()) { |
| 594 const UnhandledException& error = UnhandledException::Cast(result); | 622 const UnhandledException& error = UnhandledException::Cast(result); |
| 595 RawInstance* exception = error.exception(); | 623 RawInstance* exception = error.exception(); |
| 596 if ((exception == I->object_store()->out_of_memory()) || | 624 if ((exception == I->object_store()->out_of_memory()) || |
| 597 (exception == I->object_store()->stack_overflow())) { | 625 (exception == I->object_store()->stack_overflow())) { |
| 598 // We didn't notify the debugger when the stack was full. Do it now. | 626 // We didn't notify the debugger when the stack was full. Do it now. |
| 599 I->debugger()->SignalExceptionThrown(Instance::Handle(exception)); | 627 I->debugger()->SignalExceptionThrown(Instance::Handle(exception)); |
| 600 } | 628 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 624 const Instance& stacktrace = Instance::Handle(I, uhe.stacktrace()); | 652 const Instance& stacktrace = Instance::Handle(I, uhe.stacktrace()); |
| 625 tmp = DartLibraryCalls::ToString(stacktrace); | 653 tmp = DartLibraryCalls::ToString(stacktrace); |
| 626 if (!tmp.IsString()) { | 654 if (!tmp.IsString()) { |
| 627 tmp = String::New(stacktrace.ToCString()); | 655 tmp = String::New(stacktrace.ToCString()); |
| 628 } | 656 } |
| 629 stacktrace_str ^= tmp.raw();; | 657 stacktrace_str ^= tmp.raw();; |
| 630 } else { | 658 } else { |
| 631 exc_str = String::New(result.ToErrorCString()); | 659 exc_str = String::New(result.ToErrorCString()); |
| 632 } | 660 } |
| 633 if (result.IsUnwindError()) { | 661 if (result.IsUnwindError()) { |
| 634 // Unwind errors are always fatal and don't notify listeners. | 662 // When unwinding we don't notify error listeners and we ignore |
| 635 I->object_store()->set_sticky_error(result); | 663 // whether errors are fatal for the current isolate. |
| 636 return false; | 664 return StoreError(I, result); |
| 637 } else { | 665 } else { |
| 638 bool has_listener = I->NotifyErrorListeners(exc_str, stacktrace_str); | 666 bool has_listener = I->NotifyErrorListeners(exc_str, stacktrace_str); |
| 639 if (I->ErrorsFatal()) { | 667 if (I->ErrorsFatal()) { |
| 640 if (has_listener) { | 668 if (has_listener) { |
| 641 I->object_store()->clear_sticky_error(); | 669 I->object_store()->clear_sticky_error(); |
| 642 } else { | 670 } else { |
| 643 I->object_store()->set_sticky_error(result); | 671 I->object_store()->set_sticky_error(result); |
| 644 } | 672 } |
| 645 return false; | 673 return kError; |
| 646 } | 674 } |
| 647 } | 675 } |
| 648 return true; | 676 return kOK; |
| 649 } | 677 } |
| 650 | 678 |
| 651 | 679 |
| 652 Isolate::Flags::Flags() | 680 Isolate::Flags::Flags() |
| 653 : type_checks_(FLAG_enable_type_checks), | 681 : type_checks_(FLAG_enable_type_checks), |
| 654 asserts_(FLAG_enable_asserts), | 682 asserts_(FLAG_enable_asserts), |
| 655 error_on_bad_type_(FLAG_error_on_bad_type), | 683 error_on_bad_type_(FLAG_error_on_bad_type), |
| 656 error_on_bad_override_(FLAG_error_on_bad_override) {} | 684 error_on_bad_override_(FLAG_error_on_bad_override) {} |
| 657 | 685 |
| 658 | 686 |
| (...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1301 intptr_t len = 0; | 1329 intptr_t len = 0; |
| 1302 SerializeObject(arr, &data, &len, false); | 1330 SerializeObject(arr, &data, &len, false); |
| 1303 Message* msg = new Message(port_id, data, len, Message::kNormalPriority); | 1331 Message* msg = new Message(port_id, data, len, Message::kNormalPriority); |
| 1304 PortMap::PostMessage(msg); | 1332 PortMap::PostMessage(msg); |
| 1305 } | 1333 } |
| 1306 } | 1334 } |
| 1307 return listeners.Length() > 0; | 1335 return listeners.Length() > 0; |
| 1308 } | 1336 } |
| 1309 | 1337 |
| 1310 | 1338 |
| 1311 static void StoreError(Isolate* isolate, const Object& obj) { | 1339 static MessageHandler::MessageStatus RunIsolate(uword parameter) { |
| 1312 ASSERT(obj.IsError()); | |
| 1313 isolate->object_store()->set_sticky_error(Error::Cast(obj)); | |
| 1314 } | |
| 1315 | |
| 1316 | |
| 1317 static bool RunIsolate(uword parameter) { | |
| 1318 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); | 1340 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); |
| 1319 IsolateSpawnState* state = NULL; | 1341 IsolateSpawnState* state = NULL; |
| 1320 Thread* thread = Thread::Current(); | 1342 Thread* thread = Thread::Current(); |
| 1321 { | 1343 { |
| 1322 // TODO(turnidge): Is this locking required here at all anymore? | 1344 // TODO(turnidge): Is this locking required here at all anymore? |
| 1323 MutexLocker ml(isolate->mutex()); | 1345 MutexLocker ml(isolate->mutex()); |
| 1324 state = isolate->spawn_state(); | 1346 state = isolate->spawn_state(); |
| 1325 } | 1347 } |
| 1326 { | 1348 { |
| 1327 StartIsolateScope start_scope(isolate); | 1349 StartIsolateScope start_scope(isolate); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1341 const SendPort& listener = | 1363 const SendPort& listener = |
| 1342 SendPort::Handle(SendPort::New(state->on_error_port())); | 1364 SendPort::Handle(SendPort::New(state->on_error_port())); |
| 1343 isolate->AddErrorListener(listener); | 1365 isolate->AddErrorListener(listener); |
| 1344 } | 1366 } |
| 1345 | 1367 |
| 1346 // Switch back to spawning isolate. | 1368 // Switch back to spawning isolate. |
| 1347 | 1369 |
| 1348 | 1370 |
| 1349 if (!ClassFinalizer::ProcessPendingClasses()) { | 1371 if (!ClassFinalizer::ProcessPendingClasses()) { |
| 1350 // Error is in sticky error already. | 1372 // Error is in sticky error already. |
| 1351 return false; | 1373 #if defined(DEBUG) |
| 1374 const Error& error = |
| 1375 Error::Handle(isolate->object_store()->sticky_error()); |
| 1376 ASSERT(!error.IsUnwindError()); |
| 1377 #endif |
| 1378 return MessageHandler::kError; |
| 1352 } | 1379 } |
| 1353 | 1380 |
| 1354 Object& result = Object::Handle(); | 1381 Object& result = Object::Handle(); |
| 1355 result = state->ResolveFunction(); | 1382 result = state->ResolveFunction(); |
| 1356 bool is_spawn_uri = state->is_spawn_uri(); | 1383 bool is_spawn_uri = state->is_spawn_uri(); |
| 1357 if (result.IsError()) { | 1384 if (result.IsError()) { |
| 1358 StoreError(isolate, result); | 1385 return StoreError(isolate, Error::Cast(result)); |
| 1359 return false; | |
| 1360 } | 1386 } |
| 1361 ASSERT(result.IsFunction()); | 1387 ASSERT(result.IsFunction()); |
| 1362 Function& func = Function::Handle(isolate); | 1388 Function& func = Function::Handle(isolate); |
| 1363 func ^= result.raw(); | 1389 func ^= result.raw(); |
| 1364 | 1390 |
| 1365 // TODO(turnidge): Currently we need a way to force a one-time | 1391 // TODO(turnidge): Currently we need a way to force a one-time |
| 1366 // breakpoint for all spawned isolates to support isolate | 1392 // breakpoint for all spawned isolates to support isolate |
| 1367 // debugging. Remove this once the vmservice becomes the standard | 1393 // debugging. Remove this once the vmservice becomes the standard |
| 1368 // way to debug. Set the breakpoint on the static function instead | 1394 // way to debug. Set the breakpoint on the static function instead |
| 1369 // of its implicit closure function because that latter is merely | 1395 // of its implicit closure function because that latter is merely |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1404 args.SetAt(6, capabilities); | 1430 args.SetAt(6, capabilities); |
| 1405 | 1431 |
| 1406 const Library& lib = Library::Handle(Library::IsolateLibrary()); | 1432 const Library& lib = Library::Handle(Library::IsolateLibrary()); |
| 1407 const String& entry_name = String::Handle(String::New("_startIsolate")); | 1433 const String& entry_name = String::Handle(String::New("_startIsolate")); |
| 1408 const Function& entry_point = | 1434 const Function& entry_point = |
| 1409 Function::Handle(lib.LookupLocalFunction(entry_name)); | 1435 Function::Handle(lib.LookupLocalFunction(entry_name)); |
| 1410 ASSERT(entry_point.IsFunction() && !entry_point.IsNull()); | 1436 ASSERT(entry_point.IsFunction() && !entry_point.IsNull()); |
| 1411 | 1437 |
| 1412 result = DartEntry::InvokeFunction(entry_point, args); | 1438 result = DartEntry::InvokeFunction(entry_point, args); |
| 1413 if (result.IsError()) { | 1439 if (result.IsError()) { |
| 1414 StoreError(isolate, result); | 1440 return StoreError(isolate, Error::Cast(result)); |
| 1415 return false; | |
| 1416 } | 1441 } |
| 1417 } | 1442 } |
| 1418 return true; | 1443 return MessageHandler::kOK; |
| 1419 } | 1444 } |
| 1420 | 1445 |
| 1421 | 1446 |
| 1422 static void ShutdownIsolate(uword parameter) { | 1447 static void ShutdownIsolate(uword parameter) { |
| 1423 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); | 1448 Isolate* isolate = reinterpret_cast<Isolate*>(parameter); |
| 1424 { | 1449 { |
| 1425 // Print the error if there is one. This may execute dart code to | 1450 // Print the error if there is one. This may execute dart code to |
| 1426 // print the exception object, so we need to use a StartIsolateScope. | 1451 // print the exception object, so we need to use a StartIsolateScope. |
| 1427 Thread* thread = Thread::Current(); | 1452 Thread* thread = Thread::Current(); |
| 1428 StartIsolateScope start_scope(isolate); | 1453 StartIsolateScope start_scope(isolate); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1467 if ((interrupt_bits & kVMInterrupt) != 0) { | 1492 if ((interrupt_bits & kVMInterrupt) != 0) { |
| 1468 thread_registry()->CheckSafepoint(); | 1493 thread_registry()->CheckSafepoint(); |
| 1469 if (store_buffer()->Overflowed()) { | 1494 if (store_buffer()->Overflowed()) { |
| 1470 if (FLAG_verbose_gc) { | 1495 if (FLAG_verbose_gc) { |
| 1471 OS::PrintErr("Scavenge scheduled by store buffer overflow.\n"); | 1496 OS::PrintErr("Scavenge scheduled by store buffer overflow.\n"); |
| 1472 } | 1497 } |
| 1473 heap()->CollectGarbage(Heap::kNew); | 1498 heap()->CollectGarbage(Heap::kNew); |
| 1474 } | 1499 } |
| 1475 } | 1500 } |
| 1476 if ((interrupt_bits & kMessageInterrupt) != 0) { | 1501 if ((interrupt_bits & kMessageInterrupt) != 0) { |
| 1477 bool ok = message_handler()->HandleOOBMessages(); | 1502 MessageHandler::MessageStatus status = |
| 1478 if (!ok) { | 1503 message_handler()->HandleOOBMessages(); |
| 1504 if (status != MessageHandler::kOK) { |
| 1479 // False result from HandleOOBMessages signals that the isolate should | 1505 // False result from HandleOOBMessages signals that the isolate should |
| 1480 // be terminating. | 1506 // be terminating. |
| 1481 if (FLAG_trace_isolates) { | 1507 if (FLAG_trace_isolates) { |
| 1482 OS::Print("[!] Terminating isolate due to OOB message:\n" | 1508 OS::Print("[!] Terminating isolate due to OOB message:\n" |
| 1483 "\tisolate: %s\n", name()); | 1509 "\tisolate: %s\n", name()); |
| 1484 } | 1510 } |
| 1485 const Error& error = Error::Handle(object_store()->sticky_error()); | 1511 const Error& error = Error::Handle(object_store()->sticky_error()); |
| 1512 ASSERT(!error.IsNull() && error.IsUnwindError()); |
| 1486 object_store()->clear_sticky_error(); | 1513 object_store()->clear_sticky_error(); |
| 1487 ASSERT(!error.IsNull()); | |
| 1488 return error.raw(); | 1514 return error.raw(); |
| 1489 } | 1515 } |
| 1490 } | 1516 } |
| 1491 return Error::null(); | 1517 return Error::null(); |
| 1492 } | 1518 } |
| 1493 | 1519 |
| 1494 | 1520 |
| 1495 uword Isolate::GetAndClearStackOverflowFlags() { | 1521 uword Isolate::GetAndClearStackOverflowFlags() { |
| 1496 uword stack_overflow_flags = stack_overflow_flags_; | 1522 uword stack_overflow_flags = stack_overflow_flags_; |
| 1497 stack_overflow_flags_ = 0; | 1523 stack_overflow_flags_ = 0; |
| (...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2286 | 2312 |
| 2287 | 2313 |
| 2288 template<class C> | 2314 template<class C> |
| 2289 C* Isolate::AllocateReusableHandle() { | 2315 C* Isolate::AllocateReusableHandle() { |
| 2290 C* handle = reinterpret_cast<C*>(reusable_handles_.AllocateScopedHandle()); | 2316 C* handle = reinterpret_cast<C*>(reusable_handles_.AllocateScopedHandle()); |
| 2291 C::initializeHandle(handle, C::null()); | 2317 C::initializeHandle(handle, C::null()); |
| 2292 return handle; | 2318 return handle; |
| 2293 } | 2319 } |
| 2294 | 2320 |
| 2295 | 2321 |
| 2296 void Isolate::KillLocked() { | 2322 void Isolate::KillLocked(LibMsgId msg_id) { |
| 2297 Dart_CObject kill_msg; | 2323 Dart_CObject kill_msg; |
| 2298 Dart_CObject* list_values[4]; | 2324 Dart_CObject* list_values[4]; |
| 2299 kill_msg.type = Dart_CObject_kArray; | 2325 kill_msg.type = Dart_CObject_kArray; |
| 2300 kill_msg.value.as_array.length = 4; | 2326 kill_msg.value.as_array.length = 4; |
| 2301 kill_msg.value.as_array.values = list_values; | 2327 kill_msg.value.as_array.values = list_values; |
| 2302 | 2328 |
| 2303 Dart_CObject oob; | 2329 Dart_CObject oob; |
| 2304 oob.type = Dart_CObject_kInt32; | 2330 oob.type = Dart_CObject_kInt32; |
| 2305 oob.value.as_int32 = Message::kIsolateLibOOBMsg; | 2331 oob.value.as_int32 = Message::kIsolateLibOOBMsg; |
| 2306 list_values[0] = &oob; | 2332 list_values[0] = &oob; |
| 2307 | 2333 |
| 2308 Dart_CObject msg_type; | 2334 Dart_CObject msg_type; |
| 2309 msg_type.type = Dart_CObject_kInt32; | 2335 msg_type.type = Dart_CObject_kInt32; |
| 2310 msg_type.value.as_int32 = Isolate::kInternalKillMsg; | 2336 msg_type.value.as_int32 = msg_id; |
| 2311 list_values[1] = &msg_type; | 2337 list_values[1] = &msg_type; |
| 2312 | 2338 |
| 2313 Dart_CObject cap; | 2339 Dart_CObject cap; |
| 2314 cap.type = Dart_CObject_kCapability; | 2340 cap.type = Dart_CObject_kCapability; |
| 2315 cap.value.as_capability.id = terminate_capability(); | 2341 cap.value.as_capability.id = terminate_capability(); |
| 2316 list_values[2] = ∩ | 2342 list_values[2] = ∩ |
| 2317 | 2343 |
| 2318 Dart_CObject imm; | 2344 Dart_CObject imm; |
| 2319 imm.type = Dart_CObject_kInt32; | 2345 imm.type = Dart_CObject_kInt32; |
| 2320 imm.value.as_int32 = Isolate::kImmediateAction; | 2346 imm.value.as_int32 = Isolate::kImmediateAction; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2331 buffer, | 2357 buffer, |
| 2332 writer.BytesWritten(), | 2358 writer.BytesWritten(), |
| 2333 Message::kOOBPriority)); | 2359 Message::kOOBPriority)); |
| 2334 ASSERT(success); | 2360 ASSERT(success); |
| 2335 } | 2361 } |
| 2336 } | 2362 } |
| 2337 | 2363 |
| 2338 | 2364 |
| 2339 class IsolateKillerVisitor : public IsolateVisitor { | 2365 class IsolateKillerVisitor : public IsolateVisitor { |
| 2340 public: | 2366 public: |
| 2341 IsolateKillerVisitor() : target_(NULL) {} | 2367 explicit IsolateKillerVisitor(Isolate::LibMsgId msg_id) |
| 2368 : target_(NULL), msg_id_(msg_id) {} |
| 2342 | 2369 |
| 2343 explicit IsolateKillerVisitor(Isolate* isolate) | 2370 IsolateKillerVisitor(Isolate* isolate, Isolate::LibMsgId msg_id) |
| 2344 : target_(isolate) { | 2371 : target_(isolate), msg_id_(msg_id) { |
| 2345 ASSERT(isolate != Dart::vm_isolate()); | 2372 ASSERT(isolate != Dart::vm_isolate()); |
| 2346 } | 2373 } |
| 2347 | 2374 |
| 2348 virtual ~IsolateKillerVisitor() {} | 2375 virtual ~IsolateKillerVisitor() {} |
| 2349 | 2376 |
| 2350 void VisitIsolate(Isolate* isolate) { | 2377 void VisitIsolate(Isolate* isolate) { |
| 2351 ASSERT(isolate != NULL); | 2378 ASSERT(isolate != NULL); |
| 2352 if (ShouldKill(isolate)) { | 2379 if (ShouldKill(isolate)) { |
| 2353 isolate->KillLocked(); | 2380 isolate->KillLocked(msg_id_); |
| 2354 } | 2381 } |
| 2355 } | 2382 } |
| 2356 | 2383 |
| 2357 private: | 2384 private: |
| 2358 bool ShouldKill(Isolate* isolate) { | 2385 bool ShouldKill(Isolate* isolate) { |
| 2359 // If a target_ is specified, then only kill the target_. | 2386 // If a target_ is specified, then only kill the target_. |
| 2360 // Otherwise, don't kill the service isolate or vm isolate. | 2387 // Otherwise, don't kill the service isolate or vm isolate. |
| 2361 return (((target_ != NULL) && (isolate == target_)) || | 2388 return (((target_ != NULL) && (isolate == target_)) || |
| 2362 ((target_ == NULL) && | 2389 ((target_ == NULL) && |
| 2363 !ServiceIsolate::IsServiceIsolateDescendant(isolate) && | 2390 !ServiceIsolate::IsServiceIsolateDescendant(isolate) && |
| 2364 (isolate != Dart::vm_isolate()))); | 2391 (isolate != Dart::vm_isolate()))); |
| 2365 } | 2392 } |
| 2366 | 2393 |
| 2367 Isolate* target_; | 2394 Isolate* target_; |
| 2395 Isolate::LibMsgId msg_id_; |
| 2368 }; | 2396 }; |
| 2369 | 2397 |
| 2370 | 2398 |
| 2371 void Isolate::KillAllIsolates() { | 2399 void Isolate::KillAllIsolates(LibMsgId msg_id) { |
| 2372 IsolateKillerVisitor visitor; | 2400 IsolateKillerVisitor visitor(msg_id); |
| 2373 VisitIsolates(&visitor); | 2401 VisitIsolates(&visitor); |
| 2374 } | 2402 } |
| 2375 | 2403 |
| 2376 | 2404 |
| 2377 void Isolate::KillIfExists(Isolate* isolate) { | 2405 void Isolate::KillIfExists(Isolate* isolate, LibMsgId msg_id) { |
| 2378 IsolateKillerVisitor visitor(isolate); | 2406 IsolateKillerVisitor visitor(isolate, msg_id); |
| 2379 VisitIsolates(&visitor); | 2407 VisitIsolates(&visitor); |
| 2380 } | 2408 } |
| 2381 | 2409 |
| 2382 | 2410 |
| 2383 static RawInstance* DeserializeObject(Thread* thread, | 2411 static RawInstance* DeserializeObject(Thread* thread, |
| 2384 uint8_t* obj_data, | 2412 uint8_t* obj_data, |
| 2385 intptr_t obj_len) { | 2413 intptr_t obj_len) { |
| 2386 if (obj_data == NULL) { | 2414 if (obj_data == NULL) { |
| 2387 return Instance::null(); | 2415 return Instance::null(); |
| 2388 } | 2416 } |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2575 serialized_message_, serialized_message_len_); | 2603 serialized_message_, serialized_message_len_); |
| 2576 } | 2604 } |
| 2577 | 2605 |
| 2578 | 2606 |
| 2579 void IsolateSpawnState::Cleanup() { | 2607 void IsolateSpawnState::Cleanup() { |
| 2580 SwitchIsolateScope switch_scope(I); | 2608 SwitchIsolateScope switch_scope(I); |
| 2581 Dart::ShutdownIsolate(); | 2609 Dart::ShutdownIsolate(); |
| 2582 } | 2610 } |
| 2583 | 2611 |
| 2584 } // namespace dart | 2612 } // namespace dart |
| OLD | NEW |