blob: 4f94ebc7d1d7d26cefbcd8c38cfde81493091f48 [file] [log] [blame]
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +00001// Copyright 2011 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
43// Return the code of the n-th saved register available to JavaScript.
44int JSCallerSavedCode(int n);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000045
46
47// Forward declarations.
48class StackFrameIterator;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000049class ThreadLocalTop;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000050class Isolate;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000051
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000052class PcToCodeCache {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000053 public:
54 struct PcToCodeCacheEntry {
55 Address pc;
56 Code* code;
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +000057 SafepointEntry safepoint_entry;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000058 };
59
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000060 explicit PcToCodeCache(Isolate* isolate) : isolate_(isolate) {
61 Flush();
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000062 }
63
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000064 Code* GcSafeFindCodeForPc(Address pc);
65 Code* GcSafeCastToCode(HeapObject* object, Address pc);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000066
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000067 void Flush() {
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000068 memset(&cache_[0], 0, sizeof(cache_));
69 }
70
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000071 PcToCodeCacheEntry* GetCacheEntry(Address pc);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000072
73 private:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000074 PcToCodeCacheEntry* cache(int index) { return &cache_[index]; }
75
76 Isolate* isolate_;
77
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000078 static const int kPcToCodeCacheSize = 1024;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +000079 PcToCodeCacheEntry cache_[kPcToCodeCacheSize];
80
81 DISALLOW_COPY_AND_ASSIGN(PcToCodeCache);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000082};
83
84
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000085class StackHandler BASE_EMBEDDED {
86 public:
87 enum State {
88 ENTRY,
89 TRY_CATCH,
90 TRY_FINALLY
91 };
92
93 // Get the address of this stack handler.
94 inline Address address() const;
95
96 // Get the next stack handler in the chain.
97 inline StackHandler* next() const;
98
99 // Tells whether the given address is inside this handler.
100 inline bool includes(Address address) const;
101
102 // Garbage collection support.
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000103 inline void Iterate(ObjectVisitor* v, Code* holder) const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000104
105 // Conversion support.
106 static inline StackHandler* FromAddress(Address address);
107
108 // Testers
109 bool is_entry() { return state() == ENTRY; }
110 bool is_try_catch() { return state() == TRY_CATCH; }
111 bool is_try_finally() { return state() == TRY_FINALLY; }
112
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000113 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000114 // Accessors.
115 inline State state() const;
116
whesse@chromium.org4acdc2c2011-08-15 13:01:23 +0000117 inline Object** context_address() const;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000118 inline Address* pc_address() const;
mads.s.ager31e71382008-08-13 09:32:07 +0000119
120 DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000121};
122
123
124#define STACK_FRAME_TYPE_LIST(V) \
125 V(ENTRY, EntryFrame) \
126 V(ENTRY_CONSTRUCT, EntryConstructFrame) \
127 V(EXIT, ExitFrame) \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000128 V(JAVA_SCRIPT, JavaScriptFrame) \
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000129 V(OPTIMIZED, OptimizedFrame) \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000130 V(INTERNAL, InternalFrame) \
ager@chromium.org7c537e22008-10-16 08:43:32 +0000131 V(CONSTRUCT, ConstructFrame) \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000132 V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
133
134
135// Abstract base class for all stack frames.
136class StackFrame BASE_EMBEDDED {
137 public:
138#define DECLARE_TYPE(type, ignore) type,
139 enum Type {
140 NONE = 0,
141 STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
142 NUMBER_OF_TYPES
143 };
144#undef DECLARE_TYPE
145
146 // Opaque data type for identifying stack frames. Used extensively
147 // by the debugger.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000148 // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
149 // has correct value range (see Issue 830 for more details).
150 enum Id {
151 ID_MIN_VALUE = kMinInt,
152 ID_MAX_VALUE = kMaxInt,
153 NO_ID = 0
154 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000155
kmillikin@chromium.orgc53e10d2011-05-18 09:12:58 +0000156 // Used to mark the outermost JS entry frame.
157 enum JsFrameMarker {
158 INNER_JSENTRY_FRAME = 0,
159 OUTERMOST_JSENTRY_FRAME = 1
160 };
161
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000162 struct State {
163 State() : sp(NULL), fp(NULL), pc_address(NULL) { }
164 Address sp;
165 Address fp;
166 Address* pc_address;
167 };
168
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000169 // Copy constructor; it breaks the connection to host iterator
170 // (as an iterator usually lives on stack).
ager@chromium.org357bf652010-04-12 11:30:10 +0000171 StackFrame(const StackFrame& original) {
172 this->state_ = original.state_;
173 this->iterator_ = NULL;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000174 this->isolate_ = original.isolate_;
ager@chromium.org357bf652010-04-12 11:30:10 +0000175 }
176
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000177 // Type testers.
178 bool is_entry() const { return type() == ENTRY; }
179 bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
180 bool is_exit() const { return type() == EXIT; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000181 bool is_optimized() const { return type() == OPTIMIZED; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000182 bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
183 bool is_internal() const { return type() == INTERNAL; }
ager@chromium.org7c537e22008-10-16 08:43:32 +0000184 bool is_construct() const { return type() == CONSTRUCT; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000185 virtual bool is_standard() const { return false; }
186
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000187 bool is_java_script() const {
188 Type type = this->type();
189 return (type == JAVA_SCRIPT) || (type == OPTIMIZED);
190 }
191
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000192 // Accessors.
193 Address sp() const { return state_.sp; }
194 Address fp() const { return state_.fp; }
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000195 Address caller_sp() const { return GetCallerStackPointer(); }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000196
197 Address pc() const { return *pc_address(); }
198 void set_pc(Address pc) { *pc_address() = pc; }
199
ager@chromium.org357bf652010-04-12 11:30:10 +0000200 virtual void SetCallerFp(Address caller_fp) = 0;
201
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000202 Address* pc_address() const { return state_.pc_address; }
203
204 // Get the id of this stack frame.
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000205 Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000206
207 // Checks if this frame includes any stack handlers.
208 bool HasHandler() const;
209
210 // Get the type of this frame.
211 virtual Type type() const = 0;
212
213 // Get the code associated with this frame.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000214 // This method could be called during marking phase of GC.
215 virtual Code* unchecked_code() const = 0;
216
217 // Get the code associated with this frame.
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000218 Code* LookupCode() const {
219 return GetContainingCode(isolate(), pc());
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000220 }
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000221
222 // Get the code object that contains the given pc.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000223 static inline Code* GetContainingCode(Isolate* isolate, Address pc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000224
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000225 // Get the code object containing the given pc and fill in the
226 // safepoint entry and the number of stack slots. The pc must be at
227 // a safepoint.
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000228 static Code* GetSafepointData(Isolate* isolate,
229 Address pc,
sgjesse@chromium.orgc6c57182011-01-17 12:24:25 +0000230 SafepointEntry* safepoint_entry,
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000231 unsigned* stack_slots);
232
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000233 virtual void Iterate(ObjectVisitor* v) const = 0;
234 static void IteratePc(ObjectVisitor* v, Address* pc_address, Code* holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000235
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000236
237 // Printing support.
238 enum PrintMode { OVERVIEW, DETAILS };
239 virtual void Print(StringStream* accumulator,
240 PrintMode mode,
241 int index) const { }
242
243 protected:
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000244 inline explicit StackFrame(StackFrameIterator* iterator);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000245 virtual ~StackFrame() { }
246
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000247 Isolate* isolate() const { return isolate_; }
248
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000249 // Compute the stack pointer for the calling frame.
250 virtual Address GetCallerStackPointer() const = 0;
251
252 // Printing support.
253 static void PrintIndex(StringStream* accumulator,
254 PrintMode mode,
255 int index);
256
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000257 // Get the top handler from the current stack iterator.
258 inline StackHandler* top_handler() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000259
260 // Compute the stack frame type for the given state.
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000261 static Type ComputeType(Isolate* isolate, State* state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000262
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000263 private:
264 const StackFrameIterator* iterator_;
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000265 Isolate* isolate_;
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000266 State state_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000267
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000268 // Fill in the state of the calling frame.
269 virtual void ComputeCallerState(State* state) const = 0;
270
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000271 // Get the type and the state of the calling frame.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000272 virtual Type GetCallerState(State* state) const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000273
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000274 static const intptr_t kIsolateTag = 1;
275
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000276 friend class StackFrameIterator;
277 friend class StackHandlerIterator;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000278 friend class SafeStackFrameIterator;
mads.s.ager31e71382008-08-13 09:32:07 +0000279
ager@chromium.org357bf652010-04-12 11:30:10 +0000280 private:
281 void operator=(const StackFrame& original);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000282};
283
284
285// Entry frames are used to enter JavaScript execution from C.
286class EntryFrame: public StackFrame {
287 public:
288 virtual Type type() const { return ENTRY; }
289
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000290 virtual Code* unchecked_code() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000291
292 // Garbage collection support.
293 virtual void Iterate(ObjectVisitor* v) const;
294
295 static EntryFrame* cast(StackFrame* frame) {
296 ASSERT(frame->is_entry());
297 return static_cast<EntryFrame*>(frame);
298 }
ager@chromium.org357bf652010-04-12 11:30:10 +0000299 virtual void SetCallerFp(Address caller_fp);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000300
301 protected:
302 explicit EntryFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
303
304 // The caller stack pointer for entry frames is always zero. The
305 // real information about the caller frame is available through the
306 // link to the top exit frame.
307 virtual Address GetCallerStackPointer() const { return 0; }
308
309 private:
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000310 virtual void ComputeCallerState(State* state) const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000311 virtual Type GetCallerState(State* state) const;
312
313 friend class StackFrameIterator;
314};
315
316
317class EntryConstructFrame: public EntryFrame {
318 public:
319 virtual Type type() const { return ENTRY_CONSTRUCT; }
320
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000321 virtual Code* unchecked_code() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000322
323 static EntryConstructFrame* cast(StackFrame* frame) {
324 ASSERT(frame->is_entry_construct());
325 return static_cast<EntryConstructFrame*>(frame);
326 }
327
328 protected:
329 explicit EntryConstructFrame(StackFrameIterator* iterator)
330 : EntryFrame(iterator) { }
331
332 private:
333 friend class StackFrameIterator;
334};
335
336
337// Exit frames are used to exit JavaScript execution and go to C.
338class ExitFrame: public StackFrame {
339 public:
340 virtual Type type() const { return EXIT; }
341
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000342 virtual Code* unchecked_code() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000343
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000344 Object*& code_slot() const;
345
ager@chromium.org32912102009-01-16 10:38:43 +0000346 // Garbage collection support.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000347 virtual void Iterate(ObjectVisitor* v) const;
348
ager@chromium.org357bf652010-04-12 11:30:10 +0000349 virtual void SetCallerFp(Address caller_fp);
350
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000351 static ExitFrame* cast(StackFrame* frame) {
352 ASSERT(frame->is_exit());
353 return static_cast<ExitFrame*>(frame);
354 }
355
356 // Compute the state and type of an exit frame given a frame
357 // pointer. Used when constructing the first stack frame seen by an
358 // iterator and the frames following entry frames.
359 static Type GetStateForFramePointer(Address fp, State* state);
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000360 static Address ComputeStackPointer(Address fp);
361 static void FillState(Address fp, Address sp, State* state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000362
363 protected:
364 explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
365
366 virtual Address GetCallerStackPointer() const;
367
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000368 private:
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000369 virtual void ComputeCallerState(State* state) const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000370
371 friend class StackFrameIterator;
372};
373
374
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000375class StandardFrame: public StackFrame {
376 public:
377 // Testers.
378 virtual bool is_standard() const { return true; }
379
380 // Accessors.
381 inline Object* context() const;
382
383 // Access the expressions in the stack frame including locals.
384 inline Object* GetExpression(int index) const;
385 inline void SetExpression(int index, Object* value);
386 int ComputeExpressionsCount() const;
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000387 static Object* GetExpression(Address fp, int index);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000388
ager@chromium.org357bf652010-04-12 11:30:10 +0000389 virtual void SetCallerFp(Address caller_fp);
390
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000391 static StandardFrame* cast(StackFrame* frame) {
392 ASSERT(frame->is_standard());
393 return static_cast<StandardFrame*>(frame);
394 }
395
396 protected:
397 explicit StandardFrame(StackFrameIterator* iterator)
398 : StackFrame(iterator) { }
399
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000400 virtual void ComputeCallerState(State* state) const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000401
402 // Accessors.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000403 inline Address caller_fp() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000404 inline Address caller_pc() const;
405
406 // Computes the address of the PC field in the standard frame given
407 // by the provided frame pointer.
408 static inline Address ComputePCAddress(Address fp);
409
410 // Iterate over expression stack including stack handlers, locals,
411 // and parts of the fixed part including context and code fields.
412 void IterateExpressions(ObjectVisitor* v) const;
413
414 // Returns the address of the n'th expression stack element.
415 Address GetExpressionAddress(int n) const;
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000416 static Address GetExpressionAddress(Address fp, int n);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000417
418 // Determines if the n'th expression stack element is in a stack
419 // handler or not. Requires traversing all handlers in this frame.
420 bool IsExpressionInsideHandler(int n) const;
421
422 // Determines if the standard frame for the given frame pointer is
423 // an arguments adaptor frame.
424 static inline bool IsArgumentsAdaptorFrame(Address fp);
425
ager@chromium.org7c537e22008-10-16 08:43:32 +0000426 // Determines if the standard frame for the given frame pointer is a
427 // construct frame.
428 static inline bool IsConstructFrame(Address fp);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000429
430 private:
431 friend class StackFrame;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000432 friend class StackFrameIterator;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000433};
434
435
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000436class FrameSummary BASE_EMBEDDED {
437 public:
438 FrameSummary(Object* receiver,
439 JSFunction* function,
440 Code* code,
441 int offset,
442 bool is_constructor)
443 : receiver_(receiver),
444 function_(function),
445 code_(code),
446 offset_(offset),
447 is_constructor_(is_constructor) { }
448 Handle<Object> receiver() { return receiver_; }
449 Handle<JSFunction> function() { return function_; }
450 Handle<Code> code() { return code_; }
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000451 Address pc() { return code_->address() + offset_; }
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000452 int offset() { return offset_; }
453 bool is_constructor() { return is_constructor_; }
454
455 void Print();
456
457 private:
458 Handle<Object> receiver_;
459 Handle<JSFunction> function_;
460 Handle<Code> code_;
461 int offset_;
462 bool is_constructor_;
463};
464
465
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000466class JavaScriptFrame: public StandardFrame {
467 public:
468 virtual Type type() const { return JAVA_SCRIPT; }
469
470 // Accessors.
471 inline Object* function() const;
472 inline Object* receiver() const;
473 inline void set_receiver(Object* value);
474
475 // Access the parameters.
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000476 inline Address GetParameterSlot(int index) const;
477 inline Object* GetParameter(int index) const;
478 inline int ComputeParametersCount() const {
479 return GetNumberOfIncomingArguments();
480 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000481
ager@chromium.org7c537e22008-10-16 08:43:32 +0000482 // Check if this frame is a constructor frame invoked through 'new'.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000483 bool IsConstructor() const;
484
485 // Check if this frame has "adapted" arguments in the sense that the
486 // actual passed arguments are available in an arguments adaptor
487 // frame below it on the stack.
488 inline bool has_adapted_arguments() const;
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000489 int GetArgumentsLength() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000490
ager@chromium.org32912102009-01-16 10:38:43 +0000491 // Garbage collection support.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000492 virtual void Iterate(ObjectVisitor* v) const;
493
494 // Printing support.
495 virtual void Print(StringStream* accumulator,
496 PrintMode mode,
497 int index) const;
498
499 // Determine the code for the frame.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000500 virtual Code* unchecked_code() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000501
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000502 // Returns the levels of inlining for this frame.
503 virtual int GetInlineCount() { return 1; }
504
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000505 // Return a list with JSFunctions of this frame.
506 virtual void GetFunctions(List<JSFunction*>* functions);
507
508 // Build a list with summaries for this frame including all inlined frames.
509 virtual void Summarize(List<FrameSummary>* frames);
510
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000511 static JavaScriptFrame* cast(StackFrame* frame) {
512 ASSERT(frame->is_java_script());
513 return static_cast<JavaScriptFrame*>(frame);
514 }
515
516 protected:
517 explicit JavaScriptFrame(StackFrameIterator* iterator)
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000518 : StandardFrame(iterator) { }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000519
520 virtual Address GetCallerStackPointer() const;
521
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000522 virtual int GetNumberOfIncomingArguments() const;
523
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000524 // Garbage collection support. Iterates over incoming arguments,
525 // receiver, and any callee-saved registers.
526 void IterateArguments(ObjectVisitor* v) const;
527
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000528 private:
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000529 inline Object* function_slot_object() const;
530
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000531 friend class StackFrameIterator;
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000532 friend class StackTracer;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000533};
534
535
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000536class OptimizedFrame : public JavaScriptFrame {
537 public:
538 virtual Type type() const { return OPTIMIZED; }
539
540 // GC support.
541 virtual void Iterate(ObjectVisitor* v) const;
542
ricow@chromium.org4f693d62011-07-04 14:01:31 +0000543 virtual int GetInlineCount();
544
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000545 // Return a list with JSFunctions of this frame.
546 // The functions are ordered bottom-to-top (i.e. functions.last()
547 // is the top-most activation)
548 virtual void GetFunctions(List<JSFunction*>* functions);
549
550 virtual void Summarize(List<FrameSummary>* frames);
551
552 DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
553
554 protected:
555 explicit OptimizedFrame(StackFrameIterator* iterator)
556 : JavaScriptFrame(iterator) { }
557
558 private:
559 friend class StackFrameIterator;
560};
561
562
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000563// Arguments adaptor frames are automatically inserted below
564// JavaScript frames when the actual number of parameters does not
565// match the formal number of parameters.
566class ArgumentsAdaptorFrame: public JavaScriptFrame {
567 public:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000568 virtual Type type() const { return ARGUMENTS_ADAPTOR; }
569
570 // Determine the code for the frame.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000571 virtual Code* unchecked_code() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000572
573 static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
574 ASSERT(frame->is_arguments_adaptor());
575 return static_cast<ArgumentsAdaptorFrame*>(frame);
576 }
577
578 // Printing support.
579 virtual void Print(StringStream* accumulator,
580 PrintMode mode,
581 int index) const;
582 protected:
583 explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator)
584 : JavaScriptFrame(iterator) { }
585
karlklose@chromium.org44bc7082011-04-11 12:33:05 +0000586 virtual int GetNumberOfIncomingArguments() const {
587 return Smi::cast(GetExpression(0))->value();
588 }
589
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000590 virtual Address GetCallerStackPointer() const;
591
592 private:
593 friend class StackFrameIterator;
594};
595
596
597class InternalFrame: public StandardFrame {
598 public:
599 virtual Type type() const { return INTERNAL; }
600
ager@chromium.org32912102009-01-16 10:38:43 +0000601 // Garbage collection support.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000602 virtual void Iterate(ObjectVisitor* v) const;
603
604 // Determine the code for the frame.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000605 virtual Code* unchecked_code() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000606
607 static InternalFrame* cast(StackFrame* frame) {
608 ASSERT(frame->is_internal());
609 return static_cast<InternalFrame*>(frame);
610 }
611
612 protected:
613 explicit InternalFrame(StackFrameIterator* iterator)
614 : StandardFrame(iterator) { }
615
616 virtual Address GetCallerStackPointer() const;
617
618 private:
619 friend class StackFrameIterator;
620};
621
622
ager@chromium.org7c537e22008-10-16 08:43:32 +0000623// Construct frames are special trampoline frames introduced to handle
624// function invocations through 'new'.
625class ConstructFrame: public InternalFrame {
626 public:
627 virtual Type type() const { return CONSTRUCT; }
628
629 static ConstructFrame* cast(StackFrame* frame) {
630 ASSERT(frame->is_construct());
631 return static_cast<ConstructFrame*>(frame);
632 }
633
634 protected:
635 explicit ConstructFrame(StackFrameIterator* iterator)
636 : InternalFrame(iterator) { }
637
638 private:
639 friend class StackFrameIterator;
640};
641
642
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000643class StackFrameIterator BASE_EMBEDDED {
644 public:
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000645 // An iterator that iterates over the current thread's stack,
646 // and uses current isolate.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000647 StackFrameIterator();
648
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000649 // An iterator that iterates over the isolate's current thread's stack,
650 explicit StackFrameIterator(Isolate* isolate);
651
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000652 // An iterator that iterates over a given thread's stack.
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000653 StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000654
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000655 // An iterator that can start from a given FP address.
656 // If use_top, then work as usual, if fp isn't NULL, use it,
657 // otherwise, do nothing.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000658 StackFrameIterator(Isolate* isolate, bool use_top, Address fp, Address sp);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000659
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000660 StackFrame* frame() const {
661 ASSERT(!done());
662 return frame_;
663 }
664
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000665 Isolate* isolate() const { return isolate_; }
666
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000667 bool done() const { return frame_ == NULL; }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000668 void Advance() { (this->*advance_)(); }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000669
670 // Go back to the first frame.
671 void Reset();
672
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000673 private:
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000674 Isolate* isolate_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000675#define DECLARE_SINGLETON(ignore, type) type type##_;
676 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
677#undef DECLARE_SINGLETON
678 StackFrame* frame_;
679 StackHandler* handler_;
kasper.lund7276f142008-07-30 08:49:36 +0000680 ThreadLocalTop* thread_;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000681 Address fp_;
682 Address sp_;
683 void (StackFrameIterator::*advance_)();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000684
685 StackHandler* handler() const {
686 ASSERT(!done());
687 return handler_;
688 }
689
690 // Get the type-specific frame singleton in a given state.
691 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000692 // A helper function, can return a NULL pointer.
693 StackFrame* SingletonFor(StackFrame::Type type);
694
695 void AdvanceWithHandler();
696 void AdvanceWithoutHandler();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000697
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000698 friend class StackFrame;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000699 friend class SafeStackFrameIterator;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000700 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000701};
702
703
704// Iterator that supports iterating through all JavaScript frames.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000705template<typename Iterator>
706class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000707 public:
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000708 JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000709
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000710 inline explicit JavaScriptFrameIteratorTemp(Isolate* isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000711
712 // Skip frames until the frame with the given id is reached.
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000713 explicit JavaScriptFrameIteratorTemp(StackFrame::Id id) { AdvanceToId(id); }
714
715 inline JavaScriptFrameIteratorTemp(Isolate* isolate, StackFrame::Id id);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000716
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000717 JavaScriptFrameIteratorTemp(Address fp, Address sp,
718 Address low_bound, Address high_bound) :
719 iterator_(fp, sp, low_bound, high_bound) {
720 if (!done()) Advance();
721 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000722
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000723 JavaScriptFrameIteratorTemp(Isolate* isolate,
724 Address fp, Address sp,
725 Address low_bound, Address high_bound) :
726 iterator_(isolate, fp, sp, low_bound, high_bound) {
727 if (!done()) Advance();
728 }
729
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000730 inline JavaScriptFrame* frame() const;
731
732 bool done() const { return iterator_.done(); }
733 void Advance();
734
735 // Advance to the frame holding the arguments for the current
736 // frame. This only affects the current frame if it has adapted
737 // arguments.
738 void AdvanceToArgumentsFrame();
739
740 // Go back to the first frame.
741 void Reset();
742
743 private:
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000744 inline void AdvanceToId(StackFrame::Id id);
745
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000746 Iterator iterator_;
747};
748
749
750typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
751
752
753// NOTE: The stack trace frame iterator is an iterator that only
754// traverse proper JavaScript frames; that is JavaScript frames that
755// have proper JavaScript functions. This excludes the problematic
756// functions in runtime.js.
757class StackTraceFrameIterator: public JavaScriptFrameIterator {
758 public:
759 StackTraceFrameIterator();
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000760 explicit StackTraceFrameIterator(Isolate* isolate);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000761 void Advance();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000762
763 private:
764 bool IsValidFrame();
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000765};
766
767
768class SafeStackFrameIterator BASE_EMBEDDED {
769 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000770 SafeStackFrameIterator(Isolate* isolate,
771 Address fp, Address sp,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000772 Address low_bound, Address high_bound);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000773
774 StackFrame* frame() const {
775 ASSERT(is_working_iterator_);
776 return iterator_.frame();
777 }
778
779 bool done() const { return iteration_done_ ? true : iterator_.done(); }
780
781 void Advance();
782 void Reset();
783
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000784 static bool is_active(Isolate* isolate);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000785
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000786 static bool IsWithinBounds(
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000787 Address low_bound, Address high_bound, Address addr) {
788 return low_bound <= addr && addr <= high_bound;
789 }
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000790
791 private:
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000792 class StackAddressValidator {
793 public:
794 StackAddressValidator(Address low_bound, Address high_bound)
795 : low_bound_(low_bound), high_bound_(high_bound) { }
796 bool IsValid(Address addr) const {
797 return IsWithinBounds(low_bound_, high_bound_, addr);
798 }
799 private:
800 Address low_bound_;
801 Address high_bound_;
802 };
803
804 class ExitFrameValidator {
805 public:
806 explicit ExitFrameValidator(const StackAddressValidator& validator)
807 : validator_(validator) { }
808 ExitFrameValidator(Address low_bound, Address high_bound)
809 : validator_(low_bound, high_bound) { }
810 bool IsValidFP(Address fp);
811 private:
812 StackAddressValidator validator_;
813 };
814
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000815 bool IsValidStackAddress(Address addr) const {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000816 return stack_validator_.IsValid(addr);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000817 }
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +0000818 bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000819 bool IsValidFrame(StackFrame* frame) const;
820 bool IsValidCaller(StackFrame* frame);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000821 static bool IsValidTop(Isolate* isolate,
822 Address low_bound, Address high_bound);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000823
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000824 // This is a nasty hack to make sure the active count is incremented
825 // before the constructor for the embedded iterator is invoked. This
826 // is needed because the constructor will start looking at frames
827 // right away and we need to make sure it doesn't start inspecting
828 // heap objects.
829 class ActiveCountMaintainer BASE_EMBEDDED {
830 public:
vegorov@chromium.org74f333b2011-04-06 11:17:46 +0000831 explicit ActiveCountMaintainer(Isolate* isolate);
832 ~ActiveCountMaintainer();
833 private:
834 Isolate* isolate_;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000835 };
836
837 ActiveCountMaintainer maintainer_;
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000838 StackAddressValidator stack_validator_;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000839 const bool is_valid_top_;
840 const bool is_valid_fp_;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000841 const bool is_working_iterator_;
842 bool iteration_done_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000843 StackFrameIterator iterator_;
844};
845
846
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000847typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
848 SafeJavaScriptFrameIterator;
849
850
851class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
852 public:
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000853 explicit SafeStackTraceFrameIterator(Isolate* isolate,
854 Address fp, Address sp,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000855 Address low_bound, Address high_bound);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000856 void Advance();
857};
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000858
859
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000860class StackFrameLocator BASE_EMBEDDED {
861 public:
862 // Find the nth JavaScript frame on the stack. The caller must
863 // guarantee that such a frame exists.
864 JavaScriptFrame* FindJavaScriptFrame(int n);
865
866 private:
867 StackFrameIterator iterator_;
868};
869
870
ager@chromium.org357bf652010-04-12 11:30:10 +0000871// Reads all frames on the current stack and copies them into the current
872// zone memory.
873Vector<StackFrame*> CreateStackMap();
874
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000875} } // namespace v8::internal
876
877#endif // V8_FRAMES_H_