| 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 20 matching lines...) Expand all Loading... |
| 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" | 34 #include "platform.h" |
| 35 #include "simulator.h" | 35 #include "simulator.h" |
| 36 #include "string-stream.h" | 36 #include "string-stream.h" |
| 37 | 37 |
| 38 namespace v8 { | 38 namespace v8 { |
| 39 namespace internal { | 39 namespace internal { |
| 40 | 40 |
| 41 ThreadLocalTop Top::thread_local_; | |
| 42 Mutex* Top::break_access_ = OS::CreateMutex(); | |
| 43 | |
| 44 NoAllocationStringAllocator* preallocated_message_space = NULL; | |
| 45 | |
| 46 Address top_addresses[] = { | |
| 47 #define C(name) reinterpret_cast<Address>(Top::name()), | |
| 48 TOP_ADDRESS_LIST(C) | |
| 49 TOP_ADDRESS_LIST_PROF(C) | |
| 50 #undef C | |
| 51 NULL | |
| 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 | |
| 78 Address Top::get_address_from_id(Top::AddressId id) { | |
| 79 return top_addresses[id]; | |
| 80 } | |
| 81 | |
| 82 | |
| 83 char* Top::Iterate(ObjectVisitor* v, char* thread_storage) { | |
| 84 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage); | |
| 85 Iterate(v, thread); | |
| 86 return thread_storage + sizeof(ThreadLocalTop); | |
| 87 } | |
| 88 | |
| 89 | |
| 90 void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) { | |
| 91 v->VisitPointer(&(thread->pending_exception_)); | |
| 92 v->VisitPointer(&(thread->pending_message_obj_)); | |
| 93 v->VisitPointer( | |
| 94 bit_cast<Object**, Script**>(&(thread->pending_message_script_))); | |
| 95 v->VisitPointer(bit_cast<Object**, Context**>(&(thread->context_))); | |
| 96 v->VisitPointer(&(thread->scheduled_exception_)); | |
| 97 | |
| 98 for (v8::TryCatch* block = thread->TryCatchHandler(); | |
| 99 block != NULL; | |
| 100 block = TRY_CATCH_FROM_ADDRESS(block->next_)) { | |
| 101 v->VisitPointer(bit_cast<Object**, void**>(&(block->exception_))); | |
| 102 v->VisitPointer(bit_cast<Object**, void**>(&(block->message_))); | |
| 103 } | |
| 104 | |
| 105 // Iterate over pointers on native execution stack. | |
| 106 for (StackFrameIterator it(thread); !it.done(); it.Advance()) { | |
| 107 it.frame()->Iterate(v); | |
| 108 } | |
| 109 } | |
| 110 | |
| 111 | |
| 112 void Top::Iterate(ObjectVisitor* v) { | |
| 113 ThreadLocalTop* current_t = &thread_local_; | |
| 114 Iterate(v, current_t); | |
| 115 } | |
| 116 | |
| 117 | |
| 118 void Top::InitializeThreadLocal() { | |
| 119 thread_local_.Initialize(); | |
| 120 clear_pending_exception(); | |
| 121 clear_pending_message(); | |
| 122 clear_scheduled_exception(); | |
| 123 } | |
| 124 | |
| 125 | |
| 126 // Create a dummy thread that will wait forever on a semaphore. The only | 41 // Create a dummy thread that will wait forever on a semaphore. The only |
| 127 // purpose for this thread is to have some stack area to save essential data | 42 // purpose for this thread is to have some stack area to save essential data |
| 128 // into for use by a stacks only core dump (aka minidump). | 43 // into for use by a stacks only core dump (aka minidump). |
| 129 class PreallocatedMemoryThread: public Thread { | 44 class PreallocatedMemoryThread: public Thread { |
| 130 public: | 45 public: |
| 131 PreallocatedMemoryThread() : keep_running_(true) { | 46 PreallocatedMemoryThread() : keep_running_(true), |
| 132 wait_for_ever_semaphore_ = OS::CreateSemaphore(0); | 47 wait_for_ever_semaphore_(OS::CreateSemaphore(0)), |
| 133 data_ready_semaphore_ = OS::CreateSemaphore(0); | 48 data_ready_semaphore_(OS::CreateSemaphore(0)), |
| 49 data_(NULL), length_(0) { |
| 134 } | 50 } |
| 135 | 51 |
| 136 // When the thread starts running it will allocate a fixed number of bytes | 52 // When the thread starts running it will allocate a fixed number of bytes |
| 137 // on the stack and publish the location of this memory for others to use. | 53 // on the stack and publish the location of this memory for others to use. |
| 138 void Run() { | 54 void Run() { |
| 139 EmbeddedVector<char, 15 * 1024> local_buffer; | 55 EmbeddedVector<char, 15 * 1024> local_buffer; |
| 140 | 56 |
| 141 // Initialize the buffer with a known good value. | 57 // Initialize the buffer with a known good value. |
| 142 OS::StrNCpy(local_buffer, "Trace data was not generated.\n", | 58 OS::StrNCpy(local_buffer, "Trace data was not generated.\n", |
| 143 local_buffer.length()); | 59 local_buffer.length()); |
| 144 | 60 |
| 145 // Publish the local buffer and signal its availability. | 61 // Publish the local buffer and signal its availability. |
| 146 data_ = local_buffer.start(); | 62 data_ = local_buffer.start(); |
| 147 length_ = local_buffer.length(); | 63 length_ = local_buffer.length(); |
| 148 data_ready_semaphore_->Signal(); | 64 data_ready_semaphore_->Signal(); |
| 149 | 65 |
| 150 while (keep_running_) { | 66 while (keep_running_) { |
| 151 // This thread will wait here until the end of time. | 67 // This thread will wait here until the end of time. |
| 152 wait_for_ever_semaphore_->Wait(); | 68 wait_for_ever_semaphore_->Wait(); |
| 153 } | 69 } |
| 154 | 70 |
| 155 // Make sure we access the buffer after the wait to remove all possibility | 71 // Make sure we access the buffer after the wait to remove all possibility |
| 156 // of it being optimized away. | 72 // of it being optimized away. |
| 157 OS::StrNCpy(local_buffer, "PreallocatedMemoryThread shutting down.\n", | 73 OS::StrNCpy(local_buffer, "PreallocatedMemoryThread shutting down.\n", |
| 158 local_buffer.length()); | 74 local_buffer.length()); |
| 159 } | 75 } |
| 160 | 76 |
| 161 static char* data() { | 77 char* data() { |
| 162 if (data_ready_semaphore_ != NULL) { | 78 if (data_ready_semaphore_ != NULL) { |
| 163 // Initial access is guarded until the data has been published. | 79 // Initial access is guarded until the data has been published. |
| 164 data_ready_semaphore_->Wait(); | 80 data_ready_semaphore_->Wait(); |
| 165 delete data_ready_semaphore_; | 81 delete data_ready_semaphore_; |
| 166 data_ready_semaphore_ = NULL; | 82 data_ready_semaphore_ = NULL; |
| 167 } | 83 } |
| 168 return data_; | 84 return data_; |
| 169 } | 85 } |
| 170 | 86 |
| 171 static unsigned length() { | 87 unsigned length() { |
| 172 if (data_ready_semaphore_ != NULL) { | 88 if (data_ready_semaphore_ != NULL) { |
| 173 // Initial access is guarded until the data has been published. | 89 // Initial access is guarded until the data has been published. |
| 174 data_ready_semaphore_->Wait(); | 90 data_ready_semaphore_->Wait(); |
| 175 delete data_ready_semaphore_; | 91 delete data_ready_semaphore_; |
| 176 data_ready_semaphore_ = NULL; | 92 data_ready_semaphore_ = NULL; |
| 177 } | 93 } |
| 178 return length_; | 94 return length_; |
| 179 } | 95 } |
| 180 | 96 |
| 181 static void StartThread() { | |
| 182 if (the_thread_ != NULL) return; | |
| 183 | |
| 184 the_thread_ = new PreallocatedMemoryThread(); | |
| 185 the_thread_->Start(); | |
| 186 } | |
| 187 | |
| 188 // Stop the PreallocatedMemoryThread and release its resources. | 97 // Stop the PreallocatedMemoryThread and release its resources. |
| 189 static void StopThread() { | 98 void RequestEnd() { |
| 190 if (the_thread_ == NULL) return; | 99 keep_running_ = false; |
| 191 | |
| 192 the_thread_->keep_running_ = false; | |
| 193 wait_for_ever_semaphore_->Signal(); | 100 wait_for_ever_semaphore_->Signal(); |
| 194 | 101 |
| 195 // Wait for the thread to terminate. | 102 // Wait for the thread to terminate. |
| 196 the_thread_->Join(); | 103 Join(); |
| 197 | 104 |
| 198 if (data_ready_semaphore_ != NULL) { | 105 if (data_ready_semaphore_ != NULL) { |
| 199 delete data_ready_semaphore_; | 106 delete data_ready_semaphore_; |
| 200 data_ready_semaphore_ = NULL; | 107 data_ready_semaphore_ = NULL; |
| 201 } | 108 } |
| 202 | 109 |
| 203 delete wait_for_ever_semaphore_; | 110 delete wait_for_ever_semaphore_; |
| 204 wait_for_ever_semaphore_ = NULL; | 111 wait_for_ever_semaphore_ = NULL; |
| 112 } |
| 113 |
| 114 private: |
| 115 // Used to make sure that the thread keeps looping even for spurious wakeups. |
| 116 bool keep_running_; |
| 117 |
| 118 // This semaphore is used by the PreallocatedMemoryThread to wait for ever. |
| 119 Semaphore* wait_for_ever_semaphore_; |
| 120 // Semaphore to signal that the data has been initialized. |
| 121 Semaphore* data_ready_semaphore_; |
| 122 |
| 123 // Location and size of the preallocated memory block. |
| 124 char* data_; |
| 125 unsigned length_; |
| 126 |
| 127 DISALLOW_COPY_AND_ASSIGN(PreallocatedMemoryThread); |
| 128 }; |
| 129 |
| 130 class TopPrivateData { |
| 131 public: |
| 132 NoAllocationStringAllocator* preallocated_message_space; |
| 133 Address top_addresses[Top::k_top_address_count]; |
| 134 |
| 135 // The preallocated memory thread singleton. |
| 136 PreallocatedMemoryThread* the_thread_; |
| 137 int stack_trace_nesting_level; |
| 138 StringStream* incomplete_message; |
| 139 bool initialized; |
| 140 |
| 141 TopPrivateData() |
| 142 :initialized(false), preallocated_message_space(NULL), |
| 143 incomplete_message(NULL), stack_trace_nesting_level(NULL), |
| 144 the_thread_(NULL) { |
| 145 Address _top_addresses[] = { |
| 146 #define C(name) reinterpret_cast<Address>(Top::name()), |
| 147 TOP_ADDRESS_LIST(C) |
| 148 TOP_ADDRESS_LIST_PROF(C) |
| 149 #undef C |
| 150 NULL |
| 151 }; |
| 152 for (int i = 0; i < Top::k_top_address_count; ++i) |
| 153 top_addresses[i] = _top_addresses[i]; |
| 154 } |
| 155 |
| 156 void StartThread() { |
| 157 if (the_thread_ != NULL) return; |
| 158 |
| 159 the_thread_ = new PreallocatedMemoryThread(); |
| 160 the_thread_->Start(); |
| 161 } |
| 162 |
| 163 // Stop the PreallocatedMemoryThread and release its resources. |
| 164 void StopThread() { |
| 165 if (the_thread_ == NULL) return; |
| 166 the_thread_->RequestEnd(); |
| 205 | 167 |
| 206 // Done with the thread entirely. | 168 // Done with the thread entirely. |
| 207 delete the_thread_; | 169 delete the_thread_; |
| 208 the_thread_ = NULL; | 170 the_thread_ = NULL; |
| 209 } | 171 } |
| 210 | |
| 211 private: | |
| 212 // Used to make sure that the thread keeps looping even for spurious wakeups. | |
| 213 bool keep_running_; | |
| 214 | |
| 215 // The preallocated memory thread singleton. | |
| 216 static PreallocatedMemoryThread* the_thread_; | |
| 217 // This semaphore is used by the PreallocatedMemoryThread to wait for ever. | |
| 218 static Semaphore* wait_for_ever_semaphore_; | |
| 219 // Semaphore to signal that the data has been initialized. | |
| 220 static Semaphore* data_ready_semaphore_; | |
| 221 | |
| 222 // Location and size of the preallocated memory block. | |
| 223 static char* data_; | |
| 224 static unsigned length_; | |
| 225 | |
| 226 DISALLOW_COPY_AND_ASSIGN(PreallocatedMemoryThread); | |
| 227 }; | 172 }; |
| 228 | 173 |
| 229 PreallocatedMemoryThread* PreallocatedMemoryThread::the_thread_ = NULL; | 174 TopData::TopData() |
| 230 Semaphore* PreallocatedMemoryThread::wait_for_ever_semaphore_ = NULL; | 175 :break_access_(OS::CreateMutex()), |
| 231 Semaphore* PreallocatedMemoryThread::data_ready_semaphore_ = NULL; | 176 thread_local_(), |
| 232 char* PreallocatedMemoryThread::data_ = NULL; | 177 top_private_data_(NULL) { |
| 233 unsigned PreallocatedMemoryThread::length_ = 0; | 178 } |
| 234 | 179 |
| 235 static bool initialized = false; | 180 void Top::PostConstruct() { |
| 181 v8_context()->top_data_.top_private_data_ = new TopPrivateData(); |
| 182 } |
| 183 |
| 184 void Top::PreDestroy() { |
| 185 delete v8_context()->top_data_.top_private_data_; |
| 186 } |
| 187 |
| 188 ThreadLocalTop::ThreadLocalTop() |
| 189 :context_(NULL), |
| 190 has_pending_message_(false), |
| 191 external_caught_exception_(false), |
| 192 formal_count_(0), |
| 193 stack_is_cooked_(false), |
| 194 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 195 js_entry_sp_(NULL), |
| 196 #endif |
| 197 handler_(NULL), |
| 198 c_entry_fp_(NULL), |
| 199 catcher_(NULL), |
| 200 save_context_(NULL), |
| 201 scheduled_exception_(NULL), |
| 202 pending_message_end_pos_(0), |
| 203 pending_message_start_pos_(0), |
| 204 pending_message_script_(0), |
| 205 pending_message_obj_(NULL), |
| 206 pending_message_(NULL), |
| 207 pending_exception_(false), |
| 208 thread_id_(0), |
| 209 failed_access_check_callback_(NULL), |
| 210 try_catch_handler_address_(NULL) { |
| 211 } |
| 212 |
| 213 v8::TryCatch* ThreadLocalTop::TryCatchHandler() { |
| 214 return TRY_CATCH_FROM_ADDRESS(try_catch_handler_address()); |
| 215 } |
| 216 |
| 217 |
| 218 void ThreadLocalTop::Initialize() { |
| 219 c_entry_fp_ = 0; |
| 220 handler_ = 0; |
| 221 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 222 js_entry_sp_ = 0; |
| 223 #endif |
| 224 stack_is_cooked_ = false; |
| 225 try_catch_handler_address_ = NULL; |
| 226 context_ = NULL; |
| 227 int id = ThreadManager::CurrentId(); |
| 228 thread_id_ = (id == 0) ? ThreadManager::kInvalidId : id; |
| 229 external_caught_exception_ = false; |
| 230 failed_access_check_callback_ = NULL; |
| 231 save_context_ = NULL; |
| 232 catcher_ = NULL; |
| 233 } |
| 234 |
| 235 |
| 236 Address Top::get_address_from_id(Top::AddressId id) { |
| 237 return v8_context()->top_data_.top_private_data_->top_addresses[id]; |
| 238 } |
| 239 |
| 240 |
| 241 char* Top::Iterate(ObjectVisitor* v, char* thread_storage) { |
| 242 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage); |
| 243 Iterate(v, thread); |
| 244 return thread_storage + sizeof(ThreadLocalTop); |
| 245 } |
| 246 |
| 247 |
| 248 void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) { |
| 249 v->VisitPointer(&(thread->pending_exception_)); |
| 250 v->VisitPointer(&(thread->pending_message_obj_)); |
| 251 v->VisitPointer( |
| 252 bit_cast<Object**, Script**>(&(thread->pending_message_script_))); |
| 253 v->VisitPointer(bit_cast<Object**, Context**>(&(thread->context_))); |
| 254 v->VisitPointer(&(thread->scheduled_exception_)); |
| 255 |
| 256 for (v8::TryCatch* block = thread->TryCatchHandler(); |
| 257 block != NULL; |
| 258 block = TRY_CATCH_FROM_ADDRESS(block->next_)) { |
| 259 v->VisitPointer(bit_cast<Object**, void**>(&(block->exception_))); |
| 260 v->VisitPointer(bit_cast<Object**, void**>(&(block->message_))); |
| 261 } |
| 262 |
| 263 // Iterate over pointers on native execution stack. |
| 264 for (StackFrameIterator it(thread); !it.done(); it.Advance()) { |
| 265 it.frame()->Iterate(v); |
| 266 } |
| 267 } |
| 268 |
| 269 |
| 270 void Top::Iterate(ObjectVisitor* v) { |
| 271 ThreadLocalTop* current_t = &v8_context()->top_data_.thread_local_; |
| 272 Iterate(v, current_t); |
| 273 } |
| 274 |
| 275 |
| 276 void Top::InitializeThreadLocal() { |
| 277 v8_context()->top_data_.thread_local_.Initialize(); |
| 278 clear_pending_exception(); |
| 279 clear_pending_message(); |
| 280 clear_scheduled_exception(); |
| 281 } |
| 236 | 282 |
| 237 void Top::Initialize() { | 283 void Top::Initialize() { |
| 238 CHECK(!initialized); | 284 TopPrivateData* top_private_data = v8_context()->top_data_.top_private_data_; |
| 285 CHECK(!top_private_data->initialized); |
| 239 | 286 |
| 240 InitializeThreadLocal(); | 287 InitializeThreadLocal(); |
| 241 | 288 |
| 242 // Only preallocate on the first initialization. | 289 // Only preallocate on the first initialization. |
| 243 if (FLAG_preallocate_message_memory && (preallocated_message_space == NULL)) { | 290 if (FLAG_preallocate_message_memory && |
| 291 (top_private_data->preallocated_message_space == NULL)) { |
| 244 // Start the thread which will set aside some memory. | 292 // Start the thread which will set aside some memory. |
| 245 PreallocatedMemoryThread::StartThread(); | 293 top_private_data->StartThread(); |
| 246 preallocated_message_space = | 294 top_private_data->preallocated_message_space = |
| 247 new NoAllocationStringAllocator(PreallocatedMemoryThread::data(), | 295 new NoAllocationStringAllocator( |
| 248 PreallocatedMemoryThread::length()); | 296 top_private_data->the_thread_->data(), |
| 249 PreallocatedStorage::Init(PreallocatedMemoryThread::length() / 4); | 297 top_private_data->the_thread_->length()); |
| 250 } | 298 PreallocatedStorage::Init(top_private_data->the_thread_->length() / 4); |
| 251 initialized = true; | 299 } |
| 300 top_private_data->initialized = true; |
| 252 } | 301 } |
| 253 | 302 |
| 254 | 303 |
| 255 void Top::TearDown() { | 304 void Top::TearDown() { |
| 256 if (initialized) { | 305 TopPrivateData* top_private_data = v8_context()->top_data_.top_private_data_; |
| 306 if (top_private_data->initialized) { |
| 257 // Remove the external reference to the preallocated stack memory. | 307 // Remove the external reference to the preallocated stack memory. |
| 258 if (preallocated_message_space != NULL) { | 308 if (top_private_data->preallocated_message_space != NULL) { |
| 259 delete preallocated_message_space; | 309 delete top_private_data->preallocated_message_space; |
| 260 preallocated_message_space = NULL; | 310 top_private_data->preallocated_message_space = NULL; |
| 261 } | 311 } |
| 262 | 312 |
| 263 PreallocatedMemoryThread::StopThread(); | 313 top_private_data->StopThread(); |
| 264 initialized = false; | 314 top_private_data->initialized = false; |
| 265 } | 315 } |
| 266 } | 316 } |
| 267 | 317 |
| 268 | 318 |
| 269 void Top::RegisterTryCatchHandler(v8::TryCatch* that) { | 319 void Top::RegisterTryCatchHandler(v8::TryCatch* that) { |
| 270 // The ARM simulator has a separate JS stack. We therefore register | 320 // The ARM simulator has a separate JS stack. We therefore register |
| 271 // the C++ try catch handler with the simulator and get back an | 321 // the C++ try catch handler with the simulator and get back an |
| 272 // address that can be used for comparisons with addresses into the | 322 // address that can be used for comparisons with addresses into the |
| 273 // JS stack. When running without the simulator, the address | 323 // JS stack. When running without the simulator, the address |
| 274 // returned will be the address of the C++ try catch handler itself. | 324 // returned will be the address of the C++ try catch handler itself. |
| 275 Address address = reinterpret_cast<Address>( | 325 Address address = reinterpret_cast<Address>( |
| 276 SimulatorStack::RegisterCTryCatch(reinterpret_cast<uintptr_t>(that))); | 326 SimulatorStack::RegisterCTryCatch(reinterpret_cast<uintptr_t>(that))); |
| 277 thread_local_.set_try_catch_handler_address(address); | 327 v8_context()->top_data_.thread_local_.set_try_catch_handler_address(address); |
| 278 } | 328 } |
| 279 | 329 |
| 280 | 330 |
| 281 void Top::UnregisterTryCatchHandler(v8::TryCatch* that) { | 331 void Top::UnregisterTryCatchHandler(v8::TryCatch* that) { |
| 282 ASSERT(thread_local_.TryCatchHandler() == that); | 332 ThreadLocalTop& thread_local = v8_context()->top_data_.thread_local_; |
| 283 thread_local_.set_try_catch_handler_address( | 333 ASSERT(thread_local.TryCatchHandler() == that); |
| 334 thread_local.set_try_catch_handler_address( |
| 284 reinterpret_cast<Address>(that->next_)); | 335 reinterpret_cast<Address>(that->next_)); |
| 285 thread_local_.catcher_ = NULL; | 336 thread_local.catcher_ = NULL; |
| 286 SimulatorStack::UnregisterCTryCatch(); | 337 SimulatorStack::UnregisterCTryCatch(); |
| 287 } | 338 } |
| 288 | 339 |
| 289 | 340 |
| 290 void Top::MarkCompactPrologue(bool is_compacting) { | 341 void Top::MarkCompactPrologue(bool is_compacting) { |
| 291 MarkCompactPrologue(is_compacting, &thread_local_); | 342 MarkCompactPrologue(is_compacting, &v8_context()->top_data_.thread_local_); |
| 292 } | 343 } |
| 293 | 344 |
| 294 | 345 |
| 295 void Top::MarkCompactPrologue(bool is_compacting, char* data) { | 346 void Top::MarkCompactPrologue(bool is_compacting, char* data) { |
| 296 MarkCompactPrologue(is_compacting, reinterpret_cast<ThreadLocalTop*>(data)); | 347 MarkCompactPrologue(is_compacting, reinterpret_cast<ThreadLocalTop*>(data)); |
| 297 } | 348 } |
| 298 | 349 |
| 299 | 350 |
| 300 void Top::MarkCompactPrologue(bool is_compacting, ThreadLocalTop* thread) { | 351 void Top::MarkCompactPrologue(bool is_compacting, ThreadLocalTop* thread) { |
| 301 if (is_compacting) { | 352 if (is_compacting) { |
| 302 StackFrame::CookFramesForThread(thread); | 353 StackFrame::CookFramesForThread(thread); |
| 303 } | 354 } |
| 304 } | 355 } |
| 305 | 356 |
| 306 | 357 |
| 307 void Top::MarkCompactEpilogue(bool is_compacting, char* data) { | 358 void Top::MarkCompactEpilogue(bool is_compacting, char* data) { |
| 308 MarkCompactEpilogue(is_compacting, reinterpret_cast<ThreadLocalTop*>(data)); | 359 MarkCompactEpilogue(is_compacting, reinterpret_cast<ThreadLocalTop*>(data)); |
| 309 } | 360 } |
| 310 | 361 |
| 311 | 362 |
| 312 void Top::MarkCompactEpilogue(bool is_compacting) { | 363 void Top::MarkCompactEpilogue(bool is_compacting) { |
| 313 MarkCompactEpilogue(is_compacting, &thread_local_); | 364 MarkCompactEpilogue(is_compacting, &v8_context()->top_data_.thread_local_); |
| 314 } | 365 } |
| 315 | 366 |
| 316 | 367 |
| 317 void Top::MarkCompactEpilogue(bool is_compacting, ThreadLocalTop* thread) { | 368 void Top::MarkCompactEpilogue(bool is_compacting, ThreadLocalTop* thread) { |
| 318 if (is_compacting) { | 369 if (is_compacting) { |
| 319 StackFrame::UncookFramesForThread(thread); | 370 StackFrame::UncookFramesForThread(thread); |
| 320 } | 371 } |
| 321 } | 372 } |
| 322 | 373 |
| 323 | |
| 324 static int stack_trace_nesting_level = 0; | |
| 325 static StringStream* incomplete_message = NULL; | |
| 326 | |
| 327 | |
| 328 Handle<String> Top::StackTrace() { | 374 Handle<String> Top::StackTrace() { |
| 329 if (stack_trace_nesting_level == 0) { | 375 TopPrivateData* top_private_data = v8_context()->top_data_.top_private_data_; |
| 330 stack_trace_nesting_level++; | 376 if (top_private_data->stack_trace_nesting_level == 0) { |
| 377 top_private_data->stack_trace_nesting_level++; |
| 331 HeapStringAllocator allocator; | 378 HeapStringAllocator allocator; |
| 332 StringStream::ClearMentionedObjectCache(); | 379 StringStream::ClearMentionedObjectCache(); |
| 333 StringStream accumulator(&allocator); | 380 StringStream accumulator(&allocator); |
| 334 incomplete_message = &accumulator; | 381 top_private_data->incomplete_message = &accumulator; |
| 382 |
| 335 PrintStack(&accumulator); | 383 PrintStack(&accumulator); |
| 336 Handle<String> stack_trace = accumulator.ToString(); | 384 Handle<String> stack_trace = accumulator.ToString(); |
| 337 incomplete_message = NULL; | 385 top_private_data->incomplete_message = NULL; |
| 338 stack_trace_nesting_level = 0; | 386 top_private_data->stack_trace_nesting_level = 0; |
| 339 return stack_trace; | 387 return stack_trace; |
| 340 } else if (stack_trace_nesting_level == 1) { | 388 } else if (top_private_data->stack_trace_nesting_level == 1) { |
| 341 stack_trace_nesting_level++; | 389 top_private_data->stack_trace_nesting_level++; |
| 342 OS::PrintError( | 390 OS::PrintError( |
| 343 "\n\nAttempt to print stack while printing stack (double fault)\n"); | 391 "\n\nAttempt to print stack while printing stack (double fault)\n"); |
| 344 OS::PrintError( | 392 OS::PrintError( |
| 345 "If you are lucky you may find a partial stack dump on stdout.\n\n"); | 393 "If you are lucky you may find a partial stack dump on stdout.\n\n"); |
| 346 incomplete_message->OutputToStdOut(); | 394 top_private_data->incomplete_message->OutputToStdOut(); |
| 347 return Factory::empty_symbol(); | 395 return Factory::empty_symbol(); |
| 348 } else { | 396 } else { |
| 349 OS::Abort(); | 397 OS::Abort(); |
| 350 // Unreachable | 398 // Unreachable |
| 351 return Factory::empty_symbol(); | 399 return Factory::empty_symbol(); |
| 352 } | 400 } |
| 353 } | 401 } |
| 354 | 402 |
| 355 | 403 |
| 356 void Top::PrintStack() { | 404 void Top::PrintStack() { |
| 357 if (stack_trace_nesting_level == 0) { | 405 TopPrivateData* top_private_data = v8_context()->top_data_.top_private_data_; |
| 358 stack_trace_nesting_level++; | 406 if (top_private_data->stack_trace_nesting_level == 0) { |
| 407 top_private_data->stack_trace_nesting_level++; |
| 359 | 408 |
| 360 StringAllocator* allocator; | 409 StringAllocator* allocator; |
| 361 if (preallocated_message_space == NULL) { | 410 if (top_private_data->preallocated_message_space == NULL) { |
| 362 allocator = new HeapStringAllocator(); | 411 allocator = new HeapStringAllocator(); |
| 363 } else { | 412 } else { |
| 364 allocator = preallocated_message_space; | 413 allocator = top_private_data->preallocated_message_space; |
| 365 } | 414 } |
| 366 | 415 |
| 367 NativeAllocationChecker allocation_checker( | 416 NativeAllocationChecker allocation_checker( |
| 368 !FLAG_preallocate_message_memory ? | 417 !FLAG_preallocate_message_memory ? |
| 369 NativeAllocationChecker::ALLOW : | 418 NativeAllocationChecker::ALLOW : |
| 370 NativeAllocationChecker::DISALLOW); | 419 NativeAllocationChecker::DISALLOW); |
| 371 | 420 |
| 372 StringStream::ClearMentionedObjectCache(); | 421 StringStream::ClearMentionedObjectCache(); |
| 373 StringStream accumulator(allocator); | 422 StringStream accumulator(allocator); |
| 374 incomplete_message = &accumulator; | 423 top_private_data->incomplete_message = &accumulator; |
| 375 PrintStack(&accumulator); | 424 PrintStack(&accumulator); |
| 376 accumulator.OutputToStdOut(); | 425 accumulator.OutputToStdOut(); |
| 377 accumulator.Log(); | 426 accumulator.Log(); |
| 378 incomplete_message = NULL; | 427 top_private_data->incomplete_message = NULL; |
| 379 stack_trace_nesting_level = 0; | 428 top_private_data->stack_trace_nesting_level = 0; |
| 380 if (preallocated_message_space == NULL) { | 429 if (top_private_data->preallocated_message_space == NULL) { |
| 381 // Remove the HeapStringAllocator created above. | 430 // Remove the HeapStringAllocator created above. |
| 382 delete allocator; | 431 delete allocator; |
| 383 } | 432 } |
| 384 } else if (stack_trace_nesting_level == 1) { | 433 } else if (top_private_data->stack_trace_nesting_level == 1) { |
| 385 stack_trace_nesting_level++; | 434 top_private_data->stack_trace_nesting_level++; |
| 386 OS::PrintError( | 435 OS::PrintError( |
| 387 "\n\nAttempt to print stack while printing stack (double fault)\n"); | 436 "\n\nAttempt to print stack while printing stack (double fault)\n"); |
| 388 OS::PrintError( | 437 OS::PrintError( |
| 389 "If you are lucky you may find a partial stack dump on stdout.\n\n"); | 438 "If you are lucky you may find a partial stack dump on stdout.\n\n"); |
| 390 incomplete_message->OutputToStdOut(); | 439 top_private_data->incomplete_message->OutputToStdOut(); |
| 391 } | 440 } |
| 392 } | 441 } |
| 393 | 442 |
| 394 | 443 |
| 395 static void PrintFrames(StringStream* accumulator, | 444 static void PrintFrames(StringStream* accumulator, |
| 396 StackFrame::PrintMode mode) { | 445 StackFrame::PrintMode mode) { |
| 397 StackFrameIterator it; | 446 StackFrameIterator it; |
| 398 for (int i = 0; !it.done(); it.Advance()) { | 447 for (int i = 0; !it.done(); it.Advance()) { |
| 399 it.frame()->Print(accumulator, mode, i++); | 448 it.frame()->Print(accumulator, mode, i++); |
| 400 } | 449 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 416 accumulator->Add( | 465 accumulator->Add( |
| 417 "\n==== Details ================================================\n\n"); | 466 "\n==== Details ================================================\n\n"); |
| 418 PrintFrames(accumulator, StackFrame::DETAILS); | 467 PrintFrames(accumulator, StackFrame::DETAILS); |
| 419 | 468 |
| 420 accumulator->PrintMentionedObjectCache(); | 469 accumulator->PrintMentionedObjectCache(); |
| 421 accumulator->Add("=====================\n\n"); | 470 accumulator->Add("=====================\n\n"); |
| 422 } | 471 } |
| 423 | 472 |
| 424 | 473 |
| 425 void Top::SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback) { | 474 void Top::SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback) { |
| 426 ASSERT(thread_local_.failed_access_check_callback_ == NULL); | 475 ThreadLocalTop& thread_local = v8_context()->top_data_.thread_local_; |
| 427 thread_local_.failed_access_check_callback_ = callback; | 476 ASSERT(thread_local.failed_access_check_callback_ == NULL); |
| 477 thread_local.failed_access_check_callback_ = callback; |
| 428 } | 478 } |
| 429 | 479 |
| 430 | 480 |
| 431 void Top::ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type) { | 481 void Top::ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type) { |
| 432 if (!thread_local_.failed_access_check_callback_) return; | 482 ThreadLocalTop& thread_local = v8_context()->top_data_.thread_local_; |
| 483 if (!thread_local.failed_access_check_callback_) return; |
| 433 | 484 |
| 434 ASSERT(receiver->IsAccessCheckNeeded()); | 485 ASSERT(receiver->IsAccessCheckNeeded()); |
| 435 ASSERT(Top::context()); | 486 ASSERT(Top::context()); |
| 436 // The callers of this method are not expecting a GC. | 487 // The callers of this method are not expecting a GC. |
| 437 AssertNoAllocation no_gc; | 488 AssertNoAllocation no_gc; |
| 438 | 489 |
| 439 // Get the data object from access check info. | 490 // Get the data object from access check info. |
| 440 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); | 491 JSFunction* constructor = JSFunction::cast(receiver->map()->constructor()); |
| 441 Object* info = constructor->shared()->function_data(); | 492 Object* info = constructor->shared()->function_data(); |
| 442 if (info == Heap::undefined_value()) return; | 493 if (info == Heap::undefined_value()) return; |
| 443 | 494 |
| 444 Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info(); | 495 Object* data_obj = FunctionTemplateInfo::cast(info)->access_check_info(); |
| 445 if (data_obj == Heap::undefined_value()) return; | 496 if (data_obj == Heap::undefined_value()) return; |
| 446 | 497 |
| 447 HandleScope scope; | 498 HandleScope scope; |
| 448 Handle<JSObject> receiver_handle(receiver); | 499 Handle<JSObject> receiver_handle(receiver); |
| 449 Handle<Object> data(AccessCheckInfo::cast(data_obj)->data()); | 500 Handle<Object> data(AccessCheckInfo::cast(data_obj)->data()); |
| 450 thread_local_.failed_access_check_callback_( | 501 thread_local.failed_access_check_callback_( |
| 451 v8::Utils::ToLocal(receiver_handle), | 502 v8::Utils::ToLocal(receiver_handle), |
| 452 type, | 503 type, |
| 453 v8::Utils::ToLocal(data)); | 504 v8::Utils::ToLocal(data)); |
| 454 } | 505 } |
| 455 | 506 |
| 456 | 507 |
| 457 enum MayAccessDecision { | 508 enum MayAccessDecision { |
| 458 YES, NO, UNKNOWN | 509 YES, NO, UNKNOWN |
| 459 }; | 510 }; |
| 460 | 511 |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 618 | 669 |
| 619 Failure* Top::ThrowIllegalOperation() { | 670 Failure* Top::ThrowIllegalOperation() { |
| 620 return Throw(Heap::illegal_access_symbol()); | 671 return Throw(Heap::illegal_access_symbol()); |
| 621 } | 672 } |
| 622 | 673 |
| 623 | 674 |
| 624 void Top::ScheduleThrow(Object* exception) { | 675 void Top::ScheduleThrow(Object* exception) { |
| 625 // When scheduling a throw we first throw the exception to get the | 676 // When scheduling a throw we first throw the exception to get the |
| 626 // error reporting if it is uncaught before rescheduling it. | 677 // error reporting if it is uncaught before rescheduling it. |
| 627 Throw(exception); | 678 Throw(exception); |
| 628 thread_local_.scheduled_exception_ = pending_exception(); | 679 ThreadLocalTop& thread_local = v8_context()->top_data_.thread_local_; |
| 629 thread_local_.external_caught_exception_ = false; | 680 thread_local.scheduled_exception_ = pending_exception(); |
| 681 thread_local.external_caught_exception_ = false; |
| 630 clear_pending_exception(); | 682 clear_pending_exception(); |
| 631 } | 683 } |
| 632 | 684 |
| 633 | 685 |
| 634 Object* Top::PromoteScheduledException() { | 686 Object* Top::PromoteScheduledException() { |
| 635 Object* thrown = scheduled_exception(); | 687 Object* thrown = scheduled_exception(); |
| 636 clear_scheduled_exception(); | 688 clear_scheduled_exception(); |
| 637 // Re-throw the exception to avoid getting repeated error reporting. | 689 // Re-throw the exception to avoid getting repeated error reporting. |
| 638 return ReThrow(thrown); | 690 return ReThrow(thrown); |
| 639 } | 691 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 706 | 758 |
| 707 bool Top::ShouldReturnException(bool* is_caught_externally, | 759 bool Top::ShouldReturnException(bool* is_caught_externally, |
| 708 bool catchable_by_javascript) { | 760 bool catchable_by_javascript) { |
| 709 // Find the top-most try-catch handler. | 761 // Find the top-most try-catch handler. |
| 710 StackHandler* handler = | 762 StackHandler* handler = |
| 711 StackHandler::FromAddress(Top::handler(Top::GetCurrentThread())); | 763 StackHandler::FromAddress(Top::handler(Top::GetCurrentThread())); |
| 712 while (handler != NULL && !handler->is_try_catch()) { | 764 while (handler != NULL && !handler->is_try_catch()) { |
| 713 handler = handler->next(); | 765 handler = handler->next(); |
| 714 } | 766 } |
| 715 | 767 |
| 768 ThreadLocalTop& thread_local = v8_context()->top_data_.thread_local_; |
| 716 // Get the address of the external handler so we can compare the address to | 769 // Get the address of the external handler so we can compare the address to |
| 717 // determine which one is closer to the top of the stack. | 770 // determine which one is closer to the top of the stack. |
| 718 Address external_handler_address = thread_local_.try_catch_handler_address(); | 771 Address external_handler_address = thread_local.try_catch_handler_address(); |
| 719 | 772 |
| 720 // The exception has been externally caught if and only if there is | 773 // The exception has been externally caught if and only if there is |
| 721 // an external handler which is on top of the top-most try-catch | 774 // an external handler which is on top of the top-most try-catch |
| 722 // handler. | 775 // handler. |
| 723 *is_caught_externally = external_handler_address != NULL && | 776 *is_caught_externally = external_handler_address != NULL && |
| 724 (handler == NULL || handler->address() > external_handler_address || | 777 (handler == NULL || handler->address() > external_handler_address || |
| 725 !catchable_by_javascript); | 778 !catchable_by_javascript); |
| 726 | 779 |
| 727 if (*is_caught_externally) { | 780 if (*is_caught_externally) { |
| 728 // Only report the exception if the external handler is verbose. | 781 // Only report the exception if the external handler is verbose. |
| 729 return thread_local_.TryCatchHandler()->is_verbose_; | 782 return thread_local.TryCatchHandler()->is_verbose_; |
| 730 } else { | 783 } else { |
| 731 // Report the exception if it isn't caught by JavaScript code. | 784 // Report the exception if it isn't caught by JavaScript code. |
| 732 return handler == NULL; | 785 return handler == NULL; |
| 733 } | 786 } |
| 734 } | 787 } |
| 735 | 788 |
| 736 | 789 |
| 737 void Top::DoThrow(Object* exception, | 790 void Top::DoThrow(Object* exception, |
| 738 MessageLocation* location, | 791 MessageLocation* location, |
| 739 const char* message) { | 792 const char* message) { |
| 740 ASSERT(!has_pending_exception()); | 793 ASSERT(!has_pending_exception()); |
| 741 | 794 |
| 742 HandleScope scope; | 795 HandleScope scope; |
| 743 Handle<Object> exception_handle(exception); | 796 Handle<Object> exception_handle(exception); |
| 797 ThreadLocalTop& thread_local = v8_context()->top_data_.thread_local_; |
| 744 | 798 |
| 745 // Determine reporting and whether the exception is caught externally. | 799 // Determine reporting and whether the exception is caught externally. |
| 746 bool is_caught_externally = false; | 800 bool is_caught_externally = false; |
| 747 bool is_out_of_memory = exception == Failure::OutOfMemoryException(); | 801 bool is_out_of_memory = exception == Failure::OutOfMemoryException(); |
| 748 bool is_termination_exception = exception == Heap::termination_exception(); | 802 bool is_termination_exception = exception == Heap::termination_exception(); |
| 749 bool catchable_by_javascript = !is_termination_exception && !is_out_of_memory; | 803 bool catchable_by_javascript = !is_termination_exception && !is_out_of_memory; |
| 750 bool should_return_exception = | 804 bool should_return_exception = |
| 751 ShouldReturnException(&is_caught_externally, catchable_by_javascript); | 805 ShouldReturnException(&is_caught_externally, catchable_by_javascript); |
| 752 bool report_exception = catchable_by_javascript && should_return_exception; | 806 bool report_exception = catchable_by_javascript && should_return_exception; |
| 753 | 807 |
| 754 #ifdef ENABLE_DEBUGGER_SUPPORT | 808 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 755 // Notify debugger of exception. | 809 // Notify debugger of exception. |
| 756 if (catchable_by_javascript) { | 810 if (catchable_by_javascript) { |
| 757 Debugger::OnException(exception_handle, report_exception); | 811 Debugger::OnException(exception_handle, report_exception); |
| 758 } | 812 } |
| 759 #endif | 813 #endif |
| 760 | 814 |
| 761 // Generate the message. | 815 // Generate the message. |
| 762 Handle<Object> message_obj; | 816 Handle<Object> message_obj; |
| 763 MessageLocation potential_computed_location; | 817 MessageLocation potential_computed_location; |
| 764 bool try_catch_needs_message = | 818 bool try_catch_needs_message = |
| 765 is_caught_externally && | 819 is_caught_externally && |
| 766 thread_local_.TryCatchHandler()->capture_message_; | 820 thread_local.TryCatchHandler()->capture_message_; |
| 767 if (report_exception || try_catch_needs_message) { | 821 if (report_exception || try_catch_needs_message) { |
| 768 if (location == NULL) { | 822 if (location == NULL) { |
| 769 // If no location was specified we use a computed one instead | 823 // If no location was specified we use a computed one instead |
| 770 ComputeLocation(&potential_computed_location); | 824 ComputeLocation(&potential_computed_location); |
| 771 location = &potential_computed_location; | 825 location = &potential_computed_location; |
| 772 } | 826 } |
| 773 if (!Bootstrapper::IsActive()) { | 827 if (!Bootstrapper::IsActive()) { |
| 774 // It's not safe to try to make message objects or collect stack | 828 // It's not safe to try to make message objects or collect stack |
| 775 // traces while the bootstrapper is active since the infrastructure | 829 // traces while the bootstrapper is active since the infrastructure |
| 776 // may not have been properly initialized. | 830 // may not have been properly initialized. |
| 777 Handle<String> stack_trace; | 831 Handle<String> stack_trace; |
| 778 if (FLAG_trace_exception) stack_trace = StackTrace(); | 832 if (FLAG_trace_exception) stack_trace = StackTrace(); |
| 779 message_obj = MessageHandler::MakeMessageObject("uncaught_exception", | 833 message_obj = MessageHandler::MakeMessageObject("uncaught_exception", |
| 780 location, HandleVector<Object>(&exception_handle, 1), stack_trace); | 834 location, HandleVector<Object>(&exception_handle, 1), stack_trace); |
| 781 } | 835 } |
| 782 } | 836 } |
| 783 | 837 |
| 784 // Save the message for reporting if the the exception remains uncaught. | 838 // Save the message for reporting if the the exception remains uncaught. |
| 785 thread_local_.has_pending_message_ = report_exception; | 839 thread_local.has_pending_message_ = report_exception; |
| 786 thread_local_.pending_message_ = message; | 840 thread_local.pending_message_ = message; |
| 787 if (!message_obj.is_null()) { | 841 if (!message_obj.is_null()) { |
| 788 thread_local_.pending_message_obj_ = *message_obj; | 842 thread_local.pending_message_obj_ = *message_obj; |
| 789 if (location != NULL) { | 843 if (location != NULL) { |
| 790 thread_local_.pending_message_script_ = *location->script(); | 844 thread_local.pending_message_script_ = *location->script(); |
| 791 thread_local_.pending_message_start_pos_ = location->start_pos(); | 845 thread_local.pending_message_start_pos_ = location->start_pos(); |
| 792 thread_local_.pending_message_end_pos_ = location->end_pos(); | 846 thread_local.pending_message_end_pos_ = location->end_pos(); |
| 793 } | 847 } |
| 794 } | 848 } |
| 795 | 849 |
| 796 if (is_caught_externally) { | 850 if (is_caught_externally) { |
| 797 thread_local_.catcher_ = thread_local_.TryCatchHandler(); | 851 thread_local.catcher_ = thread_local.TryCatchHandler(); |
| 798 } | 852 } |
| 799 | 853 |
| 800 // NOTE: Notifying the debugger or generating the message | 854 // NOTE: Notifying the debugger or generating the message |
| 801 // may have caused new exceptions. For now, we just ignore | 855 // may have caused new exceptions. For now, we just ignore |
| 802 // that and set the pending exception to the original one. | 856 // that and set the pending exception to the original one. |
| 803 set_pending_exception(*exception_handle); | 857 set_pending_exception(*exception_handle); |
| 804 } | 858 } |
| 805 | 859 |
| 806 | 860 |
| 807 void Top::ReportPendingMessages() { | 861 void Top::ReportPendingMessages() { |
| 808 ASSERT(has_pending_exception()); | 862 ASSERT(has_pending_exception()); |
| 809 setup_external_caught(); | 863 setup_external_caught(); |
| 864 ThreadLocalTop& thread_local = v8_context()->top_data_.thread_local_; |
| 810 // If the pending exception is OutOfMemoryException set out_of_memory in | 865 // If the pending exception is OutOfMemoryException set out_of_memory in |
| 811 // the global context. Note: We have to mark the global context here | 866 // the global context. Note: We have to mark the global context here |
| 812 // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to | 867 // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to |
| 813 // set it. | 868 // set it. |
| 814 bool external_caught = thread_local_.external_caught_exception_; | 869 bool external_caught = thread_local.external_caught_exception_; |
| 815 HandleScope scope; | 870 HandleScope scope; |
| 816 if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) { | 871 if (thread_local.pending_exception_ == Failure::OutOfMemoryException()) { |
| 817 context()->mark_out_of_memory(); | 872 context()->mark_out_of_memory(); |
| 818 } else if (thread_local_.pending_exception_ == | 873 } else if (thread_local.pending_exception_ == |
| 819 Heap::termination_exception()) { | 874 Heap::termination_exception()) { |
| 820 if (external_caught) { | 875 if (external_caught) { |
| 821 thread_local_.TryCatchHandler()->can_continue_ = false; | 876 thread_local.TryCatchHandler()->can_continue_ = false; |
| 822 thread_local_.TryCatchHandler()->exception_ = Heap::null_value(); | 877 thread_local.TryCatchHandler()->exception_ = Heap::null_value(); |
| 823 } | 878 } |
| 824 } else { | 879 } else { |
| 825 Handle<Object> exception(pending_exception()); | 880 Handle<Object> exception(pending_exception()); |
| 826 thread_local_.external_caught_exception_ = false; | 881 thread_local.external_caught_exception_ = false; |
| 827 if (external_caught) { | 882 if (external_caught) { |
| 828 thread_local_.TryCatchHandler()->can_continue_ = true; | 883 thread_local.TryCatchHandler()->can_continue_ = true; |
| 829 thread_local_.TryCatchHandler()->exception_ = | 884 thread_local.TryCatchHandler()->exception_ = |
| 830 thread_local_.pending_exception_; | 885 thread_local.pending_exception_; |
| 831 if (!thread_local_.pending_message_obj_->IsTheHole()) { | 886 if (!thread_local.pending_message_obj_->IsTheHole()) { |
| 832 try_catch_handler()->message_ = thread_local_.pending_message_obj_; | 887 try_catch_handler()->message_ = thread_local.pending_message_obj_; |
| 833 } | 888 } |
| 834 } | 889 } |
| 835 if (thread_local_.has_pending_message_) { | 890 if (thread_local.has_pending_message_) { |
| 836 thread_local_.has_pending_message_ = false; | 891 thread_local.has_pending_message_ = false; |
| 837 if (thread_local_.pending_message_ != NULL) { | 892 if (thread_local.pending_message_ != NULL) { |
| 838 MessageHandler::ReportMessage(thread_local_.pending_message_); | 893 MessageHandler::ReportMessage(thread_local.pending_message_); |
| 839 } else if (!thread_local_.pending_message_obj_->IsTheHole()) { | 894 } else if (!thread_local.pending_message_obj_->IsTheHole()) { |
| 840 Handle<Object> message_obj(thread_local_.pending_message_obj_); | 895 Handle<Object> message_obj(thread_local.pending_message_obj_); |
| 841 if (thread_local_.pending_message_script_ != NULL) { | 896 if (thread_local.pending_message_script_ != NULL) { |
| 842 Handle<Script> script(thread_local_.pending_message_script_); | 897 Handle<Script> script(thread_local.pending_message_script_); |
| 843 int start_pos = thread_local_.pending_message_start_pos_; | 898 int start_pos = thread_local.pending_message_start_pos_; |
| 844 int end_pos = thread_local_.pending_message_end_pos_; | 899 int end_pos = thread_local.pending_message_end_pos_; |
| 845 MessageLocation location(script, start_pos, end_pos); | 900 MessageLocation location(script, start_pos, end_pos); |
| 846 MessageHandler::ReportMessage(&location, message_obj); | 901 MessageHandler::ReportMessage(&location, message_obj); |
| 847 } else { | 902 } else { |
| 848 MessageHandler::ReportMessage(NULL, message_obj); | 903 MessageHandler::ReportMessage(NULL, message_obj); |
| 849 } | 904 } |
| 850 } | 905 } |
| 851 } | 906 } |
| 852 thread_local_.external_caught_exception_ = external_caught; | 907 thread_local.external_caught_exception_ = external_caught; |
| 853 set_pending_exception(*exception); | 908 set_pending_exception(*exception); |
| 854 } | 909 } |
| 855 clear_pending_message(); | 910 clear_pending_message(); |
| 856 } | 911 } |
| 857 | 912 |
| 858 | 913 |
| 859 void Top::TraceException(bool flag) { | 914 void Top::TraceException(bool flag) { |
| 860 FLAG_trace_exception = flag; | 915 FLAG_trace_exception = flag; |
| 861 } | 916 } |
| 862 | 917 |
| 863 | 918 |
| 864 bool Top::OptionalRescheduleException(bool is_bottom_call) { | 919 bool Top::OptionalRescheduleException(bool is_bottom_call) { |
| 920 ThreadLocalTop& thread_local = v8_context()->top_data_.thread_local_; |
| 865 // Allways reschedule out of memory exceptions. | 921 // Allways reschedule out of memory exceptions. |
| 866 if (!is_out_of_memory()) { | 922 if (!is_out_of_memory()) { |
| 867 bool is_termination_exception = | 923 bool is_termination_exception = |
| 868 pending_exception() == Heap::termination_exception(); | 924 pending_exception() == Heap::termination_exception(); |
| 869 | 925 |
| 870 // Do not reschedule the exception if this is the bottom call. | 926 // Do not reschedule the exception if this is the bottom call. |
| 871 bool clear_exception = is_bottom_call; | 927 bool clear_exception = is_bottom_call; |
| 872 | 928 |
| 873 if (is_termination_exception) { | 929 if (is_termination_exception) { |
| 874 if (is_bottom_call) { | 930 if (is_bottom_call) { |
| 875 thread_local_.external_caught_exception_ = false; | 931 thread_local.external_caught_exception_ = false; |
| 876 clear_pending_exception(); | 932 clear_pending_exception(); |
| 877 return false; | 933 return false; |
| 878 } | 934 } |
| 879 } else if (thread_local_.external_caught_exception_) { | 935 } else if (thread_local.external_caught_exception_) { |
| 880 // If the exception is externally caught, clear it if there are no | 936 // If the exception is externally caught, clear it if there are no |
| 881 // JavaScript frames on the way to the C++ frame that has the | 937 // JavaScript frames on the way to the C++ frame that has the |
| 882 // external handler. | 938 // external handler. |
| 883 ASSERT(thread_local_.try_catch_handler_address() != NULL); | 939 ASSERT(thread_local.try_catch_handler_address() != NULL); |
| 884 Address external_handler_address = | 940 Address external_handler_address = |
| 885 thread_local_.try_catch_handler_address(); | 941 thread_local.try_catch_handler_address(); |
| 886 JavaScriptFrameIterator it; | 942 JavaScriptFrameIterator it; |
| 887 if (it.done() || (it.frame()->sp() > external_handler_address)) { | 943 if (it.done() || (it.frame()->sp() > external_handler_address)) { |
| 888 clear_exception = true; | 944 clear_exception = true; |
| 889 } | 945 } |
| 890 } | 946 } |
| 891 | 947 |
| 892 // Clear the exception if needed. | 948 // Clear the exception if needed. |
| 893 if (clear_exception) { | 949 if (clear_exception) { |
| 894 thread_local_.external_caught_exception_ = false; | 950 thread_local.external_caught_exception_ = false; |
| 895 clear_pending_exception(); | 951 clear_pending_exception(); |
| 896 return false; | 952 return false; |
| 897 } | 953 } |
| 898 } | 954 } |
| 899 | 955 |
| 900 // Reschedule the exception. | 956 // Reschedule the exception. |
| 901 thread_local_.scheduled_exception_ = pending_exception(); | 957 thread_local.scheduled_exception_ = pending_exception(); |
| 902 clear_pending_exception(); | 958 clear_pending_exception(); |
| 903 return true; | 959 return true; |
| 904 } | 960 } |
| 905 | 961 |
| 906 | 962 |
| 907 bool Top::is_out_of_memory() { | 963 bool Top::is_out_of_memory() { |
| 908 if (has_pending_exception()) { | 964 if (has_pending_exception()) { |
| 909 Object* e = pending_exception(); | 965 Object* e = pending_exception(); |
| 910 if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { | 966 if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { |
| 911 return true; | 967 return true; |
| 912 } | 968 } |
| 913 } | 969 } |
| 914 if (has_scheduled_exception()) { | 970 if (has_scheduled_exception()) { |
| 915 Object* e = scheduled_exception(); | 971 Object* e = scheduled_exception(); |
| 916 if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { | 972 if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) { |
| 917 return true; | 973 return true; |
| 918 } | 974 } |
| 919 } | 975 } |
| 920 return false; | 976 return false; |
| 921 } | 977 } |
| 922 | 978 |
| 923 | 979 |
| 924 Handle<Context> Top::global_context() { | 980 Handle<Context> Top::global_context() { |
| 925 GlobalObject* global = thread_local_.context_->global(); | 981 GlobalObject* global = v8_context()->top_data_.thread_local_.context_-> |
| 982 global(); |
| 926 return Handle<Context>(global->global_context()); | 983 return Handle<Context>(global->global_context()); |
| 927 } | 984 } |
| 928 | 985 |
| 929 | 986 |
| 930 Handle<Context> Top::GetCallingGlobalContext() { | 987 Handle<Context> Top::GetCallingGlobalContext() { |
| 931 JavaScriptFrameIterator it; | 988 JavaScriptFrameIterator it; |
| 932 #ifdef ENABLE_DEBUGGER_SUPPORT | 989 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 933 if (Debug::InDebugger()) { | 990 if (Debug::InDebugger()) { |
| 934 while (!it.done()) { | 991 while (!it.done()) { |
| 935 JavaScriptFrame* frame = it.frame(); | 992 JavaScriptFrame* frame = it.frame(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 959 (function == table->get(index+1))) { | 1016 (function == table->get(index+1))) { |
| 960 return table->get(index+2); | 1017 return table->get(index+2); |
| 961 } | 1018 } |
| 962 } | 1019 } |
| 963 } | 1020 } |
| 964 return Heap::undefined_value(); | 1021 return Heap::undefined_value(); |
| 965 } | 1022 } |
| 966 | 1023 |
| 967 | 1024 |
| 968 char* Top::ArchiveThread(char* to) { | 1025 char* Top::ArchiveThread(char* to) { |
| 969 memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(thread_local_)); | 1026 memcpy( |
| 1027 to, |
| 1028 reinterpret_cast<char*>(&v8_context()->top_data_.thread_local_), |
| 1029 sizeof(ThreadLocalTop)); |
| 970 InitializeThreadLocal(); | 1030 InitializeThreadLocal(); |
| 971 return to + sizeof(thread_local_); | 1031 return to + sizeof(ThreadLocalTop); |
| 972 } | 1032 } |
| 973 | 1033 |
| 974 | 1034 |
| 975 char* Top::RestoreThread(char* from) { | 1035 char* Top::RestoreThread(char* from) { |
| 976 memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(thread_local_)); | 1036 memcpy( |
| 977 return from + sizeof(thread_local_); | 1037 reinterpret_cast<char*>(&v8_context()->top_data_.thread_local_), |
| 1038 from, |
| 1039 sizeof(ThreadLocalTop)); |
| 1040 return from + sizeof(ThreadLocalTop); |
| 978 } | 1041 } |
| 979 | 1042 |
| 980 | 1043 |
| 981 ExecutionAccess::ExecutionAccess() { | 1044 ExecutionAccess::ExecutionAccess() { |
| 982 Top::break_access_->Lock(); | 1045 v8_context()->top_data_.break_access_->Lock(); |
| 983 } | 1046 } |
| 984 | 1047 |
| 985 | 1048 |
| 986 ExecutionAccess::~ExecutionAccess() { | 1049 ExecutionAccess::~ExecutionAccess() { |
| 987 Top::break_access_->Unlock(); | 1050 v8_context()->top_data_.break_access_->Unlock(); |
| 988 } | 1051 } |
| 989 | 1052 |
| 990 | 1053 |
| 991 } } // namespace v8::internal | 1054 } } // namespace v8::internal |
| OLD | NEW |