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 |