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

Side by Side Diff: src/top.cc

Issue 360004: Rework the way we handle the fact that the ARM simulator uses a... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 1 month 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') | src/v8.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 13 matching lines...) Expand all
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/top.h ('k') | src/v8.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698