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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 StackHandler* handler_; | 59 StackHandler* handler_; |
60 }; | 60 }; |
61 | 61 |
62 | 62 |
63 // ------------------------------------------------------------------------- | 63 // ------------------------------------------------------------------------- |
64 | 64 |
65 | 65 |
66 #define INITIALIZE_SINGLETON(type, field) field##_(this), | 66 #define INITIALIZE_SINGLETON(type, field) field##_(this), |
67 StackFrameIterator::StackFrameIterator() | 67 StackFrameIterator::StackFrameIterator() |
68 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) | 68 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) |
69 frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()) { | 69 frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()), |
| 70 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) { |
70 Reset(); | 71 Reset(); |
71 } | 72 } |
72 StackFrameIterator::StackFrameIterator(ThreadLocalTop* t) | 73 StackFrameIterator::StackFrameIterator(ThreadLocalTop* t) |
73 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) | 74 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) |
74 frame_(NULL), handler_(NULL), thread_(t) { | 75 frame_(NULL), handler_(NULL), thread_(t), |
| 76 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) { |
75 Reset(); | 77 Reset(); |
76 } | 78 } |
77 StackFrameIterator::StackFrameIterator(bool reset) | 79 StackFrameIterator::StackFrameIterator(bool use_top, Address fp, Address sp) |
78 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) | 80 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) |
79 frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()) { | 81 frame_(NULL), handler_(NULL), |
80 if (reset) Reset(); | 82 thread_(use_top ? Top::GetCurrentThread() : NULL), |
| 83 fp_(use_top ? NULL : fp), sp_(sp), |
| 84 advance_(use_top ? &StackFrameIterator::AdvanceWithHandler : |
| 85 &StackFrameIterator::AdvanceWithoutHandler) { |
| 86 if (use_top || fp != NULL) { |
| 87 Reset(); |
| 88 } |
81 } | 89 } |
| 90 |
82 #undef INITIALIZE_SINGLETON | 91 #undef INITIALIZE_SINGLETON |
83 | 92 |
84 | 93 |
85 void StackFrameIterator::Advance() { | 94 void StackFrameIterator::AdvanceWithHandler() { |
86 ASSERT(!done()); | 95 ASSERT(!done()); |
87 // Compute the state of the calling frame before restoring | 96 // Compute the state of the calling frame before restoring |
88 // callee-saved registers and unwinding handlers. This allows the | 97 // callee-saved registers and unwinding handlers. This allows the |
89 // frame code that computes the caller state to access the top | 98 // frame code that computes the caller state to access the top |
90 // handler and the value of any callee-saved register if needed. | 99 // handler and the value of any callee-saved register if needed. |
91 StackFrame::State state; | 100 StackFrame::State state; |
92 StackFrame::Type type = frame_->GetCallerState(&state); | 101 StackFrame::Type type = frame_->GetCallerState(&state); |
93 | 102 |
94 // Unwind handlers corresponding to the current frame. | 103 // Unwind handlers corresponding to the current frame. |
95 StackHandlerIterator it(frame_, handler_); | 104 StackHandlerIterator it(frame_, handler_); |
96 while (!it.done()) it.Advance(); | 105 while (!it.done()) it.Advance(); |
97 handler_ = it.handler(); | 106 handler_ = it.handler(); |
98 | 107 |
99 // Advance to the calling frame. | 108 // Advance to the calling frame. |
100 frame_ = SingletonFor(type, &state); | 109 frame_ = SingletonFor(type, &state); |
101 | 110 |
102 // When we're done iterating over the stack frames, the handler | 111 // When we're done iterating over the stack frames, the handler |
103 // chain must have been completely unwound. | 112 // chain must have been completely unwound. |
104 ASSERT(!done() || handler_ == NULL); | 113 ASSERT(!done() || handler_ == NULL); |
105 } | 114 } |
106 | 115 |
107 | 116 |
| 117 void StackFrameIterator::AdvanceWithoutHandler() { |
| 118 // A simpler version of Advance which doesn't care about handler. |
| 119 ASSERT(!done()); |
| 120 StackFrame::State state; |
| 121 StackFrame::Type type = frame_->GetCallerState(&state); |
| 122 frame_ = SingletonFor(type, &state); |
| 123 } |
| 124 |
| 125 |
108 void StackFrameIterator::Reset() { | 126 void StackFrameIterator::Reset() { |
109 Address fp = Top::c_entry_fp(thread_); | |
110 StackFrame::State state; | 127 StackFrame::State state; |
111 StackFrame::Type type = ExitFrame::GetStateForFramePointer(fp, &state); | 128 StackFrame::Type type; |
| 129 if (thread_ != NULL) { |
| 130 type = ExitFrame::GetStateForFramePointer(Top::c_entry_fp(thread_), &state); |
| 131 handler_ = StackHandler::FromAddress(Top::handler(thread_)); |
| 132 } else { |
| 133 ASSERT(fp_ != NULL); |
| 134 state.fp = fp_; |
| 135 state.sp = sp_; |
| 136 state.pc_address = |
| 137 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_)); |
| 138 type = StackFrame::ComputeType(&state); |
| 139 if (SingletonFor(type) == NULL) return; |
| 140 } |
112 frame_ = SingletonFor(type, &state); | 141 frame_ = SingletonFor(type, &state); |
113 handler_ = StackHandler::FromAddress(Top::handler(thread_)); | |
114 } | 142 } |
115 | 143 |
116 | 144 |
117 StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type, | 145 StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type, |
118 StackFrame::State* state) { | 146 StackFrame::State* state) { |
| 147 if (type == StackFrame::NONE) return NULL; |
| 148 StackFrame* result = SingletonFor(type); |
| 149 ASSERT(result != NULL); |
| 150 result->state_ = *state; |
| 151 return result; |
| 152 } |
| 153 |
| 154 |
| 155 StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) { |
119 #define FRAME_TYPE_CASE(type, field) \ | 156 #define FRAME_TYPE_CASE(type, field) \ |
120 case StackFrame::type: result = &field##_; break; | 157 case StackFrame::type: result = &field##_; break; |
121 | 158 |
122 StackFrame* result = NULL; | 159 StackFrame* result = NULL; |
123 switch (type) { | 160 switch (type) { |
124 case StackFrame::NONE: return NULL; | 161 case StackFrame::NONE: return NULL; |
125 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE) | 162 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE) |
126 default: break; | 163 default: break; |
127 } | 164 } |
128 ASSERT(result != NULL); | |
129 result->state_ = *state; | |
130 return result; | 165 return result; |
131 | 166 |
132 #undef FRAME_TYPE_CASE | 167 #undef FRAME_TYPE_CASE |
133 } | 168 } |
134 | 169 |
135 | 170 |
136 // ------------------------------------------------------------------------- | 171 // ------------------------------------------------------------------------- |
137 | 172 |
138 | 173 |
139 StackTraceFrameIterator::StackTraceFrameIterator() { | 174 StackTraceFrameIterator::StackTraceFrameIterator() { |
140 if (!done() && !frame()->function()->IsJSFunction()) Advance(); | 175 if (!done() && !frame()->function()->IsJSFunction()) Advance(); |
141 } | 176 } |
142 | 177 |
143 | 178 |
144 void StackTraceFrameIterator::Advance() { | 179 void StackTraceFrameIterator::Advance() { |
145 while (true) { | 180 while (true) { |
146 JavaScriptFrameIterator::Advance(); | 181 JavaScriptFrameIterator::Advance(); |
147 if (done()) return; | 182 if (done()) return; |
148 if (frame()->function()->IsJSFunction()) return; | 183 if (frame()->function()->IsJSFunction()) return; |
149 } | 184 } |
150 } | 185 } |
151 | 186 |
152 | 187 |
153 // ------------------------------------------------------------------------- | 188 // ------------------------------------------------------------------------- |
154 | 189 |
155 | 190 |
156 SafeStackFrameIterator::SafeStackFrameIterator( | 191 SafeStackFrameIterator::SafeStackFrameIterator( |
157 Address low_bound, Address high_bound) : | 192 Address fp, Address sp, Address low_bound, Address high_bound) : |
158 low_bound_(low_bound), high_bound_(high_bound), | 193 low_bound_(low_bound), high_bound_(high_bound), |
159 is_working_iterator_(IsInBounds(low_bound, high_bound, | 194 is_valid_top_( |
160 Top::c_entry_fp(Top::GetCurrentThread()))), | 195 IsWithinBounds(low_bound, high_bound, |
161 iteration_done_(!is_working_iterator_), iterator_(is_working_iterator_) { | 196 Top::c_entry_fp(Top::GetCurrentThread())) && |
| 197 Top::handler(Top::GetCurrentThread()) != NULL), |
| 198 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)), |
| 199 is_working_iterator_(is_valid_top_ || is_valid_fp_), |
| 200 iteration_done_(!is_working_iterator_), |
| 201 iterator_(is_valid_top_, is_valid_fp_ ? fp : NULL, sp) { |
162 } | 202 } |
163 | 203 |
164 | 204 |
165 void SafeStackFrameIterator::Advance() { | 205 void SafeStackFrameIterator::Advance() { |
166 ASSERT(is_working_iterator_); | 206 ASSERT(is_working_iterator_); |
167 ASSERT(!done()); | 207 ASSERT(!done()); |
168 StackFrame* frame = iterator_.frame(); | 208 StackFrame* last_frame = iterator_.frame(); |
169 iteration_done_ = | 209 Address last_sp = last_frame->sp(), last_fp = last_frame->fp(); |
170 !IsGoodStackAddress(frame->sp()) || !IsGoodStackAddress(frame->fp()); | 210 // Before advancing to the next stack frame, perform pointer validity tests |
171 if (!iteration_done_) { | 211 iteration_done_ = !IsValidFrame(last_frame) || !IsValidCaller(last_frame); |
172 iterator_.Advance(); | 212 if (iteration_done_) return; |
173 if (!iterator_.done()) { | 213 |
174 // Check that we have actually moved to the previous frame in the stack | 214 iterator_.Advance(); |
175 StackFrame* prev_frame = iterator_.frame(); | 215 if (iterator_.done()) return; |
176 iteration_done_ = | 216 // Check that we have actually moved to the previous frame in the stack |
177 prev_frame->sp() < frame->sp() || prev_frame->fp() < frame->fp(); | 217 StackFrame* prev_frame = iterator_.frame(); |
178 } | 218 iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_fp; |
179 } | |
180 } | 219 } |
181 | 220 |
182 | 221 |
| 222 bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const { |
| 223 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp()) && |
| 224 // JavaScriptFrame uses function shared info to advance, hence it must |
| 225 // point to a valid function object. |
| 226 (!frame->is_java_script() || |
| 227 reinterpret_cast<JavaScriptFrame*>(frame)->is_at_function()); |
| 228 } |
| 229 |
| 230 |
| 231 bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) { |
| 232 StackFrame::State state; |
| 233 frame->ComputeCallerState(&state); |
| 234 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) && |
| 235 iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL; |
| 236 } |
| 237 |
| 238 |
183 void SafeStackFrameIterator::Reset() { | 239 void SafeStackFrameIterator::Reset() { |
184 if (is_working_iterator_) { | 240 if (is_working_iterator_) { |
185 iterator_.Reset(); | 241 iterator_.Reset(); |
186 iteration_done_ = false; | 242 iteration_done_ = false; |
187 } | 243 } |
188 } | 244 } |
189 | 245 |
190 | 246 |
191 // ------------------------------------------------------------------------- | 247 // ------------------------------------------------------------------------- |
192 | 248 |
193 | 249 |
194 #ifdef ENABLE_LOGGING_AND_PROFILING | 250 #ifdef ENABLE_LOGGING_AND_PROFILING |
195 SafeStackTraceFrameIterator::SafeStackTraceFrameIterator( | 251 SafeStackTraceFrameIterator::SafeStackTraceFrameIterator( |
196 Address low_bound, Address high_bound) : | 252 Address fp, Address sp, Address low_bound, Address high_bound) : |
197 SafeJavaScriptFrameIterator(low_bound, high_bound) { | 253 SafeJavaScriptFrameIterator(fp, sp, low_bound, high_bound) { |
198 if (!done() && !frame()->function()->IsJSFunction()) Advance(); | 254 if (!done() && !frame()->is_at_function()) Advance(); |
199 } | 255 } |
200 | 256 |
201 | 257 |
202 void SafeStackTraceFrameIterator::Advance() { | 258 void SafeStackTraceFrameIterator::Advance() { |
203 while (true) { | 259 while (true) { |
204 SafeJavaScriptFrameIterator::Advance(); | 260 SafeJavaScriptFrameIterator::Advance(); |
205 if (done()) return; | 261 if (done()) return; |
206 if (frame()->function()->IsJSFunction()) return; | 262 if (frame()->is_at_function()) return; |
207 } | 263 } |
208 } | 264 } |
209 #endif | 265 #endif |
210 | 266 |
211 | 267 |
212 // ------------------------------------------------------------------------- | 268 // ------------------------------------------------------------------------- |
213 | 269 |
214 | 270 |
215 void StackHandler::Cook(Code* code) { | 271 void StackHandler::Cook(Code* code) { |
216 ASSERT(MarkCompactCollector::IsCompacting()); | 272 ASSERT(MarkCompactCollector::IsCompacting()); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 void StackFrame::Uncook() { | 328 void StackFrame::Uncook() { |
273 Code* code = this->code(); | 329 Code* code = this->code(); |
274 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { | 330 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { |
275 it.handler()->Uncook(code); | 331 it.handler()->Uncook(code); |
276 } | 332 } |
277 set_pc(code->instruction_start() + OffsetFrom(pc())); | 333 set_pc(code->instruction_start() + OffsetFrom(pc())); |
278 ASSERT(code->contains(pc())); | 334 ASSERT(code->contains(pc())); |
279 } | 335 } |
280 | 336 |
281 | 337 |
| 338 StackFrame::Type StackFrame::GetCallerState(State* state) const { |
| 339 ComputeCallerState(state); |
| 340 return ComputeType(state); |
| 341 } |
| 342 |
| 343 |
282 Code* EntryFrame::code() const { | 344 Code* EntryFrame::code() const { |
283 return Heap::js_entry_code(); | 345 return Heap::js_entry_code(); |
284 } | 346 } |
285 | 347 |
286 | 348 |
| 349 void EntryFrame::ComputeCallerState(State* state) const { |
| 350 GetCallerState(state); |
| 351 } |
| 352 |
| 353 |
287 StackFrame::Type EntryFrame::GetCallerState(State* state) const { | 354 StackFrame::Type EntryFrame::GetCallerState(State* state) const { |
288 const int offset = EntryFrameConstants::kCallerFPOffset; | 355 const int offset = EntryFrameConstants::kCallerFPOffset; |
289 Address fp = Memory::Address_at(this->fp() + offset); | 356 Address fp = Memory::Address_at(this->fp() + offset); |
290 return ExitFrame::GetStateForFramePointer(fp, state); | 357 return ExitFrame::GetStateForFramePointer(fp, state); |
291 } | 358 } |
292 | 359 |
293 | 360 |
294 Code* EntryConstructFrame::code() const { | 361 Code* EntryConstructFrame::code() const { |
295 return Heap::js_construct_entry_code(); | 362 return Heap::js_construct_entry_code(); |
296 } | 363 } |
297 | 364 |
298 | 365 |
299 Code* ExitFrame::code() const { | 366 Code* ExitFrame::code() const { |
300 return Heap::c_entry_code(); | 367 return Heap::c_entry_code(); |
301 } | 368 } |
302 | 369 |
303 | 370 |
304 StackFrame::Type ExitFrame::GetCallerState(State* state) const { | 371 void ExitFrame::ComputeCallerState(State* state) const { |
305 // Setup the caller state. | 372 // Setup the caller state. |
306 state->sp = pp(); | 373 state->sp = pp(); |
307 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset); | 374 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset); |
308 state->pc_address | 375 state->pc_address |
309 = reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset); | 376 = reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset); |
310 return ComputeType(state); | |
311 } | 377 } |
312 | 378 |
313 | 379 |
314 Address ExitFrame::GetCallerStackPointer() const { | 380 Address ExitFrame::GetCallerStackPointer() const { |
315 return fp() + ExitFrameConstants::kPPDisplacement; | 381 return fp() + ExitFrameConstants::kPPDisplacement; |
316 } | 382 } |
317 | 383 |
318 | 384 |
319 Code* ExitDebugFrame::code() const { | 385 Code* ExitDebugFrame::code() const { |
320 return Heap::c_entry_debug_break_code(); | 386 return Heap::c_entry_debug_break_code(); |
(...skipping 10 matching lines...) Expand all Loading... |
331 const int offset = | 397 const int offset = |
332 StandardFrameConstants::kExpressionsOffset + kPointerSize; | 398 StandardFrameConstants::kExpressionsOffset + kPointerSize; |
333 Address base = fp() + offset; | 399 Address base = fp() + offset; |
334 Address limit = sp(); | 400 Address limit = sp(); |
335 ASSERT(base >= limit); // stack grows downwards | 401 ASSERT(base >= limit); // stack grows downwards |
336 // Include register-allocated locals in number of expressions. | 402 // Include register-allocated locals in number of expressions. |
337 return (base - limit) / kPointerSize; | 403 return (base - limit) / kPointerSize; |
338 } | 404 } |
339 | 405 |
340 | 406 |
341 StackFrame::Type StandardFrame::GetCallerState(State* state) const { | 407 void StandardFrame::ComputeCallerState(State* state) const { |
342 state->sp = caller_sp(); | 408 state->sp = caller_sp(); |
343 state->fp = caller_fp(); | 409 state->fp = caller_fp(); |
344 state->pc_address = reinterpret_cast<Address*>(ComputePCAddress(fp())); | 410 state->pc_address = reinterpret_cast<Address*>(ComputePCAddress(fp())); |
345 return ComputeType(state); | |
346 } | 411 } |
347 | 412 |
348 | 413 |
349 bool StandardFrame::IsExpressionInsideHandler(int n) const { | 414 bool StandardFrame::IsExpressionInsideHandler(int n) const { |
350 Address address = GetExpressionAddress(n); | 415 Address address = GetExpressionAddress(n); |
351 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { | 416 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { |
352 if (it.handler()->includes(address)) return true; | 417 if (it.handler()->includes(address)) return true; |
353 } | 418 } |
354 return false; | 419 return false; |
355 } | 420 } |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 reg_code[i++] = r; | 704 reg_code[i++] = r; |
640 | 705 |
641 ASSERT(i == kNumJSCallerSaved); | 706 ASSERT(i == kNumJSCallerSaved); |
642 } | 707 } |
643 ASSERT(0 <= n && n < kNumJSCallerSaved); | 708 ASSERT(0 <= n && n < kNumJSCallerSaved); |
644 return reg_code[n]; | 709 return reg_code[n]; |
645 } | 710 } |
646 | 711 |
647 | 712 |
648 } } // namespace v8::internal | 713 } } // namespace v8::internal |
OLD | NEW |