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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 } | 100 } |
101 | 101 |
102 | 102 |
103 void Top::IterateThread(ThreadVisitor* v, char* t) { | 103 void Top::IterateThread(ThreadVisitor* v, char* t) { |
104 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(t); | 104 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(t); |
105 v->VisitThread(thread); | 105 v->VisitThread(thread); |
106 } | 106 } |
107 | 107 |
108 | 108 |
109 void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) { | 109 void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) { |
110 v->VisitPointer(&(thread->pending_exception_)); | 110 // Visit the roots from the top for a given thread. |
| 111 Object *pending; |
| 112 // The pending exception can sometimes be a failure. We can't show |
| 113 // that to the GC, which only understands objects. |
| 114 if (thread->pending_exception_->ToObject(&pending)) { |
| 115 v->VisitPointer(&pending); |
| 116 thread->pending_exception_ = pending; // In case GC updated it. |
| 117 } |
111 v->VisitPointer(&(thread->pending_message_obj_)); | 118 v->VisitPointer(&(thread->pending_message_obj_)); |
112 v->VisitPointer(BitCast<Object**>(&(thread->pending_message_script_))); | 119 v->VisitPointer(BitCast<Object**>(&(thread->pending_message_script_))); |
113 v->VisitPointer(BitCast<Object**>(&(thread->context_))); | 120 v->VisitPointer(BitCast<Object**>(&(thread->context_))); |
114 v->VisitPointer(&(thread->scheduled_exception_)); | 121 Object* scheduled; |
| 122 if (thread->scheduled_exception_->ToObject(&scheduled)) { |
| 123 v->VisitPointer(&scheduled); |
| 124 thread->scheduled_exception_ = scheduled; |
| 125 } |
115 | 126 |
116 for (v8::TryCatch* block = thread->TryCatchHandler(); | 127 for (v8::TryCatch* block = thread->TryCatchHandler(); |
117 block != NULL; | 128 block != NULL; |
118 block = TRY_CATCH_FROM_ADDRESS(block->next_)) { | 129 block = TRY_CATCH_FROM_ADDRESS(block->next_)) { |
119 v->VisitPointer(BitCast<Object**>(&(block->exception_))); | 130 v->VisitPointer(BitCast<Object**>(&(block->exception_))); |
120 v->VisitPointer(BitCast<Object**>(&(block->message_))); | 131 v->VisitPointer(BitCast<Object**>(&(block->message_))); |
121 } | 132 } |
122 | 133 |
123 // Iterate over pointers on native execution stack. | 134 // Iterate over pointers on native execution stack. |
124 for (StackFrameIterator it(thread); !it.done(); it.Advance()) { | 135 for (StackFrameIterator it(thread); !it.done(); it.Advance()) { |
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
681 return Failure::Exception(); | 692 return Failure::Exception(); |
682 } | 693 } |
683 | 694 |
684 | 695 |
685 Failure* Top::Throw(Object* exception, MessageLocation* location) { | 696 Failure* Top::Throw(Object* exception, MessageLocation* location) { |
686 DoThrow(exception, location, NULL); | 697 DoThrow(exception, location, NULL); |
687 return Failure::Exception(); | 698 return Failure::Exception(); |
688 } | 699 } |
689 | 700 |
690 | 701 |
691 Failure* Top::ReThrow(Object* exception, MessageLocation* location) { | 702 Failure* Top::ReThrow(MaybeObject* exception, MessageLocation* location) { |
692 // Set the exception being re-thrown. | 703 // Set the exception being re-thrown. |
693 set_pending_exception(exception); | 704 set_pending_exception(exception); |
694 return Failure::Exception(); | 705 return Failure::Exception(); |
695 } | 706 } |
696 | 707 |
697 | 708 |
698 Failure* Top::ThrowIllegalOperation() { | 709 Failure* Top::ThrowIllegalOperation() { |
699 return Throw(Heap::illegal_access_symbol()); | 710 return Throw(Heap::illegal_access_symbol()); |
700 } | 711 } |
701 | 712 |
702 | 713 |
703 void Top::ScheduleThrow(Object* exception) { | 714 void Top::ScheduleThrow(Object* exception) { |
704 // When scheduling a throw we first throw the exception to get the | 715 // When scheduling a throw we first throw the exception to get the |
705 // error reporting if it is uncaught before rescheduling it. | 716 // error reporting if it is uncaught before rescheduling it. |
706 Throw(exception); | 717 Throw(exception); |
707 thread_local_.scheduled_exception_ = pending_exception(); | 718 thread_local_.scheduled_exception_ = pending_exception(); |
708 thread_local_.external_caught_exception_ = false; | 719 thread_local_.external_caught_exception_ = false; |
709 clear_pending_exception(); | 720 clear_pending_exception(); |
710 } | 721 } |
711 | 722 |
712 | 723 |
713 Object* Top::PromoteScheduledException() { | 724 Failure* Top::PromoteScheduledException() { |
714 Object* thrown = scheduled_exception(); | 725 MaybeObject* thrown = scheduled_exception(); |
715 clear_scheduled_exception(); | 726 clear_scheduled_exception(); |
716 // Re-throw the exception to avoid getting repeated error reporting. | 727 // Re-throw the exception to avoid getting repeated error reporting. |
717 return ReThrow(thrown); | 728 return ReThrow(thrown); |
718 } | 729 } |
719 | 730 |
720 | 731 |
721 void Top::PrintCurrentStackTrace(FILE* out) { | 732 void Top::PrintCurrentStackTrace(FILE* out) { |
722 StackTraceFrameIterator it; | 733 StackTraceFrameIterator it; |
723 while (!it.done()) { | 734 while (!it.done()) { |
724 HandleScope scope; | 735 HandleScope scope; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
787 if (*is_caught_externally) { | 798 if (*is_caught_externally) { |
788 // Only report the exception if the external handler is verbose. | 799 // Only report the exception if the external handler is verbose. |
789 return thread_local_.TryCatchHandler()->is_verbose_; | 800 return thread_local_.TryCatchHandler()->is_verbose_; |
790 } else { | 801 } else { |
791 // Report the exception if it isn't caught by JavaScript code. | 802 // Report the exception if it isn't caught by JavaScript code. |
792 return handler == NULL; | 803 return handler == NULL; |
793 } | 804 } |
794 } | 805 } |
795 | 806 |
796 | 807 |
797 void Top::DoThrow(Object* exception, | 808 void Top::DoThrow(MaybeObject* exception, |
798 MessageLocation* location, | 809 MessageLocation* location, |
799 const char* message) { | 810 const char* message) { |
800 ASSERT(!has_pending_exception()); | 811 ASSERT(!has_pending_exception()); |
801 | 812 |
802 HandleScope scope; | 813 HandleScope scope; |
803 Handle<Object> exception_handle(exception); | 814 Object* exception_object = Smi::FromInt(0); |
| 815 bool is_object = exception->ToObject(&exception_object); |
| 816 Handle<Object> exception_handle(exception_object); |
804 | 817 |
805 // Determine reporting and whether the exception is caught externally. | 818 // Determine reporting and whether the exception is caught externally. |
806 bool is_caught_externally = false; | 819 bool is_caught_externally = false; |
807 bool is_out_of_memory = exception == Failure::OutOfMemoryException(); | 820 bool is_out_of_memory = exception == Failure::OutOfMemoryException(); |
808 bool is_termination_exception = exception == Heap::termination_exception(); | 821 bool is_termination_exception = exception == Heap::termination_exception(); |
809 bool catchable_by_javascript = !is_termination_exception && !is_out_of_memory; | 822 bool catchable_by_javascript = !is_termination_exception && !is_out_of_memory; |
| 823 // Only real objects can be caught by JS. |
| 824 ASSERT(!catchable_by_javascript || is_object); |
810 bool should_return_exception = | 825 bool should_return_exception = |
811 ShouldReturnException(&is_caught_externally, catchable_by_javascript); | 826 ShouldReturnException(&is_caught_externally, catchable_by_javascript); |
812 bool report_exception = catchable_by_javascript && should_return_exception; | 827 bool report_exception = catchable_by_javascript && should_return_exception; |
813 | 828 |
814 #ifdef ENABLE_DEBUGGER_SUPPORT | 829 #ifdef ENABLE_DEBUGGER_SUPPORT |
815 // Notify debugger of exception. | 830 // Notify debugger of exception. |
816 if (catchable_by_javascript) { | 831 if (catchable_by_javascript) { |
817 Debugger::OnException(exception_handle, report_exception); | 832 Debugger::OnException(exception_handle, report_exception); |
818 } | 833 } |
819 #endif | 834 #endif |
(...skipping 15 matching lines...) Expand all Loading... |
835 // traces while the bootstrapper is active since the infrastructure | 850 // traces while the bootstrapper is active since the infrastructure |
836 // may not have been properly initialized. | 851 // may not have been properly initialized. |
837 Handle<String> stack_trace; | 852 Handle<String> stack_trace; |
838 if (FLAG_trace_exception) stack_trace = StackTraceString(); | 853 if (FLAG_trace_exception) stack_trace = StackTraceString(); |
839 Handle<JSArray> stack_trace_object; | 854 Handle<JSArray> stack_trace_object; |
840 if (report_exception && capture_stack_trace_for_uncaught_exceptions) { | 855 if (report_exception && capture_stack_trace_for_uncaught_exceptions) { |
841 stack_trace_object = Top::CaptureCurrentStackTrace( | 856 stack_trace_object = Top::CaptureCurrentStackTrace( |
842 stack_trace_for_uncaught_exceptions_frame_limit, | 857 stack_trace_for_uncaught_exceptions_frame_limit, |
843 stack_trace_for_uncaught_exceptions_options); | 858 stack_trace_for_uncaught_exceptions_options); |
844 } | 859 } |
| 860 ASSERT(is_object); // Can't use the handle unless there's a real object. |
845 message_obj = MessageHandler::MakeMessageObject("uncaught_exception", | 861 message_obj = MessageHandler::MakeMessageObject("uncaught_exception", |
846 location, HandleVector<Object>(&exception_handle, 1), stack_trace, | 862 location, HandleVector<Object>(&exception_handle, 1), stack_trace, |
847 stack_trace_object); | 863 stack_trace_object); |
848 } | 864 } |
849 } | 865 } |
850 | 866 |
851 // Save the message for reporting if the the exception remains uncaught. | 867 // Save the message for reporting if the the exception remains uncaught. |
852 thread_local_.has_pending_message_ = report_exception; | 868 thread_local_.has_pending_message_ = report_exception; |
853 thread_local_.pending_message_ = message; | 869 thread_local_.pending_message_ = message; |
854 if (!message_obj.is_null()) { | 870 if (!message_obj.is_null()) { |
855 thread_local_.pending_message_obj_ = *message_obj; | 871 thread_local_.pending_message_obj_ = *message_obj; |
856 if (location != NULL) { | 872 if (location != NULL) { |
857 thread_local_.pending_message_script_ = *location->script(); | 873 thread_local_.pending_message_script_ = *location->script(); |
858 thread_local_.pending_message_start_pos_ = location->start_pos(); | 874 thread_local_.pending_message_start_pos_ = location->start_pos(); |
859 thread_local_.pending_message_end_pos_ = location->end_pos(); | 875 thread_local_.pending_message_end_pos_ = location->end_pos(); |
860 } | 876 } |
861 } | 877 } |
862 | 878 |
863 if (is_caught_externally) { | 879 if (is_caught_externally) { |
864 thread_local_.catcher_ = thread_local_.TryCatchHandler(); | 880 thread_local_.catcher_ = thread_local_.TryCatchHandler(); |
865 } | 881 } |
866 | 882 |
867 // NOTE: Notifying the debugger or generating the message | 883 // NOTE: Notifying the debugger or generating the message |
868 // may have caused new exceptions. For now, we just ignore | 884 // may have caused new exceptions. For now, we just ignore |
869 // that and set the pending exception to the original one. | 885 // that and set the pending exception to the original one. |
870 set_pending_exception(*exception_handle); | 886 if (is_object) { |
| 887 set_pending_exception(*exception_handle); |
| 888 } else { |
| 889 // Failures are not on the heap so they neither need nor work with handles. |
| 890 ASSERT(exception_handle->IsFailure()); |
| 891 set_pending_exception(exception); |
| 892 } |
871 } | 893 } |
872 | 894 |
873 | 895 |
874 void Top::ReportPendingMessages() { | 896 void Top::ReportPendingMessages() { |
875 ASSERT(has_pending_exception()); | 897 ASSERT(has_pending_exception()); |
876 setup_external_caught(); | 898 setup_external_caught(); |
877 // If the pending exception is OutOfMemoryException set out_of_memory in | 899 // If the pending exception is OutOfMemoryException set out_of_memory in |
878 // the global context. Note: We have to mark the global context here | 900 // the global context. Note: We have to mark the global context here |
879 // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to | 901 // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to |
880 // set it. | 902 // set it. |
881 bool external_caught = thread_local_.external_caught_exception_; | 903 bool external_caught = thread_local_.external_caught_exception_; |
882 HandleScope scope; | 904 HandleScope scope; |
883 if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) { | 905 if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) { |
884 context()->mark_out_of_memory(); | 906 context()->mark_out_of_memory(); |
885 } else if (thread_local_.pending_exception_ == | 907 } else if (thread_local_.pending_exception_ == |
886 Heap::termination_exception()) { | 908 Heap::termination_exception()) { |
887 if (external_caught) { | 909 if (external_caught) { |
888 thread_local_.TryCatchHandler()->can_continue_ = false; | 910 thread_local_.TryCatchHandler()->can_continue_ = false; |
889 thread_local_.TryCatchHandler()->exception_ = Heap::null_value(); | 911 thread_local_.TryCatchHandler()->exception_ = Heap::null_value(); |
890 } | 912 } |
891 } else { | 913 } else { |
892 Handle<Object> exception(pending_exception()); | 914 // At this point all non-object (failure) exceptions have |
| 915 // been dealt with so this shouldn't fail. |
| 916 Object* pending_exception_object = pending_exception()->ToObjectUnchecked(); |
| 917 Handle<Object> exception(pending_exception_object); |
893 thread_local_.external_caught_exception_ = false; | 918 thread_local_.external_caught_exception_ = false; |
894 if (external_caught) { | 919 if (external_caught) { |
895 thread_local_.TryCatchHandler()->can_continue_ = true; | 920 thread_local_.TryCatchHandler()->can_continue_ = true; |
896 thread_local_.TryCatchHandler()->exception_ = | 921 thread_local_.TryCatchHandler()->exception_ = |
897 thread_local_.pending_exception_; | 922 thread_local_.pending_exception_; |
898 if (!thread_local_.pending_message_obj_->IsTheHole()) { | 923 if (!thread_local_.pending_message_obj_->IsTheHole()) { |
899 try_catch_handler()->message_ = thread_local_.pending_message_obj_; | 924 try_catch_handler()->message_ = thread_local_.pending_message_obj_; |
900 } | 925 } |
901 } | 926 } |
902 if (thread_local_.has_pending_message_) { | 927 if (thread_local_.has_pending_message_) { |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
976 int frame_limit, | 1001 int frame_limit, |
977 StackTrace::StackTraceOptions options) { | 1002 StackTrace::StackTraceOptions options) { |
978 capture_stack_trace_for_uncaught_exceptions = capture; | 1003 capture_stack_trace_for_uncaught_exceptions = capture; |
979 stack_trace_for_uncaught_exceptions_frame_limit = frame_limit; | 1004 stack_trace_for_uncaught_exceptions_frame_limit = frame_limit; |
980 stack_trace_for_uncaught_exceptions_options = options; | 1005 stack_trace_for_uncaught_exceptions_options = options; |
981 } | 1006 } |
982 | 1007 |
983 | 1008 |
984 bool Top::is_out_of_memory() { | 1009 bool Top::is_out_of_memory() { |
985 if (has_pending_exception()) { | 1010 if (has_pending_exception()) { |
986 Object* e = pending_exception(); | 1011 MaybeObject* e = pending_exception(); |
987 if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { | 1012 if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { |
988 return true; | 1013 return true; |
989 } | 1014 } |
990 } | 1015 } |
991 if (has_scheduled_exception()) { | 1016 if (has_scheduled_exception()) { |
992 Object* e = scheduled_exception(); | 1017 MaybeObject* e = scheduled_exception(); |
993 if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { | 1018 if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { |
994 return true; | 1019 return true; |
995 } | 1020 } |
996 } | 1021 } |
997 return false; | 1022 return false; |
998 } | 1023 } |
999 | 1024 |
1000 | 1025 |
1001 Handle<Context> Top::global_context() { | 1026 Handle<Context> Top::global_context() { |
1002 GlobalObject* global = thread_local_.context_->global(); | 1027 GlobalObject* global = thread_local_.context_->global(); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1043 Top::break_access_->Lock(); | 1068 Top::break_access_->Lock(); |
1044 } | 1069 } |
1045 | 1070 |
1046 | 1071 |
1047 ExecutionAccess::~ExecutionAccess() { | 1072 ExecutionAccess::~ExecutionAccess() { |
1048 Top::break_access_->Unlock(); | 1073 Top::break_access_->Unlock(); |
1049 } | 1074 } |
1050 | 1075 |
1051 | 1076 |
1052 } } // namespace v8::internal | 1077 } } // namespace v8::internal |
OLD | NEW |