summaryrefslogtreecommitdiff
path: root/src/3rdparty/v8/src/frames.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/v8/src/frames.h')
-rw-r--r--src/3rdparty/v8/src/frames.h854
1 files changed, 854 insertions, 0 deletions
diff --git a/src/3rdparty/v8/src/frames.h b/src/3rdparty/v8/src/frames.h
new file mode 100644
index 0000000..d6307f0
--- /dev/null
+++ b/src/3rdparty/v8/src/frames.h
@@ -0,0 +1,854 @@
+// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_FRAMES_H_
+#define V8_FRAMES_H_
+
+#include "handles.h"
+#include "safepoint-table.h"
+
+namespace v8 {
+namespace internal {
+
+typedef uint32_t RegList;
+
+// Get the number of registers in a given register list.
+int NumRegs(RegList list);
+
+// Return the code of the n-th saved register available to JavaScript.
+int JSCallerSavedCode(int n);
+
+
+// Forward declarations.
+class StackFrameIterator;
+class ThreadLocalTop;
+class Isolate;
+
+class PcToCodeCache {
+ public:
+ struct PcToCodeCacheEntry {
+ Address pc;
+ Code* code;
+ SafepointEntry safepoint_entry;
+ };
+
+ explicit PcToCodeCache(Isolate* isolate) : isolate_(isolate) {
+ Flush();
+ }
+
+ Code* GcSafeFindCodeForPc(Address pc);
+ Code* GcSafeCastToCode(HeapObject* object, Address pc);
+
+ void Flush() {
+ memset(&cache_[0], 0, sizeof(cache_));
+ }
+
+ PcToCodeCacheEntry* GetCacheEntry(Address pc);
+
+ private:
+ PcToCodeCacheEntry* cache(int index) { return &cache_[index]; }
+
+ Isolate* isolate_;
+
+ static const int kPcToCodeCacheSize = 1024;
+ PcToCodeCacheEntry cache_[kPcToCodeCacheSize];
+
+ DISALLOW_COPY_AND_ASSIGN(PcToCodeCache);
+};
+
+
+class StackHandler BASE_EMBEDDED {
+ public:
+ enum State {
+ ENTRY,
+ TRY_CATCH,
+ TRY_FINALLY
+ };
+
+ // Get the address of this stack handler.
+ inline Address address() const;
+
+ // Get the next stack handler in the chain.
+ inline StackHandler* next() const;
+
+ // Tells whether the given address is inside this handler.
+ inline bool includes(Address address) const;
+
+ // Garbage collection support.
+ inline void Iterate(ObjectVisitor* v, Code* holder) const;
+
+ // Conversion support.
+ static inline StackHandler* FromAddress(Address address);
+
+ // Testers
+ bool is_entry() { return state() == ENTRY; }
+ bool is_try_catch() { return state() == TRY_CATCH; }
+ bool is_try_finally() { return state() == TRY_FINALLY; }
+
+ private:
+ // Accessors.
+ inline State state() const;
+
+ inline Address* pc_address() const;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
+};
+
+
+#define STACK_FRAME_TYPE_LIST(V) \
+ V(ENTRY, EntryFrame) \
+ V(ENTRY_CONSTRUCT, EntryConstructFrame) \
+ V(EXIT, ExitFrame) \
+ V(JAVA_SCRIPT, JavaScriptFrame) \
+ V(OPTIMIZED, OptimizedFrame) \
+ V(INTERNAL, InternalFrame) \
+ V(CONSTRUCT, ConstructFrame) \
+ V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
+
+
+// Abstract base class for all stack frames.
+class StackFrame BASE_EMBEDDED {
+ public:
+#define DECLARE_TYPE(type, ignore) type,
+ enum Type {
+ NONE = 0,
+ STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
+ NUMBER_OF_TYPES
+ };
+#undef DECLARE_TYPE
+
+ // Opaque data type for identifying stack frames. Used extensively
+ // by the debugger.
+ // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
+ // has correct value range (see Issue 830 for more details).
+ enum Id {
+ ID_MIN_VALUE = kMinInt,
+ ID_MAX_VALUE = kMaxInt,
+ NO_ID = 0
+ };
+
+ struct State {
+ State() : sp(NULL), fp(NULL), pc_address(NULL) { }
+ Address sp;
+ Address fp;
+ Address* pc_address;
+ };
+
+ // Copy constructor; it breaks the connection to host iterator
+ // (as an iterator usually lives on stack).
+ StackFrame(const StackFrame& original) {
+ this->state_ = original.state_;
+ this->iterator_ = NULL;
+ this->isolate_ = original.isolate_;
+ }
+
+ // Type testers.
+ bool is_entry() const { return type() == ENTRY; }
+ bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
+ bool is_exit() const { return type() == EXIT; }
+ bool is_optimized() const { return type() == OPTIMIZED; }
+ bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
+ bool is_internal() const { return type() == INTERNAL; }
+ bool is_construct() const { return type() == CONSTRUCT; }
+ virtual bool is_standard() const { return false; }
+
+ bool is_java_script() const {
+ Type type = this->type();
+ return (type == JAVA_SCRIPT) || (type == OPTIMIZED);
+ }
+
+ // Accessors.
+ Address sp() const { return state_.sp; }
+ Address fp() const { return state_.fp; }
+ Address caller_sp() const { return GetCallerStackPointer(); }
+
+ Address pc() const { return *pc_address(); }
+ void set_pc(Address pc) { *pc_address() = pc; }
+
+ virtual void SetCallerFp(Address caller_fp) = 0;
+
+ Address* pc_address() const { return state_.pc_address; }
+
+ // Get the id of this stack frame.
+ Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
+
+ // Checks if this frame includes any stack handlers.
+ bool HasHandler() const;
+
+ // Get the type of this frame.
+ virtual Type type() const = 0;
+
+ // Get the code associated with this frame.
+ // This method could be called during marking phase of GC.
+ virtual Code* unchecked_code() const = 0;
+
+ // Get the code associated with this frame.
+ Code* LookupCode() const {
+ return GetContainingCode(isolate(), pc());
+ }
+
+ // Get the code object that contains the given pc.
+ static inline Code* GetContainingCode(Isolate* isolate, Address pc);
+
+ // Get the code object containing the given pc and fill in the
+ // safepoint entry and the number of stack slots. The pc must be at
+ // a safepoint.
+ static Code* GetSafepointData(Isolate* isolate,
+ Address pc,
+ SafepointEntry* safepoint_entry,
+ unsigned* stack_slots);
+
+ virtual void Iterate(ObjectVisitor* v) const = 0;
+ static void IteratePc(ObjectVisitor* v, Address* pc_address, Code* holder);
+
+
+ // Printing support.
+ enum PrintMode { OVERVIEW, DETAILS };
+ virtual void Print(StringStream* accumulator,
+ PrintMode mode,
+ int index) const { }
+
+ protected:
+ inline explicit StackFrame(StackFrameIterator* iterator);
+ virtual ~StackFrame() { }
+
+ Isolate* isolate() const { return isolate_; }
+
+ // Compute the stack pointer for the calling frame.
+ virtual Address GetCallerStackPointer() const = 0;
+
+ // Printing support.
+ static void PrintIndex(StringStream* accumulator,
+ PrintMode mode,
+ int index);
+
+ // Get the top handler from the current stack iterator.
+ inline StackHandler* top_handler() const;
+
+ // Compute the stack frame type for the given state.
+ static Type ComputeType(Isolate* isolate, State* state);
+
+ private:
+ const StackFrameIterator* iterator_;
+ Isolate* isolate_;
+ State state_;
+
+ // Fill in the state of the calling frame.
+ virtual void ComputeCallerState(State* state) const = 0;
+
+ // Get the type and the state of the calling frame.
+ virtual Type GetCallerState(State* state) const;
+
+ static const intptr_t kIsolateTag = 1;
+
+ friend class StackFrameIterator;
+ friend class StackHandlerIterator;
+ friend class SafeStackFrameIterator;
+
+ private:
+ void operator=(const StackFrame& original);
+};
+
+
+// Entry frames are used to enter JavaScript execution from C.
+class EntryFrame: public StackFrame {
+ public:
+ virtual Type type() const { return ENTRY; }
+
+ virtual Code* unchecked_code() const;
+
+ // Garbage collection support.
+ virtual void Iterate(ObjectVisitor* v) const;
+
+ static EntryFrame* cast(StackFrame* frame) {
+ ASSERT(frame->is_entry());
+ return static_cast<EntryFrame*>(frame);
+ }
+ virtual void SetCallerFp(Address caller_fp);
+
+ protected:
+ explicit EntryFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
+
+ // The caller stack pointer for entry frames is always zero. The
+ // real information about the caller frame is available through the
+ // link to the top exit frame.
+ virtual Address GetCallerStackPointer() const { return 0; }
+
+ private:
+ virtual void ComputeCallerState(State* state) const;
+ virtual Type GetCallerState(State* state) const;
+
+ friend class StackFrameIterator;
+};
+
+
+class EntryConstructFrame: public EntryFrame {
+ public:
+ virtual Type type() const { return ENTRY_CONSTRUCT; }
+
+ virtual Code* unchecked_code() const;
+
+ static EntryConstructFrame* cast(StackFrame* frame) {
+ ASSERT(frame->is_entry_construct());
+ return static_cast<EntryConstructFrame*>(frame);
+ }
+
+ protected:
+ explicit EntryConstructFrame(StackFrameIterator* iterator)
+ : EntryFrame(iterator) { }
+
+ private:
+ friend class StackFrameIterator;
+};
+
+
+// Exit frames are used to exit JavaScript execution and go to C.
+class ExitFrame: public StackFrame {
+ public:
+ virtual Type type() const { return EXIT; }
+
+ virtual Code* unchecked_code() const;
+
+ Object*& code_slot() const;
+
+ // Garbage collection support.
+ virtual void Iterate(ObjectVisitor* v) const;
+
+ virtual void SetCallerFp(Address caller_fp);
+
+ static ExitFrame* cast(StackFrame* frame) {
+ ASSERT(frame->is_exit());
+ return static_cast<ExitFrame*>(frame);
+ }
+
+ // Compute the state and type of an exit frame given a frame
+ // pointer. Used when constructing the first stack frame seen by an
+ // iterator and the frames following entry frames.
+ static Type GetStateForFramePointer(Address fp, State* state);
+ static Address ComputeStackPointer(Address fp);
+ static void FillState(Address fp, Address sp, State* state);
+
+ protected:
+ explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
+
+ virtual Address GetCallerStackPointer() const;
+
+ private:
+ virtual void ComputeCallerState(State* state) const;
+
+ friend class StackFrameIterator;
+};
+
+
+class StandardFrame: public StackFrame {
+ public:
+ // Testers.
+ virtual bool is_standard() const { return true; }
+
+ // Accessors.
+ inline Object* context() const;
+
+ // Access the expressions in the stack frame including locals.
+ inline Object* GetExpression(int index) const;
+ inline void SetExpression(int index, Object* value);
+ int ComputeExpressionsCount() const;
+
+ virtual void SetCallerFp(Address caller_fp);
+
+ static StandardFrame* cast(StackFrame* frame) {
+ ASSERT(frame->is_standard());
+ return static_cast<StandardFrame*>(frame);
+ }
+
+ protected:
+ explicit StandardFrame(StackFrameIterator* iterator)
+ : StackFrame(iterator) { }
+
+ virtual void ComputeCallerState(State* state) const;
+
+ // Accessors.
+ inline Address caller_fp() const;
+ inline Address caller_pc() const;
+
+ // Computes the address of the PC field in the standard frame given
+ // by the provided frame pointer.
+ static inline Address ComputePCAddress(Address fp);
+
+ // Iterate over expression stack including stack handlers, locals,
+ // and parts of the fixed part including context and code fields.
+ void IterateExpressions(ObjectVisitor* v) const;
+
+ // Returns the address of the n'th expression stack element.
+ Address GetExpressionAddress(int n) const;
+
+ // Determines if the n'th expression stack element is in a stack
+ // handler or not. Requires traversing all handlers in this frame.
+ bool IsExpressionInsideHandler(int n) const;
+
+ // Determines if the standard frame for the given frame pointer is
+ // an arguments adaptor frame.
+ static inline bool IsArgumentsAdaptorFrame(Address fp);
+
+ // Determines if the standard frame for the given frame pointer is a
+ // construct frame.
+ static inline bool IsConstructFrame(Address fp);
+
+ private:
+ friend class StackFrame;
+ friend class StackFrameIterator;
+};
+
+
+class FrameSummary BASE_EMBEDDED {
+ public:
+ FrameSummary(Object* receiver,
+ JSFunction* function,
+ Code* code,
+ int offset,
+ bool is_constructor)
+ : receiver_(receiver),
+ function_(function),
+ code_(code),
+ offset_(offset),
+ is_constructor_(is_constructor) { }
+ Handle<Object> receiver() { return receiver_; }
+ Handle<JSFunction> function() { return function_; }
+ Handle<Code> code() { return code_; }
+ Address pc() { return code_->address() + offset_; }
+ int offset() { return offset_; }
+ bool is_constructor() { return is_constructor_; }
+
+ void Print();
+
+ private:
+ Handle<Object> receiver_;
+ Handle<JSFunction> function_;
+ Handle<Code> code_;
+ int offset_;
+ bool is_constructor_;
+};
+
+
+class JavaScriptFrame: public StandardFrame {
+ public:
+ virtual Type type() const { return JAVA_SCRIPT; }
+
+ // Accessors.
+ inline Object* function() const;
+ inline Object* receiver() const;
+ inline void set_receiver(Object* value);
+
+ // Access the parameters.
+ Object* GetParameter(int index) const;
+ int ComputeParametersCount() const;
+
+ // Check if this frame is a constructor frame invoked through 'new'.
+ bool IsConstructor() const;
+
+ // Check if this frame has "adapted" arguments in the sense that the
+ // actual passed arguments are available in an arguments adaptor
+ // frame below it on the stack.
+ inline bool has_adapted_arguments() const;
+
+ // Garbage collection support.
+ virtual void Iterate(ObjectVisitor* v) const;
+
+ // Printing support.
+ virtual void Print(StringStream* accumulator,
+ PrintMode mode,
+ int index) const;
+
+ // Determine the code for the frame.
+ virtual Code* unchecked_code() const;
+
+ // Return a list with JSFunctions of this frame.
+ virtual void GetFunctions(List<JSFunction*>* functions);
+
+ // Build a list with summaries for this frame including all inlined frames.
+ virtual void Summarize(List<FrameSummary>* frames);
+
+ static JavaScriptFrame* cast(StackFrame* frame) {
+ ASSERT(frame->is_java_script());
+ return static_cast<JavaScriptFrame*>(frame);
+ }
+
+ protected:
+ explicit JavaScriptFrame(StackFrameIterator* iterator)
+ : StandardFrame(iterator) { }
+
+ virtual Address GetCallerStackPointer() const;
+
+ // Garbage collection support. Iterates over incoming arguments,
+ // receiver, and any callee-saved registers.
+ void IterateArguments(ObjectVisitor* v) const;
+
+ private:
+ inline Object* function_slot_object() const;
+
+ friend class StackFrameIterator;
+ friend class StackTracer;
+};
+
+
+class OptimizedFrame : public JavaScriptFrame {
+ public:
+ virtual Type type() const { return OPTIMIZED; }
+
+ // GC support.
+ virtual void Iterate(ObjectVisitor* v) const;
+
+ // Return a list with JSFunctions of this frame.
+ // The functions are ordered bottom-to-top (i.e. functions.last()
+ // is the top-most activation)
+ virtual void GetFunctions(List<JSFunction*>* functions);
+
+ virtual void Summarize(List<FrameSummary>* frames);
+
+ DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
+
+ protected:
+ explicit OptimizedFrame(StackFrameIterator* iterator)
+ : JavaScriptFrame(iterator) { }
+
+ private:
+ friend class StackFrameIterator;
+};
+
+
+// Arguments adaptor frames are automatically inserted below
+// JavaScript frames when the actual number of parameters does not
+// match the formal number of parameters.
+class ArgumentsAdaptorFrame: public JavaScriptFrame {
+ public:
+ virtual Type type() const { return ARGUMENTS_ADAPTOR; }
+
+ // Determine the code for the frame.
+ virtual Code* unchecked_code() const;
+
+ static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
+ ASSERT(frame->is_arguments_adaptor());
+ return static_cast<ArgumentsAdaptorFrame*>(frame);
+ }
+
+ // Printing support.
+ virtual void Print(StringStream* accumulator,
+ PrintMode mode,
+ int index) const;
+ protected:
+ explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator)
+ : JavaScriptFrame(iterator) { }
+
+ virtual Address GetCallerStackPointer() const;
+
+ private:
+ friend class StackFrameIterator;
+};
+
+
+class InternalFrame: public StandardFrame {
+ public:
+ virtual Type type() const { return INTERNAL; }
+
+ // Garbage collection support.
+ virtual void Iterate(ObjectVisitor* v) const;
+
+ // Determine the code for the frame.
+ virtual Code* unchecked_code() const;
+
+ static InternalFrame* cast(StackFrame* frame) {
+ ASSERT(frame->is_internal());
+ return static_cast<InternalFrame*>(frame);
+ }
+
+ protected:
+ explicit InternalFrame(StackFrameIterator* iterator)
+ : StandardFrame(iterator) { }
+
+ virtual Address GetCallerStackPointer() const;
+
+ private:
+ friend class StackFrameIterator;
+};
+
+
+// Construct frames are special trampoline frames introduced to handle
+// function invocations through 'new'.
+class ConstructFrame: public InternalFrame {
+ public:
+ virtual Type type() const { return CONSTRUCT; }
+
+ static ConstructFrame* cast(StackFrame* frame) {
+ ASSERT(frame->is_construct());
+ return static_cast<ConstructFrame*>(frame);
+ }
+
+ protected:
+ explicit ConstructFrame(StackFrameIterator* iterator)
+ : InternalFrame(iterator) { }
+
+ private:
+ friend class StackFrameIterator;
+};
+
+
+class StackFrameIterator BASE_EMBEDDED {
+ public:
+ // An iterator that iterates over the current thread's stack,
+ // and uses current isolate.
+ StackFrameIterator();
+
+ // 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);
+
+ // 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.
+ StackFrameIterator(Isolate* isolate, bool use_top, Address fp, Address sp);
+
+ StackFrame* frame() const {
+ ASSERT(!done());
+ return frame_;
+ }
+
+ Isolate* isolate() const { return isolate_; }
+
+ bool done() const { return frame_ == NULL; }
+ void Advance() { (this->*advance_)(); }
+
+ // Go back to the first frame.
+ void Reset();
+
+ private:
+ Isolate* isolate_;
+#define DECLARE_SINGLETON(ignore, type) type type##_;
+ STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
+#undef DECLARE_SINGLETON
+ StackFrame* frame_;
+ StackHandler* handler_;
+ ThreadLocalTop* thread_;
+ Address fp_;
+ Address sp_;
+ void (StackFrameIterator::*advance_)();
+
+ StackHandler* handler() const {
+ ASSERT(!done());
+ return handler_;
+ }
+
+ // Get the type-specific frame singleton in a given state.
+ StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
+ // A helper function, can return a NULL pointer.
+ StackFrame* SingletonFor(StackFrame::Type type);
+
+ void AdvanceWithHandler();
+ void AdvanceWithoutHandler();
+
+ friend class StackFrame;
+ friend class SafeStackFrameIterator;
+ DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
+};
+
+
+// Iterator that supports iterating through all JavaScript frames.
+template<typename Iterator>
+class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
+ public:
+ JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
+
+ inline explicit JavaScriptFrameIteratorTemp(Isolate* isolate);
+
+ // Skip frames until the frame with the given id is reached.
+ explicit JavaScriptFrameIteratorTemp(StackFrame::Id id) { AdvanceToId(id); }
+
+ inline JavaScriptFrameIteratorTemp(Isolate* isolate, StackFrame::Id id);
+
+ JavaScriptFrameIteratorTemp(Address fp, Address sp,
+ Address low_bound, Address high_bound) :
+ iterator_(fp, sp, low_bound, high_bound) {
+ if (!done()) Advance();
+ }
+
+ JavaScriptFrameIteratorTemp(Isolate* isolate,
+ Address fp, Address sp,
+ Address low_bound, Address high_bound) :
+ iterator_(isolate, fp, sp, low_bound, high_bound) {
+ if (!done()) Advance();
+ }
+
+ inline JavaScriptFrame* frame() const;
+
+ bool done() const { return iterator_.done(); }
+ void Advance();
+
+ // Advance to the frame holding the arguments for the current
+ // frame. This only affects the current frame if it has adapted
+ // arguments.
+ void AdvanceToArgumentsFrame();
+
+ // Go back to the first frame.
+ void Reset();
+
+ private:
+ inline void AdvanceToId(StackFrame::Id id);
+
+ Iterator iterator_;
+};
+
+
+typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
+
+
+// NOTE: The stack trace frame iterator is an iterator that only
+// traverse proper JavaScript frames; that is JavaScript frames that
+// have proper JavaScript functions. This excludes the problematic
+// functions in runtime.js.
+class StackTraceFrameIterator: public JavaScriptFrameIterator {
+ public:
+ StackTraceFrameIterator();
+ explicit StackTraceFrameIterator(Isolate* isolate);
+ void Advance();
+
+ private:
+ bool IsValidFrame();
+};
+
+
+class SafeStackFrameIterator BASE_EMBEDDED {
+ public:
+ SafeStackFrameIterator(Isolate* isolate,
+ Address fp, Address sp,
+ Address low_bound, Address high_bound);
+
+ StackFrame* frame() const {
+ ASSERT(is_working_iterator_);
+ return iterator_.frame();
+ }
+
+ bool done() const { return iteration_done_ ? true : iterator_.done(); }
+
+ void Advance();
+ void Reset();
+
+ static bool is_active(Isolate* isolate);
+
+ static bool IsWithinBounds(
+ Address low_bound, Address high_bound, Address addr) {
+ return low_bound <= addr && addr <= high_bound;
+ }
+
+ private:
+ 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);
+ }
+ bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
+ bool IsValidFrame(StackFrame* frame) const;
+ bool IsValidCaller(StackFrame* frame);
+ static bool IsValidTop(Isolate* isolate,
+ Address low_bound, Address high_bound);
+
+ // This is a nasty hack to make sure the active count is incremented
+ // before the constructor for the embedded iterator is invoked. This
+ // is needed because the constructor will start looking at frames
+ // right away and we need to make sure it doesn't start inspecting
+ // heap objects.
+ class ActiveCountMaintainer BASE_EMBEDDED {
+ public:
+ explicit ActiveCountMaintainer(Isolate* isolate);
+ ~ActiveCountMaintainer();
+ private:
+ Isolate* isolate_;
+ };
+
+ ActiveCountMaintainer maintainer_;
+ StackAddressValidator stack_validator_;
+ const bool is_valid_top_;
+ const bool is_valid_fp_;
+ const bool is_working_iterator_;
+ bool iteration_done_;
+ StackFrameIterator iterator_;
+};
+
+
+#ifdef ENABLE_LOGGING_AND_PROFILING
+typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
+ SafeJavaScriptFrameIterator;
+
+
+class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
+ public:
+ explicit SafeStackTraceFrameIterator(Isolate* isolate,
+ Address fp, Address sp,
+ Address low_bound, Address high_bound);
+ void Advance();
+};
+#endif
+
+
+class StackFrameLocator BASE_EMBEDDED {
+ public:
+ // Find the nth JavaScript frame on the stack. The caller must
+ // guarantee that such a frame exists.
+ JavaScriptFrame* FindJavaScriptFrame(int n);
+
+ private:
+ StackFrameIterator iterator_;
+};
+
+
+// Reads all frames on the current stack and copies them into the current
+// zone memory.
+Vector<StackFrame*> CreateStackMap();
+
+} } // namespace v8::internal
+
+#endif // V8_FRAMES_H_