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