| 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 13 matching lines...) Expand all Loading... |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "api.h" | 30 #include "api.h" |
| 31 #include "bootstrapper.h" | 31 #include "bootstrapper.h" |
| 32 #include "debug.h" | 32 #include "debug.h" |
| 33 #include "execution.h" | 33 #include "execution.h" |
| 34 #include "platform.h" |
| 35 #include "simulator.h" |
| 34 #include "string-stream.h" | 36 #include "string-stream.h" |
| 35 #include "platform.h" | |
| 36 | 37 |
| 37 namespace v8 { | 38 namespace v8 { |
| 38 namespace internal { | 39 namespace internal { |
| 39 | 40 |
| 40 ThreadLocalTop Top::thread_local_; | 41 ThreadLocalTop Top::thread_local_; |
| 41 Mutex* Top::break_access_ = OS::CreateMutex(); | 42 Mutex* Top::break_access_ = OS::CreateMutex(); |
| 42 | 43 |
| 43 NoAllocationStringAllocator* preallocated_message_space = NULL; | 44 NoAllocationStringAllocator* preallocated_message_space = NULL; |
| 44 | 45 |
| 45 Address top_addresses[] = { | 46 Address top_addresses[] = { |
| 46 #define C(name) reinterpret_cast<Address>(Top::name()), | 47 #define C(name) reinterpret_cast<Address>(Top::name()), |
| 47 TOP_ADDRESS_LIST(C) | 48 TOP_ADDRESS_LIST(C) |
| 48 TOP_ADDRESS_LIST_PROF(C) | 49 TOP_ADDRESS_LIST_PROF(C) |
| 49 #undef C | 50 #undef C |
| 50 NULL | 51 NULL |
| 51 }; | 52 }; |
| 52 | 53 |
| 54 |
| 55 v8::TryCatch* ThreadLocalTop::TryCatchHandler() { |
| 56 return TRY_CATCH_FROM_ADDRESS(try_catch_handler_address()); |
| 57 } |
| 58 |
| 59 |
| 60 void ThreadLocalTop::Initialize() { |
| 61 c_entry_fp_ = 0; |
| 62 handler_ = 0; |
| 63 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 64 js_entry_sp_ = 0; |
| 65 #endif |
| 66 stack_is_cooked_ = false; |
| 67 try_catch_handler_address_ = NULL; |
| 68 context_ = NULL; |
| 69 int id = ThreadManager::CurrentId(); |
| 70 thread_id_ = (id == 0) ? ThreadManager::kInvalidId : id; |
| 71 external_caught_exception_ = false; |
| 72 failed_access_check_callback_ = NULL; |
| 73 save_context_ = NULL; |
| 74 catcher_ = NULL; |
| 75 } |
| 76 |
| 77 |
| 53 Address Top::get_address_from_id(Top::AddressId id) { | 78 Address Top::get_address_from_id(Top::AddressId id) { |
| 54 return top_addresses[id]; | 79 return top_addresses[id]; |
| 55 } | 80 } |
| 56 | 81 |
| 57 | 82 |
| 58 char* Top::Iterate(ObjectVisitor* v, char* thread_storage) { | 83 char* Top::Iterate(ObjectVisitor* v, char* thread_storage) { |
| 59 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage); | 84 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage); |
| 60 Iterate(v, thread); | 85 Iterate(v, thread); |
| 61 return thread_storage + sizeof(ThreadLocalTop); | 86 return thread_storage + sizeof(ThreadLocalTop); |
| 62 } | 87 } |
| 63 | 88 |
| 64 | 89 |
| 65 void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) { | 90 void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) { |
| 66 v->VisitPointer(&(thread->pending_exception_)); | 91 v->VisitPointer(&(thread->pending_exception_)); |
| 67 v->VisitPointer(&(thread->pending_message_obj_)); | 92 v->VisitPointer(&(thread->pending_message_obj_)); |
| 68 v->VisitPointer( | 93 v->VisitPointer( |
| 69 bit_cast<Object**, Script**>(&(thread->pending_message_script_))); | 94 bit_cast<Object**, Script**>(&(thread->pending_message_script_))); |
| 70 v->VisitPointer(bit_cast<Object**, Context**>(&(thread->context_))); | 95 v->VisitPointer(bit_cast<Object**, Context**>(&(thread->context_))); |
| 71 v->VisitPointer(&(thread->scheduled_exception_)); | 96 v->VisitPointer(&(thread->scheduled_exception_)); |
| 72 | 97 |
| 73 for (v8::TryCatch* block = thread->try_catch_handler_; | 98 for (v8::TryCatch* block = thread->TryCatchHandler(); |
| 74 block != NULL; | 99 block != NULL; |
| 75 block = block->next_) { | 100 block = TRY_CATCH_FROM_ADDRESS(block->next_)) { |
| 76 v->VisitPointer(bit_cast<Object**, void**>(&(block->exception_))); | 101 v->VisitPointer(bit_cast<Object**, void**>(&(block->exception_))); |
| 77 v->VisitPointer(bit_cast<Object**, void**>(&(block->message_))); | 102 v->VisitPointer(bit_cast<Object**, void**>(&(block->message_))); |
| 78 } | 103 } |
| 79 | 104 |
| 80 // Iterate over pointers on native execution stack. | 105 // Iterate over pointers on native execution stack. |
| 81 for (StackFrameIterator it(thread); !it.done(); it.Advance()) { | 106 for (StackFrameIterator it(thread); !it.done(); it.Advance()) { |
| 82 it.frame()->Iterate(v); | 107 it.frame()->Iterate(v); |
| 83 } | 108 } |
| 84 } | 109 } |
| 85 | 110 |
| 86 | 111 |
| 87 void Top::Iterate(ObjectVisitor* v) { | 112 void Top::Iterate(ObjectVisitor* v) { |
| 88 ThreadLocalTop* current_t = &thread_local_; | 113 ThreadLocalTop* current_t = &thread_local_; |
| 89 Iterate(v, current_t); | 114 Iterate(v, current_t); |
| 90 } | 115 } |
| 91 | 116 |
| 92 | 117 |
| 93 void Top::InitializeThreadLocal() { | 118 void Top::InitializeThreadLocal() { |
| 94 thread_local_.c_entry_fp_ = 0; | 119 thread_local_.Initialize(); |
| 95 thread_local_.handler_ = 0; | |
| 96 #ifdef ENABLE_LOGGING_AND_PROFILING | |
| 97 thread_local_.js_entry_sp_ = 0; | |
| 98 #endif | |
| 99 thread_local_.stack_is_cooked_ = false; | |
| 100 thread_local_.try_catch_handler_ = NULL; | |
| 101 thread_local_.context_ = NULL; | |
| 102 int id = ThreadManager::CurrentId(); | |
| 103 thread_local_.thread_id_ = (id == 0) ? ThreadManager::kInvalidId : id; | |
| 104 thread_local_.external_caught_exception_ = false; | |
| 105 thread_local_.failed_access_check_callback_ = NULL; | |
| 106 clear_pending_exception(); | 120 clear_pending_exception(); |
| 107 clear_pending_message(); | 121 clear_pending_message(); |
| 108 clear_scheduled_exception(); | 122 clear_scheduled_exception(); |
| 109 thread_local_.save_context_ = NULL; | |
| 110 thread_local_.catcher_ = NULL; | |
| 111 } | 123 } |
| 112 | 124 |
| 113 | 125 |
| 114 // Create a dummy thread that will wait forever on a semaphore. The only | 126 // Create a dummy thread that will wait forever on a semaphore. The only |
| 115 // purpose for this thread is to have some stack area to save essential data | 127 // purpose for this thread is to have some stack area to save essential data |
| 116 // into for use by a stacks only core dump (aka minidump). | 128 // into for use by a stacks only core dump (aka minidump). |
| 117 class PreallocatedMemoryThread: public Thread { | 129 class PreallocatedMemoryThread: public Thread { |
| 118 public: | 130 public: |
| 119 PreallocatedMemoryThread() : keep_running_(true) { | 131 PreallocatedMemoryThread() : keep_running_(true) { |
| 120 wait_for_ever_semaphore_ = OS::CreateSemaphore(0); | 132 wait_for_ever_semaphore_ = OS::CreateSemaphore(0); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 delete preallocated_message_space; | 259 delete preallocated_message_space; |
| 248 preallocated_message_space = NULL; | 260 preallocated_message_space = NULL; |
| 249 } | 261 } |
| 250 | 262 |
| 251 PreallocatedMemoryThread::StopThread(); | 263 PreallocatedMemoryThread::StopThread(); |
| 252 initialized = false; | 264 initialized = false; |
| 253 } | 265 } |
| 254 } | 266 } |
| 255 | 267 |
| 256 | 268 |
| 257 // There are cases where the C stack is separated from JS stack (ARM simulator). | |
| 258 // To figure out the order of top-most JS try-catch handler and the top-most C | |
| 259 // try-catch handler, the C try-catch handler keeps a reference to the top-most | |
| 260 // JS try_catch handler when it was created. | |
| 261 // | |
| 262 // Here is a picture to explain the idea: | |
| 263 // Top::thread_local_.handler_ Top::thread_local_.try_catch_handler_ | |
| 264 // | |
| 265 // | | | |
| 266 // v v | |
| 267 // | |
| 268 // | JS handler | | C try_catch handler | | |
| 269 // | next |--+ +-------- | js_handler_ | | |
| 270 // | | | next_ |--+ | |
| 271 // | | | | |
| 272 // | JS handler |--+ <---------+ | | |
| 273 // | next | | |
| 274 // | |
| 275 // If the top-most JS try-catch handler is not equal to | |
| 276 // Top::thread_local_.try_catch_handler_.js_handler_, it means the JS handler | |
| 277 // is on the top. Otherwise, it means the C try-catch handler is on the top. | |
| 278 // | |
| 279 void Top::RegisterTryCatchHandler(v8::TryCatch* that) { | 269 void Top::RegisterTryCatchHandler(v8::TryCatch* that) { |
| 280 StackHandler* handler = | 270 // The ARM simulator has a separate JS stack. We therefore register |
| 281 reinterpret_cast<StackHandler*>(thread_local_.handler_); | 271 // the C++ try catch handler with the simulator and get back an |
| 282 | 272 // address that can be used for comparisons with addresses into the |
| 283 // Find the top-most try-catch handler. | 273 // JS stack. When running without the simulator, the address |
| 284 while (handler != NULL && !handler->is_try_catch()) { | 274 // returned will be the address of the C++ try catch handler itself. |
| 285 handler = handler->next(); | 275 Address address = reinterpret_cast<Address>( |
| 286 } | 276 SimulatorStack::RegisterCTryCatch(reinterpret_cast<uintptr_t>(that))); |
| 287 | 277 thread_local_.set_try_catch_handler_address(address); |
| 288 that->js_handler_ = handler; // casted to void* | |
| 289 thread_local_.try_catch_handler_ = that; | |
| 290 } | 278 } |
| 291 | 279 |
| 292 | 280 |
| 293 void Top::UnregisterTryCatchHandler(v8::TryCatch* that) { | 281 void Top::UnregisterTryCatchHandler(v8::TryCatch* that) { |
| 294 ASSERT(thread_local_.try_catch_handler_ == that); | 282 ASSERT(thread_local_.TryCatchHandler() == that); |
| 295 thread_local_.try_catch_handler_ = that->next_; | 283 thread_local_.set_try_catch_handler_address( |
| 284 reinterpret_cast<Address>(that->next_)); |
| 296 thread_local_.catcher_ = NULL; | 285 thread_local_.catcher_ = NULL; |
| 286 SimulatorStack::UnregisterCTryCatch(); |
| 297 } | 287 } |
| 298 | 288 |
| 299 | 289 |
| 300 void Top::MarkCompactPrologue(bool is_compacting) { | 290 void Top::MarkCompactPrologue(bool is_compacting) { |
| 301 MarkCompactPrologue(is_compacting, &thread_local_); | 291 MarkCompactPrologue(is_compacting, &thread_local_); |
| 302 } | 292 } |
| 303 | 293 |
| 304 | 294 |
| 305 void Top::MarkCompactPrologue(bool is_compacting, char* data) { | 295 void Top::MarkCompactPrologue(bool is_compacting, char* data) { |
| 306 MarkCompactPrologue(is_compacting, reinterpret_cast<ThreadLocalTop*>(data)); | 296 MarkCompactPrologue(is_compacting, reinterpret_cast<ThreadLocalTop*>(data)); |
| (...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 718 bool catchable_by_javascript) { | 708 bool catchable_by_javascript) { |
| 719 // Find the top-most try-catch handler. | 709 // Find the top-most try-catch handler. |
| 720 StackHandler* handler = | 710 StackHandler* handler = |
| 721 StackHandler::FromAddress(Top::handler(Top::GetCurrentThread())); | 711 StackHandler::FromAddress(Top::handler(Top::GetCurrentThread())); |
| 722 while (handler != NULL && !handler->is_try_catch()) { | 712 while (handler != NULL && !handler->is_try_catch()) { |
| 723 handler = handler->next(); | 713 handler = handler->next(); |
| 724 } | 714 } |
| 725 | 715 |
| 726 // Get the address of the external handler so we can compare the address to | 716 // Get the address of the external handler so we can compare the address to |
| 727 // determine which one is closer to the top of the stack. | 717 // determine which one is closer to the top of the stack. |
| 728 v8::TryCatch* try_catch = thread_local_.try_catch_handler_; | 718 Address external_handler_address = thread_local_.try_catch_handler_address(); |
| 729 | 719 |
| 730 // The exception has been externally caught if and only if there is | 720 // The exception has been externally caught if and only if there is |
| 731 // an external handler which is on top of the top-most try-catch | 721 // an external handler which is on top of the top-most try-catch |
| 732 // handler. | 722 // handler. |
| 733 // | 723 *is_caught_externally = external_handler_address != NULL && |
| 734 // See comments in RegisterTryCatchHandler for details. | 724 (handler == NULL || handler->address() > external_handler_address || |
| 735 *is_caught_externally = try_catch != NULL && | |
| 736 (handler == NULL || handler == try_catch->js_handler_ || | |
| 737 !catchable_by_javascript); | 725 !catchable_by_javascript); |
| 738 | 726 |
| 739 if (*is_caught_externally) { | 727 if (*is_caught_externally) { |
| 740 // Only report the exception if the external handler is verbose. | 728 // Only report the exception if the external handler is verbose. |
| 741 return thread_local_.try_catch_handler_->is_verbose_; | 729 return thread_local_.TryCatchHandler()->is_verbose_; |
| 742 } else { | 730 } else { |
| 743 // Report the exception if it isn't caught by JavaScript code. | 731 // Report the exception if it isn't caught by JavaScript code. |
| 744 return handler == NULL; | 732 return handler == NULL; |
| 745 } | 733 } |
| 746 } | 734 } |
| 747 | 735 |
| 748 | 736 |
| 749 void Top::DoThrow(Object* exception, | 737 void Top::DoThrow(Object* exception, |
| 750 MessageLocation* location, | 738 MessageLocation* location, |
| 751 const char* message) { | 739 const char* message) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 768 if (catchable_by_javascript) { | 756 if (catchable_by_javascript) { |
| 769 Debugger::OnException(exception_handle, report_exception); | 757 Debugger::OnException(exception_handle, report_exception); |
| 770 } | 758 } |
| 771 #endif | 759 #endif |
| 772 | 760 |
| 773 // Generate the message. | 761 // Generate the message. |
| 774 Handle<Object> message_obj; | 762 Handle<Object> message_obj; |
| 775 MessageLocation potential_computed_location; | 763 MessageLocation potential_computed_location; |
| 776 bool try_catch_needs_message = | 764 bool try_catch_needs_message = |
| 777 is_caught_externally && | 765 is_caught_externally && |
| 778 thread_local_.try_catch_handler_->capture_message_; | 766 thread_local_.TryCatchHandler()->capture_message_; |
| 779 if (report_exception || try_catch_needs_message) { | 767 if (report_exception || try_catch_needs_message) { |
| 780 if (location == NULL) { | 768 if (location == NULL) { |
| 781 // If no location was specified we use a computed one instead | 769 // If no location was specified we use a computed one instead |
| 782 ComputeLocation(&potential_computed_location); | 770 ComputeLocation(&potential_computed_location); |
| 783 location = &potential_computed_location; | 771 location = &potential_computed_location; |
| 784 } | 772 } |
| 785 if (!Bootstrapper::IsActive()) { | 773 if (!Bootstrapper::IsActive()) { |
| 786 // It's not safe to try to make message objects or collect stack | 774 // It's not safe to try to make message objects or collect stack |
| 787 // traces while the bootstrapper is active since the infrastructure | 775 // traces while the bootstrapper is active since the infrastructure |
| 788 // may not have been properly initialized. | 776 // may not have been properly initialized. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 799 if (!message_obj.is_null()) { | 787 if (!message_obj.is_null()) { |
| 800 thread_local_.pending_message_obj_ = *message_obj; | 788 thread_local_.pending_message_obj_ = *message_obj; |
| 801 if (location != NULL) { | 789 if (location != NULL) { |
| 802 thread_local_.pending_message_script_ = *location->script(); | 790 thread_local_.pending_message_script_ = *location->script(); |
| 803 thread_local_.pending_message_start_pos_ = location->start_pos(); | 791 thread_local_.pending_message_start_pos_ = location->start_pos(); |
| 804 thread_local_.pending_message_end_pos_ = location->end_pos(); | 792 thread_local_.pending_message_end_pos_ = location->end_pos(); |
| 805 } | 793 } |
| 806 } | 794 } |
| 807 | 795 |
| 808 if (is_caught_externally) { | 796 if (is_caught_externally) { |
| 809 thread_local_.catcher_ = thread_local_.try_catch_handler_; | 797 thread_local_.catcher_ = thread_local_.TryCatchHandler(); |
| 810 } | 798 } |
| 811 | 799 |
| 812 // NOTE: Notifying the debugger or generating the message | 800 // NOTE: Notifying the debugger or generating the message |
| 813 // may have caused new exceptions. For now, we just ignore | 801 // may have caused new exceptions. For now, we just ignore |
| 814 // that and set the pending exception to the original one. | 802 // that and set the pending exception to the original one. |
| 815 set_pending_exception(*exception_handle); | 803 set_pending_exception(*exception_handle); |
| 816 } | 804 } |
| 817 | 805 |
| 818 | 806 |
| 819 void Top::ReportPendingMessages() { | 807 void Top::ReportPendingMessages() { |
| 820 ASSERT(has_pending_exception()); | 808 ASSERT(has_pending_exception()); |
| 821 setup_external_caught(); | 809 setup_external_caught(); |
| 822 // If the pending exception is OutOfMemoryException set out_of_memory in | 810 // If the pending exception is OutOfMemoryException set out_of_memory in |
| 823 // the global context. Note: We have to mark the global context here | 811 // the global context. Note: We have to mark the global context here |
| 824 // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to | 812 // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to |
| 825 // set it. | 813 // set it. |
| 826 bool external_caught = thread_local_.external_caught_exception_; | 814 bool external_caught = thread_local_.external_caught_exception_; |
| 827 HandleScope scope; | 815 HandleScope scope; |
| 828 if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) { | 816 if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) { |
| 829 context()->mark_out_of_memory(); | 817 context()->mark_out_of_memory(); |
| 830 } else if (thread_local_.pending_exception_ == | 818 } else if (thread_local_.pending_exception_ == |
| 831 Heap::termination_exception()) { | 819 Heap::termination_exception()) { |
| 832 if (external_caught) { | 820 if (external_caught) { |
| 833 thread_local_.try_catch_handler_->can_continue_ = false; | 821 thread_local_.TryCatchHandler()->can_continue_ = false; |
| 834 thread_local_.try_catch_handler_->exception_ = Heap::null_value(); | 822 thread_local_.TryCatchHandler()->exception_ = Heap::null_value(); |
| 835 } | 823 } |
| 836 } else { | 824 } else { |
| 837 Handle<Object> exception(pending_exception()); | 825 Handle<Object> exception(pending_exception()); |
| 838 thread_local_.external_caught_exception_ = false; | 826 thread_local_.external_caught_exception_ = false; |
| 839 if (external_caught) { | 827 if (external_caught) { |
| 840 thread_local_.try_catch_handler_->can_continue_ = true; | 828 thread_local_.TryCatchHandler()->can_continue_ = true; |
| 841 thread_local_.try_catch_handler_->exception_ = | 829 thread_local_.TryCatchHandler()->exception_ = |
| 842 thread_local_.pending_exception_; | 830 thread_local_.pending_exception_; |
| 843 if (!thread_local_.pending_message_obj_->IsTheHole()) { | 831 if (!thread_local_.pending_message_obj_->IsTheHole()) { |
| 844 try_catch_handler()->message_ = thread_local_.pending_message_obj_; | 832 try_catch_handler()->message_ = thread_local_.pending_message_obj_; |
| 845 } | 833 } |
| 846 } | 834 } |
| 847 if (thread_local_.has_pending_message_) { | 835 if (thread_local_.has_pending_message_) { |
| 848 thread_local_.has_pending_message_ = false; | 836 thread_local_.has_pending_message_ = false; |
| 849 if (thread_local_.pending_message_ != NULL) { | 837 if (thread_local_.pending_message_ != NULL) { |
| 850 MessageHandler::ReportMessage(thread_local_.pending_message_); | 838 MessageHandler::ReportMessage(thread_local_.pending_message_); |
| 851 } else if (!thread_local_.pending_message_obj_->IsTheHole()) { | 839 } else if (!thread_local_.pending_message_obj_->IsTheHole()) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 885 if (is_termination_exception) { | 873 if (is_termination_exception) { |
| 886 if (is_bottom_call) { | 874 if (is_bottom_call) { |
| 887 thread_local_.external_caught_exception_ = false; | 875 thread_local_.external_caught_exception_ = false; |
| 888 clear_pending_exception(); | 876 clear_pending_exception(); |
| 889 return false; | 877 return false; |
| 890 } | 878 } |
| 891 } else if (thread_local_.external_caught_exception_) { | 879 } else if (thread_local_.external_caught_exception_) { |
| 892 // If the exception is externally caught, clear it if there are no | 880 // If the exception is externally caught, clear it if there are no |
| 893 // JavaScript frames on the way to the C++ frame that has the | 881 // JavaScript frames on the way to the C++ frame that has the |
| 894 // external handler. | 882 // external handler. |
| 895 ASSERT(thread_local_.try_catch_handler_ != NULL); | 883 ASSERT(thread_local_.try_catch_handler_address() != NULL); |
| 896 Address external_handler_address = | 884 Address external_handler_address = |
| 897 reinterpret_cast<Address>(thread_local_.try_catch_handler_); | 885 thread_local_.try_catch_handler_address(); |
| 898 JavaScriptFrameIterator it; | 886 JavaScriptFrameIterator it; |
| 899 if (it.done() || (it.frame()->sp() > external_handler_address)) { | 887 if (it.done() || (it.frame()->sp() > external_handler_address)) { |
| 900 clear_exception = true; | 888 clear_exception = true; |
| 901 } | 889 } |
| 902 } | 890 } |
| 903 | 891 |
| 904 // Clear the exception if needed. | 892 // Clear the exception if needed. |
| 905 if (clear_exception) { | 893 if (clear_exception) { |
| 906 thread_local_.external_caught_exception_ = false; | 894 thread_local_.external_caught_exception_ = false; |
| 907 clear_pending_exception(); | 895 clear_pending_exception(); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 981 Top::break_access_->Lock(); | 969 Top::break_access_->Lock(); |
| 982 } | 970 } |
| 983 | 971 |
| 984 | 972 |
| 985 ExecutionAccess::~ExecutionAccess() { | 973 ExecutionAccess::~ExecutionAccess() { |
| 986 Top::break_access_->Unlock(); | 974 Top::break_access_->Unlock(); |
| 987 } | 975 } |
| 988 | 976 |
| 989 | 977 |
| 990 } } // namespace v8::internal | 978 } } // namespace v8::internal |
| OLD | NEW |