| Index: src/frames.cc
|
| diff --git a/src/frames.cc b/src/frames.cc
|
| index 53f510849ec0cd3ebb13e4397c1477637d7eebd7..0ca6991488464994be3300cf56e1ec47978036a4 100644
|
| --- a/src/frames.cc
|
| +++ b/src/frames.cc
|
| @@ -88,39 +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) {
|
| - Reset();
|
| + can_access_heap_objects_(can_access_heap_objects) {
|
| }
|
| -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) {
|
| - Reset();
|
| -}
|
| -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_(use_top ? &StackFrameIterator::AdvanceWithHandler :
|
| - &StackFrameIterator::AdvanceWithoutHandler) {
|
| - 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
|
| @@ -143,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(isolate(), &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);
|
| @@ -183,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;
|
|
|
| @@ -202,6 +172,33 @@ StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) {
|
| // -------------------------------------------------------------------------
|
|
|
|
|
| +JavaScriptFrameIterator::JavaScriptFrameIterator(
|
| + Isolate* isolate, StackFrame::Id id)
|
| + : iterator_(isolate) {
|
| + while (!done()) {
|
| + Advance();
|
| + if (frame()->id() == id) return;
|
| + }
|
| +}
|
| +
|
| +
|
| +void JavaScriptFrameIterator::Advance() {
|
| + do {
|
| + iterator_.Advance();
|
| + } while (!iterator_.done() && !iterator_.frame()->is_java_script());
|
| +}
|
| +
|
| +
|
| +void JavaScriptFrameIterator::AdvanceToArgumentsFrame() {
|
| + if (!frame()->has_adapted_arguments()) return;
|
| + iterator_.Advance();
|
| + ASSERT(iterator_.frame()->is_arguments_adaptor());
|
| +}
|
| +
|
| +
|
| +// -------------------------------------------------------------------------
|
| +
|
| +
|
| StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
|
| : JavaScriptFrameIterator(isolate) {
|
| if (!done() && !IsValidFrame()) Advance();
|
| @@ -228,85 +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::ActiveCountMaintainer::ActiveCountMaintainer(
|
| - Isolate* isolate)
|
| - : isolate_(isolate) {
|
| - isolate_->set_safe_stack_iterator_counter(
|
| - isolate_->safe_stack_iterator_counter() + 1);
|
| -}
|
| -
|
| -
|
| -SafeStackFrameIterator::ActiveCountMaintainer::~ActiveCountMaintainer() {
|
| - isolate_->set_safe_stack_iterator_counter(
|
| - isolate_->safe_stack_iterator_counter() - 1);
|
| -}
|
| -
|
| -
|
| SafeStackFrameIterator::SafeStackFrameIterator(
|
| Isolate* isolate,
|
| Address fp, Address sp, Address low_bound, Address high_bound) :
|
| - maintainer_(isolate),
|
| - stack_validator_(low_bound, high_bound),
|
| - is_valid_top_(IsValidTop(isolate, low_bound, high_bound)),
|
| - is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)),
|
| - is_working_iterator_(is_valid_top_ || is_valid_fp_),
|
| - iteration_done_(!is_working_iterator_),
|
| - 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);
|
|
|
| -bool SafeStackFrameIterator::is_active(Isolate* isolate) {
|
| - return isolate->safe_stack_iterator_counter() > 0;
|
| + 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::Advance() {
|
| - ASSERT(is_working_iterator_);
|
| +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) ||
|
| - !CanIterateHandles(last_frame, iterator_.handler()) ||
|
| - !IsValidCaller(last_frame);
|
| - if (iteration_done_) 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;
|
| -}
|
| + // Before advancing to the next stack frame, perform pointer validity tests.
|
| + if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) {
|
| + frame_ = NULL;
|
| + return;
|
| + }
|
|
|
| + // Advance to the previous frame.
|
| + StackFrame::State state;
|
| + StackFrame::Type type = frame_->GetCallerState(&state);
|
| + frame_ = SingletonFor(type, &state);
|
| + if (frame_ == NULL) return;
|
|
|
| -bool SafeStackFrameIterator::CanIterateHandles(StackFrame* frame,
|
| - StackHandler* handler) {
|
| - // If StackIterator iterates over StackHandles, verify that
|
| - // StackHandlerIterator can be instantiated (see StackHandlerIterator
|
| - // constructor.)
|
| - return !is_valid_top_ || (frame->sp() <= handler->address());
|
| + // Check that we have actually moved to the previous frame in the stack.
|
| + if (frame_->sp() < last_sp || frame_->fp() < last_fp) {
|
| + frame_ = NULL;
|
| + }
|
| }
|
|
|
|
|
| @@ -323,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
|
| @@ -337,38 +309,35 @@ 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;
|
| }
|
|
|
|
|
| -void SafeStackFrameIterator::Reset() {
|
| - if (is_working_iterator_) {
|
| - iterator_.Reset();
|
| - iteration_done_ = false;
|
| +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;
|
| }
|
|
|
|
|
| -// -------------------------------------------------------------------------
|
| -
|
| -
|
| -SafeStackTraceFrameIterator::SafeStackTraceFrameIterator(
|
| - Isolate* isolate,
|
| - Address fp, Address sp, Address low_bound, Address high_bound) :
|
| - SafeJavaScriptFrameIterator(isolate, fp, sp, low_bound, high_bound) {
|
| - if (!done() && !frame()->is_java_script()) Advance();
|
| -}
|
| -
|
| -
|
| -void SafeStackTraceFrameIterator::Advance() {
|
| +void SafeStackFrameIterator::Advance() {
|
| while (true) {
|
| - SafeJavaScriptFrameIterator::Advance();
|
| + AdvanceOneFrame();
|
| if (done()) return;
|
| - if (frame()->is_java_script()) return;
|
| + if (frame_->is_java_script()) return;
|
| }
|
| }
|
|
|
|
|
| +// -------------------------------------------------------------------------
|
| +
|
| +
|
| Code* StackFrame::GetSafepointData(Isolate* isolate,
|
| Address inner_pointer,
|
| SafepointEntry* safepoint_entry,
|
| @@ -425,7 +394,8 @@ void StackFrame::SetReturnAddressLocationResolver(
|
| }
|
|
|
|
|
| -StackFrame::Type StackFrame::ComputeType(Isolate* isolate, State* state) {
|
| +StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
|
| + State* state) {
|
| ASSERT(state->fp != NULL);
|
| if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
|
| return ARGUMENTS_ADAPTOR;
|
| @@ -440,8 +410,9 @@ StackFrame::Type StackFrame::ComputeType(Isolate* isolate, State* state) {
|
| // frames as normal JavaScript frames to avoid having to look
|
| // into the heap to determine the state. This is safe as long
|
| // as nobody tries to GC...
|
| - if (SafeStackFrameIterator::is_active(isolate)) return JAVA_SCRIPT;
|
| - Code::Kind kind = GetContainingCode(isolate, *(state->pc_address))->kind();
|
| + if (!iterator->can_access_heap_objects_) return JAVA_SCRIPT;
|
| + Code::Kind kind = GetContainingCode(iterator->isolate(),
|
| + *(state->pc_address))->kind();
|
| ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION);
|
| return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT;
|
| }
|
| @@ -449,10 +420,16 @@ StackFrame::Type StackFrame::ComputeType(Isolate* isolate, State* state) {
|
| }
|
|
|
|
|
| +#ifdef DEBUG
|
| +bool StackFrame::can_access_heap_objects() const {
|
| + return iterator_->can_access_heap_objects_;
|
| +}
|
| +#endif
|
| +
|
|
|
| StackFrame::Type StackFrame::GetCallerState(State* state) const {
|
| ComputeCallerState(state);
|
| - return ComputeType(isolate(), state);
|
| + return ComputeType(iterator_, state);
|
| }
|
|
|
|
|
| @@ -545,6 +522,11 @@ StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
|
| }
|
|
|
|
|
| +Address ExitFrame::ComputeStackPointer(Address fp) {
|
| + return Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
|
| +}
|
| +
|
| +
|
| void ExitFrame::FillState(Address fp, Address sp, State* state) {
|
| state->sp = sp;
|
| state->fp = fp;
|
| @@ -607,7 +589,7 @@ bool StandardFrame::IsExpressionInsideHandler(int n) const {
|
| void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const {
|
| // Make sure that we're not doing "safe" stack frame iteration. We cannot
|
| // possibly find pointers in optimized frames in that state.
|
| - ASSERT(!SafeStackFrameIterator::is_active(isolate()));
|
| + ASSERT(can_access_heap_objects());
|
|
|
| // Compute the safepoint information.
|
| unsigned stack_slots = 0;
|
| @@ -734,12 +716,12 @@ int JavaScriptFrame::GetArgumentsLength() const {
|
|
|
| Code* JavaScriptFrame::unchecked_code() const {
|
| JSFunction* function = JSFunction::cast(this->function());
|
| - return function->unchecked_code();
|
| + return function->code();
|
| }
|
|
|
|
|
| int JavaScriptFrame::GetNumberOfIncomingArguments() const {
|
| - ASSERT(!SafeStackFrameIterator::is_active(isolate()) &&
|
| + ASSERT(can_access_heap_objects() &&
|
| isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
|
|
|
| JSFunction* function = JSFunction::cast(this->function());
|
|
|