| 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 |