2008-09-09 20:08:45 +00:00
|
|
|
// Copyright 2006-2008 the V8 project authors. All rights reserved.
|
2008-07-03 15:10:15 +00:00
|
|
|
// 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_
|
|
|
|
|
|
|
|
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 Top;
|
|
|
|
class ThreadLocalTop;
|
|
|
|
|
|
|
|
|
|
|
|
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) 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; }
|
|
|
|
|
|
|
|
// Garbage collection support.
|
|
|
|
void Cook(Code* code);
|
|
|
|
void Uncook(Code* code);
|
|
|
|
|
|
|
|
// TODO(1233780): Get rid of the code slot in stack handlers.
|
|
|
|
static const int kCodeNotPresent = 0;
|
|
|
|
|
|
|
|
private:
|
|
|
|
// Accessors.
|
|
|
|
inline State state() const;
|
|
|
|
|
|
|
|
inline Address pc() const;
|
|
|
|
inline void set_pc(Address value);
|
2008-08-13 09:32:07 +00:00
|
|
|
|
|
|
|
DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
|
2008-07-03 15:10:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#define STACK_FRAME_TYPE_LIST(V) \
|
|
|
|
V(ENTRY, EntryFrame) \
|
|
|
|
V(ENTRY_CONSTRUCT, EntryConstructFrame) \
|
|
|
|
V(EXIT, ExitFrame) \
|
|
|
|
V(EXIT_DEBUG, ExitDebugFrame) \
|
|
|
|
V(JAVA_SCRIPT, JavaScriptFrame) \
|
|
|
|
V(INTERNAL, InternalFrame) \
|
2008-10-10 09:09:38 +00:00
|
|
|
V(CONSTRUCT, ConstructFrame) \
|
2008-07-03 15:10:15 +00:00
|
|
|
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.
|
|
|
|
enum Id { NO_ID = 0 };
|
|
|
|
|
|
|
|
// 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_exit_debug() const { return type() == EXIT_DEBUG; }
|
|
|
|
bool is_java_script() const { return type() == JAVA_SCRIPT; }
|
|
|
|
bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
|
|
|
|
bool is_internal() const { return type() == INTERNAL; }
|
2008-10-10 09:09:38 +00:00
|
|
|
bool is_construct() const { return type() == CONSTRUCT; }
|
2008-07-03 15:10:15 +00:00
|
|
|
virtual bool is_standard() const { return false; }
|
|
|
|
|
|
|
|
// Accessors.
|
|
|
|
Address sp() const { return state_.sp; }
|
|
|
|
Address fp() const { return state_.fp; }
|
|
|
|
Address pp() const { return GetCallerStackPointer(); }
|
|
|
|
|
|
|
|
Address pc() const { return *pc_address(); }
|
|
|
|
void set_pc(Address pc) { *pc_address() = pc; }
|
|
|
|
|
|
|
|
Address* pc_address() const { return state_.pc_address; }
|
|
|
|
|
|
|
|
// Get the id of this stack frame.
|
|
|
|
Id id() const { return static_cast<Id>(OffsetFrom(pp())); }
|
|
|
|
|
|
|
|
// 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.
|
2009-02-25 16:52:15 +00:00
|
|
|
virtual Code* code() const = 0;
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
// Garbage collection support.
|
|
|
|
static void CookFramesForThread(ThreadLocalTop* thread);
|
|
|
|
static void UncookFramesForThread(ThreadLocalTop* thread);
|
|
|
|
|
|
|
|
virtual void Iterate(ObjectVisitor* v) const { }
|
|
|
|
|
|
|
|
// Printing support.
|
|
|
|
enum PrintMode { OVERVIEW, DETAILS };
|
|
|
|
virtual void Print(StringStream* accumulator,
|
|
|
|
PrintMode mode,
|
|
|
|
int index) const { }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
struct State {
|
|
|
|
Address sp;
|
|
|
|
Address fp;
|
|
|
|
Address* pc_address;
|
|
|
|
};
|
|
|
|
|
|
|
|
explicit StackFrame(StackFrameIterator* iterator) : iterator_(iterator) { }
|
|
|
|
virtual ~StackFrame() { }
|
|
|
|
|
|
|
|
// 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(State* state);
|
|
|
|
|
|
|
|
private:
|
|
|
|
const StackFrameIterator* iterator_;
|
2008-09-12 03:29:06 +00:00
|
|
|
State state_;
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2009-03-20 14:49:12 +00:00
|
|
|
// Fill in the state of the calling frame.
|
|
|
|
virtual void ComputeCallerState(State* state) const = 0;
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
// Get the type and the state of the calling frame.
|
2009-03-20 14:49:12 +00:00
|
|
|
virtual Type GetCallerState(State* state) const;
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
// Cooking/uncooking support.
|
|
|
|
void Cook();
|
|
|
|
void Uncook();
|
|
|
|
|
|
|
|
friend class StackFrameIterator;
|
|
|
|
friend class StackHandlerIterator;
|
2009-03-20 14:49:12 +00:00
|
|
|
friend class SafeStackFrameIterator;
|
2008-08-13 09:32:07 +00:00
|
|
|
|
|
|
|
DISALLOW_IMPLICIT_CONSTRUCTORS(StackFrame);
|
2008-07-03 15:10:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Entry frames are used to enter JavaScript execution from C.
|
|
|
|
class EntryFrame: public StackFrame {
|
|
|
|
public:
|
|
|
|
virtual Type type() const { return ENTRY; }
|
|
|
|
|
2009-02-25 16:52:15 +00:00
|
|
|
virtual Code* code() const;
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
// Garbage collection support.
|
|
|
|
virtual void Iterate(ObjectVisitor* v) const;
|
|
|
|
|
|
|
|
static EntryFrame* cast(StackFrame* frame) {
|
|
|
|
ASSERT(frame->is_entry());
|
|
|
|
return static_cast<EntryFrame*>(frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
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:
|
2009-03-20 14:49:12 +00:00
|
|
|
virtual void ComputeCallerState(State* state) const;
|
2008-07-03 15:10:15 +00:00
|
|
|
virtual Type GetCallerState(State* state) const;
|
|
|
|
|
|
|
|
friend class StackFrameIterator;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class EntryConstructFrame: public EntryFrame {
|
|
|
|
public:
|
|
|
|
virtual Type type() const { return ENTRY_CONSTRUCT; }
|
|
|
|
|
2009-02-25 16:52:15 +00:00
|
|
|
virtual Code* code() const;
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
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; }
|
|
|
|
|
2009-02-25 16:52:15 +00:00
|
|
|
virtual Code* code() const;
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2009-01-15 19:08:34 +00:00
|
|
|
// Garbage collection support.
|
2008-07-03 15:10:15 +00:00
|
|
|
virtual void Iterate(ObjectVisitor* v) const;
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
|
|
|
|
|
|
|
|
virtual Address GetCallerStackPointer() const;
|
|
|
|
|
|
|
|
private:
|
2009-03-20 14:49:12 +00:00
|
|
|
virtual void ComputeCallerState(State* state) const;
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
friend class StackFrameIterator;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class ExitDebugFrame: public ExitFrame {
|
|
|
|
public:
|
|
|
|
virtual Type type() const { return EXIT_DEBUG; }
|
|
|
|
|
2009-02-25 16:52:15 +00:00
|
|
|
virtual Code* code() const;
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
static ExitDebugFrame* cast(StackFrame* frame) {
|
|
|
|
ASSERT(frame->is_exit_debug());
|
|
|
|
return static_cast<ExitDebugFrame*>(frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
explicit ExitDebugFrame(StackFrameIterator* iterator)
|
|
|
|
: ExitFrame(iterator) { }
|
|
|
|
|
|
|
|
private:
|
|
|
|
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;
|
|
|
|
|
|
|
|
static StandardFrame* cast(StackFrame* frame) {
|
|
|
|
ASSERT(frame->is_standard());
|
|
|
|
return static_cast<StandardFrame*>(frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
explicit StandardFrame(StackFrameIterator* iterator)
|
|
|
|
: StackFrame(iterator) { }
|
|
|
|
|
2009-03-20 14:49:12 +00:00
|
|
|
virtual void ComputeCallerState(State* state) const;
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
// Accessors.
|
|
|
|
inline Address caller_sp() const;
|
|
|
|
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);
|
|
|
|
|
2008-10-10 09:09:38 +00:00
|
|
|
// Determines if the standard frame for the given frame pointer is a
|
|
|
|
// construct frame.
|
|
|
|
static inline bool IsConstructFrame(Address fp);
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
friend class StackFrame;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
// Temporary way of getting access to the number of parameters
|
|
|
|
// passed on the stack by the caller. Once argument adaptor frames
|
|
|
|
// has been introduced on ARM, this number will always match the
|
|
|
|
// computed parameters count.
|
|
|
|
int GetProvidedParametersCount() const;
|
|
|
|
|
2008-10-10 09:09:38 +00:00
|
|
|
// Check if this frame is a constructor frame invoked through 'new'.
|
2008-07-03 15:10:15 +00:00
|
|
|
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;
|
|
|
|
|
2009-01-15 19:08:34 +00:00
|
|
|
// Garbage collection support.
|
2008-07-03 15:10:15 +00:00
|
|
|
virtual void Iterate(ObjectVisitor* v) const;
|
|
|
|
|
|
|
|
// Printing support.
|
|
|
|
virtual void Print(StringStream* accumulator,
|
|
|
|
PrintMode mode,
|
|
|
|
int index) const;
|
|
|
|
|
|
|
|
// Determine the code for the frame.
|
2009-02-25 16:52:15 +00:00
|
|
|
virtual Code* code() const;
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
static JavaScriptFrame* cast(StackFrame* frame) {
|
|
|
|
ASSERT(frame->is_java_script());
|
|
|
|
return static_cast<JavaScriptFrame*>(frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
explicit JavaScriptFrame(StackFrameIterator* iterator)
|
2009-04-13 23:12:04 +00:00
|
|
|
: StandardFrame(iterator), disable_heap_access_(false) { }
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
virtual Address GetCallerStackPointer() const;
|
|
|
|
|
2009-04-13 23:12:04 +00:00
|
|
|
// When this mode is enabled it is not allowed to access heap objects.
|
|
|
|
// This is a special mode used when gathering stack samples in profiler.
|
|
|
|
// A shortcoming is that caller's SP value will be calculated incorrectly
|
|
|
|
// (see GetCallerStackPointer implementation), but it is not used for stack
|
|
|
|
// sampling.
|
|
|
|
void DisableHeapAccess() { disable_heap_access_ = true; }
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
private:
|
2009-04-13 23:12:04 +00:00
|
|
|
bool disable_heap_access_;
|
2009-03-20 14:49:12 +00:00
|
|
|
inline Object* function_slot_object() const;
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
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:
|
|
|
|
// This sentinel value is temporarily used to distinguish arguments
|
|
|
|
// adaptor frames from ordinary JavaScript frames. If a frame has
|
|
|
|
// the sentinel as its context, it is an arguments adaptor frame. It
|
|
|
|
// must be tagged as a small integer to avoid GC issues. Crud.
|
|
|
|
enum {
|
|
|
|
SENTINEL = (1 << kSmiTagSize) | kSmiTag
|
|
|
|
};
|
|
|
|
|
|
|
|
virtual Type type() const { return ARGUMENTS_ADAPTOR; }
|
|
|
|
|
|
|
|
// Determine the code for the frame.
|
2009-02-25 16:52:15 +00:00
|
|
|
virtual Code* code() const;
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
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; }
|
|
|
|
|
2009-01-15 19:08:34 +00:00
|
|
|
// Garbage collection support.
|
2008-07-03 15:10:15 +00:00
|
|
|
virtual void Iterate(ObjectVisitor* v) const;
|
|
|
|
|
|
|
|
// Determine the code for the frame.
|
2009-02-25 16:52:15 +00:00
|
|
|
virtual Code* code() const;
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2008-10-10 09:09:38 +00:00
|
|
|
// 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;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
class StackFrameIterator BASE_EMBEDDED {
|
|
|
|
public:
|
|
|
|
// An iterator that iterates over the current thread's stack.
|
|
|
|
StackFrameIterator();
|
|
|
|
|
|
|
|
// An iterator that iterates over a given thread's stack.
|
|
|
|
explicit StackFrameIterator(ThreadLocalTop* thread);
|
|
|
|
|
2009-03-20 14:49:12 +00:00
|
|
|
// 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(bool use_top, Address fp, Address sp);
|
2009-03-03 11:56:44 +00:00
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
StackFrame* frame() const {
|
|
|
|
ASSERT(!done());
|
|
|
|
return frame_;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool done() const { return frame_ == NULL; }
|
2009-03-20 14:49:12 +00:00
|
|
|
void Advance() { (this->*advance_)(); }
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
// Go back to the first frame.
|
|
|
|
void Reset();
|
|
|
|
|
|
|
|
private:
|
|
|
|
#define DECLARE_SINGLETON(ignore, type) type type##_;
|
|
|
|
STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
|
|
|
|
#undef DECLARE_SINGLETON
|
|
|
|
StackFrame* frame_;
|
|
|
|
StackHandler* handler_;
|
2008-07-30 08:49:36 +00:00
|
|
|
ThreadLocalTop* thread_;
|
2009-03-20 14:49:12 +00:00
|
|
|
Address fp_;
|
|
|
|
Address sp_;
|
|
|
|
void (StackFrameIterator::*advance_)();
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
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);
|
2009-03-20 14:49:12 +00:00
|
|
|
// A helper function, can return a NULL pointer.
|
|
|
|
StackFrame* SingletonFor(StackFrame::Type type);
|
|
|
|
|
|
|
|
void AdvanceWithHandler();
|
|
|
|
void AdvanceWithoutHandler();
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
friend class StackFrame;
|
2009-03-20 14:49:12 +00:00
|
|
|
friend class SafeStackFrameIterator;
|
2008-08-28 09:55:41 +00:00
|
|
|
DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
|
2008-07-03 15:10:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// Iterator that supports iterating through all JavaScript frames.
|
2009-03-03 11:56:44 +00:00
|
|
|
template<typename Iterator>
|
|
|
|
class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
|
2008-07-03 15:10:15 +00:00
|
|
|
public:
|
2009-03-03 11:56:44 +00:00
|
|
|
JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
|
2008-07-03 15:10:15 +00:00
|
|
|
|
2009-03-03 11:56:44 +00:00
|
|
|
explicit JavaScriptFrameIteratorTemp(ThreadLocalTop* thread) :
|
|
|
|
iterator_(thread) {
|
2008-07-03 15:10:15 +00:00
|
|
|
if (!done()) Advance();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Skip frames until the frame with the given id is reached.
|
2009-03-03 11:56:44 +00:00
|
|
|
explicit JavaScriptFrameIteratorTemp(StackFrame::Id id);
|
|
|
|
|
2009-03-20 14:49:12 +00:00
|
|
|
JavaScriptFrameIteratorTemp(Address fp, Address sp,
|
|
|
|
Address low_bound, Address high_bound) :
|
|
|
|
iterator_(fp, sp, low_bound, high_bound) {
|
|
|
|
if (!done()) Advance();
|
|
|
|
}
|
2008-07-03 15:10:15 +00:00
|
|
|
|
|
|
|
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:
|
2009-03-03 11:56:44 +00:00
|
|
|
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();
|
|
|
|
void Advance();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class SafeStackFrameIterator BASE_EMBEDDED {
|
|
|
|
public:
|
2009-03-20 14:49:12 +00:00
|
|
|
SafeStackFrameIterator(Address fp, Address sp,
|
|
|
|
Address low_bound, Address high_bound);
|
2009-03-03 11:56:44 +00:00
|
|
|
|
|
|
|
StackFrame* frame() const {
|
|
|
|
ASSERT(is_working_iterator_);
|
|
|
|
return iterator_.frame();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool done() const { return iteration_done_ ? true : iterator_.done(); }
|
|
|
|
|
|
|
|
void Advance();
|
|
|
|
void Reset();
|
|
|
|
|
|
|
|
private:
|
2009-03-20 14:49:12 +00:00
|
|
|
static bool IsWithinBounds(
|
2009-03-03 11:56:44 +00:00
|
|
|
Address low_bound, Address high_bound, Address addr) {
|
|
|
|
return low_bound <= addr && addr <= high_bound;
|
|
|
|
}
|
2009-03-20 14:49:12 +00:00
|
|
|
bool IsValidStackAddress(Address addr) const {
|
|
|
|
return IsWithinBounds(low_bound_, high_bound_, addr);
|
2009-03-03 11:56:44 +00:00
|
|
|
}
|
2009-04-13 14:42:01 +00:00
|
|
|
bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
|
2009-03-20 14:49:12 +00:00
|
|
|
bool IsValidFrame(StackFrame* frame) const;
|
|
|
|
bool IsValidCaller(StackFrame* frame);
|
2009-03-03 11:56:44 +00:00
|
|
|
|
|
|
|
Address low_bound_;
|
|
|
|
Address high_bound_;
|
2009-03-20 14:49:12 +00:00
|
|
|
const bool is_valid_top_;
|
|
|
|
const bool is_valid_fp_;
|
2009-03-03 11:56:44 +00:00
|
|
|
const bool is_working_iterator_;
|
|
|
|
bool iteration_done_;
|
2008-07-03 15:10:15 +00:00
|
|
|
StackFrameIterator iterator_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2009-03-03 11:56:44 +00:00
|
|
|
#ifdef ENABLE_LOGGING_AND_PROFILING
|
|
|
|
typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
|
|
|
|
SafeJavaScriptFrameIterator;
|
|
|
|
|
|
|
|
|
|
|
|
class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
|
|
|
|
public:
|
2009-03-20 14:49:12 +00:00
|
|
|
explicit SafeStackTraceFrameIterator(Address fp, Address sp,
|
|
|
|
Address low_bound, Address high_bound);
|
2009-03-03 11:56:44 +00:00
|
|
|
void Advance();
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2008-07-03 15:10:15 +00:00
|
|
|
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_;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
} } // namespace v8::internal
|
|
|
|
|
|
|
|
#endif // V8_FRAMES_H_
|