blob: 2d4f338ae0f7f76f16cfe25fc0c53a8934222619 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 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
kasperl@chromium.org71affb52009-05-26 05:44:31 +000031namespace v8 {
32namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000033
34typedef uint32_t RegList;
35
36// Get the number of registers in a given register list.
37int NumRegs(RegList list);
38
39// Return the code of the n-th saved register available to JavaScript.
40int JSCallerSavedCode(int n);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000041
42
43// Forward declarations.
44class StackFrameIterator;
45class Top;
46class ThreadLocalTop;
47
48
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000049class PcToCodeCache : AllStatic {
50 public:
51 struct PcToCodeCacheEntry {
52 Address pc;
53 Code* code;
54 };
55
56 static PcToCodeCacheEntry* cache(int index) {
57 return &cache_[index];
58 }
59
60 static Code* GcSafeFindCodeForPc(Address pc);
61 static Code* GcSafeCastToCode(HeapObject* object, Address pc);
62
63 static void FlushPcToCodeCache() {
64 memset(&cache_[0], 0, sizeof(cache_));
65 }
66
67 static PcToCodeCacheEntry* GetCacheEntry(Address pc);
68
69 private:
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +000070 static const int kPcToCodeCacheSize = 1024;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000071 static PcToCodeCacheEntry cache_[kPcToCodeCacheSize];
72};
73
74
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000075class StackHandler BASE_EMBEDDED {
76 public:
77 enum State {
78 ENTRY,
79 TRY_CATCH,
80 TRY_FINALLY
81 };
82
83 // Get the address of this stack handler.
84 inline Address address() const;
85
86 // Get the next stack handler in the chain.
87 inline StackHandler* next() const;
88
89 // Tells whether the given address is inside this handler.
90 inline bool includes(Address address) const;
91
92 // Garbage collection support.
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +000093 inline void Iterate(ObjectVisitor* v, Code* holder) const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000094
95 // Conversion support.
96 static inline StackHandler* FromAddress(Address address);
97
98 // Testers
99 bool is_entry() { return state() == ENTRY; }
100 bool is_try_catch() { return state() == TRY_CATCH; }
101 bool is_try_finally() { return state() == TRY_FINALLY; }
102
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000103 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000104 // Accessors.
105 inline State state() const;
106
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000107 inline Address* pc_address() const;
mads.s.ager31e71382008-08-13 09:32:07 +0000108
109 DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000110};
111
112
113#define STACK_FRAME_TYPE_LIST(V) \
114 V(ENTRY, EntryFrame) \
115 V(ENTRY_CONSTRUCT, EntryConstructFrame) \
116 V(EXIT, ExitFrame) \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000117 V(JAVA_SCRIPT, JavaScriptFrame) \
118 V(INTERNAL, InternalFrame) \
ager@chromium.org7c537e22008-10-16 08:43:32 +0000119 V(CONSTRUCT, ConstructFrame) \
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000120 V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
121
122
123// Abstract base class for all stack frames.
124class StackFrame BASE_EMBEDDED {
125 public:
126#define DECLARE_TYPE(type, ignore) type,
127 enum Type {
128 NONE = 0,
129 STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
130 NUMBER_OF_TYPES
131 };
132#undef DECLARE_TYPE
133
134 // Opaque data type for identifying stack frames. Used extensively
135 // by the debugger.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000136 // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
137 // has correct value range (see Issue 830 for more details).
138 enum Id {
139 ID_MIN_VALUE = kMinInt,
140 ID_MAX_VALUE = kMaxInt,
141 NO_ID = 0
142 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000143
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000144 struct State {
145 State() : sp(NULL), fp(NULL), pc_address(NULL) { }
146 Address sp;
147 Address fp;
148 Address* pc_address;
149 };
150
ager@chromium.org357bf652010-04-12 11:30:10 +0000151 // Copy constructor; it breaks the connection to host iterator.
152 StackFrame(const StackFrame& original) {
153 this->state_ = original.state_;
154 this->iterator_ = NULL;
155 }
156
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000157 // Type testers.
158 bool is_entry() const { return type() == ENTRY; }
159 bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
160 bool is_exit() const { return type() == EXIT; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000161 bool is_java_script() const { return type() == JAVA_SCRIPT; }
162 bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
163 bool is_internal() const { return type() == INTERNAL; }
ager@chromium.org7c537e22008-10-16 08:43:32 +0000164 bool is_construct() const { return type() == CONSTRUCT; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000165 virtual bool is_standard() const { return false; }
166
167 // Accessors.
168 Address sp() const { return state_.sp; }
169 Address fp() const { return state_.fp; }
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000170 Address caller_sp() const { return GetCallerStackPointer(); }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000171
172 Address pc() const { return *pc_address(); }
173 void set_pc(Address pc) { *pc_address() = pc; }
174
ager@chromium.org357bf652010-04-12 11:30:10 +0000175 virtual void SetCallerFp(Address caller_fp) = 0;
176
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000177 Address* pc_address() const { return state_.pc_address; }
178
179 // Get the id of this stack frame.
ager@chromium.orgeadaf222009-06-16 09:43:10 +0000180 Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000181
182 // Checks if this frame includes any stack handlers.
183 bool HasHandler() const;
184
185 // Get the type of this frame.
186 virtual Type type() const = 0;
187
188 // Get the code associated with this frame.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000189 // This method could be called during marking phase of GC.
190 virtual Code* unchecked_code() const = 0;
191
192 // Get the code associated with this frame.
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000193 Code* code() const { return GetContainingCode(pc()); }
194
195 // Get the code object that contains the given pc.
196 Code* GetContainingCode(Address pc) const {
197 return PcToCodeCache::GetCacheEntry(pc)->code;
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000198 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000199
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000200 virtual void Iterate(ObjectVisitor* v) const = 0;
201 static void IteratePc(ObjectVisitor* v, Address* pc_address, Code* holder);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000202
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000203
204 // Printing support.
205 enum PrintMode { OVERVIEW, DETAILS };
206 virtual void Print(StringStream* accumulator,
207 PrintMode mode,
208 int index) const { }
209
210 protected:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000211 explicit StackFrame(StackFrameIterator* iterator) : iterator_(iterator) { }
212 virtual ~StackFrame() { }
213
214 // Compute the stack pointer for the calling frame.
215 virtual Address GetCallerStackPointer() const = 0;
216
217 // Printing support.
218 static void PrintIndex(StringStream* accumulator,
219 PrintMode mode,
220 int index);
221
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000222 // Get the top handler from the current stack iterator.
223 inline StackHandler* top_handler() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000224
225 // Compute the stack frame type for the given state.
226 static Type ComputeType(State* state);
227
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000228 private:
229 const StackFrameIterator* iterator_;
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000230 State state_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000231
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000232 // Fill in the state of the calling frame.
233 virtual void ComputeCallerState(State* state) const = 0;
234
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000235 // Get the type and the state of the calling frame.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000236 virtual Type GetCallerState(State* state) const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000237
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000238 friend class StackFrameIterator;
239 friend class StackHandlerIterator;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000240 friend class SafeStackFrameIterator;
mads.s.ager31e71382008-08-13 09:32:07 +0000241
ager@chromium.org357bf652010-04-12 11:30:10 +0000242 private:
243 void operator=(const StackFrame& original);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000244};
245
246
247// Entry frames are used to enter JavaScript execution from C.
248class EntryFrame: public StackFrame {
249 public:
250 virtual Type type() const { return ENTRY; }
251
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000252 virtual Code* unchecked_code() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000253
254 // Garbage collection support.
255 virtual void Iterate(ObjectVisitor* v) const;
256
257 static EntryFrame* cast(StackFrame* frame) {
258 ASSERT(frame->is_entry());
259 return static_cast<EntryFrame*>(frame);
260 }
ager@chromium.org357bf652010-04-12 11:30:10 +0000261 virtual void SetCallerFp(Address caller_fp);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000262
263 protected:
264 explicit EntryFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
265
266 // The caller stack pointer for entry frames is always zero. The
267 // real information about the caller frame is available through the
268 // link to the top exit frame.
269 virtual Address GetCallerStackPointer() const { return 0; }
270
271 private:
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000272 virtual void ComputeCallerState(State* state) const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000273 virtual Type GetCallerState(State* state) const;
274
275 friend class StackFrameIterator;
276};
277
278
279class EntryConstructFrame: public EntryFrame {
280 public:
281 virtual Type type() const { return ENTRY_CONSTRUCT; }
282
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000283 virtual Code* unchecked_code() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000284
285 static EntryConstructFrame* cast(StackFrame* frame) {
286 ASSERT(frame->is_entry_construct());
287 return static_cast<EntryConstructFrame*>(frame);
288 }
289
290 protected:
291 explicit EntryConstructFrame(StackFrameIterator* iterator)
292 : EntryFrame(iterator) { }
293
294 private:
295 friend class StackFrameIterator;
296};
297
298
299// Exit frames are used to exit JavaScript execution and go to C.
300class ExitFrame: public StackFrame {
301 public:
302 virtual Type type() const { return EXIT; }
303
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000304 virtual Code* unchecked_code() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000305
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000306 Object*& code_slot() const;
307
ager@chromium.org32912102009-01-16 10:38:43 +0000308 // Garbage collection support.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000309 virtual void Iterate(ObjectVisitor* v) const;
310
ager@chromium.org357bf652010-04-12 11:30:10 +0000311 virtual void SetCallerFp(Address caller_fp);
312
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000313 static ExitFrame* cast(StackFrame* frame) {
314 ASSERT(frame->is_exit());
315 return static_cast<ExitFrame*>(frame);
316 }
317
318 // Compute the state and type of an exit frame given a frame
319 // pointer. Used when constructing the first stack frame seen by an
320 // iterator and the frames following entry frames.
321 static Type GetStateForFramePointer(Address fp, State* state);
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000322 static Address ComputeStackPointer(Address fp);
323 static void FillState(Address fp, Address sp, State* state);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000324
325 protected:
326 explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
327
328 virtual Address GetCallerStackPointer() const;
329
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000330 private:
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000331 virtual void ComputeCallerState(State* state) const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000332
333 friend class StackFrameIterator;
334};
335
336
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000337class StandardFrame: public StackFrame {
338 public:
339 // Testers.
340 virtual bool is_standard() const { return true; }
341
342 // Accessors.
343 inline Object* context() const;
344
345 // Access the expressions in the stack frame including locals.
346 inline Object* GetExpression(int index) const;
347 inline void SetExpression(int index, Object* value);
348 int ComputeExpressionsCount() const;
349
ager@chromium.org357bf652010-04-12 11:30:10 +0000350 virtual void SetCallerFp(Address caller_fp);
351
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000352 static StandardFrame* cast(StackFrame* frame) {
353 ASSERT(frame->is_standard());
354 return static_cast<StandardFrame*>(frame);
355 }
356
357 protected:
358 explicit StandardFrame(StackFrameIterator* iterator)
359 : StackFrame(iterator) { }
360
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000361 virtual void ComputeCallerState(State* state) const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000362
363 // Accessors.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000364 inline Address caller_fp() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000365 inline Address caller_pc() const;
366
367 // Computes the address of the PC field in the standard frame given
368 // by the provided frame pointer.
369 static inline Address ComputePCAddress(Address fp);
370
371 // Iterate over expression stack including stack handlers, locals,
372 // and parts of the fixed part including context and code fields.
373 void IterateExpressions(ObjectVisitor* v) const;
374
375 // Returns the address of the n'th expression stack element.
376 Address GetExpressionAddress(int n) const;
377
378 // Determines if the n'th expression stack element is in a stack
379 // handler or not. Requires traversing all handlers in this frame.
380 bool IsExpressionInsideHandler(int n) const;
381
382 // Determines if the standard frame for the given frame pointer is
383 // an arguments adaptor frame.
384 static inline bool IsArgumentsAdaptorFrame(Address fp);
385
ager@chromium.org7c537e22008-10-16 08:43:32 +0000386 // Determines if the standard frame for the given frame pointer is a
387 // construct frame.
388 static inline bool IsConstructFrame(Address fp);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000389
390 private:
391 friend class StackFrame;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +0000392 friend class StackFrameIterator;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000393};
394
395
396class JavaScriptFrame: public StandardFrame {
397 public:
398 virtual Type type() const { return JAVA_SCRIPT; }
399
400 // Accessors.
401 inline Object* function() const;
402 inline Object* receiver() const;
403 inline void set_receiver(Object* value);
404
405 // Access the parameters.
406 Object* GetParameter(int index) const;
407 int ComputeParametersCount() const;
408
409 // Temporary way of getting access to the number of parameters
410 // passed on the stack by the caller. Once argument adaptor frames
411 // has been introduced on ARM, this number will always match the
412 // computed parameters count.
413 int GetProvidedParametersCount() const;
414
ager@chromium.org7c537e22008-10-16 08:43:32 +0000415 // Check if this frame is a constructor frame invoked through 'new'.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000416 bool IsConstructor() const;
417
418 // Check if this frame has "adapted" arguments in the sense that the
419 // actual passed arguments are available in an arguments adaptor
420 // frame below it on the stack.
421 inline bool has_adapted_arguments() const;
422
ager@chromium.org32912102009-01-16 10:38:43 +0000423 // Garbage collection support.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000424 virtual void Iterate(ObjectVisitor* v) const;
425
426 // Printing support.
427 virtual void Print(StringStream* accumulator,
428 PrintMode mode,
429 int index) const;
430
431 // Determine the code for the frame.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000432 virtual Code* unchecked_code() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000433
434 static JavaScriptFrame* cast(StackFrame* frame) {
435 ASSERT(frame->is_java_script());
436 return static_cast<JavaScriptFrame*>(frame);
437 }
438
439 protected:
440 explicit JavaScriptFrame(StackFrameIterator* iterator)
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000441 : StandardFrame(iterator) { }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000442
443 virtual Address GetCallerStackPointer() const;
444
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000445 private:
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000446 inline Object* function_slot_object() const;
447
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000448 friend class StackFrameIterator;
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000449 friend class StackTracer;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000450};
451
452
453// Arguments adaptor frames are automatically inserted below
454// JavaScript frames when the actual number of parameters does not
455// match the formal number of parameters.
456class ArgumentsAdaptorFrame: public JavaScriptFrame {
457 public:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000458 virtual Type type() const { return ARGUMENTS_ADAPTOR; }
459
460 // Determine the code for the frame.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000461 virtual Code* unchecked_code() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000462
463 static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
464 ASSERT(frame->is_arguments_adaptor());
465 return static_cast<ArgumentsAdaptorFrame*>(frame);
466 }
467
468 // Printing support.
469 virtual void Print(StringStream* accumulator,
470 PrintMode mode,
471 int index) const;
472 protected:
473 explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator)
474 : JavaScriptFrame(iterator) { }
475
476 virtual Address GetCallerStackPointer() const;
477
478 private:
479 friend class StackFrameIterator;
480};
481
482
483class InternalFrame: public StandardFrame {
484 public:
485 virtual Type type() const { return INTERNAL; }
486
ager@chromium.org32912102009-01-16 10:38:43 +0000487 // Garbage collection support.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000488 virtual void Iterate(ObjectVisitor* v) const;
489
490 // Determine the code for the frame.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000491 virtual Code* unchecked_code() const;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000492
493 static InternalFrame* cast(StackFrame* frame) {
494 ASSERT(frame->is_internal());
495 return static_cast<InternalFrame*>(frame);
496 }
497
498 protected:
499 explicit InternalFrame(StackFrameIterator* iterator)
500 : StandardFrame(iterator) { }
501
502 virtual Address GetCallerStackPointer() const;
503
504 private:
505 friend class StackFrameIterator;
506};
507
508
ager@chromium.org7c537e22008-10-16 08:43:32 +0000509// Construct frames are special trampoline frames introduced to handle
510// function invocations through 'new'.
511class ConstructFrame: public InternalFrame {
512 public:
513 virtual Type type() const { return CONSTRUCT; }
514
515 static ConstructFrame* cast(StackFrame* frame) {
516 ASSERT(frame->is_construct());
517 return static_cast<ConstructFrame*>(frame);
518 }
519
520 protected:
521 explicit ConstructFrame(StackFrameIterator* iterator)
522 : InternalFrame(iterator) { }
523
524 private:
525 friend class StackFrameIterator;
526};
527
528
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000529class StackFrameIterator BASE_EMBEDDED {
530 public:
531 // An iterator that iterates over the current thread's stack.
532 StackFrameIterator();
533
534 // An iterator that iterates over a given thread's stack.
535 explicit StackFrameIterator(ThreadLocalTop* thread);
536
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000537 // An iterator that can start from a given FP address.
538 // If use_top, then work as usual, if fp isn't NULL, use it,
539 // otherwise, do nothing.
540 StackFrameIterator(bool use_top, Address fp, Address sp);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000541
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000542 StackFrame* frame() const {
543 ASSERT(!done());
544 return frame_;
545 }
546
547 bool done() const { return frame_ == NULL; }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000548 void Advance() { (this->*advance_)(); }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000549
550 // Go back to the first frame.
551 void Reset();
552
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000553 private:
554#define DECLARE_SINGLETON(ignore, type) type type##_;
555 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
556#undef DECLARE_SINGLETON
557 StackFrame* frame_;
558 StackHandler* handler_;
kasper.lund7276f142008-07-30 08:49:36 +0000559 ThreadLocalTop* thread_;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000560 Address fp_;
561 Address sp_;
562 void (StackFrameIterator::*advance_)();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000563
564 StackHandler* handler() const {
565 ASSERT(!done());
566 return handler_;
567 }
568
569 // Get the type-specific frame singleton in a given state.
570 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000571 // A helper function, can return a NULL pointer.
572 StackFrame* SingletonFor(StackFrame::Type type);
573
574 void AdvanceWithHandler();
575 void AdvanceWithoutHandler();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000576
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000577 friend class StackFrame;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000578 friend class SafeStackFrameIterator;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000579 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000580};
581
582
583// Iterator that supports iterating through all JavaScript frames.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000584template<typename Iterator>
585class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000586 public:
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000587 JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000588
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000589 explicit JavaScriptFrameIteratorTemp(ThreadLocalTop* thread) :
590 iterator_(thread) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000591 if (!done()) Advance();
592 }
593
594 // Skip frames until the frame with the given id is reached.
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000595 explicit JavaScriptFrameIteratorTemp(StackFrame::Id id);
596
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000597 JavaScriptFrameIteratorTemp(Address fp, Address sp,
598 Address low_bound, Address high_bound) :
599 iterator_(fp, sp, low_bound, high_bound) {
600 if (!done()) Advance();
601 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000602
603 inline JavaScriptFrame* frame() const;
604
605 bool done() const { return iterator_.done(); }
606 void Advance();
607
608 // Advance to the frame holding the arguments for the current
609 // frame. This only affects the current frame if it has adapted
610 // arguments.
611 void AdvanceToArgumentsFrame();
612
613 // Go back to the first frame.
614 void Reset();
615
616 private:
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000617 Iterator iterator_;
618};
619
620
621typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
622
623
624// NOTE: The stack trace frame iterator is an iterator that only
625// traverse proper JavaScript frames; that is JavaScript frames that
626// have proper JavaScript functions. This excludes the problematic
627// functions in runtime.js.
628class StackTraceFrameIterator: public JavaScriptFrameIterator {
629 public:
630 StackTraceFrameIterator();
631 void Advance();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000632
633 private:
634 bool IsValidFrame();
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000635};
636
637
638class SafeStackFrameIterator BASE_EMBEDDED {
639 public:
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000640 SafeStackFrameIterator(Address fp, Address sp,
641 Address low_bound, Address high_bound);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000642
643 StackFrame* frame() const {
644 ASSERT(is_working_iterator_);
645 return iterator_.frame();
646 }
647
648 bool done() const { return iteration_done_ ? true : iterator_.done(); }
649
650 void Advance();
651 void Reset();
652
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000653 static bool is_active() { return active_count_ > 0; }
654
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000655 static bool IsWithinBounds(
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000656 Address low_bound, Address high_bound, Address addr) {
657 return low_bound <= addr && addr <= high_bound;
658 }
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000659
660 private:
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000661 class StackAddressValidator {
662 public:
663 StackAddressValidator(Address low_bound, Address high_bound)
664 : low_bound_(low_bound), high_bound_(high_bound) { }
665 bool IsValid(Address addr) const {
666 return IsWithinBounds(low_bound_, high_bound_, addr);
667 }
668 private:
669 Address low_bound_;
670 Address high_bound_;
671 };
672
673 class ExitFrameValidator {
674 public:
675 explicit ExitFrameValidator(const StackAddressValidator& validator)
676 : validator_(validator) { }
677 ExitFrameValidator(Address low_bound, Address high_bound)
678 : validator_(low_bound, high_bound) { }
679 bool IsValidFP(Address fp);
680 private:
681 StackAddressValidator validator_;
682 };
683
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000684 bool IsValidStackAddress(Address addr) const {
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000685 return stack_validator_.IsValid(addr);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000686 }
kasperl@chromium.orgd1e3e722009-04-14 13:38:25 +0000687 bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000688 bool IsValidFrame(StackFrame* frame) const;
689 bool IsValidCaller(StackFrame* frame);
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000690 static bool IsValidTop(Address low_bound, Address high_bound);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000691
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000692 // This is a nasty hack to make sure the active count is incremented
693 // before the constructor for the embedded iterator is invoked. This
694 // is needed because the constructor will start looking at frames
695 // right away and we need to make sure it doesn't start inspecting
696 // heap objects.
697 class ActiveCountMaintainer BASE_EMBEDDED {
698 public:
699 ActiveCountMaintainer() { active_count_++; }
700 ~ActiveCountMaintainer() { active_count_--; }
701 };
702
703 ActiveCountMaintainer maintainer_;
704 static int active_count_;
fschneider@chromium.orgc20610a2010-09-22 09:44:58 +0000705 StackAddressValidator stack_validator_;
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000706 const bool is_valid_top_;
707 const bool is_valid_fp_;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000708 const bool is_working_iterator_;
709 bool iteration_done_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000710 StackFrameIterator iterator_;
711};
712
713
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000714#ifdef ENABLE_LOGGING_AND_PROFILING
715typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
716 SafeJavaScriptFrameIterator;
717
718
719class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
720 public:
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000721 explicit SafeStackTraceFrameIterator(Address fp, Address sp,
722 Address low_bound, Address high_bound);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000723 void Advance();
724};
725#endif
726
727
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000728class StackFrameLocator BASE_EMBEDDED {
729 public:
730 // Find the nth JavaScript frame on the stack. The caller must
731 // guarantee that such a frame exists.
732 JavaScriptFrame* FindJavaScriptFrame(int n);
733
734 private:
735 StackFrameIterator iterator_;
736};
737
738
ager@chromium.org357bf652010-04-12 11:30:10 +0000739// Reads all frames on the current stack and copies them into the current
740// zone memory.
741Vector<StackFrame*> CreateStackMap();
742
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000743} } // namespace v8::internal
744
745#endif // V8_FRAMES_H_