| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 81 private: | 81 private: |
| 82 const Address limit_; | 82 const Address limit_; |
| 83 StackHandler* handler_; | 83 StackHandler* handler_; |
| 84 }; | 84 }; |
| 85 | 85 |
| 86 | 86 |
| 87 // ------------------------------------------------------------------------- | 87 // ------------------------------------------------------------------------- |
| 88 | 88 |
| 89 | 89 |
| 90 #define INITIALIZE_SINGLETON(type, field) field##_(this), | 90 #define INITIALIZE_SINGLETON(type, field) field##_(this), |
| 91 StackFrameIterator::StackFrameIterator(Isolate* isolate) | 91 StackFrameIteratorBase::StackFrameIteratorBase(Isolate* isolate, |
| 92 bool can_access_heap_objects) |
| 92 : isolate_(isolate), | 93 : isolate_(isolate), |
| 93 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) | 94 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) |
| 94 frame_(NULL), handler_(NULL), | 95 frame_(NULL), handler_(NULL), |
| 95 thread_(isolate_->thread_local_top()), | 96 can_access_heap_objects_(can_access_heap_objects) { |
| 96 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler), | |
| 97 can_access_heap_objects_(true) { | |
| 98 Reset(); | |
| 99 } | 97 } |
| 100 StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t) | |
| 101 : isolate_(isolate), | |
| 102 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) | |
| 103 frame_(NULL), handler_(NULL), thread_(t), | |
| 104 fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler), | |
| 105 can_access_heap_objects_(true) { | |
| 106 Reset(); | |
| 107 } | |
| 108 StackFrameIterator::StackFrameIterator(Isolate* isolate, | |
| 109 bool use_top, Address fp, Address sp) | |
| 110 : isolate_(isolate), | |
| 111 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) | |
| 112 frame_(NULL), handler_(NULL), | |
| 113 thread_(use_top ? isolate_->thread_local_top() : NULL), | |
| 114 fp_(use_top ? NULL : fp), sp_(sp), | |
| 115 advance_(&StackFrameIterator::AdvanceWithoutHandler), | |
| 116 can_access_heap_objects_(false) { | |
| 117 if (use_top || fp != NULL) { | |
| 118 Reset(); | |
| 119 } | |
| 120 } | |
| 121 | |
| 122 #undef INITIALIZE_SINGLETON | 98 #undef INITIALIZE_SINGLETON |
| 123 | 99 |
| 124 | 100 |
| 125 void StackFrameIterator::AdvanceWithHandler() { | 101 StackFrameIterator::StackFrameIterator(Isolate* isolate) |
| 102 : StackFrameIteratorBase(isolate, true) { |
| 103 Reset(isolate->thread_local_top()); |
| 104 } |
| 105 |
| 106 |
| 107 StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t) |
| 108 : StackFrameIteratorBase(isolate, true) { |
| 109 Reset(t); |
| 110 } |
| 111 |
| 112 |
| 113 void StackFrameIterator::Advance() { |
| 126 ASSERT(!done()); | 114 ASSERT(!done()); |
| 127 // Compute the state of the calling frame before restoring | 115 // Compute the state of the calling frame before restoring |
| 128 // callee-saved registers and unwinding handlers. This allows the | 116 // callee-saved registers and unwinding handlers. This allows the |
| 129 // frame code that computes the caller state to access the top | 117 // frame code that computes the caller state to access the top |
| 130 // handler and the value of any callee-saved register if needed. | 118 // handler and the value of any callee-saved register if needed. |
| 131 StackFrame::State state; | 119 StackFrame::State state; |
| 132 StackFrame::Type type = frame_->GetCallerState(&state); | 120 StackFrame::Type type = frame_->GetCallerState(&state); |
| 133 | 121 |
| 134 // Unwind handlers corresponding to the current frame. | 122 // Unwind handlers corresponding to the current frame. |
| 135 StackHandlerIterator it(frame_, handler_); | 123 StackHandlerIterator it(frame_, handler_); |
| 136 while (!it.done()) it.Advance(); | 124 while (!it.done()) it.Advance(); |
| 137 handler_ = it.handler(); | 125 handler_ = it.handler(); |
| 138 | 126 |
| 139 // Advance to the calling frame. | 127 // Advance to the calling frame. |
| 140 frame_ = SingletonFor(type, &state); | 128 frame_ = SingletonFor(type, &state); |
| 141 | 129 |
| 142 // When we're done iterating over the stack frames, the handler | 130 // When we're done iterating over the stack frames, the handler |
| 143 // chain must have been completely unwound. | 131 // chain must have been completely unwound. |
| 144 ASSERT(!done() || handler_ == NULL); | 132 ASSERT(!done() || handler_ == NULL); |
| 145 } | 133 } |
| 146 | 134 |
| 147 | 135 |
| 148 void StackFrameIterator::AdvanceWithoutHandler() { | 136 void StackFrameIterator::Reset(ThreadLocalTop* top) { |
| 149 // A simpler version of Advance which doesn't care about handler. | |
| 150 ASSERT(!done()); | |
| 151 StackFrame::State state; | 137 StackFrame::State state; |
| 152 StackFrame::Type type = frame_->GetCallerState(&state); | 138 StackFrame::Type type = ExitFrame::GetStateForFramePointer( |
| 153 frame_ = SingletonFor(type, &state); | 139 Isolate::c_entry_fp(top), &state); |
| 154 } | 140 handler_ = StackHandler::FromAddress(Isolate::handler(top)); |
| 155 | |
| 156 | |
| 157 void StackFrameIterator::Reset() { | |
| 158 StackFrame::State state; | |
| 159 StackFrame::Type type; | |
| 160 if (thread_ != NULL) { | |
| 161 type = ExitFrame::GetStateForFramePointer( | |
| 162 Isolate::c_entry_fp(thread_), &state); | |
| 163 handler_ = StackHandler::FromAddress( | |
| 164 Isolate::handler(thread_)); | |
| 165 } else { | |
| 166 ASSERT(fp_ != NULL); | |
| 167 state.fp = fp_; | |
| 168 state.sp = sp_; | |
| 169 state.pc_address = ResolveReturnAddressLocation( | |
| 170 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_))); | |
| 171 type = StackFrame::ComputeType(this, &state); | |
| 172 } | |
| 173 if (SingletonFor(type) == NULL) return; | 141 if (SingletonFor(type) == NULL) return; |
| 174 frame_ = SingletonFor(type, &state); | 142 frame_ = SingletonFor(type, &state); |
| 175 } | 143 } |
| 176 | 144 |
| 177 | 145 |
| 178 StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type, | 146 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type, |
| 179 StackFrame::State* state) { | 147 StackFrame::State* state) { |
| 180 if (type == StackFrame::NONE) return NULL; | 148 if (type == StackFrame::NONE) return NULL; |
| 181 StackFrame* result = SingletonFor(type); | 149 StackFrame* result = SingletonFor(type); |
| 182 ASSERT(result != NULL); | 150 ASSERT(result != NULL); |
| 183 result->state_ = *state; | 151 result->state_ = *state; |
| 184 return result; | 152 return result; |
| 185 } | 153 } |
| 186 | 154 |
| 187 | 155 |
| 188 StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) { | 156 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) { |
| 189 #define FRAME_TYPE_CASE(type, field) \ | 157 #define FRAME_TYPE_CASE(type, field) \ |
| 190 case StackFrame::type: result = &field##_; break; | 158 case StackFrame::type: result = &field##_; break; |
| 191 | 159 |
| 192 StackFrame* result = NULL; | 160 StackFrame* result = NULL; |
| 193 switch (type) { | 161 switch (type) { |
| 194 case StackFrame::NONE: return NULL; | 162 case StackFrame::NONE: return NULL; |
| 195 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE) | 163 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE) |
| 196 default: break; | 164 default: break; |
| 197 } | 165 } |
| 198 return result; | 166 return result; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 Object* script = JSFunction::cast(frame()->function())->shared()->script(); | 218 Object* script = JSFunction::cast(frame()->function())->shared()->script(); |
| 251 // Don't show functions from native scripts to user. | 219 // Don't show functions from native scripts to user. |
| 252 return (script->IsScript() && | 220 return (script->IsScript() && |
| 253 Script::TYPE_NATIVE != Script::cast(script)->type()->value()); | 221 Script::TYPE_NATIVE != Script::cast(script)->type()->value()); |
| 254 } | 222 } |
| 255 | 223 |
| 256 | 224 |
| 257 // ------------------------------------------------------------------------- | 225 // ------------------------------------------------------------------------- |
| 258 | 226 |
| 259 | 227 |
| 260 bool SafeStackFrameIterator::ExitFrameValidator::IsValidFP(Address fp) { | |
| 261 if (!validator_.IsValid(fp)) return false; | |
| 262 Address sp = ExitFrame::ComputeStackPointer(fp); | |
| 263 if (!validator_.IsValid(sp)) return false; | |
| 264 StackFrame::State state; | |
| 265 ExitFrame::FillState(fp, sp, &state); | |
| 266 if (!validator_.IsValid(reinterpret_cast<Address>(state.pc_address))) { | |
| 267 return false; | |
| 268 } | |
| 269 return *state.pc_address != NULL; | |
| 270 } | |
| 271 | |
| 272 | |
| 273 SafeStackFrameIterator::SafeStackFrameIterator( | 228 SafeStackFrameIterator::SafeStackFrameIterator( |
| 274 Isolate* isolate, | 229 Isolate* isolate, |
| 275 Address fp, Address sp, Address low_bound, Address high_bound) : | 230 Address fp, Address sp, Address low_bound, Address high_bound) : |
| 276 stack_validator_(low_bound, high_bound), | 231 StackFrameIteratorBase(isolate, false), |
| 277 is_valid_top_(IsValidTop(isolate, low_bound, high_bound)), | 232 low_bound_(low_bound), high_bound_(high_bound) { |
| 278 is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)), | 233 StackFrame::State state; |
| 279 iteration_done_(!is_valid_top_ && !is_valid_fp_), | 234 StackFrame::Type type; |
| 280 iterator_(isolate, is_valid_top_, is_valid_fp_ ? fp : NULL, sp) { | 235 ThreadLocalTop* top = isolate->thread_local_top(); |
| 236 if (IsValidTop(top)) { |
| 237 type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state); |
| 238 } else if (IsValidStackAddress(fp)) { |
| 239 ASSERT(fp != NULL); |
| 240 state.fp = fp; |
| 241 state.sp = sp; |
| 242 state.pc_address = ResolveReturnAddressLocation( |
| 243 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp))); |
| 244 type = StackFrame::ComputeType(this, &state); |
| 245 } else { |
| 246 return; |
| 247 } |
| 248 if (SingletonFor(type) == NULL) return; |
| 249 frame_ = SingletonFor(type, &state); |
| 250 |
| 281 if (!done()) Advance(); | 251 if (!done()) Advance(); |
| 282 } | 252 } |
| 283 | 253 |
| 284 | 254 |
| 285 bool SafeStackFrameIterator::IsValidTop(Isolate* isolate, | 255 bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const { |
| 286 Address low_bound, Address high_bound) { | |
| 287 ThreadLocalTop* top = isolate->thread_local_top(); | |
| 288 Address fp = Isolate::c_entry_fp(top); | 256 Address fp = Isolate::c_entry_fp(top); |
| 289 ExitFrameValidator validator(low_bound, high_bound); | 257 if (!IsValidExitFrame(fp)) return false; |
| 290 if (!validator.IsValidFP(fp)) return false; | 258 // There should be at least one JS_ENTRY stack handler. |
| 291 return Isolate::handler(top) != NULL; | 259 return Isolate::handler(top) != NULL; |
| 292 } | 260 } |
| 293 | 261 |
| 294 | 262 |
| 295 void SafeStackFrameIterator::AdvanceOneFrame() { | 263 void SafeStackFrameIterator::AdvanceOneFrame() { |
| 296 ASSERT(!done()); | 264 ASSERT(!done()); |
| 297 StackFrame* last_frame = iterator_.frame(); | 265 StackFrame* last_frame = frame_; |
| 298 Address last_sp = last_frame->sp(), last_fp = last_frame->fp(); | 266 Address last_sp = last_frame->sp(), last_fp = last_frame->fp(); |
| 299 // Before advancing to the next stack frame, perform pointer validity tests | 267 // Before advancing to the next stack frame, perform pointer validity tests. |
| 300 iteration_done_ = !IsValidFrame(last_frame) || | 268 if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) { |
| 301 !IsValidCaller(last_frame); | 269 frame_ = NULL; |
| 302 if (iteration_done_) return; | 270 return; |
| 271 } |
| 303 | 272 |
| 304 iterator_.Advance(); | 273 // Advance to the previous frame. |
| 305 if (iterator_.done()) return; | 274 StackFrame::State state; |
| 306 // Check that we have actually moved to the previous frame in the stack | 275 StackFrame::Type type = frame_->GetCallerState(&state); |
| 307 StackFrame* prev_frame = iterator_.frame(); | 276 frame_ = SingletonFor(type, &state); |
| 308 iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_fp; | 277 if (frame_ == NULL) return; |
| 278 |
| 279 // Check that we have actually moved to the previous frame in the stack. |
| 280 if (frame_->sp() < last_sp || frame_->fp() < last_fp) { |
| 281 frame_ = NULL; |
| 282 } |
| 309 } | 283 } |
| 310 | 284 |
| 311 | 285 |
| 312 bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const { | 286 bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const { |
| 313 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp()); | 287 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp()); |
| 314 } | 288 } |
| 315 | 289 |
| 316 | 290 |
| 317 bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) { | 291 bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) { |
| 318 StackFrame::State state; | 292 StackFrame::State state; |
| 319 if (frame->is_entry() || frame->is_entry_construct()) { | 293 if (frame->is_entry() || frame->is_entry_construct()) { |
| 320 // See EntryFrame::GetCallerState. It computes the caller FP address | 294 // See EntryFrame::GetCallerState. It computes the caller FP address |
| 321 // and calls ExitFrame::GetStateForFramePointer on it. We need to be | 295 // and calls ExitFrame::GetStateForFramePointer on it. We need to be |
| 322 // sure that caller FP address is valid. | 296 // sure that caller FP address is valid. |
| 323 Address caller_fp = Memory::Address_at( | 297 Address caller_fp = Memory::Address_at( |
| 324 frame->fp() + EntryFrameConstants::kCallerFPOffset); | 298 frame->fp() + EntryFrameConstants::kCallerFPOffset); |
| 325 ExitFrameValidator validator(stack_validator_); | 299 if (!IsValidExitFrame(caller_fp)) return false; |
| 326 if (!validator.IsValidFP(caller_fp)) return false; | |
| 327 } else if (frame->is_arguments_adaptor()) { | 300 } else if (frame->is_arguments_adaptor()) { |
| 328 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that | 301 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that |
| 329 // the number of arguments is stored on stack as Smi. We need to check | 302 // the number of arguments is stored on stack as Smi. We need to check |
| 330 // that it really an Smi. | 303 // that it really an Smi. |
| 331 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)-> | 304 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)-> |
| 332 GetExpression(0); | 305 GetExpression(0); |
| 333 if (!number_of_args->IsSmi()) { | 306 if (!number_of_args->IsSmi()) { |
| 334 return false; | 307 return false; |
| 335 } | 308 } |
| 336 } | 309 } |
| 337 frame->ComputeCallerState(&state); | 310 frame->ComputeCallerState(&state); |
| 338 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) && | 311 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) && |
| 339 iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL; | 312 SingletonFor(frame->GetCallerState(&state)) != NULL; |
| 340 } | 313 } |
| 341 | 314 |
| 342 | 315 |
| 316 bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const { |
| 317 if (!IsValidStackAddress(fp)) return false; |
| 318 Address sp = ExitFrame::ComputeStackPointer(fp); |
| 319 if (!IsValidStackAddress(sp)) return false; |
| 320 StackFrame::State state; |
| 321 ExitFrame::FillState(fp, sp, &state); |
| 322 if (!IsValidStackAddress(reinterpret_cast<Address>(state.pc_address))) { |
| 323 return false; |
| 324 } |
| 325 return *state.pc_address != NULL; |
| 326 } |
| 327 |
| 328 |
| 343 void SafeStackFrameIterator::Advance() { | 329 void SafeStackFrameIterator::Advance() { |
| 344 while (true) { | 330 while (true) { |
| 345 AdvanceOneFrame(); | 331 AdvanceOneFrame(); |
| 346 if (done()) return; | 332 if (done()) return; |
| 347 if (iterator_.frame()->is_java_script()) return; | 333 if (frame_->is_java_script()) return; |
| 348 } | 334 } |
| 349 } | 335 } |
| 350 | 336 |
| 351 | 337 |
| 352 // ------------------------------------------------------------------------- | 338 // ------------------------------------------------------------------------- |
| 353 | 339 |
| 354 | 340 |
| 355 Code* StackFrame::GetSafepointData(Isolate* isolate, | 341 Code* StackFrame::GetSafepointData(Isolate* isolate, |
| 356 Address inner_pointer, | 342 Address inner_pointer, |
| 357 SafepointEntry* safepoint_entry, | 343 SafepointEntry* safepoint_entry, |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 401 } | 387 } |
| 402 | 388 |
| 403 | 389 |
| 404 void StackFrame::SetReturnAddressLocationResolver( | 390 void StackFrame::SetReturnAddressLocationResolver( |
| 405 ReturnAddressLocationResolver resolver) { | 391 ReturnAddressLocationResolver resolver) { |
| 406 ASSERT(return_address_location_resolver == NULL); | 392 ASSERT(return_address_location_resolver == NULL); |
| 407 return_address_location_resolver = resolver; | 393 return_address_location_resolver = resolver; |
| 408 } | 394 } |
| 409 | 395 |
| 410 | 396 |
| 411 StackFrame::Type StackFrame::ComputeType(const StackFrameIterator* iterator, | 397 StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator, |
| 412 State* state) { | 398 State* state) { |
| 413 ASSERT(state->fp != NULL); | 399 ASSERT(state->fp != NULL); |
| 414 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { | 400 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { |
| 415 return ARGUMENTS_ADAPTOR; | 401 return ARGUMENTS_ADAPTOR; |
| 416 } | 402 } |
| 417 // The marker and function offsets overlap. If the marker isn't a | 403 // The marker and function offsets overlap. If the marker isn't a |
| 418 // smi then the frame is a JavaScript frame -- and the marker is | 404 // smi then the frame is a JavaScript frame -- and the marker is |
| 419 // really the function. | 405 // really the function. |
| 420 const int offset = StandardFrameConstants::kMarkerOffset; | 406 const int offset = StandardFrameConstants::kMarkerOffset; |
| 421 Object* marker = Memory::Object_at(state->fp + offset); | 407 Object* marker = Memory::Object_at(state->fp + offset); |
| (...skipping 1188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1610 ZoneList<StackFrame*> list(10, zone); | 1596 ZoneList<StackFrame*> list(10, zone); |
| 1611 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { | 1597 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { |
| 1612 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); | 1598 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); |
| 1613 list.Add(frame, zone); | 1599 list.Add(frame, zone); |
| 1614 } | 1600 } |
| 1615 return list.ToVector(); | 1601 return list.ToVector(); |
| 1616 } | 1602 } |
| 1617 | 1603 |
| 1618 | 1604 |
| 1619 } } // namespace v8::internal | 1605 } } // namespace v8::internal |
| OLD | NEW |