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 |