| Index: src/frames.cc
|
| diff --git a/src/frames.cc b/src/frames.cc
|
| index acdcbdfb141ddab54723ad9c6365821b0770004b..0ca6991488464994be3300cf56e1ec47978036a4 100644
|
| --- a/src/frames.cc
|
| +++ b/src/frames.cc
|
| @@ -88,41 +88,29 @@ class StackHandlerIterator BASE_EMBEDDED {
|
|
|
|
|
| #define INITIALIZE_SINGLETON(type, field) field##_(this),
|
| -StackFrameIterator::StackFrameIterator(Isolate* isolate)
|
| +StackFrameIteratorBase::StackFrameIteratorBase(Isolate* isolate,
|
| + bool can_access_heap_objects)
|
| : isolate_(isolate),
|
| STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
|
| frame_(NULL), handler_(NULL),
|
| - thread_(isolate_->thread_local_top()),
|
| - fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler),
|
| - can_access_heap_objects_(true) {
|
| - Reset();
|
| -}
|
| -StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
|
| - : isolate_(isolate),
|
| - STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
|
| - frame_(NULL), handler_(NULL), thread_(t),
|
| - fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler),
|
| - can_access_heap_objects_(true) {
|
| - Reset();
|
| + can_access_heap_objects_(can_access_heap_objects) {
|
| }
|
| -StackFrameIterator::StackFrameIterator(Isolate* isolate,
|
| - bool use_top, Address fp, Address sp)
|
| - : isolate_(isolate),
|
| - STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
|
| - frame_(NULL), handler_(NULL),
|
| - thread_(use_top ? isolate_->thread_local_top() : NULL),
|
| - fp_(use_top ? NULL : fp), sp_(sp),
|
| - advance_(&StackFrameIterator::AdvanceWithoutHandler),
|
| - can_access_heap_objects_(false) {
|
| - if (use_top || fp != NULL) {
|
| - Reset();
|
| - }
|
| +#undef INITIALIZE_SINGLETON
|
| +
|
| +
|
| +StackFrameIterator::StackFrameIterator(Isolate* isolate)
|
| + : StackFrameIteratorBase(isolate, true) {
|
| + Reset(isolate->thread_local_top());
|
| }
|
|
|
| -#undef INITIALIZE_SINGLETON
|
| +
|
| +StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
|
| + : StackFrameIteratorBase(isolate, true) {
|
| + Reset(t);
|
| +}
|
|
|
|
|
| -void StackFrameIterator::AdvanceWithHandler() {
|
| +void StackFrameIterator::Advance() {
|
| ASSERT(!done());
|
| // Compute the state of the calling frame before restoring
|
| // callee-saved registers and unwinding handlers. This allows the
|
| @@ -145,37 +133,17 @@ void StackFrameIterator::AdvanceWithHandler() {
|
| }
|
|
|
|
|
| -void StackFrameIterator::AdvanceWithoutHandler() {
|
| - // A simpler version of Advance which doesn't care about handler.
|
| - ASSERT(!done());
|
| +void StackFrameIterator::Reset(ThreadLocalTop* top) {
|
| StackFrame::State state;
|
| - StackFrame::Type type = frame_->GetCallerState(&state);
|
| - frame_ = SingletonFor(type, &state);
|
| -}
|
| -
|
| -
|
| -void StackFrameIterator::Reset() {
|
| - StackFrame::State state;
|
| - StackFrame::Type type;
|
| - if (thread_ != NULL) {
|
| - type = ExitFrame::GetStateForFramePointer(
|
| - Isolate::c_entry_fp(thread_), &state);
|
| - handler_ = StackHandler::FromAddress(
|
| - Isolate::handler(thread_));
|
| - } else {
|
| - ASSERT(fp_ != NULL);
|
| - state.fp = fp_;
|
| - state.sp = sp_;
|
| - state.pc_address = ResolveReturnAddressLocation(
|
| - reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_)));
|
| - type = StackFrame::ComputeType(this, &state);
|
| - }
|
| + StackFrame::Type type = ExitFrame::GetStateForFramePointer(
|
| + Isolate::c_entry_fp(top), &state);
|
| + handler_ = StackHandler::FromAddress(Isolate::handler(top));
|
| if (SingletonFor(type) == NULL) return;
|
| frame_ = SingletonFor(type, &state);
|
| }
|
|
|
|
|
| -StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
|
| +StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type,
|
| StackFrame::State* state) {
|
| if (type == StackFrame::NONE) return NULL;
|
| StackFrame* result = SingletonFor(type);
|
| @@ -185,7 +153,7 @@ StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
|
| }
|
|
|
|
|
| -StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) {
|
| +StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) {
|
| #define FRAME_TYPE_CASE(type, field) \
|
| case StackFrame::type: result = &field##_; break;
|
|
|
| @@ -257,55 +225,61 @@ bool StackTraceFrameIterator::IsValidFrame() {
|
| // -------------------------------------------------------------------------
|
|
|
|
|
| -bool SafeStackFrameIterator::ExitFrameValidator::IsValidFP(Address fp) {
|
| - if (!validator_.IsValid(fp)) return false;
|
| - Address sp = ExitFrame::ComputeStackPointer(fp);
|
| - if (!validator_.IsValid(sp)) return false;
|
| - StackFrame::State state;
|
| - ExitFrame::FillState(fp, sp, &state);
|
| - if (!validator_.IsValid(reinterpret_cast<Address>(state.pc_address))) {
|
| - return false;
|
| - }
|
| - return *state.pc_address != NULL;
|
| -}
|
| -
|
| -
|
| SafeStackFrameIterator::SafeStackFrameIterator(
|
| Isolate* isolate,
|
| Address fp, Address sp, Address low_bound, Address high_bound) :
|
| - stack_validator_(low_bound, high_bound),
|
| - is_valid_top_(IsValidTop(isolate, low_bound, high_bound)),
|
| - is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)),
|
| - iteration_done_(!is_valid_top_ && !is_valid_fp_),
|
| - iterator_(isolate, is_valid_top_, is_valid_fp_ ? fp : NULL, sp) {
|
| + StackFrameIteratorBase(isolate, false),
|
| + low_bound_(low_bound), high_bound_(high_bound) {
|
| + StackFrame::State state;
|
| + StackFrame::Type type;
|
| + ThreadLocalTop* top = isolate->thread_local_top();
|
| + if (IsValidTop(top)) {
|
| + type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state);
|
| + } else if (IsValidStackAddress(fp)) {
|
| + ASSERT(fp != NULL);
|
| + state.fp = fp;
|
| + state.sp = sp;
|
| + state.pc_address = ResolveReturnAddressLocation(
|
| + reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp)));
|
| + type = StackFrame::ComputeType(this, &state);
|
| + } else {
|
| + return;
|
| + }
|
| + if (SingletonFor(type) == NULL) return;
|
| + frame_ = SingletonFor(type, &state);
|
| +
|
| if (!done()) Advance();
|
| }
|
|
|
|
|
| -bool SafeStackFrameIterator::IsValidTop(Isolate* isolate,
|
| - Address low_bound, Address high_bound) {
|
| - ThreadLocalTop* top = isolate->thread_local_top();
|
| +bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const {
|
| Address fp = Isolate::c_entry_fp(top);
|
| - ExitFrameValidator validator(low_bound, high_bound);
|
| - if (!validator.IsValidFP(fp)) return false;
|
| + if (!IsValidExitFrame(fp)) return false;
|
| + // There should be at least one JS_ENTRY stack handler.
|
| return Isolate::handler(top) != NULL;
|
| }
|
|
|
|
|
| void SafeStackFrameIterator::AdvanceOneFrame() {
|
| ASSERT(!done());
|
| - StackFrame* last_frame = iterator_.frame();
|
| + StackFrame* last_frame = frame_;
|
| Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
|
| - // Before advancing to the next stack frame, perform pointer validity tests
|
| - iteration_done_ = !IsValidFrame(last_frame) ||
|
| - !IsValidCaller(last_frame);
|
| - if (iteration_done_) return;
|
| + // Before advancing to the next stack frame, perform pointer validity tests.
|
| + if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) {
|
| + frame_ = NULL;
|
| + return;
|
| + }
|
|
|
| - iterator_.Advance();
|
| - if (iterator_.done()) return;
|
| - // Check that we have actually moved to the previous frame in the stack
|
| - StackFrame* prev_frame = iterator_.frame();
|
| - iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_fp;
|
| + // Advance to the previous frame.
|
| + StackFrame::State state;
|
| + StackFrame::Type type = frame_->GetCallerState(&state);
|
| + frame_ = SingletonFor(type, &state);
|
| + if (frame_ == NULL) return;
|
| +
|
| + // Check that we have actually moved to the previous frame in the stack.
|
| + if (frame_->sp() < last_sp || frame_->fp() < last_fp) {
|
| + frame_ = NULL;
|
| + }
|
| }
|
|
|
|
|
| @@ -322,8 +296,7 @@ bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
|
| // sure that caller FP address is valid.
|
| Address caller_fp = Memory::Address_at(
|
| frame->fp() + EntryFrameConstants::kCallerFPOffset);
|
| - ExitFrameValidator validator(stack_validator_);
|
| - if (!validator.IsValidFP(caller_fp)) return false;
|
| + if (!IsValidExitFrame(caller_fp)) return false;
|
| } else if (frame->is_arguments_adaptor()) {
|
| // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
|
| // the number of arguments is stored on stack as Smi. We need to check
|
| @@ -336,7 +309,20 @@ bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
|
| }
|
| frame->ComputeCallerState(&state);
|
| return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
|
| - iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL;
|
| + SingletonFor(frame->GetCallerState(&state)) != NULL;
|
| +}
|
| +
|
| +
|
| +bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const {
|
| + if (!IsValidStackAddress(fp)) return false;
|
| + Address sp = ExitFrame::ComputeStackPointer(fp);
|
| + if (!IsValidStackAddress(sp)) return false;
|
| + StackFrame::State state;
|
| + ExitFrame::FillState(fp, sp, &state);
|
| + if (!IsValidStackAddress(reinterpret_cast<Address>(state.pc_address))) {
|
| + return false;
|
| + }
|
| + return *state.pc_address != NULL;
|
| }
|
|
|
|
|
| @@ -344,7 +330,7 @@ void SafeStackFrameIterator::Advance() {
|
| while (true) {
|
| AdvanceOneFrame();
|
| if (done()) return;
|
| - if (iterator_.frame()->is_java_script()) return;
|
| + if (frame_->is_java_script()) return;
|
| }
|
| }
|
|
|
| @@ -408,7 +394,7 @@ void StackFrame::SetReturnAddressLocationResolver(
|
| }
|
|
|
|
|
| -StackFrame::Type StackFrame::ComputeType(const StackFrameIterator* iterator,
|
| +StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
|
| State* state) {
|
| ASSERT(state->fp != NULL);
|
| if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
|
|
|