Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: src/top.cc

Issue 6526016: Properly process try/finally blocks. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressing Mads' comments Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/top.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/top.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698