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 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 // address that can be used for comparisons with addresses into the | 326 // address that can be used for comparisons with addresses into the |
327 // JS stack. When running without the simulator, the address | 327 // JS stack. When running without the simulator, the address |
328 // returned will be the address of the C++ try catch handler itself. | 328 // returned will be the address of the C++ try catch handler itself. |
329 Address address = reinterpret_cast<Address>( | 329 Address address = reinterpret_cast<Address>( |
330 SimulatorStack::RegisterCTryCatch(reinterpret_cast<uintptr_t>(that))); | 330 SimulatorStack::RegisterCTryCatch(reinterpret_cast<uintptr_t>(that))); |
331 thread_local_.set_try_catch_handler_address(address); | 331 thread_local_.set_try_catch_handler_address(address); |
332 } | 332 } |
333 | 333 |
334 | 334 |
335 void Top::UnregisterTryCatchHandler(v8::TryCatch* that) { | 335 void Top::UnregisterTryCatchHandler(v8::TryCatch* that) { |
336 ASSERT(thread_local_.TryCatchHandler() == that); | 336 ASSERT(try_catch_handler() == that); |
337 thread_local_.set_try_catch_handler_address( | 337 thread_local_.set_try_catch_handler_address( |
338 reinterpret_cast<Address>(that->next_)); | 338 reinterpret_cast<Address>(that->next_)); |
339 thread_local_.catcher_ = NULL; | 339 thread_local_.catcher_ = NULL; |
340 SimulatorStack::UnregisterCTryCatch(); | 340 SimulatorStack::UnregisterCTryCatch(); |
341 } | 341 } |
342 | 342 |
343 | 343 |
344 | 344 |
345 static int stack_trace_nesting_level = 0; | 345 static int stack_trace_nesting_level = 0; |
346 static StringStream* incomplete_message = NULL; | 346 static StringStream* incomplete_message = NULL; |
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 } | 725 } |
726 | 726 |
727 | 727 |
728 Failure* Top::Throw(Object* exception, MessageLocation* location) { | 728 Failure* Top::Throw(Object* exception, MessageLocation* location) { |
729 DoThrow(exception, location, NULL); | 729 DoThrow(exception, location, NULL); |
730 return Failure::Exception(); | 730 return Failure::Exception(); |
731 } | 731 } |
732 | 732 |
733 | 733 |
734 Failure* Top::ReThrow(MaybeObject* exception, MessageLocation* location) { | 734 Failure* Top::ReThrow(MaybeObject* exception, MessageLocation* location) { |
| 735 bool can_be_caught_externally = false; |
| 736 ShouldReportException(&can_be_caught_externally, |
| 737 is_catchable_by_javascript(exception)); |
| 738 if (can_be_caught_externally) { |
| 739 thread_local_.catcher_ = try_catch_handler(); |
| 740 } |
| 741 |
735 // Set the exception being re-thrown. | 742 // Set the exception being re-thrown. |
736 set_pending_exception(exception); | 743 set_pending_exception(exception); |
737 return Failure::Exception(); | 744 return Failure::Exception(); |
738 } | 745 } |
739 | 746 |
740 | 747 |
741 Failure* Top::ThrowIllegalOperation() { | 748 Failure* Top::ThrowIllegalOperation() { |
742 return Throw(Heap::illegal_access_symbol()); | 749 return Throw(Heap::illegal_access_symbol()); |
743 } | 750 } |
744 | 751 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
800 !(Script::cast(script)->source()->IsUndefined())) { | 807 !(Script::cast(script)->source()->IsUndefined())) { |
801 int pos = frame->code()->SourcePosition(frame->pc()); | 808 int pos = frame->code()->SourcePosition(frame->pc()); |
802 // Compute the location from the function and the reloc info. | 809 // Compute the location from the function and the reloc info. |
803 Handle<Script> casted_script(Script::cast(script)); | 810 Handle<Script> casted_script(Script::cast(script)); |
804 *target = MessageLocation(casted_script, pos, pos + 1); | 811 *target = MessageLocation(casted_script, pos, pos + 1); |
805 } | 812 } |
806 } | 813 } |
807 } | 814 } |
808 | 815 |
809 | 816 |
810 bool Top::ShouldReportException(bool* is_caught_externally, | 817 bool Top::ShouldReportException(bool* can_be_caught_externally, |
811 bool catchable_by_javascript) { | 818 bool catchable_by_javascript) { |
812 // Find the top-most try-catch handler. | 819 // Find the top-most try-catch handler. |
813 StackHandler* handler = | 820 StackHandler* handler = |
814 StackHandler::FromAddress(Top::handler(Top::GetCurrentThread())); | 821 StackHandler::FromAddress(Top::handler(Top::GetCurrentThread())); |
815 while (handler != NULL && !handler->is_try_catch()) { | 822 while (handler != NULL && !handler->is_try_catch()) { |
816 handler = handler->next(); | 823 handler = handler->next(); |
817 } | 824 } |
818 | 825 |
819 // Get the address of the external handler so we can compare the address to | 826 // Get the address of the external handler so we can compare the address to |
820 // determine which one is closer to the top of the stack. | 827 // determine which one is closer to the top of the stack. |
821 Address external_handler_address = thread_local_.try_catch_handler_address(); | 828 Address external_handler_address = thread_local_.try_catch_handler_address(); |
822 | 829 |
823 // The exception has been externally caught if and only if there is | 830 // The exception has been externally caught if and only if there is |
824 // an external handler which is on top of the top-most try-catch | 831 // an external handler which is on top of the top-most try-catch |
825 // handler. | 832 // handler. |
826 *is_caught_externally = external_handler_address != NULL && | 833 *can_be_caught_externally = external_handler_address != NULL && |
827 (handler == NULL || handler->address() > external_handler_address || | 834 (handler == NULL || handler->address() > external_handler_address || |
828 !catchable_by_javascript); | 835 !catchable_by_javascript); |
829 | 836 |
830 if (*is_caught_externally) { | 837 if (*can_be_caught_externally) { |
831 // Only report the exception if the external handler is verbose. | 838 // Only report the exception if the external handler is verbose. |
832 return thread_local_.TryCatchHandler()->is_verbose_; | 839 return try_catch_handler()->is_verbose_; |
833 } else { | 840 } else { |
834 // Report the exception if it isn't caught by JavaScript code. | 841 // Report the exception if it isn't caught by JavaScript code. |
835 return handler == NULL; | 842 return handler == NULL; |
836 } | 843 } |
837 } | 844 } |
838 | 845 |
839 | 846 |
840 void Top::DoThrow(MaybeObject* exception, | 847 void Top::DoThrow(MaybeObject* exception, |
841 MessageLocation* location, | 848 MessageLocation* location, |
842 const char* message) { | 849 const char* message) { |
843 ASSERT(!has_pending_exception()); | 850 ASSERT(!has_pending_exception()); |
844 | 851 |
845 HandleScope scope; | 852 HandleScope scope; |
846 Object* exception_object = Smi::FromInt(0); | 853 Object* exception_object = Smi::FromInt(0); |
847 bool is_object = exception->ToObject(&exception_object); | 854 bool is_object = exception->ToObject(&exception_object); |
848 Handle<Object> exception_handle(exception_object); | 855 Handle<Object> exception_handle(exception_object); |
849 | 856 |
850 // Determine reporting and whether the exception is caught externally. | 857 // Determine reporting and whether the exception is caught externally. |
851 bool is_out_of_memory = exception == Failure::OutOfMemoryException(); | 858 bool catchable_by_javascript = is_catchable_by_javascript(exception); |
852 bool is_termination_exception = exception == Heap::termination_exception(); | |
853 bool catchable_by_javascript = !is_termination_exception && !is_out_of_memory; | |
854 // Only real objects can be caught by JS. | 859 // Only real objects can be caught by JS. |
855 ASSERT(!catchable_by_javascript || is_object); | 860 ASSERT(!catchable_by_javascript || is_object); |
856 bool is_caught_externally = false; | 861 bool can_be_caught_externally = false; |
857 bool should_report_exception = | 862 bool should_report_exception = |
858 ShouldReportException(&is_caught_externally, catchable_by_javascript); | 863 ShouldReportException(&can_be_caught_externally, catchable_by_javascript); |
859 bool report_exception = catchable_by_javascript && should_report_exception; | 864 bool report_exception = catchable_by_javascript && should_report_exception; |
860 | 865 |
861 #ifdef ENABLE_DEBUGGER_SUPPORT | 866 #ifdef ENABLE_DEBUGGER_SUPPORT |
862 // Notify debugger of exception. | 867 // Notify debugger of exception. |
863 if (catchable_by_javascript) { | 868 if (catchable_by_javascript) { |
864 Debugger::OnException(exception_handle, report_exception); | 869 Debugger::OnException(exception_handle, report_exception); |
865 } | 870 } |
866 #endif | 871 #endif |
867 | 872 |
868 // Generate the message. | 873 // Generate the message. |
869 Handle<Object> message_obj; | 874 Handle<Object> message_obj; |
870 MessageLocation potential_computed_location; | 875 MessageLocation potential_computed_location; |
871 bool try_catch_needs_message = | 876 bool try_catch_needs_message = |
872 is_caught_externally && | 877 can_be_caught_externally && |
873 thread_local_.TryCatchHandler()->capture_message_; | 878 try_catch_handler()->capture_message_; |
874 if (report_exception || try_catch_needs_message) { | 879 if (report_exception || try_catch_needs_message) { |
875 if (location == NULL) { | 880 if (location == NULL) { |
876 // If no location was specified we use a computed one instead | 881 // If no location was specified we use a computed one instead |
877 ComputeLocation(&potential_computed_location); | 882 ComputeLocation(&potential_computed_location); |
878 location = &potential_computed_location; | 883 location = &potential_computed_location; |
879 } | 884 } |
880 if (!Bootstrapper::IsActive()) { | 885 if (!Bootstrapper::IsActive()) { |
881 // It's not safe to try to make message objects or collect stack | 886 // It's not safe to try to make message objects or collect stack |
882 // traces while the bootstrapper is active since the infrastructure | 887 // traces while the bootstrapper is active since the infrastructure |
883 // may not have been properly initialized. | 888 // may not have been properly initialized. |
(...skipping 17 matching lines...) Expand all Loading... |
901 thread_local_.pending_message_ = message; | 906 thread_local_.pending_message_ = message; |
902 if (!message_obj.is_null()) { | 907 if (!message_obj.is_null()) { |
903 thread_local_.pending_message_obj_ = *message_obj; | 908 thread_local_.pending_message_obj_ = *message_obj; |
904 if (location != NULL) { | 909 if (location != NULL) { |
905 thread_local_.pending_message_script_ = *location->script(); | 910 thread_local_.pending_message_script_ = *location->script(); |
906 thread_local_.pending_message_start_pos_ = location->start_pos(); | 911 thread_local_.pending_message_start_pos_ = location->start_pos(); |
907 thread_local_.pending_message_end_pos_ = location->end_pos(); | 912 thread_local_.pending_message_end_pos_ = location->end_pos(); |
908 } | 913 } |
909 } | 914 } |
910 | 915 |
911 if (is_caught_externally) { | 916 if (can_be_caught_externally) { |
912 thread_local_.catcher_ = thread_local_.TryCatchHandler(); | 917 thread_local_.catcher_ = try_catch_handler(); |
913 } | 918 } |
914 | 919 |
915 // NOTE: Notifying the debugger or generating the message | 920 // NOTE: Notifying the debugger or generating the message |
916 // may have caused new exceptions. For now, we just ignore | 921 // may have caused new exceptions. For now, we just ignore |
917 // that and set the pending exception to the original one. | 922 // that and set the pending exception to the original one. |
918 if (is_object) { | 923 if (is_object) { |
919 set_pending_exception(*exception_handle); | 924 set_pending_exception(*exception_handle); |
920 } else { | 925 } else { |
921 // Failures are not on the heap so they neither need nor work with handles. | 926 // Failures are not on the heap so they neither need nor work with handles. |
922 ASSERT(exception_handle->IsFailure()); | 927 ASSERT(exception_handle->IsFailure()); |
923 set_pending_exception(exception); | 928 set_pending_exception(exception); |
924 } | 929 } |
925 } | 930 } |
926 | 931 |
927 | 932 |
| 933 bool Top::IsExternallyCaught() { |
| 934 ASSERT(has_pending_exception()); |
| 935 |
| 936 if ((thread_local_.catcher_ == NULL) || |
| 937 (try_catch_handler() != thread_local_.catcher_)) { |
| 938 // When throwing the exception, we found no v8::TryCatch |
| 939 // which should care about this exception. |
| 940 return false; |
| 941 } |
| 942 |
| 943 if (!is_catchable_by_javascript(pending_exception())) { |
| 944 return true; |
| 945 } |
| 946 |
| 947 // Get the address of the external handler so we can compare the address to |
| 948 // determine which one is closer to the top of the stack. |
| 949 Address external_handler_address = thread_local_.try_catch_handler_address(); |
| 950 ASSERT(external_handler_address != NULL); |
| 951 |
| 952 // The exception has been externally caught if and only if there is |
| 953 // an external handler which is on top of the top-most try-finally |
| 954 // handler. |
| 955 // There should be no try-catch blocks as they would prohibit us from |
| 956 // finding external catcher in the first place (see catcher_ check above). |
| 957 // |
| 958 // Note, that finally clause would rethrow an exception unless it's |
| 959 // aborted by jumps in control flow like return, break, etc. and we'll |
| 960 // have another chances to set proper v8::TryCatch. |
| 961 StackHandler* handler = |
| 962 StackHandler::FromAddress(Top::handler(Top::GetCurrentThread())); |
| 963 while (handler != NULL && handler->address() < external_handler_address) { |
| 964 ASSERT(!handler->is_try_catch()); |
| 965 if (handler->is_try_finally()) return false; |
| 966 |
| 967 handler = handler->next(); |
| 968 } |
| 969 |
| 970 return true; |
| 971 } |
| 972 |
| 973 |
928 void Top::ReportPendingMessages() { | 974 void Top::ReportPendingMessages() { |
929 ASSERT(has_pending_exception()); | 975 ASSERT(has_pending_exception()); |
930 setup_external_caught(); | |
931 // If the pending exception is OutOfMemoryException set out_of_memory in | 976 // If the pending exception is OutOfMemoryException set out_of_memory in |
932 // the global context. Note: We have to mark the global context here | 977 // the global context. Note: We have to mark the global context here |
933 // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to | 978 // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to |
934 // set it. | 979 // set it. |
935 bool external_caught = thread_local_.external_caught_exception_; | 980 bool external_caught = IsExternallyCaught(); |
| 981 thread_local_.external_caught_exception_ = external_caught; |
936 HandleScope scope; | 982 HandleScope scope; |
937 if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) { | 983 if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) { |
938 context()->mark_out_of_memory(); | 984 context()->mark_out_of_memory(); |
939 } else if (thread_local_.pending_exception_ == | 985 } else if (thread_local_.pending_exception_ == |
940 Heap::termination_exception()) { | 986 Heap::termination_exception()) { |
941 if (external_caught) { | 987 if (external_caught) { |
942 thread_local_.TryCatchHandler()->can_continue_ = false; | 988 try_catch_handler()->can_continue_ = false; |
943 thread_local_.TryCatchHandler()->exception_ = Heap::null_value(); | 989 try_catch_handler()->exception_ = Heap::null_value(); |
944 } | 990 } |
945 } else { | 991 } else { |
946 // At this point all non-object (failure) exceptions have | 992 // At this point all non-object (failure) exceptions have |
947 // been dealt with so this shouldn't fail. | 993 // been dealt with so this shouldn't fail. |
948 Object* pending_exception_object = pending_exception()->ToObjectUnchecked(); | 994 Object* pending_exception_object = pending_exception()->ToObjectUnchecked(); |
949 Handle<Object> exception(pending_exception_object); | 995 Handle<Object> exception(pending_exception_object); |
950 thread_local_.external_caught_exception_ = false; | 996 thread_local_.external_caught_exception_ = false; |
951 if (external_caught) { | 997 if (external_caught) { |
952 thread_local_.TryCatchHandler()->can_continue_ = true; | 998 try_catch_handler()->can_continue_ = true; |
953 thread_local_.TryCatchHandler()->exception_ = | 999 try_catch_handler()->exception_ = thread_local_.pending_exception_; |
954 thread_local_.pending_exception_; | |
955 if (!thread_local_.pending_message_obj_->IsTheHole()) { | 1000 if (!thread_local_.pending_message_obj_->IsTheHole()) { |
956 try_catch_handler()->message_ = thread_local_.pending_message_obj_; | 1001 try_catch_handler()->message_ = thread_local_.pending_message_obj_; |
957 } | 1002 } |
958 } | 1003 } |
959 if (thread_local_.has_pending_message_) { | 1004 if (thread_local_.has_pending_message_) { |
960 thread_local_.has_pending_message_ = false; | 1005 thread_local_.has_pending_message_ = false; |
961 if (thread_local_.pending_message_ != NULL) { | 1006 if (thread_local_.pending_message_ != NULL) { |
962 MessageHandler::ReportMessage(thread_local_.pending_message_); | 1007 MessageHandler::ReportMessage(thread_local_.pending_message_); |
963 } else if (!thread_local_.pending_message_obj_->IsTheHole()) { | 1008 } else if (!thread_local_.pending_message_obj_->IsTheHole()) { |
964 Handle<Object> message_obj(thread_local_.pending_message_obj_); | 1009 Handle<Object> message_obj(thread_local_.pending_message_obj_); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1098 #ifdef V8_TARGET_ARCH_ARM | 1143 #ifdef V8_TARGET_ARCH_ARM |
1099 thread_local_.simulator_ = Simulator::current(); | 1144 thread_local_.simulator_ = Simulator::current(); |
1100 #elif V8_TARGET_ARCH_MIPS | 1145 #elif V8_TARGET_ARCH_MIPS |
1101 thread_local_.simulator_ = assembler::mips::Simulator::current(); | 1146 thread_local_.simulator_ = assembler::mips::Simulator::current(); |
1102 #endif | 1147 #endif |
1103 #endif | 1148 #endif |
1104 return from + sizeof(thread_local_); | 1149 return from + sizeof(thread_local_); |
1105 } | 1150 } |
1106 | 1151 |
1107 } } // namespace v8::internal | 1152 } } // namespace v8::internal |
OLD | NEW |