Commit 52d848bc authored by yurys@chromium.org's avatar yurys@chromium.org

Extract StackFrameIteratorBase

This change introduces StackFrameIteratorBase which owns singleton frame instances and encapsulates some basic iterator functionality. It has two actual implementations: StackFrameIterator and SafeStackFrameIterator.

All logic specific to frame iteration at a random point (basically checks that fp and sp extracted from stack frames are within current stack boundaries) used only by CPU profiler is now concentrated in SafeStackFrameIterator.

Generic stack iteration used in all other places is put into StackFrameIterator. Also this iterator unlike SafeStackFrameIterator iterates through stack handlers.

StackAddressValidator and ExitFrameValidator classes were removed in favor of inline checks and simple methods.

BUG=None
R=loislo@chromium.org, svenpanne@chromium.org

Review URL: https://codereview.chromium.org/17819003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15349 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 4aeccdb2
......@@ -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<JavaScriptFrame*>(frame);
ASSERT(!done());
ASSERT(frame_->is_java_script());
return static_cast<JavaScriptFrame*>(frame_);
}
......
......@@ -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)) {
......
......@@ -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_;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment