frames.h revision a7e24c173cf37484693b9abb38e494fa7bd7baeb
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2008 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_FRAMES_H_
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_FRAMES_H_
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef uint32_t RegList;
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Get the number of registers in a given register list.
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint NumRegs(RegList list);
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Return the code of the n-th saved register available to JavaScript.
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint JSCallerSavedCode(int n);
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Forward declarations.
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass StackFrameIterator;
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Top;
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ThreadLocalTop;
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass StackHandler BASE_EMBEDDED {
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum State {
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ENTRY,
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    TRY_CATCH,
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    TRY_FINALLY
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the address of this stack handler.
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline Address address() const;
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the next stack handler in the chain.
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline StackHandler* next() const;
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tells whether the given address is inside this handler.
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline bool includes(Address address) const;
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Garbage collection support.
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void Iterate(ObjectVisitor* v) const;
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Conversion support.
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static inline StackHandler* FromAddress(Address address);
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Testers
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_entry() { return state() == ENTRY; }
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_try_catch() { return state() == TRY_CATCH; }
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_try_finally() { return state() == TRY_FINALLY; }
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Garbage collection support.
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Cook(Code* code);
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Uncook(Code* code);
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Accessors.
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline State state() const;
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline Address pc() const;
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void set_pc(Address value);
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define STACK_FRAME_TYPE_LIST(V)              \
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V(ENTRY,             EntryFrame)            \
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V(ENTRY_CONSTRUCT,   EntryConstructFrame)   \
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V(EXIT,              ExitFrame)             \
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V(EXIT_DEBUG,        ExitDebugFrame)        \
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V(JAVA_SCRIPT,       JavaScriptFrame)       \
98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V(INTERNAL,          InternalFrame)         \
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V(CONSTRUCT,         ConstructFrame)        \
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Abstract base class for all stack frames.
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass StackFrame BASE_EMBEDDED {
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define DECLARE_TYPE(type, ignore) type,
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum Type {
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    NONE = 0,
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    NUMBER_OF_TYPES
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef DECLARE_TYPE
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Opaque data type for identifying stack frames. Used extensively
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // by the debugger.
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum Id { NO_ID = 0 };
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Type testers.
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_entry() const { return type() == ENTRY; }
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_exit() const { return type() == EXIT; }
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_exit_debug() const { return type() == EXIT_DEBUG; }
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_java_script() const { return type() == JAVA_SCRIPT; }
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_internal() const { return type() == INTERNAL; }
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool is_construct() const { return type() == CONSTRUCT; }
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual bool is_standard() const { return false; }
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Accessors.
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address sp() const { return state_.sp; }
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address fp() const { return state_.fp; }
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address caller_sp() const { return GetCallerStackPointer(); }
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address pc() const { return *pc_address(); }
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void set_pc(Address pc) { *pc_address() = pc; }
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address* pc_address() const { return state_.pc_address; }
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the id of this stack frame.
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Checks if this frame includes any stack handlers.
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool HasHandler() const;
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the type of this frame.
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Type type() const = 0;
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the code associated with this frame.
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Code* code() const = 0;
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Garbage collection support.
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void CookFramesForThread(ThreadLocalTop* thread);
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void UncookFramesForThread(ThreadLocalTop* thread);
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void Iterate(ObjectVisitor* v) const { }
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Printing support.
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum PrintMode { OVERVIEW, DETAILS };
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void Print(StringStream* accumulator,
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     PrintMode mode,
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int index) const { }
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block protected:
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  struct State {
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address sp;
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address fp;
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address* pc_address;
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit StackFrame(StackFrameIterator* iterator) : iterator_(iterator) { }
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual ~StackFrame() { }
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the stack pointer for the calling frame.
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Address GetCallerStackPointer() const = 0;
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Printing support.
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void PrintIndex(StringStream* accumulator,
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         PrintMode mode,
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         int index);
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the top handler from the current stack iterator.
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline StackHandler* top_handler() const;
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the stack frame type for the given state.
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static Type ComputeType(State* state);
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const StackFrameIterator* iterator_;
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  State state_;
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill in the state of the calling frame.
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void ComputeCallerState(State* state) const = 0;
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the type and the state of the calling frame.
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Type GetCallerState(State* state) const;
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Cooking/uncooking support.
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Cook();
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Uncook();
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class StackFrameIterator;
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class StackHandlerIterator;
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class SafeStackFrameIterator;
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DISALLOW_IMPLICIT_CONSTRUCTORS(StackFrame);
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Entry frames are used to enter JavaScript execution from C.
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass EntryFrame: public StackFrame {
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Type type() const { return ENTRY; }
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Code* code() const;
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Garbage collection support.
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void Iterate(ObjectVisitor* v) const;
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static EntryFrame* cast(StackFrame* frame) {
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(frame->is_entry());
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return static_cast<EntryFrame*>(frame);
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block protected:
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit EntryFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The caller stack pointer for entry frames is always zero. The
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // real information about the caller frame is available through the
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // link to the top exit frame.
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Address GetCallerStackPointer() const { return 0; }
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void ComputeCallerState(State* state) const;
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Type GetCallerState(State* state) const;
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class StackFrameIterator;
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass EntryConstructFrame: public EntryFrame {
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Type type() const { return ENTRY_CONSTRUCT; }
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Code* code() const;
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static EntryConstructFrame* cast(StackFrame* frame) {
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(frame->is_entry_construct());
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return static_cast<EntryConstructFrame*>(frame);
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block protected:
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit EntryConstructFrame(StackFrameIterator* iterator)
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : EntryFrame(iterator) { }
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class StackFrameIterator;
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Exit frames are used to exit JavaScript execution and go to C.
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ExitFrame: public StackFrame {
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Type type() const { return EXIT; }
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Code* code() const;
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Garbage collection support.
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void Iterate(ObjectVisitor* v) const;
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static ExitFrame* cast(StackFrame* frame) {
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(frame->is_exit());
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return static_cast<ExitFrame*>(frame);
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the state and type of an exit frame given a frame
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // pointer. Used when constructing the first stack frame seen by an
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // iterator and the frames following entry frames.
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static Type GetStateForFramePointer(Address fp, State* state);
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block protected:
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Address GetCallerStackPointer() const;
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void ComputeCallerState(State* state) const;
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class StackFrameIterator;
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ExitDebugFrame: public ExitFrame {
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Type type() const { return EXIT_DEBUG; }
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Code* code() const;
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static ExitDebugFrame* cast(StackFrame* frame) {
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(frame->is_exit_debug());
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return static_cast<ExitDebugFrame*>(frame);
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block protected:
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit ExitDebugFrame(StackFrameIterator* iterator)
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : ExitFrame(iterator) { }
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class StackFrameIterator;
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass StandardFrame: public StackFrame {
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Testers.
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual bool is_standard() const { return true; }
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Accessors.
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline Object* context() const;
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Access the expressions in the stack frame including locals.
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline Object* GetExpression(int index) const;
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void SetExpression(int index, Object* value);
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int ComputeExpressionsCount() const;
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static StandardFrame* cast(StackFrame* frame) {
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(frame->is_standard());
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return static_cast<StandardFrame*>(frame);
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block protected:
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit StandardFrame(StackFrameIterator* iterator)
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : StackFrame(iterator) { }
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void ComputeCallerState(State* state) const;
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Accessors.
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline Address caller_fp() const;
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline Address caller_pc() const;
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Computes the address of the PC field in the standard frame given
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // by the provided frame pointer.
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static inline Address ComputePCAddress(Address fp);
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Iterate over expression stack including stack handlers, locals,
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // and parts of the fixed part including context and code fields.
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void IterateExpressions(ObjectVisitor* v) const;
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns the address of the n'th expression stack element.
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address GetExpressionAddress(int n) const;
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Determines if the n'th expression stack element is in a stack
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // handler or not. Requires traversing all handlers in this frame.
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool IsExpressionInsideHandler(int n) const;
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Determines if the standard frame for the given frame pointer is
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // an arguments adaptor frame.
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static inline bool IsArgumentsAdaptorFrame(Address fp);
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Determines if the standard frame for the given frame pointer is a
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // construct frame.
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static inline bool IsConstructFrame(Address fp);
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class StackFrame;
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass JavaScriptFrame: public StandardFrame {
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Type type() const { return JAVA_SCRIPT; }
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Accessors.
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline Object* function() const;
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline Object* receiver() const;
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline void set_receiver(Object* value);
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Access the parameters.
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* GetParameter(int index) const;
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int ComputeParametersCount() const;
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Temporary way of getting access to the number of parameters
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // passed on the stack by the caller. Once argument adaptor frames
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // has been introduced on ARM, this number will always match the
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // computed parameters count.
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int GetProvidedParametersCount() const;
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if this frame is a constructor frame invoked through 'new'.
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool IsConstructor() const;
389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check if this frame has "adapted" arguments in the sense that the
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // actual passed arguments are available in an arguments adaptor
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // frame below it on the stack.
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline bool has_adapted_arguments() const;
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Garbage collection support.
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void Iterate(ObjectVisitor* v) const;
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Printing support.
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void Print(StringStream* accumulator,
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     PrintMode mode,
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int index) const;
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Determine the code for the frame.
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Code* code() const;
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static JavaScriptFrame* cast(StackFrame* frame) {
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(frame->is_java_script());
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return static_cast<JavaScriptFrame*>(frame);
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block protected:
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit JavaScriptFrame(StackFrameIterator* iterator)
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : StandardFrame(iterator), disable_heap_access_(false) { }
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Address GetCallerStackPointer() const;
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When this mode is enabled it is not allowed to access heap objects.
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This is a special mode used when gathering stack samples in profiler.
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // A shortcoming is that caller's SP value will be calculated incorrectly
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // (see GetCallerStackPointer implementation), but it is not used for stack
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // sampling.
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void DisableHeapAccess() { disable_heap_access_ = true; }
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool disable_heap_access_;
426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline Object* function_slot_object() const;
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class StackFrameIterator;
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Arguments adaptor frames are automatically inserted below
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// JavaScript frames when the actual number of parameters does not
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// match the formal number of parameters.
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ArgumentsAdaptorFrame: public JavaScriptFrame {
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Type type() const { return ARGUMENTS_ADAPTOR; }
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Determine the code for the frame.
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Code* code() const;
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(frame->is_arguments_adaptor());
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return static_cast<ArgumentsAdaptorFrame*>(frame);
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Printing support.
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void Print(StringStream* accumulator,
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     PrintMode mode,
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                     int index) const;
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block protected:
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator)
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : JavaScriptFrame(iterator) { }
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Address GetCallerStackPointer() const;
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class StackFrameIterator;
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass InternalFrame: public StandardFrame {
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Type type() const { return INTERNAL; }
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Garbage collection support.
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void Iterate(ObjectVisitor* v) const;
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Determine the code for the frame.
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Code* code() const;
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static InternalFrame* cast(StackFrame* frame) {
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(frame->is_internal());
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return static_cast<InternalFrame*>(frame);
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block protected:
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit InternalFrame(StackFrameIterator* iterator)
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : StandardFrame(iterator) { }
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Address GetCallerStackPointer() const;
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class StackFrameIterator;
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Construct frames are special trampoline frames introduced to handle
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// function invocations through 'new'.
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ConstructFrame: public InternalFrame {
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual Type type() const { return CONSTRUCT; }
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static ConstructFrame* cast(StackFrame* frame) {
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(frame->is_construct());
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return static_cast<ConstructFrame*>(frame);
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block protected:
500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit ConstructFrame(StackFrameIterator* iterator)
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : InternalFrame(iterator) { }
502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class StackFrameIterator;
505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass StackFrameIterator BASE_EMBEDDED {
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // An iterator that iterates over the current thread's stack.
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrameIterator();
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // An iterator that iterates over a given thread's stack.
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit StackFrameIterator(ThreadLocalTop* thread);
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // An iterator that can start from a given FP address.
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If use_top, then work as usual, if fp isn't NULL, use it,
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // otherwise, do nothing.
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrameIterator(bool use_top, Address fp, Address sp);
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrame* frame() const {
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!done());
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return frame_;
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool done() const { return frame_ == NULL; }
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Advance() { (this->*advance_)(); }
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Go back to the first frame.
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Reset();
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define DECLARE_SINGLETON(ignore, type) type type##_;
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef DECLARE_SINGLETON
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrame* frame_;
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackHandler* handler_;
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ThreadLocalTop* thread_;
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address fp_;
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address sp_;
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void (StackFrameIterator::*advance_)();
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackHandler* handler() const {
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!done());
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return handler_;
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the type-specific frame singleton in a given state.
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // A helper function, can return a NULL pointer.
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrame* SingletonFor(StackFrame::Type type);
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AdvanceWithHandler();
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AdvanceWithoutHandler();
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class StackFrame;
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class SafeStackFrameIterator;
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Iterator that supports iterating through all JavaScript frames.
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate<typename Iterator>
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass JavaScriptFrameIteratorTemp BASE_EMBEDDED {
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit JavaScriptFrameIteratorTemp(ThreadLocalTop* thread) :
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      iterator_(thread) {
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!done()) Advance();
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Skip frames until the frame with the given id is reached.
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit JavaScriptFrameIteratorTemp(StackFrame::Id id);
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JavaScriptFrameIteratorTemp(Address fp, Address sp,
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                              Address low_bound, Address high_bound) :
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      iterator_(fp, sp, low_bound, high_bound) {
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!done()) Advance();
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline JavaScriptFrame* frame() const;
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool done() const { return iterator_.done(); }
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Advance();
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Advance to the frame holding the arguments for the current
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // frame. This only affects the current frame if it has adapted
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // arguments.
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void AdvanceToArgumentsFrame();
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Go back to the first frame.
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Reset();
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Iterator iterator_;
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// NOTE: The stack trace frame iterator is an iterator that only
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// traverse proper JavaScript frames; that is JavaScript frames that
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// have proper JavaScript functions. This excludes the problematic
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// functions in runtime.js.
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass StackTraceFrameIterator: public JavaScriptFrameIterator {
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackTraceFrameIterator();
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Advance();
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass SafeStackFrameIterator BASE_EMBEDDED {
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SafeStackFrameIterator(Address fp, Address sp,
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                         Address low_bound, Address high_bound);
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrame* frame() const {
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(is_working_iterator_);
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return iterator_.frame();
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool done() const { return iteration_done_ ? true : iterator_.done(); }
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Advance();
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Reset();
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static bool IsWithinBounds(
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Address low_bound, Address high_bound, Address addr) {
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return low_bound <= addr && addr <= high_bound;
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool IsValidStackAddress(Address addr) const {
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return IsWithinBounds(low_bound_, high_bound_, addr);
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool IsValidFrame(StackFrame* frame) const;
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool IsValidCaller(StackFrame* frame);
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address low_bound_;
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address high_bound_;
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const bool is_valid_top_;
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const bool is_valid_fp_;
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const bool is_working_iterator_;
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool iteration_done_;
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrameIterator iterator_;
648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_LOGGING_AND_PROFILING
652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SafeJavaScriptFrameIterator;
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit SafeStackTraceFrameIterator(Address fp, Address sp,
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                       Address low_bound, Address high_bound);
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Advance();
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass StackFrameLocator BASE_EMBEDDED {
666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Find the nth JavaScript frame on the stack. The caller must
668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // guarantee that such a frame exists.
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JavaScriptFrame* FindJavaScriptFrame(int n);
670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrameIterator iterator_;
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_FRAMES_H_
679