| 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 "platform/assert.h" | 8 #include "platform/assert.h" |
| 9 #include "platform/json.h" | 9 #include "platform/json.h" |
| 10 #include "vm/code_observers.h" | 10 #include "vm/code_observers.h" |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 const char* name() const; | 90 const char* name() const; |
| 91 void MessageNotify(Message::Priority priority); | 91 void MessageNotify(Message::Priority priority); |
| 92 bool HandleMessage(Message* message); | 92 bool HandleMessage(Message* message); |
| 93 | 93 |
| 94 #if defined(DEBUG) | 94 #if defined(DEBUG) |
| 95 // Check that it is safe to access this handler. | 95 // Check that it is safe to access this handler. |
| 96 void CheckAccess(); | 96 void CheckAccess(); |
| 97 #endif | 97 #endif |
| 98 bool IsCurrentIsolate() const; | 98 bool IsCurrentIsolate() const; |
| 99 virtual Isolate* isolate() const { return isolate_; } | 99 virtual Isolate* isolate() const { return isolate_; } |
| 100 bool UnhandledExceptionCallbackHandler(const Object& message, | |
| 101 const UnhandledException& error); | |
| 102 | 100 |
| 103 private: | 101 private: |
| 104 // Keep in sync with isolate_patch.dart. | 102 // Keep in sync with isolate_patch.dart. |
| 105 enum { | 103 enum { |
| 106 kPauseMsg = 1, | 104 kPauseMsg = 1, |
| 107 kResumeMsg = 2, | 105 kResumeMsg = 2, |
| 108 kPingMsg = 3, | 106 kPingMsg = 3, |
| 109 kKillMsg = 4, | 107 kKillMsg = 4, |
| 110 | 108 |
| 111 kImmediateAction = 0, | 109 kImmediateAction = 0, |
| 112 kBeforeNextEventAction = 1, | 110 kBeforeNextEventAction = 1, |
| 113 kAsEventAction = 2 | 111 kAsEventAction = 2 |
| 114 }; | 112 }; |
| 115 | 113 |
| 116 // A result of false indicates that the isolate should terminate the | 114 // A result of false indicates that the isolate should terminate the |
| 117 // processing of further events. | 115 // processing of further events. |
| 118 bool HandleLibMessage(const Array& message); | 116 bool HandleLibMessage(const Array& message); |
| 119 | 117 |
| 120 bool ProcessUnhandledException(const Object& message, const Error& result); | 118 bool ProcessUnhandledException(const Error& result); |
| 121 RawFunction* ResolveCallbackFunction(); | |
| 122 Isolate* isolate_; | 119 Isolate* isolate_; |
| 123 }; | 120 }; |
| 124 | 121 |
| 125 | 122 |
| 126 IsolateMessageHandler::IsolateMessageHandler(Isolate* isolate) | 123 IsolateMessageHandler::IsolateMessageHandler(Isolate* isolate) |
| 127 : isolate_(isolate) { | 124 : isolate_(isolate) { |
| 128 } | 125 } |
| 129 | 126 |
| 130 | 127 |
| 131 IsolateMessageHandler::~IsolateMessageHandler() { | 128 IsolateMessageHandler::~IsolateMessageHandler() { |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 | 262 |
| 266 // If the message is in band we lookup the handler to dispatch to. If the | 263 // If the message is in band we lookup the handler to dispatch to. If the |
| 267 // receive port was closed, we drop the message without deserializing it. | 264 // receive port was closed, we drop the message without deserializing it. |
| 268 // Illegal port is a special case for artificially enqueued isolate library | 265 // Illegal port is a special case for artificially enqueued isolate library |
| 269 // messages which are handled in C++ code below. | 266 // messages which are handled in C++ code below. |
| 270 Object& msg_handler = Object::Handle(I); | 267 Object& msg_handler = Object::Handle(I); |
| 271 if (!message->IsOOB() && (message->dest_port() != Message::kIllegalPort)) { | 268 if (!message->IsOOB() && (message->dest_port() != Message::kIllegalPort)) { |
| 272 msg_handler = DartLibraryCalls::LookupHandler(message->dest_port()); | 269 msg_handler = DartLibraryCalls::LookupHandler(message->dest_port()); |
| 273 if (msg_handler.IsError()) { | 270 if (msg_handler.IsError()) { |
| 274 delete message; | 271 delete message; |
| 275 return ProcessUnhandledException(Object::null_instance(), | 272 return ProcessUnhandledException(Error::Cast(msg_handler)); |
| 276 Error::Cast(msg_handler)); | |
| 277 } | 273 } |
| 278 if (msg_handler.IsNull()) { | 274 if (msg_handler.IsNull()) { |
| 279 // If the port has been closed then the message will be dropped at this | 275 // If the port has been closed then the message will be dropped at this |
| 280 // point. Make sure to post to the delivery failure port in that case. | 276 // point. Make sure to post to the delivery failure port in that case. |
| 281 if (message->RedirectToDeliveryFailurePort()) { | 277 if (message->RedirectToDeliveryFailurePort()) { |
| 282 PortMap::PostMessage(message); | 278 PortMap::PostMessage(message); |
| 283 } else { | 279 } else { |
| 284 delete message; | 280 delete message; |
| 285 } | 281 } |
| 286 return true; | 282 return true; |
| 287 } | 283 } |
| 288 } | 284 } |
| 289 | 285 |
| 290 // Parse the message. | 286 // Parse the message. |
| 291 SnapshotReader reader(message->data(), message->len(), Snapshot::kMessage, I); | 287 SnapshotReader reader(message->data(), message->len(), Snapshot::kMessage, I); |
| 292 const Object& msg_obj = Object::Handle(I, reader.ReadObject()); | 288 const Object& msg_obj = Object::Handle(I, reader.ReadObject()); |
| 293 if (msg_obj.IsError()) { | 289 if (msg_obj.IsError()) { |
| 294 // An error occurred while reading the message. | 290 // An error occurred while reading the message. |
| 295 delete message; | 291 delete message; |
| 296 return ProcessUnhandledException(Object::null_instance(), | 292 return ProcessUnhandledException(Error::Cast(msg_obj)); |
| 297 Error::Cast(msg_obj)); | |
| 298 } | 293 } |
| 299 if (!msg_obj.IsNull() && !msg_obj.IsInstance()) { | 294 if (!msg_obj.IsNull() && !msg_obj.IsInstance()) { |
| 300 // TODO(turnidge): We need to decide what an isolate does with | 295 // TODO(turnidge): We need to decide what an isolate does with |
| 301 // malformed messages. If they (eventually) come from a remote | 296 // malformed messages. If they (eventually) come from a remote |
| 302 // machine, then it might make sense to drop the message entirely. | 297 // machine, then it might make sense to drop the message entirely. |
| 303 // In the case that the message originated locally, which is | 298 // In the case that the message originated locally, which is |
| 304 // always true for now, then this should never occur. | 299 // always true for now, then this should never occur. |
| 305 UNREACHABLE(); | 300 UNREACHABLE(); |
| 306 } | 301 } |
| 307 | 302 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 if (oob_tag.IsSmi() && | 344 if (oob_tag.IsSmi() && |
| 350 (Smi::Cast(oob_tag).Value() == Message::kDelayedIsolateLibOOBMsg)) { | 345 (Smi::Cast(oob_tag).Value() == Message::kDelayedIsolateLibOOBMsg)) { |
| 351 success = HandleLibMessage(Array::Cast(msg_arr)); | 346 success = HandleLibMessage(Array::Cast(msg_arr)); |
| 352 } | 347 } |
| 353 } | 348 } |
| 354 } | 349 } |
| 355 } else { | 350 } else { |
| 356 const Object& result = Object::Handle(I, | 351 const Object& result = Object::Handle(I, |
| 357 DartLibraryCalls::HandleMessage(msg_handler, msg)); | 352 DartLibraryCalls::HandleMessage(msg_handler, msg)); |
| 358 if (result.IsError()) { | 353 if (result.IsError()) { |
| 359 success = ProcessUnhandledException(msg, Error::Cast(result)); | 354 success = ProcessUnhandledException(Error::Cast(result)); |
| 360 } else { | 355 } else { |
| 361 ASSERT(result.IsNull()); | 356 ASSERT(result.IsNull()); |
| 362 } | 357 } |
| 363 } | 358 } |
| 364 delete message; | 359 delete message; |
| 365 return success; | 360 return success; |
| 366 } | 361 } |
| 367 | 362 |
| 368 | 363 |
| 369 RawFunction* IsolateMessageHandler::ResolveCallbackFunction() { | |
| 370 ASSERT(I->object_store()->unhandled_exception_handler() != NULL); | |
| 371 String& callback_name = String::Handle(I); | |
| 372 if (I->object_store()->unhandled_exception_handler() != String::null()) { | |
| 373 callback_name = I->object_store()->unhandled_exception_handler(); | |
| 374 } else { | |
| 375 callback_name = String::New("_unhandledExceptionCallback"); | |
| 376 } | |
| 377 Library& lib = Library::Handle(I, I->object_store()->isolate_library()); | |
| 378 Function& func = Function::Handle(I, lib.LookupLocalFunction(callback_name)); | |
| 379 if (func.IsNull()) { | |
| 380 lib = I->object_store()->root_library(); | |
| 381 // Note: bootstrap code in builtin library may attempt to resolve a | |
| 382 // callback function before the script is fully loaded, in which case | |
| 383 // the root library may not be registered yet. | |
| 384 if (!lib.IsNull()) { | |
| 385 func = lib.LookupLocalFunction(callback_name); | |
| 386 } | |
| 387 } | |
| 388 return func.raw(); | |
| 389 } | |
| 390 | |
| 391 | |
| 392 bool IsolateMessageHandler::UnhandledExceptionCallbackHandler( | |
| 393 const Object& message, const UnhandledException& error) { | |
| 394 const Instance& cause = Instance::Handle(I, error.exception()); | |
| 395 const Instance& stacktrace = Instance::Handle(I, error.stacktrace()); | |
| 396 | |
| 397 // Wrap these args into an IsolateUncaughtException object. | |
| 398 const Array& exception_args = Array::Handle(I, Array::New(3)); | |
| 399 exception_args.SetAt(0, message); | |
| 400 exception_args.SetAt(1, cause); | |
| 401 exception_args.SetAt(2, stacktrace); | |
| 402 const Object& exception = Object::Handle(I, | |
| 403 Exceptions::Create(Exceptions::kIsolateUnhandledException, | |
| 404 exception_args)); | |
| 405 if (exception.IsError()) { | |
| 406 return false; | |
| 407 } | |
| 408 ASSERT(exception.IsInstance()); | |
| 409 | |
| 410 // Invoke script's callback function. | |
| 411 Object& function = Object::Handle(I, ResolveCallbackFunction()); | |
| 412 if (function.IsNull() || function.IsError()) { | |
| 413 return false; | |
| 414 } | |
| 415 const Array& callback_args = Array::Handle(I, Array::New(1)); | |
| 416 callback_args.SetAt(0, exception); | |
| 417 const Object& result = Object::Handle(I, | |
| 418 DartEntry::InvokeFunction(Function::Cast(function), callback_args)); | |
| 419 if (result.IsError()) { | |
| 420 const Error& err = Error::Cast(result); | |
| 421 OS::PrintErr("failed calling unhandled exception callback: %s\n", | |
| 422 err.ToErrorCString()); | |
| 423 return false; | |
| 424 } | |
| 425 | |
| 426 ASSERT(result.IsBool()); | |
| 427 bool continue_from_exception = Bool::Cast(result).value(); | |
| 428 if (continue_from_exception) { | |
| 429 I->object_store()->clear_sticky_error(); | |
| 430 } | |
| 431 return continue_from_exception; | |
| 432 } | |
| 433 | |
| 434 #if defined(DEBUG) | 364 #if defined(DEBUG) |
| 435 void IsolateMessageHandler::CheckAccess() { | 365 void IsolateMessageHandler::CheckAccess() { |
| 436 ASSERT(IsCurrentIsolate()); | 366 ASSERT(IsCurrentIsolate()); |
| 437 } | 367 } |
| 438 #endif | 368 #endif |
| 439 | 369 |
| 440 | 370 |
| 441 bool IsolateMessageHandler::IsCurrentIsolate() const { | 371 bool IsolateMessageHandler::IsCurrentIsolate() const { |
| 442 return (I == Isolate::Current()); | 372 return (I == Isolate::Current()); |
| 443 } | 373 } |
| 444 | 374 |
| 445 | 375 |
| 446 bool IsolateMessageHandler::ProcessUnhandledException( | 376 bool IsolateMessageHandler::ProcessUnhandledException(const Error& result) { |
| 447 const Object& message, const Error& result) { | 377 // Notify the debugger about specific unhandled exceptions which are withheld |
| 378 // when being thrown. |
| 448 if (result.IsUnhandledException()) { | 379 if (result.IsUnhandledException()) { |
| 449 // Invoke the isolate's uncaught exception handler, if it exists. | |
| 450 const UnhandledException& error = UnhandledException::Cast(result); | 380 const UnhandledException& error = UnhandledException::Cast(result); |
| 451 RawInstance* exception = error.exception(); | 381 RawInstance* exception = error.exception(); |
| 452 if ((exception == I->object_store()->out_of_memory()) || | 382 if ((exception == I->object_store()->out_of_memory()) || |
| 453 (exception == I->object_store()->stack_overflow())) { | 383 (exception == I->object_store()->stack_overflow())) { |
| 454 // We didn't notify the debugger when the stack was full. Do it now. | 384 // We didn't notify the debugger when the stack was full. Do it now. |
| 455 I->debugger()->SignalExceptionThrown(Instance::Handle(exception)); | 385 I->debugger()->SignalExceptionThrown(Instance::Handle(exception)); |
| 456 } | 386 } |
| 457 if ((exception != I->object_store()->out_of_memory()) && | |
| 458 (exception != I->object_store()->stack_overflow())) { | |
| 459 if (UnhandledExceptionCallbackHandler(message, error)) { | |
| 460 return true; | |
| 461 } | |
| 462 } | |
| 463 } | 387 } |
| 464 | 388 |
| 465 // Invoke the isolate's unhandled exception callback if there is one. | 389 // Invoke the isolate's unhandled exception callback if there is one. |
| 466 if (Isolate::UnhandledExceptionCallback() != NULL) { | 390 if (Isolate::UnhandledExceptionCallback() != NULL) { |
| 467 Dart_EnterScope(); | 391 Dart_EnterScope(); |
| 468 Dart_Handle error = Api::NewHandle(I, result.raw()); | 392 Dart_Handle error = Api::NewHandle(I, result.raw()); |
| 469 (Isolate::UnhandledExceptionCallback())(error); | 393 (Isolate::UnhandledExceptionCallback())(error); |
| 470 Dart_ExitScope(); | 394 Dart_ExitScope(); |
| 471 } | 395 } |
| 472 | 396 |
| (...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 922 } | 846 } |
| 923 { | 847 { |
| 924 StartIsolateScope start_scope(isolate); | 848 StartIsolateScope start_scope(isolate); |
| 925 StackZone zone(isolate); | 849 StackZone zone(isolate); |
| 926 HandleScope handle_scope(isolate); | 850 HandleScope handle_scope(isolate); |
| 927 if (!ClassFinalizer::ProcessPendingClasses()) { | 851 if (!ClassFinalizer::ProcessPendingClasses()) { |
| 928 // Error is in sticky error already. | 852 // Error is in sticky error already. |
| 929 return false; | 853 return false; |
| 930 } | 854 } |
| 931 | 855 |
| 932 // Set up specific unhandled exception handler. | |
| 933 const String& callback_name = String::Handle( | |
| 934 isolate, String::New(state->exception_callback_name())); | |
| 935 isolate->object_store()-> | |
| 936 set_unhandled_exception_handler(callback_name); | |
| 937 | |
| 938 Object& result = Object::Handle(); | 856 Object& result = Object::Handle(); |
| 939 result = state->ResolveFunction(); | 857 result = state->ResolveFunction(); |
| 940 bool is_spawn_uri = state->is_spawn_uri(); | 858 bool is_spawn_uri = state->is_spawn_uri(); |
| 941 if (result.IsError()) { | 859 if (result.IsError()) { |
| 942 StoreError(isolate, result); | 860 StoreError(isolate, result); |
| 943 return false; | 861 return false; |
| 944 } | 862 } |
| 945 ASSERT(result.IsFunction()); | 863 ASSERT(result.IsFunction()); |
| 946 Function& func = Function::Handle(isolate); | 864 Function& func = Function::Handle(isolate); |
| 947 func ^= result.raw(); | 865 func ^= result.raw(); |
| (...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1544 const Function& func, | 1462 const Function& func, |
| 1545 const Instance& message, | 1463 const Instance& message, |
| 1546 bool paused) | 1464 bool paused) |
| 1547 : isolate_(NULL), | 1465 : isolate_(NULL), |
| 1548 parent_port_(parent_port), | 1466 parent_port_(parent_port), |
| 1549 script_url_(NULL), | 1467 script_url_(NULL), |
| 1550 package_root_(NULL), | 1468 package_root_(NULL), |
| 1551 library_url_(NULL), | 1469 library_url_(NULL), |
| 1552 class_name_(NULL), | 1470 class_name_(NULL), |
| 1553 function_name_(NULL), | 1471 function_name_(NULL), |
| 1554 exception_callback_name_(NULL), | |
| 1555 serialized_args_(NULL), | 1472 serialized_args_(NULL), |
| 1556 serialized_args_len_(0), | 1473 serialized_args_len_(0), |
| 1557 serialized_message_(NULL), | 1474 serialized_message_(NULL), |
| 1558 serialized_message_len_(0), | 1475 serialized_message_len_(0), |
| 1559 paused_(paused) { | 1476 paused_(paused) { |
| 1560 script_url_ = NULL; | 1477 script_url_ = NULL; |
| 1561 const Class& cls = Class::Handle(func.Owner()); | 1478 const Class& cls = Class::Handle(func.Owner()); |
| 1562 const Library& lib = Library::Handle(cls.library()); | 1479 const Library& lib = Library::Handle(cls.library()); |
| 1563 const String& lib_url = String::Handle(lib.url()); | 1480 const String& lib_url = String::Handle(lib.url()); |
| 1564 library_url_ = strdup(lib_url.ToCString()); | 1481 library_url_ = strdup(lib_url.ToCString()); |
| 1565 | 1482 |
| 1566 const String& func_name = String::Handle(func.name()); | 1483 const String& func_name = String::Handle(func.name()); |
| 1567 function_name_ = strdup(func_name.ToCString()); | 1484 function_name_ = strdup(func_name.ToCString()); |
| 1568 if (!cls.IsTopLevel()) { | 1485 if (!cls.IsTopLevel()) { |
| 1569 const String& class_name = String::Handle(cls.Name()); | 1486 const String& class_name = String::Handle(cls.Name()); |
| 1570 class_name_ = strdup(class_name.ToCString()); | 1487 class_name_ = strdup(class_name.ToCString()); |
| 1571 } | 1488 } |
| 1572 exception_callback_name_ = strdup("_unhandledExceptionCallback"); | |
| 1573 SerializeObject(message, &serialized_message_, &serialized_message_len_); | 1489 SerializeObject(message, &serialized_message_, &serialized_message_len_); |
| 1574 } | 1490 } |
| 1575 | 1491 |
| 1576 | 1492 |
| 1577 IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port, | 1493 IsolateSpawnState::IsolateSpawnState(Dart_Port parent_port, |
| 1578 const char* script_url, | 1494 const char* script_url, |
| 1579 const char* package_root, | 1495 const char* package_root, |
| 1580 const Instance& args, | 1496 const Instance& args, |
| 1581 const Instance& message, | 1497 const Instance& message, |
| 1582 bool paused) | 1498 bool paused) |
| 1583 : isolate_(NULL), | 1499 : isolate_(NULL), |
| 1584 parent_port_(parent_port), | 1500 parent_port_(parent_port), |
| 1585 package_root_(NULL), | 1501 package_root_(NULL), |
| 1586 library_url_(NULL), | 1502 library_url_(NULL), |
| 1587 class_name_(NULL), | 1503 class_name_(NULL), |
| 1588 function_name_(NULL), | 1504 function_name_(NULL), |
| 1589 exception_callback_name_(NULL), | |
| 1590 serialized_args_(NULL), | 1505 serialized_args_(NULL), |
| 1591 serialized_args_len_(0), | 1506 serialized_args_len_(0), |
| 1592 serialized_message_(NULL), | 1507 serialized_message_(NULL), |
| 1593 serialized_message_len_(0), | 1508 serialized_message_len_(0), |
| 1594 paused_(paused) { | 1509 paused_(paused) { |
| 1595 script_url_ = strdup(script_url); | 1510 script_url_ = strdup(script_url); |
| 1596 if (package_root != NULL) { | 1511 if (package_root != NULL) { |
| 1597 package_root_ = strdup(package_root); | 1512 package_root_ = strdup(package_root); |
| 1598 } | 1513 } |
| 1599 library_url_ = NULL; | 1514 library_url_ = NULL; |
| 1600 function_name_ = strdup("main"); | 1515 function_name_ = strdup("main"); |
| 1601 exception_callback_name_ = strdup("_unhandledExceptionCallback"); | |
| 1602 SerializeObject(args, &serialized_args_, &serialized_args_len_); | 1516 SerializeObject(args, &serialized_args_, &serialized_args_len_); |
| 1603 SerializeObject(message, &serialized_message_, &serialized_message_len_); | 1517 SerializeObject(message, &serialized_message_, &serialized_message_len_); |
| 1604 } | 1518 } |
| 1605 | 1519 |
| 1606 | 1520 |
| 1607 IsolateSpawnState::~IsolateSpawnState() { | 1521 IsolateSpawnState::~IsolateSpawnState() { |
| 1608 free(script_url_); | 1522 free(script_url_); |
| 1609 free(package_root_); | 1523 free(package_root_); |
| 1610 free(library_url_); | 1524 free(library_url_); |
| 1611 free(function_name_); | 1525 free(function_name_); |
| 1612 free(class_name_); | 1526 free(class_name_); |
| 1613 free(exception_callback_name_); | |
| 1614 free(serialized_args_); | 1527 free(serialized_args_); |
| 1615 free(serialized_message_); | 1528 free(serialized_message_); |
| 1616 } | 1529 } |
| 1617 | 1530 |
| 1618 | 1531 |
| 1619 RawObject* IsolateSpawnState::ResolveFunction() { | 1532 RawObject* IsolateSpawnState::ResolveFunction() { |
| 1620 // Resolve the library. | 1533 // Resolve the library. |
| 1621 Library& lib = Library::Handle(); | 1534 Library& lib = Library::Handle(); |
| 1622 if (library_url()) { | 1535 if (library_url()) { |
| 1623 const String& lib_url = String::Handle(String::New(library_url())); | 1536 const String& lib_url = String::Handle(String::New(library_url())); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1679 serialized_message_, serialized_message_len_); | 1592 serialized_message_, serialized_message_len_); |
| 1680 } | 1593 } |
| 1681 | 1594 |
| 1682 | 1595 |
| 1683 void IsolateSpawnState::Cleanup() { | 1596 void IsolateSpawnState::Cleanup() { |
| 1684 SwitchIsolateScope switch_scope(I); | 1597 SwitchIsolateScope switch_scope(I); |
| 1685 Dart::ShutdownIsolate(); | 1598 Dart::ShutdownIsolate(); |
| 1686 } | 1599 } |
| 1687 | 1600 |
| 1688 } // namespace dart | 1601 } // namespace dart |
| OLD | NEW |