blob: 2bbbd98ac07e81e720532813fa29a04aaf529ad1 [file] [log] [blame]
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +00001// Copyright 2012 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_FRAMES_H_
29#define V8_FRAMES_H_
30
lrn@chromium.org1c092762011-05-09 09:42:16 +000031#include "allocation.h"
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000032#include "handles.h"
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000033#include "safepoint-table.h"
34
kasperl@chromium.org71affb52009-05-26 05:44:31 +000035namespace v8 {
36namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000037
38typedef uint32_t RegList;
39
40// Get the number of registers in a given register list.
41int NumRegs(RegList list);
42
fschneider@chromium.org7d10be52012-04-10 12:30:14 +000043void SetUpJSCallerSavedCodeData();
44
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045// Return the code of the n-th saved register available to JavaScript.
46int JSCallerSavedCode(int n);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000047
48
49// Forward declarations.
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +000050class ExternalCallbackScope;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +000051class StackFrameIteratorBase;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000052class ThreadLocalTop;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000053class Isolate;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000054
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000055class InnerPointerToCodeCache {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000056 public:
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000057 struct InnerPointerToCodeCacheEntry {
58 Address inner_pointer;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000059 Code* code;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000060 SafepointEntry safepoint_entry;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000061 };
62
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000063 explicit InnerPointerToCodeCache(Isolate* isolate) : isolate_(isolate) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000064 Flush();
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000065 }
66
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000067 Code* GcSafeFindCodeForInnerPointer(Address inner_pointer);
68 Code* GcSafeCastToCode(HeapObject* object, Address inner_pointer);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000069
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000070 void Flush() {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000071 memset(&cache_[0], 0, sizeof(cache_));
72 }
73
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000074 InnerPointerToCodeCacheEntry* GetCacheEntry(Address inner_pointer);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000075
76 private:
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000077 InnerPointerToCodeCacheEntry* cache(int index) { return &cache_[index]; }
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000078
79 Isolate* isolate_;
80
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000081 static const int kInnerPointerToCodeCacheSize = 1024;
82 InnerPointerToCodeCacheEntry cache_[kInnerPointerToCodeCacheSize];
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000083
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000084 DISALLOW_COPY_AND_ASSIGN(InnerPointerToCodeCache);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000085};
86
87
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000088class StackHandlerConstants : public AllStatic {
89 public:
90 static const int kNextOffset = 0 * kPointerSize;
91 static const int kCodeOffset = 1 * kPointerSize;
92 static const int kStateOffset = 2 * kPointerSize;
93 static const int kContextOffset = 3 * kPointerSize;
94 static const int kFPOffset = 4 * kPointerSize;
95
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +000096 static const int kSize = kFPOffset + kFPOnStackSize;
ulan@chromium.org57ff8812013-05-10 08:16:55 +000097 static const int kSlotCount = kSize >> kPointerSizeLog2;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +000098};
99
100
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000101class StackHandler BASE_EMBEDDED {
102 public:
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000103 enum Kind {
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000104 JS_ENTRY,
105 CATCH,
106 FINALLY,
107 LAST_KIND = FINALLY
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000108 };
109
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000110 static const int kKindWidth = 2;
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000111 STATIC_ASSERT(LAST_KIND < (1 << kKindWidth));
112 static const int kIndexWidth = 32 - kKindWidth;
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000113 class KindField: public BitField<StackHandler::Kind, 0, kKindWidth> {};
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000114 class IndexField: public BitField<unsigned, kKindWidth, kIndexWidth> {};
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000115
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000116 // Get the address of this stack handler.
117 inline Address address() const;
118
119 // Get the next stack handler in the chain.
120 inline StackHandler* next() const;
121
122 // Tells whether the given address is inside this handler.
123 inline bool includes(Address address) const;
124
125 // Garbage collection support.
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000126 inline void Iterate(ObjectVisitor* v, Code* holder) const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000127
128 // Conversion support.
129 static inline StackHandler* FromAddress(Address address);
130
131 // Testers
yangguo@chromium.org78d1ad42012-02-09 13:53:47 +0000132 inline bool is_js_entry() const;
133 inline bool is_catch() const;
134 inline bool is_finally() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000135
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000136 // Generator support to preserve stack handlers.
137 void Unwind(Isolate* isolate, FixedArray* array, int offset,
138 int previous_handler_offset) const;
139 int Rewind(Isolate* isolate, FixedArray* array, int offset, Address fp);
140
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000141 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000142 // Accessors.
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000143 inline Kind kind() const;
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000144 inline unsigned index() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000145
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000146 inline Object** context_address() const;
jkummerow@chromium.org04e4f1e2011-11-14 13:36:17 +0000147 inline Object** code_address() const;
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000148 inline void SetFp(Address slot, Address fp);
mads.s.ager31e71382008-08-13 09:32:07 +0000149
150 DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000151};
152
153
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000154#define STACK_FRAME_TYPE_LIST(V) \
155 V(ENTRY, EntryFrame) \
156 V(ENTRY_CONSTRUCT, EntryConstructFrame) \
157 V(EXIT, ExitFrame) \
158 V(JAVA_SCRIPT, JavaScriptFrame) \
159 V(OPTIMIZED, OptimizedFrame) \
160 V(STUB, StubFrame) \
161 V(STUB_FAILURE_TRAMPOLINE, StubFailureTrampolineFrame) \
162 V(INTERNAL, InternalFrame) \
163 V(CONSTRUCT, ConstructFrame) \
164 V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000165
166
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000167class StandardFrameConstants : public AllStatic {
168 public:
169 // Fixed part of the frame consists of return address, caller fp,
170 // context and function.
171 // StandardFrame::IterateExpressions assumes that kContextOffset is the last
172 // object pointer.
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000173 static const int kFixedFrameSize = kPCOnStackSize + kFPOnStackSize +
174 2 * kPointerSize;
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000175 static const int kExpressionsOffset = -3 * kPointerSize;
176 static const int kMarkerOffset = -2 * kPointerSize;
177 static const int kContextOffset = -1 * kPointerSize;
178 static const int kCallerFPOffset = 0 * kPointerSize;
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000179 static const int kCallerPCOffset = +1 * kFPOnStackSize;
danno@chromium.orgd3c42102013-08-01 16:58:23 +0000180 static const int kCallerSPOffset = kCallerPCOffset + 1 * kPCOnStackSize;
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000181};
182
183
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000184// Abstract base class for all stack frames.
185class StackFrame BASE_EMBEDDED {
186 public:
187#define DECLARE_TYPE(type, ignore) type,
188 enum Type {
189 NONE = 0,
190 STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000191 NUMBER_OF_TYPES,
192 // Used by FrameScope to indicate that the stack frame is constructed
193 // manually and the FrameScope does not need to emit code.
194 MANUAL
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000195 };
196#undef DECLARE_TYPE
197
198 // Opaque data type for identifying stack frames. Used extensively
199 // by the debugger.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000200 // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
201 // has correct value range (see Issue 830 for more details).
202 enum Id {
203 ID_MIN_VALUE = kMinInt,
204 ID_MAX_VALUE = kMaxInt,
205 NO_ID = 0
206 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000207
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +0000208 // Used to mark the outermost JS entry frame.
209 enum JsFrameMarker {
210 INNER_JSENTRY_FRAME = 0,
211 OUTERMOST_JSENTRY_FRAME = 1
212 };
213
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000214 struct State {
215 State() : sp(NULL), fp(NULL), pc_address(NULL) { }
216 Address sp;
217 Address fp;
218 Address* pc_address;
219 };
220
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000221 // Copy constructor; it breaks the connection to host iterator
222 // (as an iterator usually lives on stack).
ager@chromium.org357bf652010-04-12 11:30:10 +0000223 StackFrame(const StackFrame& original) {
224 this->state_ = original.state_;
225 this->iterator_ = NULL;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000226 this->isolate_ = original.isolate_;
ager@chromium.org357bf652010-04-12 11:30:10 +0000227 }
228
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000229 // Type testers.
230 bool is_entry() const { return type() == ENTRY; }
231 bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
232 bool is_exit() const { return type() == EXIT; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000233 bool is_optimized() const { return type() == OPTIMIZED; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000234 bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
235 bool is_internal() const { return type() == INTERNAL; }
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000236 bool is_stub_failure_trampoline() const {
237 return type() == STUB_FAILURE_TRAMPOLINE;
238 }
ager@chromium.org7c537e22008-10-16 08:43:32 +0000239 bool is_construct() const { return type() == CONSTRUCT; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000240 virtual bool is_standard() const { return false; }
241
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000242 bool is_java_script() const {
243 Type type = this->type();
244 return (type == JAVA_SCRIPT) || (type == OPTIMIZED);
245 }
246
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000247 // Accessors.
248 Address sp() const { return state_.sp; }
249 Address fp() const { return state_.fp; }
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000250 Address caller_sp() const { return GetCallerStackPointer(); }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000251
mmassi@chromium.org7028c052012-06-13 11:51:58 +0000252 // If this frame is optimized and was dynamically aligned return its old
253 // unaligned frame pointer. When the frame is deoptimized its FP will shift
254 // up one word and become unaligned.
255 Address UnpaddedFP() const;
256
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000257 Address pc() const { return *pc_address(); }
258 void set_pc(Address pc) { *pc_address() = pc; }
259
ager@chromium.org357bf652010-04-12 11:30:10 +0000260 virtual void SetCallerFp(Address caller_fp) = 0;
261
jkummerow@chromium.org212d9642012-05-11 15:02:09 +0000262 // Manually changes value of fp in this object.
263 void UpdateFp(Address fp) { state_.fp = fp; }
264
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000265 Address* pc_address() const { return state_.pc_address; }
266
267 // Get the id of this stack frame.
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000268 Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000269
270 // Checks if this frame includes any stack handlers.
271 bool HasHandler() const;
272
273 // Get the type of this frame.
274 virtual Type type() const = 0;
275
276 // Get the code associated with this frame.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000277 // This method could be called during marking phase of GC.
278 virtual Code* unchecked_code() const = 0;
279
280 // Get the code associated with this frame.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000281 inline Code* LookupCode() const;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000282
283 // Get the code object that contains the given pc.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000284 static inline Code* GetContainingCode(Isolate* isolate, Address pc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000285
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000286 // Get the code object containing the given pc and fill in the
287 // safepoint entry and the number of stack slots. The pc must be at
288 // a safepoint.
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000289 static Code* GetSafepointData(Isolate* isolate,
290 Address pc,
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000291 SafepointEntry* safepoint_entry,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000292 unsigned* stack_slots);
293
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000294 virtual void Iterate(ObjectVisitor* v) const = 0;
295 static void IteratePc(ObjectVisitor* v, Address* pc_address, Code* holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000296
ulan@chromium.org967e2702012-02-28 09:49:15 +0000297 // Sets a callback function for return-address rewriting profilers
298 // to resolve the location of a return address to the location of the
299 // profiler's stashed return address.
300 static void SetReturnAddressLocationResolver(
301 ReturnAddressLocationResolver resolver);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000302
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000303 // Resolves pc_address through the resolution address function if one is set.
304 static inline Address* ResolveReturnAddressLocation(Address* pc_address);
305
306
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000307 // Printing support.
308 enum PrintMode { OVERVIEW, DETAILS };
309 virtual void Print(StringStream* accumulator,
310 PrintMode mode,
311 int index) const { }
312
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000313 Isolate* isolate() const { return isolate_; }
314
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000315 protected:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000316 inline explicit StackFrame(StackFrameIteratorBase* iterator);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000317 virtual ~StackFrame() { }
318
319 // Compute the stack pointer for the calling frame.
320 virtual Address GetCallerStackPointer() const = 0;
321
322 // Printing support.
323 static void PrintIndex(StringStream* accumulator,
324 PrintMode mode,
325 int index);
326
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000327 // Get the top handler from the current stack iterator.
328 inline StackHandler* top_handler() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000329
330 // Compute the stack frame type for the given state.
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000331 static Type ComputeType(const StackFrameIteratorBase* iterator, State* state);
332
333#ifdef DEBUG
334 bool can_access_heap_objects() const;
335#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000336
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000337 private:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000338 const StackFrameIteratorBase* iterator_;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000339 Isolate* isolate_;
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000340 State state_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000341
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000342 static ReturnAddressLocationResolver return_address_location_resolver_;
343
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000344 // Fill in the state of the calling frame.
345 virtual void ComputeCallerState(State* state) const = 0;
346
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000347 // Get the type and the state of the calling frame.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000348 virtual Type GetCallerState(State* state) const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000349
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000350 static const intptr_t kIsolateTag = 1;
351
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000352 friend class StackFrameIterator;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000353 friend class StackFrameIteratorBase;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000354 friend class StackHandlerIterator;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000355 friend class SafeStackFrameIterator;
mads.s.ager31e71382008-08-13 09:32:07 +0000356
ager@chromium.org357bf652010-04-12 11:30:10 +0000357 private:
358 void operator=(const StackFrame& original);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000359};
360
361
362// Entry frames are used to enter JavaScript execution from C.
363class EntryFrame: public StackFrame {
364 public:
365 virtual Type type() const { return ENTRY; }
366
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000367 virtual Code* unchecked_code() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000368
369 // Garbage collection support.
370 virtual void Iterate(ObjectVisitor* v) const;
371
372 static EntryFrame* cast(StackFrame* frame) {
373 ASSERT(frame->is_entry());
374 return static_cast<EntryFrame*>(frame);
375 }
ager@chromium.org357bf652010-04-12 11:30:10 +0000376 virtual void SetCallerFp(Address caller_fp);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000377
378 protected:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000379 inline explicit EntryFrame(StackFrameIteratorBase* iterator);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000380
381 // The caller stack pointer for entry frames is always zero. The
382 // real information about the caller frame is available through the
383 // link to the top exit frame.
384 virtual Address GetCallerStackPointer() const { return 0; }
385
386 private:
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000387 virtual void ComputeCallerState(State* state) const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000388 virtual Type GetCallerState(State* state) const;
389
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000390 friend class StackFrameIteratorBase;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000391};
392
393
394class EntryConstructFrame: public EntryFrame {
395 public:
396 virtual Type type() const { return ENTRY_CONSTRUCT; }
397
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000398 virtual Code* unchecked_code() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000399
400 static EntryConstructFrame* cast(StackFrame* frame) {
401 ASSERT(frame->is_entry_construct());
402 return static_cast<EntryConstructFrame*>(frame);
403 }
404
405 protected:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000406 inline explicit EntryConstructFrame(StackFrameIteratorBase* iterator);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000407
408 private:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000409 friend class StackFrameIteratorBase;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000410};
411
412
413// Exit frames are used to exit JavaScript execution and go to C.
414class ExitFrame: public StackFrame {
415 public:
416 virtual Type type() const { return EXIT; }
417
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000418 virtual Code* unchecked_code() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000419
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000420 Object*& code_slot() const;
421
ager@chromium.org32912102009-01-16 10:38:43 +0000422 // Garbage collection support.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000423 virtual void Iterate(ObjectVisitor* v) const;
424
ager@chromium.org357bf652010-04-12 11:30:10 +0000425 virtual void SetCallerFp(Address caller_fp);
426
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000427 static ExitFrame* cast(StackFrame* frame) {
428 ASSERT(frame->is_exit());
429 return static_cast<ExitFrame*>(frame);
430 }
431
432 // Compute the state and type of an exit frame given a frame
433 // pointer. Used when constructing the first stack frame seen by an
434 // iterator and the frames following entry frames.
435 static Type GetStateForFramePointer(Address fp, State* state);
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000436 static Address ComputeStackPointer(Address fp);
437 static void FillState(Address fp, Address sp, State* state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000438
439 protected:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000440 inline explicit ExitFrame(StackFrameIteratorBase* iterator);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000441
442 virtual Address GetCallerStackPointer() const;
443
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000444 private:
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000445 virtual void ComputeCallerState(State* state) const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000446
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000447 friend class StackFrameIteratorBase;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000448};
449
450
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000451class StandardFrame: public StackFrame {
452 public:
453 // Testers.
454 virtual bool is_standard() const { return true; }
455
456 // Accessors.
457 inline Object* context() const;
458
459 // Access the expressions in the stack frame including locals.
460 inline Object* GetExpression(int index) const;
461 inline void SetExpression(int index, Object* value);
462 int ComputeExpressionsCount() const;
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000463 static Object* GetExpression(Address fp, int index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000464
ager@chromium.org357bf652010-04-12 11:30:10 +0000465 virtual void SetCallerFp(Address caller_fp);
466
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000467 static StandardFrame* cast(StackFrame* frame) {
468 ASSERT(frame->is_standard());
469 return static_cast<StandardFrame*>(frame);
470 }
471
472 protected:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000473 inline explicit StandardFrame(StackFrameIteratorBase* iterator);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000474
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000475 virtual void ComputeCallerState(State* state) const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000476
477 // Accessors.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000478 inline Address caller_fp() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000479 inline Address caller_pc() const;
480
481 // Computes the address of the PC field in the standard frame given
482 // by the provided frame pointer.
483 static inline Address ComputePCAddress(Address fp);
484
485 // Iterate over expression stack including stack handlers, locals,
486 // and parts of the fixed part including context and code fields.
487 void IterateExpressions(ObjectVisitor* v) const;
488
489 // Returns the address of the n'th expression stack element.
490 Address GetExpressionAddress(int n) const;
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000491 static Address GetExpressionAddress(Address fp, int n);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000492
493 // Determines if the n'th expression stack element is in a stack
494 // handler or not. Requires traversing all handlers in this frame.
495 bool IsExpressionInsideHandler(int n) const;
496
497 // Determines if the standard frame for the given frame pointer is
498 // an arguments adaptor frame.
499 static inline bool IsArgumentsAdaptorFrame(Address fp);
500
ager@chromium.org7c537e22008-10-16 08:43:32 +0000501 // Determines if the standard frame for the given frame pointer is a
502 // construct frame.
503 static inline bool IsConstructFrame(Address fp);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000504
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000505 // Used by OptimizedFrames and StubFrames.
506 void IterateCompiledFrame(ObjectVisitor* v) const;
507
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000508 private:
509 friend class StackFrame;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000510 friend class SafeStackFrameIterator;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000511};
512
513
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000514class FrameSummary BASE_EMBEDDED {
515 public:
516 FrameSummary(Object* receiver,
517 JSFunction* function,
518 Code* code,
519 int offset,
520 bool is_constructor)
ulan@chromium.org09d7ab52013-02-25 15:50:35 +0000521 : receiver_(receiver, function->GetIsolate()),
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000522 function_(function),
523 code_(code),
524 offset_(offset),
525 is_constructor_(is_constructor) { }
526 Handle<Object> receiver() { return receiver_; }
527 Handle<JSFunction> function() { return function_; }
528 Handle<Code> code() { return code_; }
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000529 Address pc() { return code_->address() + offset_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000530 int offset() { return offset_; }
531 bool is_constructor() { return is_constructor_; }
532
533 void Print();
534
535 private:
536 Handle<Object> receiver_;
537 Handle<JSFunction> function_;
538 Handle<Code> code_;
539 int offset_;
540 bool is_constructor_;
541};
542
543
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000544class JavaScriptFrame: public StandardFrame {
545 public:
546 virtual Type type() const { return JAVA_SCRIPT; }
547
548 // Accessors.
danno@chromium.org169691d2013-07-15 08:01:13 +0000549 inline JSFunction* function() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000550 inline Object* receiver() const;
551 inline void set_receiver(Object* value);
552
553 // Access the parameters.
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000554 inline Address GetParameterSlot(int index) const;
555 inline Object* GetParameter(int index) const;
556 inline int ComputeParametersCount() const {
557 return GetNumberOfIncomingArguments();
558 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000559
danno@chromium.orgf005df62013-04-30 16:36:45 +0000560 // Access the operand stack.
561 inline Address GetOperandSlot(int index) const;
562 inline Object* GetOperand(int index) const;
563 inline int ComputeOperandsCount() const;
564
ulan@chromium.org57ff8812013-05-10 08:16:55 +0000565 // Generator support to preserve operand stack and stack handlers.
566 void SaveOperandStack(FixedArray* store, int* stack_handler_index) const;
567 void RestoreOperandStack(FixedArray* store, int stack_handler_index);
568
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000569 // Debugger access.
570 void SetParameterValue(int index, Object* value) const;
571
ager@chromium.org7c537e22008-10-16 08:43:32 +0000572 // Check if this frame is a constructor frame invoked through 'new'.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000573 bool IsConstructor() const;
574
575 // Check if this frame has "adapted" arguments in the sense that the
576 // actual passed arguments are available in an arguments adaptor
577 // frame below it on the stack.
578 inline bool has_adapted_arguments() const;
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000579 int GetArgumentsLength() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000580
ager@chromium.org32912102009-01-16 10:38:43 +0000581 // Garbage collection support.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000582 virtual void Iterate(ObjectVisitor* v) const;
583
584 // Printing support.
585 virtual void Print(StringStream* accumulator,
586 PrintMode mode,
587 int index) const;
588
589 // Determine the code for the frame.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000590 virtual Code* unchecked_code() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000591
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000592 // Returns the levels of inlining for this frame.
593 virtual int GetInlineCount() { return 1; }
594
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000595 // Return a list with JSFunctions of this frame.
596 virtual void GetFunctions(List<JSFunction*>* functions);
597
598 // Build a list with summaries for this frame including all inlined frames.
599 virtual void Summarize(List<FrameSummary>* frames);
600
jkummerow@chromium.org4e308cf2013-05-17 13:39:16 +0000601 // Architecture-specific register description.
602 static Register fp_register();
603 static Register context_register();
604
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000605 static JavaScriptFrame* cast(StackFrame* frame) {
606 ASSERT(frame->is_java_script());
607 return static_cast<JavaScriptFrame*>(frame);
608 }
609
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000610 static void PrintTop(Isolate* isolate,
611 FILE* file,
612 bool print_args,
613 bool print_line_number);
erik.corry@gmail.com394dbcf2011-10-27 07:38:48 +0000614
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000615 protected:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000616 inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000617
618 virtual Address GetCallerStackPointer() const;
619
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000620 virtual int GetNumberOfIncomingArguments() const;
621
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000622 // Garbage collection support. Iterates over incoming arguments,
623 // receiver, and any callee-saved registers.
624 void IterateArguments(ObjectVisitor* v) const;
625
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000626 private:
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000627 inline Object* function_slot_object() const;
628
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000629 friend class StackFrameIteratorBase;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000630};
631
632
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000633class StubFrame : public StandardFrame {
634 public:
635 virtual Type type() const { return STUB; }
636
637 // GC support.
638 virtual void Iterate(ObjectVisitor* v) const;
639
640 // Determine the code for the frame.
641 virtual Code* unchecked_code() const;
642
643 protected:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000644 inline explicit StubFrame(StackFrameIteratorBase* iterator);
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000645
646 virtual Address GetCallerStackPointer() const;
647
648 virtual int GetNumberOfIncomingArguments() const;
649
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000650 friend class StackFrameIteratorBase;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000651};
652
653
jkummerow@chromium.org5323a9c2012-12-10 19:00:50 +0000654class OptimizedFrame : public JavaScriptFrame {
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000655 public:
656 virtual Type type() const { return OPTIMIZED; }
657
658 // GC support.
659 virtual void Iterate(ObjectVisitor* v) const;
660
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000661 virtual int GetInlineCount();
662
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000663 // Return a list with JSFunctions of this frame.
664 // The functions are ordered bottom-to-top (i.e. functions.last()
665 // is the top-most activation)
666 virtual void GetFunctions(List<JSFunction*>* functions);
667
668 virtual void Summarize(List<FrameSummary>* frames);
669
670 DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
671
672 protected:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000673 inline explicit OptimizedFrame(StackFrameIteratorBase* iterator);
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000674
675 private:
yangguo@chromium.org5a11aaf2012-06-20 11:29:00 +0000676 JSFunction* LiteralAt(FixedArray* literal_array, int literal_id);
677
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000678 friend class StackFrameIteratorBase;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000679};
680
681
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000682// Arguments adaptor frames are automatically inserted below
683// JavaScript frames when the actual number of parameters does not
684// match the formal number of parameters.
685class ArgumentsAdaptorFrame: public JavaScriptFrame {
686 public:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000687 virtual Type type() const { return ARGUMENTS_ADAPTOR; }
688
689 // Determine the code for the frame.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000690 virtual Code* unchecked_code() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000691
692 static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
693 ASSERT(frame->is_arguments_adaptor());
694 return static_cast<ArgumentsAdaptorFrame*>(frame);
695 }
696
697 // Printing support.
698 virtual void Print(StringStream* accumulator,
699 PrintMode mode,
700 int index) const;
kmillikin@chromium.org83e16822011-09-13 08:21:47 +0000701
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000702 protected:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000703 inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000704
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000705 virtual int GetNumberOfIncomingArguments() const;
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000706
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000707 virtual Address GetCallerStackPointer() const;
708
709 private:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000710 friend class StackFrameIteratorBase;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000711};
712
713
714class InternalFrame: public StandardFrame {
715 public:
716 virtual Type type() const { return INTERNAL; }
717
ager@chromium.org32912102009-01-16 10:38:43 +0000718 // Garbage collection support.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000719 virtual void Iterate(ObjectVisitor* v) const;
720
721 // Determine the code for the frame.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000722 virtual Code* unchecked_code() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000723
724 static InternalFrame* cast(StackFrame* frame) {
725 ASSERT(frame->is_internal());
726 return static_cast<InternalFrame*>(frame);
727 }
728
729 protected:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000730 inline explicit InternalFrame(StackFrameIteratorBase* iterator);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000731
732 virtual Address GetCallerStackPointer() const;
733
734 private:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000735 friend class StackFrameIteratorBase;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000736};
737
738
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000739class StubFailureTrampolineFrame: public StandardFrame {
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000740 public:
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000741 // sizeof(Arguments) - sizeof(Arguments*) is 3 * kPointerSize), but the
742 // presubmit script complains about using sizeof() on a type.
743 static const int kFirstRegisterParameterFrameOffset =
744 StandardFrameConstants::kMarkerOffset - 3 * kPointerSize;
745
746 static const int kCallerStackParameterCountFrameOffset =
747 StandardFrameConstants::kMarkerOffset - 2 * kPointerSize;
748
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000749 virtual Type type() const { return STUB_FAILURE_TRAMPOLINE; }
750
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000751 // Get the code associated with this frame.
752 // This method could be called during marking phase of GC.
753 virtual Code* unchecked_code() const;
754
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000755 virtual void Iterate(ObjectVisitor* v) const;
756
ulan@chromium.org6e196bf2013-03-13 09:38:22 +0000757 // Architecture-specific register description.
758 static Register fp_register();
759 static Register context_register();
760
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000761 protected:
762 inline explicit StubFailureTrampolineFrame(
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000763 StackFrameIteratorBase* iterator);
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000764
mmassi@chromium.org2f0efde2013-02-06 14:12:58 +0000765 virtual Address GetCallerStackPointer() const;
766
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000767 private:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000768 friend class StackFrameIteratorBase;
mstarzinger@chromium.org068ea0a2013-01-30 09:39:44 +0000769};
770
771
ager@chromium.org7c537e22008-10-16 08:43:32 +0000772// Construct frames are special trampoline frames introduced to handle
773// function invocations through 'new'.
774class ConstructFrame: public InternalFrame {
775 public:
776 virtual Type type() const { return CONSTRUCT; }
777
778 static ConstructFrame* cast(StackFrame* frame) {
779 ASSERT(frame->is_construct());
780 return static_cast<ConstructFrame*>(frame);
781 }
782
783 protected:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000784 inline explicit ConstructFrame(StackFrameIteratorBase* iterator);
ager@chromium.org7c537e22008-10-16 08:43:32 +0000785
786 private:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000787 friend class StackFrameIteratorBase;
ager@chromium.org7c537e22008-10-16 08:43:32 +0000788};
789
790
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000791class StackFrameIteratorBase BASE_EMBEDDED {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000792 public:
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000793 Isolate* isolate() const { return isolate_; }
794
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000795 bool done() const { return frame_ == NULL; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000796
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000797 protected:
798 // An iterator that iterates over a given thread's stack.
799 StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000800
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000801 Isolate* isolate_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000802#define DECLARE_SINGLETON(ignore, type) type type##_;
803 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
804#undef DECLARE_SINGLETON
805 StackFrame* frame_;
806 StackHandler* handler_;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000807 const bool can_access_heap_objects_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000808
809 StackHandler* handler() const {
810 ASSERT(!done());
811 return handler_;
812 }
813
814 // Get the type-specific frame singleton in a given state.
815 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000816 // A helper function, can return a NULL pointer.
817 StackFrame* SingletonFor(StackFrame::Type type);
818
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000819 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000820 friend class StackFrame;
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000821 DISALLOW_COPY_AND_ASSIGN(StackFrameIteratorBase);
822};
823
824
825class StackFrameIterator: public StackFrameIteratorBase {
826 public:
827 // An iterator that iterates over the isolate's current thread's stack,
828 explicit StackFrameIterator(Isolate* isolate);
829 // An iterator that iterates over a given thread's stack.
830 StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
831
832 StackFrame* frame() const {
833 ASSERT(!done());
834 return frame_;
835 }
836 void Advance();
837
838 private:
839 // Go back to the first frame.
840 void Reset(ThreadLocalTop* top);
841
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000842 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000843};
844
845
846// Iterator that supports iterating through all JavaScript frames.
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000847class JavaScriptFrameIterator BASE_EMBEDDED {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000848 public:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000849 inline explicit JavaScriptFrameIterator(Isolate* isolate);
850 inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000851 // Skip frames until the frame with the given id is reached.
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000852 JavaScriptFrameIterator(Isolate* isolate, StackFrame::Id id);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000853
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000854 inline JavaScriptFrame* frame() const;
855
856 bool done() const { return iterator_.done(); }
857 void Advance();
858
859 // Advance to the frame holding the arguments for the current
860 // frame. This only affects the current frame if it has adapted
861 // arguments.
862 void AdvanceToArgumentsFrame();
863
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000864 private:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000865 StackFrameIterator iterator_;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000866};
867
868
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000869// NOTE: The stack trace frame iterator is an iterator that only
870// traverse proper JavaScript frames; that is JavaScript frames that
871// have proper JavaScript functions. This excludes the problematic
872// functions in runtime.js.
873class StackTraceFrameIterator: public JavaScriptFrameIterator {
874 public:
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000875 explicit StackTraceFrameIterator(Isolate* isolate);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000876 void Advance();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000877
878 private:
879 bool IsValidFrame();
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000880};
881
882
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000883class SafeStackFrameIterator: public StackFrameIteratorBase {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000884 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000885 SafeStackFrameIterator(Isolate* isolate,
886 Address fp, Address sp,
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +0000887 Address js_entry_sp);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000888
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000889 inline StackFrame* frame() const;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000890 void Advance();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000891
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +0000892 StackFrame::Type top_frame_type() const { return top_frame_type_; }
893
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000894 private:
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000895 void AdvanceOneFrame();
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000896
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000897 bool IsValidStackAddress(Address addr) const {
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000898 return low_bound_ <= addr && addr <= high_bound_;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000899 }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000900 bool IsValidFrame(StackFrame* frame) const;
901 bool IsValidCaller(StackFrame* frame);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000902 bool IsValidExitFrame(Address fp) const;
903 bool IsValidTop(ThreadLocalTop* top) const;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000904
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +0000905 const Address low_bound_;
906 const Address high_bound_;
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +0000907 StackFrame::Type top_frame_type_;
yangguo@chromium.orgc73d55b2013-07-24 08:18:28 +0000908 ExternalCallbackScope* external_callback_scope_;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000909};
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000910
911
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000912class StackFrameLocator BASE_EMBEDDED {
913 public:
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000914 explicit StackFrameLocator(Isolate* isolate) : iterator_(isolate) {}
915
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000916 // Find the nth JavaScript frame on the stack. The caller must
917 // guarantee that such a frame exists.
918 JavaScriptFrame* FindJavaScriptFrame(int n);
919
920 private:
921 StackFrameIterator iterator_;
922};
923
924
ager@chromium.org357bf652010-04-12 11:30:10 +0000925// Reads all frames on the current stack and copies them into the current
926// zone memory.
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000927Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone);
ager@chromium.org357bf652010-04-12 11:30:10 +0000928
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000929} } // namespace v8::internal
930
931#endif // V8_FRAMES_H_