OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 | 91 |
92 void Top::InitializeThreadLocal() { | 92 void Top::InitializeThreadLocal() { |
93 thread_local_.c_entry_fp_ = 0; | 93 thread_local_.c_entry_fp_ = 0; |
94 thread_local_.handler_ = 0; | 94 thread_local_.handler_ = 0; |
95 #ifdef ENABLE_LOGGING_AND_PROFILING | 95 #ifdef ENABLE_LOGGING_AND_PROFILING |
96 thread_local_.js_entry_sp_ = 0; | 96 thread_local_.js_entry_sp_ = 0; |
97 #endif | 97 #endif |
98 thread_local_.stack_is_cooked_ = false; | 98 thread_local_.stack_is_cooked_ = false; |
99 thread_local_.try_catch_handler_ = NULL; | 99 thread_local_.try_catch_handler_ = NULL; |
100 thread_local_.context_ = NULL; | 100 thread_local_.context_ = NULL; |
| 101 thread_local_.thread_id_ = ThreadManager::kInvalidId; |
101 thread_local_.external_caught_exception_ = false; | 102 thread_local_.external_caught_exception_ = false; |
102 thread_local_.failed_access_check_callback_ = NULL; | 103 thread_local_.failed_access_check_callback_ = NULL; |
103 clear_pending_exception(); | 104 clear_pending_exception(); |
104 clear_pending_message(); | 105 clear_pending_message(); |
105 clear_scheduled_exception(); | 106 clear_scheduled_exception(); |
106 thread_local_.save_context_ = NULL; | 107 thread_local_.save_context_ = NULL; |
107 thread_local_.catcher_ = NULL; | 108 thread_local_.catcher_ = NULL; |
108 } | 109 } |
109 | 110 |
110 | 111 |
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
591 // double fault with another stack overflow exception, we use a | 592 // double fault with another stack overflow exception, we use a |
592 // precomputed message. This is somewhat problematic in that it | 593 // precomputed message. This is somewhat problematic in that it |
593 // doesn't use ReportUncaughtException to determine the location | 594 // doesn't use ReportUncaughtException to determine the location |
594 // from where the exception occurred. It should probably be | 595 // from where the exception occurred. It should probably be |
595 // reworked. | 596 // reworked. |
596 DoThrow(*exception, NULL, kStackOverflowMessage); | 597 DoThrow(*exception, NULL, kStackOverflowMessage); |
597 return Failure::Exception(); | 598 return Failure::Exception(); |
598 } | 599 } |
599 | 600 |
600 | 601 |
| 602 Failure* Top::TerminateExecution() { |
| 603 DoThrow(Heap::termination_exception(), NULL, NULL); |
| 604 return Failure::Exception(); |
| 605 } |
| 606 |
| 607 |
601 Failure* Top::Throw(Object* exception, MessageLocation* location) { | 608 Failure* Top::Throw(Object* exception, MessageLocation* location) { |
602 DoThrow(exception, location, NULL); | 609 DoThrow(exception, location, NULL); |
603 return Failure::Exception(); | 610 return Failure::Exception(); |
604 } | 611 } |
605 | 612 |
606 | 613 |
607 Failure* Top::ReThrow(Object* exception, MessageLocation* location) { | 614 Failure* Top::ReThrow(Object* exception, MessageLocation* location) { |
608 // Set the exception being re-thrown. | 615 // Set the exception being re-thrown. |
609 set_pending_exception(exception); | 616 set_pending_exception(exception); |
610 return Failure::Exception(); | 617 return Failure::Exception(); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 MessageHandler::MakeMessageObject("uncaught_exception", | 694 MessageHandler::MakeMessageObject("uncaught_exception", |
688 location, | 695 location, |
689 HandleVector<Object>(&exception, 1), | 696 HandleVector<Object>(&exception, 1), |
690 stack_trace); | 697 stack_trace); |
691 | 698 |
692 // Report the uncaught exception. | 699 // Report the uncaught exception. |
693 MessageHandler::ReportMessage(location, message); | 700 MessageHandler::ReportMessage(location, message); |
694 } | 701 } |
695 | 702 |
696 | 703 |
697 bool Top::ShouldReportException(bool* is_caught_externally) { | 704 bool Top::ShouldReturnException(bool* is_caught_externally, |
| 705 bool catchable_by_javascript) { |
698 // Find the top-most try-catch handler. | 706 // Find the top-most try-catch handler. |
699 StackHandler* handler = | 707 StackHandler* handler = |
700 StackHandler::FromAddress(Top::handler(Top::GetCurrentThread())); | 708 StackHandler::FromAddress(Top::handler(Top::GetCurrentThread())); |
701 while (handler != NULL && !handler->is_try_catch()) { | 709 while (handler != NULL && !handler->is_try_catch()) { |
702 handler = handler->next(); | 710 handler = handler->next(); |
703 } | 711 } |
704 | 712 |
705 // Get the address of the external handler so we can compare the address to | 713 // Get the address of the external handler so we can compare the address to |
706 // determine which one is closer to the top of the stack. | 714 // determine which one is closer to the top of the stack. |
707 v8::TryCatch* try_catch = thread_local_.try_catch_handler_; | 715 v8::TryCatch* try_catch = thread_local_.try_catch_handler_; |
708 | 716 |
709 // The exception has been externally caught if and only if there is | 717 // The exception has been externally caught if and only if there is |
710 // an external handler which is on top of the top-most try-catch | 718 // an external handler which is on top of the top-most try-catch |
711 // handler. | 719 // handler. |
712 // | 720 // |
713 // See comments in RegisterTryCatchHandler for details. | 721 // See comments in RegisterTryCatchHandler for details. |
714 *is_caught_externally = try_catch != NULL && | 722 *is_caught_externally = try_catch != NULL && |
715 (handler == NULL || handler == try_catch->js_handler_); | 723 (handler == NULL || handler == try_catch->js_handler_ || |
| 724 !catchable_by_javascript); |
716 | 725 |
717 if (*is_caught_externally) { | 726 if (*is_caught_externally) { |
718 // Only report the exception if the external handler is verbose. | 727 // Only report the exception if the external handler is verbose. |
719 return thread_local_.try_catch_handler_->is_verbose_; | 728 return thread_local_.try_catch_handler_->is_verbose_; |
720 } else { | 729 } else { |
721 // Report the exception if it isn't caught by JavaScript code. | 730 // Report the exception if it isn't caught by JavaScript code. |
722 return handler == NULL; | 731 return handler == NULL; |
723 } | 732 } |
724 } | 733 } |
725 | 734 |
726 | 735 |
727 void Top::DoThrow(Object* exception, | 736 void Top::DoThrow(Object* exception, |
728 MessageLocation* location, | 737 MessageLocation* location, |
729 const char* message) { | 738 const char* message) { |
730 ASSERT(!has_pending_exception()); | 739 ASSERT(!has_pending_exception()); |
731 | 740 |
732 HandleScope scope; | 741 HandleScope scope; |
733 Handle<Object> exception_handle(exception); | 742 Handle<Object> exception_handle(exception); |
734 | 743 |
735 // Determine reporting and whether the exception is caught externally. | 744 // Determine reporting and whether the exception is caught externally. |
736 bool is_caught_externally = false; | 745 bool is_caught_externally = false; |
737 bool is_out_of_memory = exception == Failure::OutOfMemoryException(); | 746 bool is_out_of_memory = exception == Failure::OutOfMemoryException(); |
738 bool should_return_exception = ShouldReportException(&is_caught_externally); | 747 bool is_termination_exception = exception == Heap::termination_exception(); |
739 bool report_exception = !is_out_of_memory && should_return_exception; | 748 bool catchable_by_javascript = !is_termination_exception && !is_out_of_memory; |
| 749 bool should_return_exception = |
| 750 ShouldReturnException(&is_caught_externally, catchable_by_javascript); |
| 751 bool report_exception = catchable_by_javascript && should_return_exception; |
740 | 752 |
741 #ifdef ENABLE_DEBUGGER_SUPPORT | 753 #ifdef ENABLE_DEBUGGER_SUPPORT |
742 // Notify debugger of exception. | 754 // Notify debugger of exception. |
743 Debugger::OnException(exception_handle, report_exception); | 755 if (catchable_by_javascript) { |
| 756 Debugger::OnException(exception_handle, report_exception); |
| 757 } |
744 #endif | 758 #endif |
745 | 759 |
746 // Generate the message. | 760 // Generate the message. |
747 Handle<Object> message_obj; | 761 Handle<Object> message_obj; |
748 MessageLocation potential_computed_location; | 762 MessageLocation potential_computed_location; |
749 bool try_catch_needs_message = | 763 bool try_catch_needs_message = |
750 is_caught_externally && | 764 is_caught_externally && |
751 thread_local_.try_catch_handler_->capture_message_; | 765 thread_local_.try_catch_handler_->capture_message_; |
752 if (report_exception || try_catch_needs_message) { | 766 if (report_exception || try_catch_needs_message) { |
753 if (location == NULL) { | 767 if (location == NULL) { |
(...skipping 30 matching lines...) Expand all Loading... |
784 } | 798 } |
785 | 799 |
786 | 800 |
787 void Top::ReportPendingMessages() { | 801 void Top::ReportPendingMessages() { |
788 ASSERT(has_pending_exception()); | 802 ASSERT(has_pending_exception()); |
789 setup_external_caught(); | 803 setup_external_caught(); |
790 // If the pending exception is OutOfMemoryException set out_of_memory in | 804 // If the pending exception is OutOfMemoryException set out_of_memory in |
791 // the global context. Note: We have to mark the global context here | 805 // the global context. Note: We have to mark the global context here |
792 // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to | 806 // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to |
793 // set it. | 807 // set it. |
| 808 bool external_caught = thread_local_.external_caught_exception_; |
794 HandleScope scope; | 809 HandleScope scope; |
795 if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) { | 810 if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) { |
796 context()->mark_out_of_memory(); | 811 context()->mark_out_of_memory(); |
| 812 } else if (thread_local_.pending_exception_ == |
| 813 Heap::termination_exception()) { |
| 814 if (external_caught) { |
| 815 thread_local_.try_catch_handler_->can_continue_ = false; |
| 816 thread_local_.try_catch_handler_->exception_ = Heap::null_value(); |
| 817 } |
797 } else { | 818 } else { |
798 Handle<Object> exception(pending_exception()); | 819 Handle<Object> exception(pending_exception()); |
799 bool external_caught = thread_local_.external_caught_exception_; | |
800 thread_local_.external_caught_exception_ = false; | 820 thread_local_.external_caught_exception_ = false; |
801 if (external_caught) { | 821 if (external_caught) { |
| 822 thread_local_.try_catch_handler_->can_continue_ = true; |
802 thread_local_.try_catch_handler_->exception_ = | 823 thread_local_.try_catch_handler_->exception_ = |
803 thread_local_.pending_exception_; | 824 thread_local_.pending_exception_; |
804 if (!thread_local_.pending_message_obj_->IsTheHole()) { | 825 if (!thread_local_.pending_message_obj_->IsTheHole()) { |
805 try_catch_handler()->message_ = thread_local_.pending_message_obj_; | 826 try_catch_handler()->message_ = thread_local_.pending_message_obj_; |
806 } | 827 } |
807 } | 828 } |
808 if (thread_local_.has_pending_message_) { | 829 if (thread_local_.has_pending_message_) { |
809 thread_local_.has_pending_message_ = false; | 830 thread_local_.has_pending_message_ = false; |
810 if (thread_local_.pending_message_ != NULL) { | 831 if (thread_local_.pending_message_ != NULL) { |
811 MessageHandler::ReportMessage(thread_local_.pending_message_); | 832 MessageHandler::ReportMessage(thread_local_.pending_message_); |
(...skipping 15 matching lines...) Expand all Loading... |
827 } | 848 } |
828 clear_pending_message(); | 849 clear_pending_message(); |
829 } | 850 } |
830 | 851 |
831 | 852 |
832 void Top::TraceException(bool flag) { | 853 void Top::TraceException(bool flag) { |
833 FLAG_trace_exception = flag; | 854 FLAG_trace_exception = flag; |
834 } | 855 } |
835 | 856 |
836 | 857 |
837 bool Top::optional_reschedule_exception(bool is_bottom_call) { | 858 bool Top::OptionalRescheduleException(bool is_bottom_call, |
| 859 bool force_clear_catchable) { |
838 // Allways reschedule out of memory exceptions. | 860 // Allways reschedule out of memory exceptions. |
839 if (!is_out_of_memory()) { | 861 if (!is_out_of_memory()) { |
840 // Never reschedule the exception if this is the bottom call. | 862 bool is_termination_exception = |
841 bool clear_exception = is_bottom_call; | 863 pending_exception() == Heap::termination_exception(); |
842 | 864 |
843 // If the exception is externally caught, clear it if there are no | 865 // Do not reschedule the exception if this is the bottom call or |
844 // JavaScript frames on the way to the C++ frame that has the | 866 // if we are asked to clear catchable exceptions. Termination |
845 // external handler. | 867 // exceptions are not catchable and are only cleared if this is |
846 if (thread_local_.external_caught_exception_) { | 868 // the bottom call. |
| 869 bool clear_exception = is_bottom_call || |
| 870 (force_clear_catchable && !is_termination_exception); |
| 871 |
| 872 if (is_termination_exception) { |
| 873 thread_local_.external_caught_exception_ = false; |
| 874 if (is_bottom_call) { |
| 875 clear_pending_exception(); |
| 876 return false; |
| 877 } |
| 878 } else if (thread_local_.external_caught_exception_) { |
| 879 // If the exception is externally caught, clear it if there are no |
| 880 // JavaScript frames on the way to the C++ frame that has the |
| 881 // external handler. |
847 ASSERT(thread_local_.try_catch_handler_ != NULL); | 882 ASSERT(thread_local_.try_catch_handler_ != NULL); |
848 Address external_handler_address = | 883 Address external_handler_address = |
849 reinterpret_cast<Address>(thread_local_.try_catch_handler_); | 884 reinterpret_cast<Address>(thread_local_.try_catch_handler_); |
850 JavaScriptFrameIterator it; | 885 JavaScriptFrameIterator it; |
851 if (it.done() || (it.frame()->sp() > external_handler_address)) { | 886 if (it.done() || (it.frame()->sp() > external_handler_address)) { |
852 clear_exception = true; | 887 clear_exception = true; |
853 } | 888 } |
854 } | 889 } |
855 | 890 |
856 // Clear the exception if needed. | 891 // Clear the exception if needed. |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
933 Top::break_access_->Lock(); | 968 Top::break_access_->Lock(); |
934 } | 969 } |
935 | 970 |
936 | 971 |
937 ExecutionAccess::~ExecutionAccess() { | 972 ExecutionAccess::~ExecutionAccess() { |
938 Top::break_access_->Unlock(); | 973 Top::break_access_->Unlock(); |
939 } | 974 } |
940 | 975 |
941 | 976 |
942 } } // namespace v8::internal | 977 } } // namespace v8::internal |
OLD | NEW |