diff --git a/src/frames-inl.h b/src/frames-inl.h index c22a018fb0..bd652da5c4 100644 --- a/src/frames-inl.h +++ b/src/frames-inl.h @@ -116,7 +116,7 @@ inline Object** StackHandler::code_address() const { } -inline StackFrame::StackFrame(StackFrameIterator* iterator) +inline StackFrame::StackFrame(StackFrameIteratorBase* iterator) : iterator_(iterator), isolate_(iterator_->isolate()) { } @@ -136,22 +136,23 @@ inline Code* StackFrame::GetContainingCode(Isolate* isolate, Address pc) { } -inline EntryFrame::EntryFrame(StackFrameIterator* iterator) +inline EntryFrame::EntryFrame(StackFrameIteratorBase* iterator) : StackFrame(iterator) { } -inline EntryConstructFrame::EntryConstructFrame(StackFrameIterator* iterator) +inline EntryConstructFrame::EntryConstructFrame( + StackFrameIteratorBase* iterator) : EntryFrame(iterator) { } -inline ExitFrame::ExitFrame(StackFrameIterator* iterator) +inline ExitFrame::ExitFrame(StackFrameIteratorBase* iterator) : StackFrame(iterator) { } -inline StandardFrame::StandardFrame(StackFrameIterator* iterator) +inline StandardFrame::StandardFrame(StackFrameIteratorBase* iterator) : StackFrame(iterator) { } @@ -201,7 +202,7 @@ inline bool StandardFrame::IsConstructFrame(Address fp) { } -inline JavaScriptFrame::JavaScriptFrame(StackFrameIterator* iterator) +inline JavaScriptFrame::JavaScriptFrame(StackFrameIteratorBase* iterator) : StandardFrame(iterator) { } @@ -269,32 +270,32 @@ inline Object* JavaScriptFrame::function() const { } -inline StubFrame::StubFrame(StackFrameIterator* iterator) +inline StubFrame::StubFrame(StackFrameIteratorBase* iterator) : StandardFrame(iterator) { } -inline OptimizedFrame::OptimizedFrame(StackFrameIterator* iterator) +inline OptimizedFrame::OptimizedFrame(StackFrameIteratorBase* iterator) : JavaScriptFrame(iterator) { } inline ArgumentsAdaptorFrame::ArgumentsAdaptorFrame( - StackFrameIterator* iterator) : JavaScriptFrame(iterator) { + StackFrameIteratorBase* iterator) : JavaScriptFrame(iterator) { } -inline InternalFrame::InternalFrame(StackFrameIterator* iterator) +inline InternalFrame::InternalFrame(StackFrameIteratorBase* iterator) : StandardFrame(iterator) { } inline StubFailureTrampolineFrame::StubFailureTrampolineFrame( - StackFrameIterator* iterator) : StandardFrame(iterator) { + StackFrameIteratorBase* iterator) : StandardFrame(iterator) { } -inline ConstructFrame::ConstructFrame(StackFrameIterator* iterator) +inline ConstructFrame::ConstructFrame(StackFrameIteratorBase* iterator) : InternalFrame(iterator) { } @@ -325,14 +326,9 @@ inline JavaScriptFrame* JavaScriptFrameIterator::frame() const { inline JavaScriptFrame* SafeStackFrameIterator::frame() const { - ASSERT(!iteration_done_); - // TODO(1233797): The frame hierarchy needs to change. It's - // problematic that we can't use the safe-cast operator to cast to - // the JavaScript frame type, because we may encounter arguments - // adaptor frames. - StackFrame* frame = iterator_.frame(); - ASSERT(frame->is_java_script()); - return static_cast(frame); + ASSERT(!done()); + ASSERT(frame_->is_java_script()); + return static_cast(frame_); } diff --git a/src/frames.cc b/src/frames.cc index acdcbdfb14..0ca6991488 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(); + 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), - can_access_heap_objects_(true) { - 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_(&StackFrameIterator::AdvanceWithoutHandler), - can_access_heap_objects_(false) { - if (use_top || fp != NULL) { - Reset(); - } -} - #undef INITIALIZE_SINGLETON -void StackFrameIterator::AdvanceWithHandler() { +StackFrameIterator::StackFrameIterator(Isolate* isolate) + : StackFrameIteratorBase(isolate, true) { + Reset(isolate->thread_local_top()); +} + + +StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t) + : StackFrameIteratorBase(isolate, true) { + Reset(t); +} + + +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(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
(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(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
(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)) { diff --git a/src/frames.h b/src/frames.h index 91a8b12e28..19e4d609b5 100644 --- a/src/frames.h +++ b/src/frames.h @@ -47,7 +47,7 @@ int JSCallerSavedCode(int n); // Forward declarations. -class StackFrameIterator; +class StackFrameIteratorBase; class ThreadLocalTop; class Isolate; @@ -306,7 +306,7 @@ class StackFrame BASE_EMBEDDED { Isolate* isolate() const { return isolate_; } protected: - inline explicit StackFrame(StackFrameIterator* iterator); + inline explicit StackFrame(StackFrameIteratorBase* iterator); virtual ~StackFrame() { } // Compute the stack pointer for the calling frame. @@ -321,14 +321,14 @@ class StackFrame BASE_EMBEDDED { inline StackHandler* top_handler() const; // Compute the stack frame type for the given state. - static Type ComputeType(const StackFrameIterator* iterator, State* state); + static Type ComputeType(const StackFrameIteratorBase* iterator, State* state); #ifdef DEBUG bool can_access_heap_objects() const; #endif private: - const StackFrameIterator* iterator_; + const StackFrameIteratorBase* iterator_; Isolate* isolate_; State state_; @@ -341,6 +341,7 @@ class StackFrame BASE_EMBEDDED { static const intptr_t kIsolateTag = 1; friend class StackFrameIterator; + friend class StackFrameIteratorBase; friend class StackHandlerIterator; friend class SafeStackFrameIterator; @@ -366,7 +367,7 @@ class EntryFrame: public StackFrame { virtual void SetCallerFp(Address caller_fp); protected: - inline explicit EntryFrame(StackFrameIterator* iterator); + inline explicit EntryFrame(StackFrameIteratorBase* iterator); // The caller stack pointer for entry frames is always zero. The // real information about the caller frame is available through the @@ -377,7 +378,7 @@ class EntryFrame: public StackFrame { virtual void ComputeCallerState(State* state) const; virtual Type GetCallerState(State* state) const; - friend class StackFrameIterator; + friend class StackFrameIteratorBase; }; @@ -393,10 +394,10 @@ class EntryConstructFrame: public EntryFrame { } protected: - inline explicit EntryConstructFrame(StackFrameIterator* iterator); + inline explicit EntryConstructFrame(StackFrameIteratorBase* iterator); private: - friend class StackFrameIterator; + friend class StackFrameIteratorBase; }; @@ -427,14 +428,14 @@ class ExitFrame: public StackFrame { static void FillState(Address fp, Address sp, State* state); protected: - inline explicit ExitFrame(StackFrameIterator* iterator); + inline explicit ExitFrame(StackFrameIteratorBase* iterator); virtual Address GetCallerStackPointer() const; private: virtual void ComputeCallerState(State* state) const; - friend class StackFrameIterator; + friend class StackFrameIteratorBase; }; @@ -460,7 +461,7 @@ class StandardFrame: public StackFrame { } protected: - inline explicit StandardFrame(StackFrameIterator* iterator); + inline explicit StandardFrame(StackFrameIteratorBase* iterator); virtual void ComputeCallerState(State* state) const; @@ -497,7 +498,7 @@ class StandardFrame: public StackFrame { private: friend class StackFrame; - friend class StackFrameIterator; + friend class SafeStackFrameIterator; }; @@ -603,7 +604,7 @@ class JavaScriptFrame: public StandardFrame { bool print_line_number); protected: - inline explicit JavaScriptFrame(StackFrameIterator* iterator); + inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator); virtual Address GetCallerStackPointer() const; @@ -616,7 +617,7 @@ class JavaScriptFrame: public StandardFrame { private: inline Object* function_slot_object() const; - friend class StackFrameIterator; + friend class StackFrameIteratorBase; }; @@ -631,13 +632,13 @@ class StubFrame : public StandardFrame { virtual Code* unchecked_code() const; protected: - inline explicit StubFrame(StackFrameIterator* iterator); + inline explicit StubFrame(StackFrameIteratorBase* iterator); virtual Address GetCallerStackPointer() const; virtual int GetNumberOfIncomingArguments() const; - friend class StackFrameIterator; + friend class StackFrameIteratorBase; }; @@ -660,12 +661,12 @@ class OptimizedFrame : public JavaScriptFrame { DeoptimizationInputData* GetDeoptimizationData(int* deopt_index); protected: - inline explicit OptimizedFrame(StackFrameIterator* iterator); + inline explicit OptimizedFrame(StackFrameIteratorBase* iterator); private: JSFunction* LiteralAt(FixedArray* literal_array, int literal_id); - friend class StackFrameIterator; + friend class StackFrameIteratorBase; }; @@ -690,14 +691,14 @@ class ArgumentsAdaptorFrame: public JavaScriptFrame { int index) const; protected: - inline explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator); + inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator); virtual int GetNumberOfIncomingArguments() const; virtual Address GetCallerStackPointer() const; private: - friend class StackFrameIterator; + friend class StackFrameIteratorBase; }; @@ -717,12 +718,12 @@ class InternalFrame: public StandardFrame { } protected: - inline explicit InternalFrame(StackFrameIterator* iterator); + inline explicit InternalFrame(StackFrameIteratorBase* iterator); virtual Address GetCallerStackPointer() const; private: - friend class StackFrameIterator; + friend class StackFrameIteratorBase; }; @@ -750,12 +751,12 @@ class StubFailureTrampolineFrame: public StandardFrame { protected: inline explicit StubFailureTrampolineFrame( - StackFrameIterator* iterator); + StackFrameIteratorBase* iterator); virtual Address GetCallerStackPointer() const; private: - friend class StackFrameIterator; + friend class StackFrameIteratorBase; }; @@ -771,40 +772,22 @@ class ConstructFrame: public InternalFrame { } protected: - inline explicit ConstructFrame(StackFrameIterator* iterator); + inline explicit ConstructFrame(StackFrameIteratorBase* iterator); private: - friend class StackFrameIterator; + friend class StackFrameIteratorBase; }; -class StackFrameIterator BASE_EMBEDDED { +class StackFrameIteratorBase BASE_EMBEDDED { public: - // An iterator that iterates over the isolate's current thread's stack, - explicit StackFrameIterator(Isolate* isolate); - - // An iterator that iterates over a given thread's stack. - StackFrameIterator(Isolate* isolate, ThreadLocalTop* t); - - StackFrame* frame() const { - ASSERT(!done()); - return frame_; - } - Isolate* isolate() const { return isolate_; } bool done() const { return frame_ == NULL; } - void Advance() { (this->*advance_)(); } - private: - // An iterator that can start from a given FP address. - // If use_top, then work as usual, if fp isn't NULL, use it, - // otherwise, do nothing. This constructor is used to create - // StackFrameIterator for "safe" stack iteration. - StackFrameIterator(Isolate* isolate, bool use_top, Address fp, Address sp); - - // Go back to the first frame. - void Reset(); + protected: + // An iterator that iterates over a given thread's stack. + StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects); Isolate* isolate_; #define DECLARE_SINGLETON(ignore, type) type type##_; @@ -812,10 +795,6 @@ class StackFrameIterator BASE_EMBEDDED { #undef DECLARE_SINGLETON StackFrame* frame_; StackHandler* handler_; - ThreadLocalTop* thread_; - Address fp_; - Address sp_; - void (StackFrameIterator::*advance_)(); const bool can_access_heap_objects_; StackHandler* handler() const { @@ -828,11 +807,29 @@ class StackFrameIterator BASE_EMBEDDED { // A helper function, can return a NULL pointer. StackFrame* SingletonFor(StackFrame::Type type); - void AdvanceWithHandler(); - void AdvanceWithoutHandler(); - + private: friend class StackFrame; - friend class SafeStackFrameIterator; + DISALLOW_COPY_AND_ASSIGN(StackFrameIteratorBase); +}; + + +class StackFrameIterator: public StackFrameIteratorBase { + public: + // An iterator that iterates over the isolate's current thread's stack, + explicit StackFrameIterator(Isolate* isolate); + // An iterator that iterates over a given thread's stack. + StackFrameIterator(Isolate* isolate, ThreadLocalTop* t); + + StackFrame* frame() const { + ASSERT(!done()); + return frame_; + } + void Advance(); + + private: + // Go back to the first frame. + void Reset(ThreadLocalTop* top); + DISALLOW_COPY_AND_ASSIGN(StackFrameIterator); }; @@ -874,61 +871,28 @@ class StackTraceFrameIterator: public JavaScriptFrameIterator { }; -class SafeStackFrameIterator BASE_EMBEDDED { +class SafeStackFrameIterator: public StackFrameIteratorBase { public: SafeStackFrameIterator(Isolate* isolate, Address fp, Address sp, Address low_bound, Address high_bound); inline JavaScriptFrame* frame() const; - - bool done() const { return iteration_done_ || iterator_.done(); } void Advance(); private: void AdvanceOneFrame(); - static bool IsWithinBounds( - Address low_bound, Address high_bound, Address addr) { - return low_bound <= addr && addr <= high_bound; - } - - class StackAddressValidator { - public: - StackAddressValidator(Address low_bound, Address high_bound) - : low_bound_(low_bound), high_bound_(high_bound) { } - bool IsValid(Address addr) const { - return IsWithinBounds(low_bound_, high_bound_, addr); - } - private: - Address low_bound_; - Address high_bound_; - }; - - class ExitFrameValidator { - public: - explicit ExitFrameValidator(const StackAddressValidator& validator) - : validator_(validator) { } - ExitFrameValidator(Address low_bound, Address high_bound) - : validator_(low_bound, high_bound) { } - bool IsValidFP(Address fp); - private: - StackAddressValidator validator_; - }; - bool IsValidStackAddress(Address addr) const { - return stack_validator_.IsValid(addr); + return low_bound_ <= addr && addr <= high_bound_; } bool IsValidFrame(StackFrame* frame) const; bool IsValidCaller(StackFrame* frame); - static bool IsValidTop(Isolate* isolate, - Address low_bound, Address high_bound); + bool IsValidExitFrame(Address fp) const; + bool IsValidTop(ThreadLocalTop* top) const; - StackAddressValidator stack_validator_; - const bool is_valid_top_; - const bool is_valid_fp_; - bool iteration_done_; - StackFrameIterator iterator_; + const Address low_bound_; + const Address high_bound_; };