blob: 537870906221e95fcb56737ad5aa49db8daf23fb [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
2// 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
Ben Murdochb8e0da22011-05-16 14:20:40 +010031#include "safepoint-table.h"
32
Steve Blocka7e24c12009-10-30 11:49:00 +000033namespace v8 {
34namespace internal {
35
36typedef uint32_t RegList;
37
38// Get the number of registers in a given register list.
39int NumRegs(RegList list);
40
41// Return the code of the n-th saved register available to JavaScript.
42int JSCallerSavedCode(int n);
43
44
45// Forward declarations.
46class StackFrameIterator;
47class Top;
48class ThreadLocalTop;
49
50
Kristian Monsen80d68ea2010-09-08 11:05:35 +010051class PcToCodeCache : AllStatic {
52 public:
53 struct PcToCodeCacheEntry {
54 Address pc;
55 Code* code;
Ben Murdochb8e0da22011-05-16 14:20:40 +010056 SafepointEntry safepoint_entry;
Kristian Monsen80d68ea2010-09-08 11:05:35 +010057 };
58
59 static PcToCodeCacheEntry* cache(int index) {
60 return &cache_[index];
61 }
62
63 static Code* GcSafeFindCodeForPc(Address pc);
64 static Code* GcSafeCastToCode(HeapObject* object, Address pc);
65
66 static void FlushPcToCodeCache() {
67 memset(&cache_[0], 0, sizeof(cache_));
68 }
69
70 static PcToCodeCacheEntry* GetCacheEntry(Address pc);
71
72 private:
Kristian Monsen0d5e1162010-09-30 15:31:59 +010073 static const int kPcToCodeCacheSize = 1024;
Kristian Monsen80d68ea2010-09-08 11:05:35 +010074 static PcToCodeCacheEntry cache_[kPcToCodeCacheSize];
75};
76
77
Steve Blocka7e24c12009-10-30 11:49:00 +000078class StackHandler BASE_EMBEDDED {
79 public:
80 enum State {
81 ENTRY,
82 TRY_CATCH,
83 TRY_FINALLY
84 };
85
86 // Get the address of this stack handler.
87 inline Address address() const;
88
89 // Get the next stack handler in the chain.
90 inline StackHandler* next() const;
91
92 // Tells whether the given address is inside this handler.
93 inline bool includes(Address address) const;
94
95 // Garbage collection support.
Kristian Monsen80d68ea2010-09-08 11:05:35 +010096 inline void Iterate(ObjectVisitor* v, Code* holder) const;
Steve Blocka7e24c12009-10-30 11:49:00 +000097
98 // Conversion support.
99 static inline StackHandler* FromAddress(Address address);
100
101 // Testers
102 bool is_entry() { return state() == ENTRY; }
103 bool is_try_catch() { return state() == TRY_CATCH; }
104 bool is_try_finally() { return state() == TRY_FINALLY; }
105
Steve Blocka7e24c12009-10-30 11:49:00 +0000106 private:
107 // Accessors.
108 inline State state() const;
109
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100110 inline Address* pc_address() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000111
112 DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
113};
114
115
116#define STACK_FRAME_TYPE_LIST(V) \
117 V(ENTRY, EntryFrame) \
118 V(ENTRY_CONSTRUCT, EntryConstructFrame) \
119 V(EXIT, ExitFrame) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000120 V(JAVA_SCRIPT, JavaScriptFrame) \
Ben Murdochb0fe1622011-05-05 13:52:32 +0100121 V(OPTIMIZED, OptimizedFrame) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000122 V(INTERNAL, InternalFrame) \
123 V(CONSTRUCT, ConstructFrame) \
124 V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
125
126
127// Abstract base class for all stack frames.
128class StackFrame BASE_EMBEDDED {
129 public:
130#define DECLARE_TYPE(type, ignore) type,
131 enum Type {
132 NONE = 0,
133 STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
134 NUMBER_OF_TYPES
135 };
136#undef DECLARE_TYPE
137
138 // Opaque data type for identifying stack frames. Used extensively
139 // by the debugger.
Iain Merrick75681382010-08-19 15:07:18 +0100140 // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
141 // has correct value range (see Issue 830 for more details).
142 enum Id {
143 ID_MIN_VALUE = kMinInt,
144 ID_MAX_VALUE = kMaxInt,
145 NO_ID = 0
146 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000147
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100148 struct State {
149 State() : sp(NULL), fp(NULL), pc_address(NULL) { }
150 Address sp;
151 Address fp;
152 Address* pc_address;
153 };
154
Steve Block6ded16b2010-05-10 14:33:55 +0100155 // Copy constructor; it breaks the connection to host iterator.
156 StackFrame(const StackFrame& original) {
157 this->state_ = original.state_;
158 this->iterator_ = NULL;
159 }
160
Steve Blocka7e24c12009-10-30 11:49:00 +0000161 // Type testers.
162 bool is_entry() const { return type() == ENTRY; }
163 bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
164 bool is_exit() const { return type() == EXIT; }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100165 bool is_optimized() const { return type() == OPTIMIZED; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000166 bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
167 bool is_internal() const { return type() == INTERNAL; }
168 bool is_construct() const { return type() == CONSTRUCT; }
169 virtual bool is_standard() const { return false; }
170
Ben Murdochb0fe1622011-05-05 13:52:32 +0100171 bool is_java_script() const {
172 Type type = this->type();
173 return (type == JAVA_SCRIPT) || (type == OPTIMIZED);
174 }
175
Steve Blocka7e24c12009-10-30 11:49:00 +0000176 // Accessors.
177 Address sp() const { return state_.sp; }
178 Address fp() const { return state_.fp; }
179 Address caller_sp() const { return GetCallerStackPointer(); }
180
181 Address pc() const { return *pc_address(); }
182 void set_pc(Address pc) { *pc_address() = pc; }
183
Steve Block6ded16b2010-05-10 14:33:55 +0100184 virtual void SetCallerFp(Address caller_fp) = 0;
185
Steve Blocka7e24c12009-10-30 11:49:00 +0000186 Address* pc_address() const { return state_.pc_address; }
187
188 // Get the id of this stack frame.
189 Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
190
191 // Checks if this frame includes any stack handlers.
192 bool HasHandler() const;
193
194 // Get the type of this frame.
195 virtual Type type() const = 0;
196
197 // Get the code associated with this frame.
Iain Merrick75681382010-08-19 15:07:18 +0100198 // This method could be called during marking phase of GC.
199 virtual Code* unchecked_code() const = 0;
200
201 // Get the code associated with this frame.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100202 Code* code() const { return GetContainingCode(pc()); }
203
204 // Get the code object that contains the given pc.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100205 static Code* GetContainingCode(Address pc) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100206 return PcToCodeCache::GetCacheEntry(pc)->code;
Iain Merrick75681382010-08-19 15:07:18 +0100207 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000208
Ben Murdochb0fe1622011-05-05 13:52:32 +0100209 // Get the code object containing the given pc and fill in the
210 // safepoint entry and the number of stack slots. The pc must be at
211 // a safepoint.
212 static Code* GetSafepointData(Address pc,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100213 SafepointEntry* safepoint_entry,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100214 unsigned* stack_slots);
215
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100216 virtual void Iterate(ObjectVisitor* v) const = 0;
217 static void IteratePc(ObjectVisitor* v, Address* pc_address, Code* holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000218
Steve Blocka7e24c12009-10-30 11:49:00 +0000219
220 // Printing support.
221 enum PrintMode { OVERVIEW, DETAILS };
222 virtual void Print(StringStream* accumulator,
223 PrintMode mode,
224 int index) const { }
225
226 protected:
Steve Blocka7e24c12009-10-30 11:49:00 +0000227 explicit StackFrame(StackFrameIterator* iterator) : iterator_(iterator) { }
228 virtual ~StackFrame() { }
229
230 // Compute the stack pointer for the calling frame.
231 virtual Address GetCallerStackPointer() const = 0;
232
233 // Printing support.
234 static void PrintIndex(StringStream* accumulator,
235 PrintMode mode,
236 int index);
237
238 // Get the top handler from the current stack iterator.
239 inline StackHandler* top_handler() const;
240
241 // Compute the stack frame type for the given state.
242 static Type ComputeType(State* state);
243
244 private:
245 const StackFrameIterator* iterator_;
246 State state_;
247
248 // Fill in the state of the calling frame.
249 virtual void ComputeCallerState(State* state) const = 0;
250
251 // Get the type and the state of the calling frame.
252 virtual Type GetCallerState(State* state) const;
253
Steve Blocka7e24c12009-10-30 11:49:00 +0000254 friend class StackFrameIterator;
255 friend class StackHandlerIterator;
256 friend class SafeStackFrameIterator;
257
Steve Block6ded16b2010-05-10 14:33:55 +0100258 private:
259 void operator=(const StackFrame& original);
Steve Blocka7e24c12009-10-30 11:49:00 +0000260};
261
262
263// Entry frames are used to enter JavaScript execution from C.
264class EntryFrame: public StackFrame {
265 public:
266 virtual Type type() const { return ENTRY; }
267
Iain Merrick75681382010-08-19 15:07:18 +0100268 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000269
270 // Garbage collection support.
271 virtual void Iterate(ObjectVisitor* v) const;
272
273 static EntryFrame* cast(StackFrame* frame) {
274 ASSERT(frame->is_entry());
275 return static_cast<EntryFrame*>(frame);
276 }
Steve Block6ded16b2010-05-10 14:33:55 +0100277 virtual void SetCallerFp(Address caller_fp);
Steve Blocka7e24c12009-10-30 11:49:00 +0000278
279 protected:
280 explicit EntryFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
281
282 // The caller stack pointer for entry frames is always zero. The
283 // real information about the caller frame is available through the
284 // link to the top exit frame.
285 virtual Address GetCallerStackPointer() const { return 0; }
286
287 private:
288 virtual void ComputeCallerState(State* state) const;
289 virtual Type GetCallerState(State* state) const;
290
291 friend class StackFrameIterator;
292};
293
294
295class EntryConstructFrame: public EntryFrame {
296 public:
297 virtual Type type() const { return ENTRY_CONSTRUCT; }
298
Iain Merrick75681382010-08-19 15:07:18 +0100299 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000300
301 static EntryConstructFrame* cast(StackFrame* frame) {
302 ASSERT(frame->is_entry_construct());
303 return static_cast<EntryConstructFrame*>(frame);
304 }
305
306 protected:
307 explicit EntryConstructFrame(StackFrameIterator* iterator)
308 : EntryFrame(iterator) { }
309
310 private:
311 friend class StackFrameIterator;
312};
313
314
315// Exit frames are used to exit JavaScript execution and go to C.
316class ExitFrame: public StackFrame {
317 public:
318 virtual Type type() const { return EXIT; }
319
Iain Merrick75681382010-08-19 15:07:18 +0100320 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000321
Steve Blockd0582a62009-12-15 09:54:21 +0000322 Object*& code_slot() const;
323
Steve Blocka7e24c12009-10-30 11:49:00 +0000324 // Garbage collection support.
325 virtual void Iterate(ObjectVisitor* v) const;
326
Steve Block6ded16b2010-05-10 14:33:55 +0100327 virtual void SetCallerFp(Address caller_fp);
328
Steve Blocka7e24c12009-10-30 11:49:00 +0000329 static ExitFrame* cast(StackFrame* frame) {
330 ASSERT(frame->is_exit());
331 return static_cast<ExitFrame*>(frame);
332 }
333
334 // Compute the state and type of an exit frame given a frame
335 // pointer. Used when constructing the first stack frame seen by an
336 // iterator and the frames following entry frames.
337 static Type GetStateForFramePointer(Address fp, State* state);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100338 static Address ComputeStackPointer(Address fp);
339 static void FillState(Address fp, Address sp, State* state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000340
341 protected:
342 explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
343
344 virtual Address GetCallerStackPointer() const;
345
346 private:
347 virtual void ComputeCallerState(State* state) const;
348
349 friend class StackFrameIterator;
350};
351
352
Steve Blocka7e24c12009-10-30 11:49:00 +0000353class StandardFrame: public StackFrame {
354 public:
355 // Testers.
356 virtual bool is_standard() const { return true; }
357
358 // Accessors.
359 inline Object* context() const;
360
361 // Access the expressions in the stack frame including locals.
362 inline Object* GetExpression(int index) const;
363 inline void SetExpression(int index, Object* value);
364 int ComputeExpressionsCount() const;
365
Steve Block6ded16b2010-05-10 14:33:55 +0100366 virtual void SetCallerFp(Address caller_fp);
367
Steve Blocka7e24c12009-10-30 11:49:00 +0000368 static StandardFrame* cast(StackFrame* frame) {
369 ASSERT(frame->is_standard());
370 return static_cast<StandardFrame*>(frame);
371 }
372
373 protected:
374 explicit StandardFrame(StackFrameIterator* iterator)
375 : StackFrame(iterator) { }
376
377 virtual void ComputeCallerState(State* state) const;
378
379 // Accessors.
380 inline Address caller_fp() const;
381 inline Address caller_pc() const;
382
383 // Computes the address of the PC field in the standard frame given
384 // by the provided frame pointer.
385 static inline Address ComputePCAddress(Address fp);
386
387 // Iterate over expression stack including stack handlers, locals,
388 // and parts of the fixed part including context and code fields.
389 void IterateExpressions(ObjectVisitor* v) const;
390
391 // Returns the address of the n'th expression stack element.
392 Address GetExpressionAddress(int n) const;
393
394 // Determines if the n'th expression stack element is in a stack
395 // handler or not. Requires traversing all handlers in this frame.
396 bool IsExpressionInsideHandler(int n) const;
397
398 // Determines if the standard frame for the given frame pointer is
399 // an arguments adaptor frame.
400 static inline bool IsArgumentsAdaptorFrame(Address fp);
401
402 // Determines if the standard frame for the given frame pointer is a
403 // construct frame.
404 static inline bool IsConstructFrame(Address fp);
405
406 private:
407 friend class StackFrame;
Kristian Monsen25f61362010-05-21 11:50:48 +0100408 friend class StackFrameIterator;
Steve Blocka7e24c12009-10-30 11:49:00 +0000409};
410
411
Ben Murdochb0fe1622011-05-05 13:52:32 +0100412class FrameSummary BASE_EMBEDDED {
413 public:
414 FrameSummary(Object* receiver,
415 JSFunction* function,
416 Code* code,
417 int offset,
418 bool is_constructor)
419 : receiver_(receiver),
420 function_(function),
421 code_(code),
422 offset_(offset),
423 is_constructor_(is_constructor) { }
424 Handle<Object> receiver() { return receiver_; }
425 Handle<JSFunction> function() { return function_; }
426 Handle<Code> code() { return code_; }
427 Address pc() { return reinterpret_cast<Address>(*code_) + offset_; }
428 int offset() { return offset_; }
429 bool is_constructor() { return is_constructor_; }
430
431 void Print();
432
433 private:
434 Handle<Object> receiver_;
435 Handle<JSFunction> function_;
436 Handle<Code> code_;
437 int offset_;
438 bool is_constructor_;
439};
440
441
Steve Blocka7e24c12009-10-30 11:49:00 +0000442class JavaScriptFrame: public StandardFrame {
443 public:
444 virtual Type type() const { return JAVA_SCRIPT; }
445
446 // Accessors.
447 inline Object* function() const;
448 inline Object* receiver() const;
449 inline void set_receiver(Object* value);
450
451 // Access the parameters.
452 Object* GetParameter(int index) const;
453 int ComputeParametersCount() const;
454
455 // Temporary way of getting access to the number of parameters
456 // passed on the stack by the caller. Once argument adaptor frames
457 // has been introduced on ARM, this number will always match the
458 // computed parameters count.
459 int GetProvidedParametersCount() const;
460
461 // Check if this frame is a constructor frame invoked through 'new'.
462 bool IsConstructor() const;
463
464 // Check if this frame has "adapted" arguments in the sense that the
465 // actual passed arguments are available in an arguments adaptor
466 // frame below it on the stack.
467 inline bool has_adapted_arguments() const;
468
469 // Garbage collection support.
470 virtual void Iterate(ObjectVisitor* v) const;
471
472 // Printing support.
473 virtual void Print(StringStream* accumulator,
474 PrintMode mode,
475 int index) const;
476
477 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100478 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000479
Ben Murdochb0fe1622011-05-05 13:52:32 +0100480 // Return a list with JSFunctions of this frame.
481 virtual void GetFunctions(List<JSFunction*>* functions);
482
483 // Build a list with summaries for this frame including all inlined frames.
484 virtual void Summarize(List<FrameSummary>* frames);
485
Steve Blocka7e24c12009-10-30 11:49:00 +0000486 static JavaScriptFrame* cast(StackFrame* frame) {
487 ASSERT(frame->is_java_script());
488 return static_cast<JavaScriptFrame*>(frame);
489 }
490
491 protected:
492 explicit JavaScriptFrame(StackFrameIterator* iterator)
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100493 : StandardFrame(iterator) { }
Steve Blocka7e24c12009-10-30 11:49:00 +0000494
495 virtual Address GetCallerStackPointer() const;
496
Ben Murdochb0fe1622011-05-05 13:52:32 +0100497 // Garbage collection support. Iterates over incoming arguments,
498 // receiver, and any callee-saved registers.
499 void IterateArguments(ObjectVisitor* v) const;
500
Steve Blocka7e24c12009-10-30 11:49:00 +0000501 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000502 inline Object* function_slot_object() const;
503
504 friend class StackFrameIterator;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100505 friend class StackTracer;
Steve Blocka7e24c12009-10-30 11:49:00 +0000506};
507
508
Ben Murdochb0fe1622011-05-05 13:52:32 +0100509class OptimizedFrame : public JavaScriptFrame {
510 public:
511 virtual Type type() const { return OPTIMIZED; }
512
513 // GC support.
514 virtual void Iterate(ObjectVisitor* v) const;
515
516 // Return a list with JSFunctions of this frame.
517 // The functions are ordered bottom-to-top (i.e. functions.last()
518 // is the top-most activation)
519 virtual void GetFunctions(List<JSFunction*>* functions);
520
521 virtual void Summarize(List<FrameSummary>* frames);
522
523 DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
524
525 protected:
526 explicit OptimizedFrame(StackFrameIterator* iterator)
527 : JavaScriptFrame(iterator) { }
528
529 private:
530 friend class StackFrameIterator;
531};
532
533
Steve Blocka7e24c12009-10-30 11:49:00 +0000534// Arguments adaptor frames are automatically inserted below
535// JavaScript frames when the actual number of parameters does not
536// match the formal number of parameters.
537class ArgumentsAdaptorFrame: public JavaScriptFrame {
538 public:
539 virtual Type type() const { return ARGUMENTS_ADAPTOR; }
540
541 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100542 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000543
544 static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
545 ASSERT(frame->is_arguments_adaptor());
546 return static_cast<ArgumentsAdaptorFrame*>(frame);
547 }
548
549 // Printing support.
550 virtual void Print(StringStream* accumulator,
551 PrintMode mode,
552 int index) const;
553 protected:
554 explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator)
555 : JavaScriptFrame(iterator) { }
556
557 virtual Address GetCallerStackPointer() const;
558
559 private:
560 friend class StackFrameIterator;
561};
562
563
564class InternalFrame: public StandardFrame {
565 public:
566 virtual Type type() const { return INTERNAL; }
567
568 // Garbage collection support.
569 virtual void Iterate(ObjectVisitor* v) const;
570
571 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100572 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000573
574 static InternalFrame* cast(StackFrame* frame) {
575 ASSERT(frame->is_internal());
576 return static_cast<InternalFrame*>(frame);
577 }
578
579 protected:
580 explicit InternalFrame(StackFrameIterator* iterator)
581 : StandardFrame(iterator) { }
582
583 virtual Address GetCallerStackPointer() const;
584
585 private:
586 friend class StackFrameIterator;
587};
588
589
590// Construct frames are special trampoline frames introduced to handle
591// function invocations through 'new'.
592class ConstructFrame: public InternalFrame {
593 public:
594 virtual Type type() const { return CONSTRUCT; }
595
596 static ConstructFrame* cast(StackFrame* frame) {
597 ASSERT(frame->is_construct());
598 return static_cast<ConstructFrame*>(frame);
599 }
600
601 protected:
602 explicit ConstructFrame(StackFrameIterator* iterator)
603 : InternalFrame(iterator) { }
604
605 private:
606 friend class StackFrameIterator;
607};
608
609
610class StackFrameIterator BASE_EMBEDDED {
611 public:
612 // An iterator that iterates over the current thread's stack.
613 StackFrameIterator();
614
615 // An iterator that iterates over a given thread's stack.
616 explicit StackFrameIterator(ThreadLocalTop* thread);
617
618 // An iterator that can start from a given FP address.
619 // If use_top, then work as usual, if fp isn't NULL, use it,
620 // otherwise, do nothing.
621 StackFrameIterator(bool use_top, Address fp, Address sp);
622
623 StackFrame* frame() const {
624 ASSERT(!done());
625 return frame_;
626 }
627
628 bool done() const { return frame_ == NULL; }
629 void Advance() { (this->*advance_)(); }
630
631 // Go back to the first frame.
632 void Reset();
633
634 private:
635#define DECLARE_SINGLETON(ignore, type) type type##_;
636 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
637#undef DECLARE_SINGLETON
638 StackFrame* frame_;
639 StackHandler* handler_;
640 ThreadLocalTop* thread_;
641 Address fp_;
642 Address sp_;
643 void (StackFrameIterator::*advance_)();
644
645 StackHandler* handler() const {
646 ASSERT(!done());
647 return handler_;
648 }
649
650 // Get the type-specific frame singleton in a given state.
651 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
652 // A helper function, can return a NULL pointer.
653 StackFrame* SingletonFor(StackFrame::Type type);
654
655 void AdvanceWithHandler();
656 void AdvanceWithoutHandler();
657
658 friend class StackFrame;
659 friend class SafeStackFrameIterator;
660 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
661};
662
663
664// Iterator that supports iterating through all JavaScript frames.
665template<typename Iterator>
666class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
667 public:
668 JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
669
670 explicit JavaScriptFrameIteratorTemp(ThreadLocalTop* thread) :
671 iterator_(thread) {
672 if (!done()) Advance();
673 }
674
675 // Skip frames until the frame with the given id is reached.
676 explicit JavaScriptFrameIteratorTemp(StackFrame::Id id);
677
678 JavaScriptFrameIteratorTemp(Address fp, Address sp,
679 Address low_bound, Address high_bound) :
680 iterator_(fp, sp, low_bound, high_bound) {
681 if (!done()) Advance();
682 }
683
684 inline JavaScriptFrame* frame() const;
685
686 bool done() const { return iterator_.done(); }
687 void Advance();
688
689 // Advance to the frame holding the arguments for the current
690 // frame. This only affects the current frame if it has adapted
691 // arguments.
692 void AdvanceToArgumentsFrame();
693
694 // Go back to the first frame.
695 void Reset();
696
697 private:
698 Iterator iterator_;
699};
700
701
702typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
703
704
705// NOTE: The stack trace frame iterator is an iterator that only
706// traverse proper JavaScript frames; that is JavaScript frames that
707// have proper JavaScript functions. This excludes the problematic
708// functions in runtime.js.
709class StackTraceFrameIterator: public JavaScriptFrameIterator {
710 public:
711 StackTraceFrameIterator();
712 void Advance();
Leon Clarke4515c472010-02-03 11:58:03 +0000713
714 private:
715 bool IsValidFrame();
Steve Blocka7e24c12009-10-30 11:49:00 +0000716};
717
718
719class SafeStackFrameIterator BASE_EMBEDDED {
720 public:
721 SafeStackFrameIterator(Address fp, Address sp,
722 Address low_bound, Address high_bound);
723
724 StackFrame* frame() const {
725 ASSERT(is_working_iterator_);
726 return iterator_.frame();
727 }
728
729 bool done() const { return iteration_done_ ? true : iterator_.done(); }
730
731 void Advance();
732 void Reset();
733
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100734 static bool is_active() { return active_count_ > 0; }
735
Steve Blocka7e24c12009-10-30 11:49:00 +0000736 static bool IsWithinBounds(
737 Address low_bound, Address high_bound, Address addr) {
738 return low_bound <= addr && addr <= high_bound;
739 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000740
741 private:
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100742 class StackAddressValidator {
743 public:
744 StackAddressValidator(Address low_bound, Address high_bound)
745 : low_bound_(low_bound), high_bound_(high_bound) { }
746 bool IsValid(Address addr) const {
747 return IsWithinBounds(low_bound_, high_bound_, addr);
748 }
749 private:
750 Address low_bound_;
751 Address high_bound_;
752 };
753
754 class ExitFrameValidator {
755 public:
756 explicit ExitFrameValidator(const StackAddressValidator& validator)
757 : validator_(validator) { }
758 ExitFrameValidator(Address low_bound, Address high_bound)
759 : validator_(low_bound, high_bound) { }
760 bool IsValidFP(Address fp);
761 private:
762 StackAddressValidator validator_;
763 };
764
Steve Blocka7e24c12009-10-30 11:49:00 +0000765 bool IsValidStackAddress(Address addr) const {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100766 return stack_validator_.IsValid(addr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000767 }
768 bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
769 bool IsValidFrame(StackFrame* frame) const;
770 bool IsValidCaller(StackFrame* frame);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100771 static bool IsValidTop(Address low_bound, Address high_bound);
Steve Blocka7e24c12009-10-30 11:49:00 +0000772
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100773 // This is a nasty hack to make sure the active count is incremented
774 // before the constructor for the embedded iterator is invoked. This
775 // is needed because the constructor will start looking at frames
776 // right away and we need to make sure it doesn't start inspecting
777 // heap objects.
778 class ActiveCountMaintainer BASE_EMBEDDED {
779 public:
780 ActiveCountMaintainer() { active_count_++; }
781 ~ActiveCountMaintainer() { active_count_--; }
782 };
783
784 ActiveCountMaintainer maintainer_;
785 static int active_count_;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100786 StackAddressValidator stack_validator_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000787 const bool is_valid_top_;
788 const bool is_valid_fp_;
789 const bool is_working_iterator_;
790 bool iteration_done_;
791 StackFrameIterator iterator_;
792};
793
794
795#ifdef ENABLE_LOGGING_AND_PROFILING
796typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
797 SafeJavaScriptFrameIterator;
798
799
800class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
801 public:
802 explicit SafeStackTraceFrameIterator(Address fp, Address sp,
803 Address low_bound, Address high_bound);
804 void Advance();
805};
806#endif
807
808
809class StackFrameLocator BASE_EMBEDDED {
810 public:
811 // Find the nth JavaScript frame on the stack. The caller must
812 // guarantee that such a frame exists.
813 JavaScriptFrame* FindJavaScriptFrame(int n);
814
815 private:
816 StackFrameIterator iterator_;
817};
818
819
Steve Block6ded16b2010-05-10 14:33:55 +0100820// Reads all frames on the current stack and copies them into the current
821// zone memory.
822Vector<StackFrame*> CreateStackMap();
823
Steve Blocka7e24c12009-10-30 11:49:00 +0000824} } // namespace v8::internal
825
826#endif // V8_FRAMES_H_