d6bfd7aab8d3fbe1a344106c36e30f105cbd205e
[platform/upstream/v8.git] / src / frames.h
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef V8_FRAMES_H_
6 #define V8_FRAMES_H_
7
8 #include "src/allocation.h"
9 #include "src/handles.h"
10 #include "src/safepoint-table.h"
11
12 namespace v8 {
13 namespace internal {
14
15 #if V8_TARGET_ARCH_ARM64
16 typedef uint64_t RegList;
17 #else
18 typedef uint32_t RegList;
19 #endif
20
21 // Get the number of registers in a given register list.
22 int NumRegs(RegList list);
23
24 void SetUpJSCallerSavedCodeData();
25
26 // Return the code of the n-th saved register available to JavaScript.
27 int JSCallerSavedCode(int n);
28
29
30 // Forward declarations.
31 class ExternalCallbackScope;
32 class StackFrameIteratorBase;
33 class ThreadLocalTop;
34 class Isolate;
35
36 class InnerPointerToCodeCache {
37  public:
38   struct InnerPointerToCodeCacheEntry {
39     Address inner_pointer;
40     Code* code;
41     SafepointEntry safepoint_entry;
42   };
43
44   explicit InnerPointerToCodeCache(Isolate* isolate) : isolate_(isolate) {
45     Flush();
46   }
47
48   Code* GcSafeFindCodeForInnerPointer(Address inner_pointer);
49   Code* GcSafeCastToCode(HeapObject* object, Address inner_pointer);
50
51   void Flush() {
52     memset(&cache_[0], 0, sizeof(cache_));
53   }
54
55   InnerPointerToCodeCacheEntry* GetCacheEntry(Address inner_pointer);
56
57  private:
58   InnerPointerToCodeCacheEntry* cache(int index) { return &cache_[index]; }
59
60   Isolate* isolate_;
61
62   static const int kInnerPointerToCodeCacheSize = 1024;
63   InnerPointerToCodeCacheEntry cache_[kInnerPointerToCodeCacheSize];
64
65   DISALLOW_COPY_AND_ASSIGN(InnerPointerToCodeCache);
66 };
67
68
69 // Every try-block pushes the context register.
70 class TryBlockConstant : public AllStatic {
71  public:
72   static const int kElementCount = 1;
73 };
74
75
76 class StackHandlerConstants : public AllStatic {
77  public:
78   static const int kNextOffset = 0 * kPointerSize;
79
80   static const int kSize = kNextOffset + kPointerSize;
81   static const int kSlotCount = kSize >> kPointerSizeLog2;
82 };
83
84
85 class StackHandler BASE_EMBEDDED {
86  public:
87   // Get the address of this stack handler.
88   inline Address address() const;
89
90   // Get the next stack handler in the chain.
91   inline StackHandler* next() const;
92
93   // Conversion support.
94   static inline StackHandler* FromAddress(Address address);
95
96  private:
97   DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
98 };
99
100
101 #define STACK_FRAME_TYPE_LIST(V)                         \
102   V(ENTRY,                   EntryFrame)                 \
103   V(ENTRY_CONSTRUCT,         EntryConstructFrame)        \
104   V(EXIT,                    ExitFrame)                  \
105   V(JAVA_SCRIPT,             JavaScriptFrame)            \
106   V(OPTIMIZED,               OptimizedFrame)             \
107   V(STUB,                    StubFrame)                  \
108   V(STUB_FAILURE_TRAMPOLINE, StubFailureTrampolineFrame) \
109   V(INTERNAL,                InternalFrame)              \
110   V(CONSTRUCT,               ConstructFrame)             \
111   V(ARGUMENTS_ADAPTOR,       ArgumentsAdaptorFrame)
112
113
114 class StandardFrameConstants : public AllStatic {
115  public:
116   // Fixed part of the frame consists of return address, caller fp,
117   // constant pool (if FLAG_enable_embedded_constant_pool), context, and
118   // function. StandardFrame::IterateExpressions assumes that kLastObjectOffset
119   // is the last object pointer.
120   static const int kCPSlotSize =
121       FLAG_enable_embedded_constant_pool ? kPointerSize : 0;
122   static const int kFixedFrameSizeFromFp =  2 * kPointerSize + kCPSlotSize;
123   static const int kFixedFrameSizeAboveFp = kPCOnStackSize + kFPOnStackSize;
124   static const int kFixedFrameSize =
125       kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp;
126   static const int kFixedSlotCountAboveFp =
127       kFixedFrameSizeAboveFp / kPointerSize;
128   static const int kFixedSlotCount = kFixedFrameSize / kPointerSize;
129   static const int kCPSlotCount = kCPSlotSize / kPointerSize;
130   static const int kExpressionsOffset = -3 * kPointerSize - kCPSlotSize;
131   static const int kMarkerOffset = -2 * kPointerSize - kCPSlotSize;
132   static const int kContextOffset = -1 * kPointerSize - kCPSlotSize;
133   static const int kConstantPoolOffset = kCPSlotSize ? -1 * kPointerSize : 0;
134   static const int kCallerFPOffset = 0 * kPointerSize;
135   static const int kCallerPCOffset = +1 * kFPOnStackSize;
136   static const int kCallerSPOffset = kCallerPCOffset + 1 * kPCOnStackSize;
137
138   static const int kLastObjectOffset = kContextOffset;
139 };
140
141
142 class ArgumentsAdaptorFrameConstants : public AllStatic {
143  public:
144   // FP-relative.
145   static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
146
147   static const int kFrameSize =
148       StandardFrameConstants::kFixedFrameSize + kPointerSize;
149 };
150
151
152 class InternalFrameConstants : public AllStatic {
153  public:
154   // FP-relative.
155   static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
156 };
157
158
159 class ConstructFrameConstants : public AllStatic {
160  public:
161   // FP-relative.
162   static const int kImplicitReceiverOffset =
163       StandardFrameConstants::kExpressionsOffset - 4 * kPointerSize;
164   static const int kOriginalConstructorOffset =
165       StandardFrameConstants::kExpressionsOffset - 3 * kPointerSize;
166   static const int kLengthOffset =
167       StandardFrameConstants::kExpressionsOffset - 2 * kPointerSize;
168   static const int kAllocationSiteOffset =
169       StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
170   static const int kCodeOffset =
171       StandardFrameConstants::kExpressionsOffset - 0 * kPointerSize;
172
173   static const int kFrameSize =
174       StandardFrameConstants::kFixedFrameSize + 5 * kPointerSize;
175 };
176
177
178 class InterpreterFrameConstants : public AllStatic {
179  public:
180   // Register file pointer relative.
181   static const int kLastParamFromRegisterPointer =
182       StandardFrameConstants::kFixedFrameSize + kPointerSize;
183   static const int kFunctionFromRegisterPointer = kPointerSize;
184 };
185
186
187 // Abstract base class for all stack frames.
188 class StackFrame BASE_EMBEDDED {
189  public:
190 #define DECLARE_TYPE(type, ignore) type,
191   enum Type {
192     NONE = 0,
193     STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
194     NUMBER_OF_TYPES,
195     // Used by FrameScope to indicate that the stack frame is constructed
196     // manually and the FrameScope does not need to emit code.
197     MANUAL
198   };
199 #undef DECLARE_TYPE
200
201   // Opaque data type for identifying stack frames. Used extensively
202   // by the debugger.
203   // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
204   // has correct value range (see Issue 830 for more details).
205   enum Id {
206     ID_MIN_VALUE = kMinInt,
207     ID_MAX_VALUE = kMaxInt,
208     NO_ID = 0
209   };
210
211   // Used to mark the outermost JS entry frame.
212   enum JsFrameMarker {
213     INNER_JSENTRY_FRAME = 0,
214     OUTERMOST_JSENTRY_FRAME = 1
215   };
216
217   struct State {
218     State() : sp(NULL), fp(NULL), pc_address(NULL),
219               constant_pool_address(NULL) { }
220     Address sp;
221     Address fp;
222     Address* pc_address;
223     Address* constant_pool_address;
224   };
225
226   // Copy constructor; it breaks the connection to host iterator
227   // (as an iterator usually lives on stack).
228   StackFrame(const StackFrame& original) {
229     this->state_ = original.state_;
230     this->iterator_ = NULL;
231     this->isolate_ = original.isolate_;
232   }
233
234   // Type testers.
235   bool is_entry() const { return type() == ENTRY; }
236   bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
237   bool is_exit() const { return type() == EXIT; }
238   bool is_optimized() const { return type() == OPTIMIZED; }
239   bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
240   bool is_internal() const { return type() == INTERNAL; }
241   bool is_stub_failure_trampoline() const {
242     return type() == STUB_FAILURE_TRAMPOLINE;
243   }
244   bool is_construct() const { return type() == CONSTRUCT; }
245   virtual bool is_standard() const { return false; }
246
247   bool is_java_script() const {
248     Type type = this->type();
249     return (type == JAVA_SCRIPT) || (type == OPTIMIZED);
250   }
251
252   // Accessors.
253   Address sp() const { return state_.sp; }
254   Address fp() const { return state_.fp; }
255   Address caller_sp() const { return GetCallerStackPointer(); }
256
257   // If this frame is optimized and was dynamically aligned return its old
258   // unaligned frame pointer.  When the frame is deoptimized its FP will shift
259   // up one word and become unaligned.
260   Address UnpaddedFP() const;
261
262   Address pc() const { return *pc_address(); }
263   void set_pc(Address pc) { *pc_address() = pc; }
264
265   Address constant_pool() const { return *constant_pool_address(); }
266   void set_constant_pool(Address constant_pool) {
267     *constant_pool_address() = constant_pool;
268   }
269
270   virtual void SetCallerFp(Address caller_fp) = 0;
271
272   // Manually changes value of fp in this object.
273   void UpdateFp(Address fp) { state_.fp = fp; }
274
275   Address* pc_address() const { return state_.pc_address; }
276
277   Address* constant_pool_address() const {
278     return state_.constant_pool_address;
279   }
280
281   // Get the id of this stack frame.
282   Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
283
284   // Get the top handler from the current stack iterator.
285   inline StackHandler* top_handler() const;
286
287   // Get the type of this frame.
288   virtual Type type() const = 0;
289
290   // Get the code associated with this frame.
291   // This method could be called during marking phase of GC.
292   virtual Code* unchecked_code() const = 0;
293
294   // Get the code associated with this frame.
295   inline Code* LookupCode() const;
296
297   // Get the code object that contains the given pc.
298   static inline Code* GetContainingCode(Isolate* isolate, Address pc);
299
300   // Get the code object containing the given pc and fill in the
301   // safepoint entry and the number of stack slots. The pc must be at
302   // a safepoint.
303   static Code* GetSafepointData(Isolate* isolate,
304                                 Address pc,
305                                 SafepointEntry* safepoint_entry,
306                                 unsigned* stack_slots);
307
308   virtual void Iterate(ObjectVisitor* v) const = 0;
309   static void IteratePc(ObjectVisitor* v, Address* pc_address,
310                         Address* constant_pool_address, Code* holder);
311
312   // Sets a callback function for return-address rewriting profilers
313   // to resolve the location of a return address to the location of the
314   // profiler's stashed return address.
315   static void SetReturnAddressLocationResolver(
316       ReturnAddressLocationResolver resolver);
317
318   // Resolves pc_address through the resolution address function if one is set.
319   static inline Address* ResolveReturnAddressLocation(Address* pc_address);
320
321   // Printing support.
322   enum PrintMode { OVERVIEW, DETAILS };
323   virtual void Print(StringStream* accumulator,
324                      PrintMode mode,
325                      int index) const { }
326
327   Isolate* isolate() const { return isolate_; }
328
329  protected:
330   inline explicit StackFrame(StackFrameIteratorBase* iterator);
331   virtual ~StackFrame() { }
332
333   // Compute the stack pointer for the calling frame.
334   virtual Address GetCallerStackPointer() const = 0;
335
336   // Printing support.
337   static void PrintIndex(StringStream* accumulator,
338                          PrintMode mode,
339                          int index);
340
341   // Compute the stack frame type for the given state.
342   static Type ComputeType(const StackFrameIteratorBase* iterator, State* state);
343
344 #ifdef DEBUG
345   bool can_access_heap_objects() const;
346 #endif
347
348  private:
349   const StackFrameIteratorBase* iterator_;
350   Isolate* isolate_;
351   State state_;
352
353   static ReturnAddressLocationResolver return_address_location_resolver_;
354
355   // Fill in the state of the calling frame.
356   virtual void ComputeCallerState(State* state) const = 0;
357
358   // Get the type and the state of the calling frame.
359   virtual Type GetCallerState(State* state) const;
360
361   static const intptr_t kIsolateTag = 1;
362
363   friend class StackFrameIterator;
364   friend class StackFrameIteratorBase;
365   friend class StackHandlerIterator;
366   friend class SafeStackFrameIterator;
367
368  private:
369   void operator=(const StackFrame& original);
370 };
371
372
373 // Entry frames are used to enter JavaScript execution from C.
374 class EntryFrame: public StackFrame {
375  public:
376   virtual Type type() const { return ENTRY; }
377
378   virtual Code* unchecked_code() const;
379
380   // Garbage collection support.
381   virtual void Iterate(ObjectVisitor* v) const;
382
383   static EntryFrame* cast(StackFrame* frame) {
384     DCHECK(frame->is_entry());
385     return static_cast<EntryFrame*>(frame);
386   }
387   virtual void SetCallerFp(Address caller_fp);
388
389  protected:
390   inline explicit EntryFrame(StackFrameIteratorBase* iterator);
391
392   // The caller stack pointer for entry frames is always zero. The
393   // real information about the caller frame is available through the
394   // link to the top exit frame.
395   virtual Address GetCallerStackPointer() const { return 0; }
396
397  private:
398   virtual void ComputeCallerState(State* state) const;
399   virtual Type GetCallerState(State* state) const;
400
401   friend class StackFrameIteratorBase;
402 };
403
404
405 class EntryConstructFrame: public EntryFrame {
406  public:
407   virtual Type type() const { return ENTRY_CONSTRUCT; }
408
409   virtual Code* unchecked_code() const;
410
411   static EntryConstructFrame* cast(StackFrame* frame) {
412     DCHECK(frame->is_entry_construct());
413     return static_cast<EntryConstructFrame*>(frame);
414   }
415
416  protected:
417   inline explicit EntryConstructFrame(StackFrameIteratorBase* iterator);
418
419  private:
420   friend class StackFrameIteratorBase;
421 };
422
423
424 // Exit frames are used to exit JavaScript execution and go to C.
425 class ExitFrame: public StackFrame {
426  public:
427   virtual Type type() const { return EXIT; }
428
429   virtual Code* unchecked_code() const;
430
431   Object*& code_slot() const;
432
433   // Garbage collection support.
434   virtual void Iterate(ObjectVisitor* v) const;
435
436   virtual void SetCallerFp(Address caller_fp);
437
438   static ExitFrame* cast(StackFrame* frame) {
439     DCHECK(frame->is_exit());
440     return static_cast<ExitFrame*>(frame);
441   }
442
443   // Compute the state and type of an exit frame given a frame
444   // pointer. Used when constructing the first stack frame seen by an
445   // iterator and the frames following entry frames.
446   static Type GetStateForFramePointer(Address fp, State* state);
447   static Address ComputeStackPointer(Address fp);
448   static void FillState(Address fp, Address sp, State* state);
449
450  protected:
451   inline explicit ExitFrame(StackFrameIteratorBase* iterator);
452
453   virtual Address GetCallerStackPointer() const;
454
455  private:
456   virtual void ComputeCallerState(State* state) const;
457
458   friend class StackFrameIteratorBase;
459 };
460
461
462 class StandardFrame: public StackFrame {
463  public:
464   // Testers.
465   virtual bool is_standard() const { return true; }
466
467   // Accessors.
468   inline Object* context() const;
469
470   // Access the expressions in the stack frame including locals.
471   inline Object* GetExpression(int index) const;
472   inline void SetExpression(int index, Object* value);
473   int ComputeExpressionsCount() const;
474   static Object* GetExpression(Address fp, int index);
475
476   virtual void SetCallerFp(Address caller_fp);
477
478   static StandardFrame* cast(StackFrame* frame) {
479     DCHECK(frame->is_standard());
480     return static_cast<StandardFrame*>(frame);
481   }
482
483  protected:
484   inline explicit StandardFrame(StackFrameIteratorBase* iterator);
485
486   virtual void ComputeCallerState(State* state) const;
487
488   // Accessors.
489   inline Address caller_fp() const;
490   inline Address caller_pc() const;
491
492   // Computes the address of the PC field in the standard frame given
493   // by the provided frame pointer.
494   static inline Address ComputePCAddress(Address fp);
495
496   // Computes the address of the constant pool  field in the standard
497   // frame given by the provided frame pointer.
498   static inline Address ComputeConstantPoolAddress(Address fp);
499
500   // Iterate over expression stack including stack handlers, locals,
501   // and parts of the fixed part including context and code fields.
502   void IterateExpressions(ObjectVisitor* v) const;
503
504   // Returns the address of the n'th expression stack element.
505   Address GetExpressionAddress(int n) const;
506   static Address GetExpressionAddress(Address fp, int n);
507
508   // Determines if the standard frame for the given frame pointer is
509   // an arguments adaptor frame.
510   static inline bool IsArgumentsAdaptorFrame(Address fp);
511
512   // Determines if the standard frame for the given frame pointer is a
513   // construct frame.
514   static inline bool IsConstructFrame(Address fp);
515
516   // Used by OptimizedFrames and StubFrames.
517   void IterateCompiledFrame(ObjectVisitor* v) const;
518
519  private:
520   friend class StackFrame;
521   friend class SafeStackFrameIterator;
522 };
523
524
525 class FrameSummary BASE_EMBEDDED {
526  public:
527   FrameSummary(Object* receiver, JSFunction* function, Code* code, int offset,
528                bool is_constructor);
529
530   Handle<Object> receiver() { return receiver_; }
531   Handle<JSFunction> function() { return function_; }
532   Handle<Code> code() { return code_; }
533   Address pc() { return code_->address() + offset_; }
534   int offset() { return offset_; }
535   bool is_constructor() { return is_constructor_; }
536
537   void Print();
538
539  private:
540   Handle<Object> receiver_;
541   Handle<JSFunction> function_;
542   Handle<Code> code_;
543   int offset_;
544   bool is_constructor_;
545 };
546
547
548 class JavaScriptFrame: public StandardFrame {
549  public:
550   virtual Type type() const { return JAVA_SCRIPT; }
551
552   // Accessors.
553   inline JSFunction* function() const;
554   inline Object* receiver() const;
555   inline void set_receiver(Object* value);
556
557   // Access the parameters.
558   inline Address GetParameterSlot(int index) const;
559   inline Object* GetParameter(int index) const;
560   inline int ComputeParametersCount() const {
561     return GetNumberOfIncomingArguments();
562   }
563
564   // Access the operand stack.
565   inline Address GetOperandSlot(int index) const;
566   inline Object* GetOperand(int index) const;
567   inline int ComputeOperandsCount() const;
568
569   // Generator support to preserve operand stack.
570   void SaveOperandStack(FixedArray* store) const;
571   void RestoreOperandStack(FixedArray* store);
572
573   // Debugger access.
574   void SetParameterValue(int index, Object* value) const;
575
576   // Check if this frame is a constructor frame invoked through 'new'.
577   bool IsConstructor() const;
578
579   // Determines whether this frame includes inlined activations. To get details
580   // about the inlined frames use {GetFunctions} and {Summarize}.
581   bool HasInlinedFrames();
582
583   // Returns the original constructor function that was used in the constructor
584   // call to this frame. Note that this is only valid on constructor frames.
585   Object* GetOriginalConstructor() const;
586
587   // Check if this frame has "adapted" arguments in the sense that the
588   // actual passed arguments are available in an arguments adaptor
589   // frame below it on the stack.
590   inline bool has_adapted_arguments() const;
591   int GetArgumentsLength() const;
592
593   // Garbage collection support.
594   virtual void Iterate(ObjectVisitor* v) const;
595
596   // Printing support.
597   virtual void Print(StringStream* accumulator,
598                      PrintMode mode,
599                      int index) const;
600
601   // Determine the code for the frame.
602   virtual Code* unchecked_code() const;
603
604   // Return a list with JSFunctions of this frame.
605   virtual void GetFunctions(List<JSFunction*>* functions);
606
607   // Build a list with summaries for this frame including all inlined frames.
608   virtual void Summarize(List<FrameSummary>* frames);
609
610   // Lookup exception handler for current {pc}, returns -1 if none found. Also
611   // returns the expected number of stack slots at the handler site.
612   virtual int LookupExceptionHandlerInTable(
613       int* stack_slots, HandlerTable::CatchPrediction* prediction);
614
615   // Architecture-specific register description.
616   static Register fp_register();
617   static Register context_register();
618   static Register constant_pool_pointer_register();
619
620   static JavaScriptFrame* cast(StackFrame* frame) {
621     DCHECK(frame->is_java_script());
622     return static_cast<JavaScriptFrame*>(frame);
623   }
624
625   static void PrintFunctionAndOffset(JSFunction* function, Code* code,
626                                      Address pc, FILE* file,
627                                      bool print_line_number);
628
629   static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
630                        bool print_line_number);
631
632  protected:
633   inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator);
634
635   virtual Address GetCallerStackPointer() const;
636
637   virtual int GetNumberOfIncomingArguments() const;
638
639   // Garbage collection support. Iterates over incoming arguments,
640   // receiver, and any callee-saved registers.
641   void IterateArguments(ObjectVisitor* v) const;
642
643  private:
644   inline Object* function_slot_object() const;
645
646   friend class StackFrameIteratorBase;
647 };
648
649
650 class StubFrame : public StandardFrame {
651  public:
652   virtual Type type() const { return STUB; }
653
654   // GC support.
655   virtual void Iterate(ObjectVisitor* v) const;
656
657   // Determine the code for the frame.
658   virtual Code* unchecked_code() const;
659
660  protected:
661   inline explicit StubFrame(StackFrameIteratorBase* iterator);
662
663   virtual Address GetCallerStackPointer() const;
664
665   virtual int GetNumberOfIncomingArguments() const;
666
667   friend class StackFrameIteratorBase;
668 };
669
670
671 class OptimizedFrame : public JavaScriptFrame {
672  public:
673   virtual Type type() const { return OPTIMIZED; }
674
675   // GC support.
676   virtual void Iterate(ObjectVisitor* v) const;
677
678   // Return a list with JSFunctions of this frame.
679   // The functions are ordered bottom-to-top (i.e. functions.last()
680   // is the top-most activation)
681   virtual void GetFunctions(List<JSFunction*>* functions);
682
683   virtual void Summarize(List<FrameSummary>* frames);
684
685   // Lookup exception handler for current {pc}, returns -1 if none found. Also
686   // returns the expected number of stack slots at the handler site.
687   virtual int LookupExceptionHandlerInTable(
688       int* stack_slots, HandlerTable::CatchPrediction* prediction);
689
690   DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
691
692   static int StackSlotOffsetRelativeToFp(int slot_index);
693
694  protected:
695   inline explicit OptimizedFrame(StackFrameIteratorBase* iterator);
696
697  private:
698   friend class StackFrameIteratorBase;
699
700   Object* StackSlotAt(int index) const;
701 };
702
703
704 // Arguments adaptor frames are automatically inserted below
705 // JavaScript frames when the actual number of parameters does not
706 // match the formal number of parameters.
707 class ArgumentsAdaptorFrame: public JavaScriptFrame {
708  public:
709   virtual Type type() const { return ARGUMENTS_ADAPTOR; }
710
711   // Determine the code for the frame.
712   virtual Code* unchecked_code() const;
713
714   static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
715     DCHECK(frame->is_arguments_adaptor());
716     return static_cast<ArgumentsAdaptorFrame*>(frame);
717   }
718
719   // Printing support.
720   virtual void Print(StringStream* accumulator,
721                      PrintMode mode,
722                      int index) const;
723
724  protected:
725   inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator);
726
727   virtual int GetNumberOfIncomingArguments() const;
728
729   virtual Address GetCallerStackPointer() const;
730
731  private:
732   friend class StackFrameIteratorBase;
733 };
734
735
736 class InternalFrame: public StandardFrame {
737  public:
738   virtual Type type() const { return INTERNAL; }
739
740   // Garbage collection support.
741   virtual void Iterate(ObjectVisitor* v) const;
742
743   // Determine the code for the frame.
744   virtual Code* unchecked_code() const;
745
746   static InternalFrame* cast(StackFrame* frame) {
747     DCHECK(frame->is_internal());
748     return static_cast<InternalFrame*>(frame);
749   }
750
751  protected:
752   inline explicit InternalFrame(StackFrameIteratorBase* iterator);
753
754   virtual Address GetCallerStackPointer() const;
755
756  private:
757   friend class StackFrameIteratorBase;
758 };
759
760
761 class StubFailureTrampolineFrame: public StandardFrame {
762  public:
763   // sizeof(Arguments) - sizeof(Arguments*) is 3 * kPointerSize), but the
764   // presubmit script complains about using sizeof() on a type.
765   static const int kFirstRegisterParameterFrameOffset =
766       StandardFrameConstants::kMarkerOffset - 3 * kPointerSize;
767
768   static const int kCallerStackParameterCountFrameOffset =
769       StandardFrameConstants::kMarkerOffset - 2 * kPointerSize;
770
771   virtual Type type() const { return STUB_FAILURE_TRAMPOLINE; }
772
773   // Get the code associated with this frame.
774   // This method could be called during marking phase of GC.
775   virtual Code* unchecked_code() const;
776
777   virtual void Iterate(ObjectVisitor* v) const;
778
779   // Architecture-specific register description.
780   static Register fp_register();
781   static Register context_register();
782   static Register constant_pool_pointer_register();
783
784  protected:
785   inline explicit StubFailureTrampolineFrame(
786       StackFrameIteratorBase* iterator);
787
788   virtual Address GetCallerStackPointer() const;
789
790  private:
791   friend class StackFrameIteratorBase;
792 };
793
794
795 // Construct frames are special trampoline frames introduced to handle
796 // function invocations through 'new'.
797 class ConstructFrame: public InternalFrame {
798  public:
799   virtual Type type() const { return CONSTRUCT; }
800
801   static ConstructFrame* cast(StackFrame* frame) {
802     DCHECK(frame->is_construct());
803     return static_cast<ConstructFrame*>(frame);
804   }
805
806  protected:
807   inline explicit ConstructFrame(StackFrameIteratorBase* iterator);
808
809  private:
810   friend class StackFrameIteratorBase;
811 };
812
813
814 class StackFrameIteratorBase BASE_EMBEDDED {
815  public:
816   Isolate* isolate() const { return isolate_; }
817
818   bool done() const { return frame_ == NULL; }
819
820  protected:
821   // An iterator that iterates over a given thread's stack.
822   StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects);
823
824   Isolate* isolate_;
825 #define DECLARE_SINGLETON(ignore, type) type type##_;
826   STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
827 #undef DECLARE_SINGLETON
828   StackFrame* frame_;
829   StackHandler* handler_;
830   const bool can_access_heap_objects_;
831
832   StackHandler* handler() const {
833     DCHECK(!done());
834     return handler_;
835   }
836
837   // Get the type-specific frame singleton in a given state.
838   StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
839   // A helper function, can return a NULL pointer.
840   StackFrame* SingletonFor(StackFrame::Type type);
841
842  private:
843   friend class StackFrame;
844   DISALLOW_COPY_AND_ASSIGN(StackFrameIteratorBase);
845 };
846
847
848 class StackFrameIterator: public StackFrameIteratorBase {
849  public:
850   // An iterator that iterates over the isolate's current thread's stack,
851   explicit StackFrameIterator(Isolate* isolate);
852   // An iterator that iterates over a given thread's stack.
853   StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
854
855   StackFrame* frame() const {
856     DCHECK(!done());
857     return frame_;
858   }
859   void Advance();
860
861  private:
862   // Go back to the first frame.
863   void Reset(ThreadLocalTop* top);
864
865   DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
866 };
867
868
869 // Iterator that supports iterating through all JavaScript frames.
870 class JavaScriptFrameIterator BASE_EMBEDDED {
871  public:
872   inline explicit JavaScriptFrameIterator(Isolate* isolate);
873   inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top);
874   // Skip frames until the frame with the given id is reached.
875   JavaScriptFrameIterator(Isolate* isolate, StackFrame::Id id);
876
877   inline JavaScriptFrame* frame() const;
878
879   bool done() const { return iterator_.done(); }
880   void Advance();
881
882   // Advance to the frame holding the arguments for the current
883   // frame. This only affects the current frame if it has adapted
884   // arguments.
885   void AdvanceToArgumentsFrame();
886
887  private:
888   StackFrameIterator iterator_;
889 };
890
891
892 // NOTE: The stack trace frame iterator is an iterator that only
893 // traverse proper JavaScript frames; that is JavaScript frames that
894 // have proper JavaScript functions. This excludes the problematic
895 // functions in runtime.js.
896 class StackTraceFrameIterator: public JavaScriptFrameIterator {
897  public:
898   explicit StackTraceFrameIterator(Isolate* isolate);
899   void Advance();
900
901  private:
902   bool IsValidFrame();
903 };
904
905
906 class SafeStackFrameIterator: public StackFrameIteratorBase {
907  public:
908   SafeStackFrameIterator(Isolate* isolate,
909                          Address fp, Address sp,
910                          Address js_entry_sp);
911
912   inline StackFrame* frame() const;
913   void Advance();
914
915   StackFrame::Type top_frame_type() const { return top_frame_type_; }
916
917  private:
918   void AdvanceOneFrame();
919
920   bool IsValidStackAddress(Address addr) const {
921     return low_bound_ <= addr && addr <= high_bound_;
922   }
923   bool IsValidFrame(StackFrame* frame) const;
924   bool IsValidCaller(StackFrame* frame);
925   bool IsValidExitFrame(Address fp) const;
926   bool IsValidTop(ThreadLocalTop* top) const;
927
928   const Address low_bound_;
929   const Address high_bound_;
930   StackFrame::Type top_frame_type_;
931   ExternalCallbackScope* external_callback_scope_;
932 };
933
934
935 class StackFrameLocator BASE_EMBEDDED {
936  public:
937   explicit StackFrameLocator(Isolate* isolate) : iterator_(isolate) {}
938
939   // Find the nth JavaScript frame on the stack. The caller must
940   // guarantee that such a frame exists.
941   JavaScriptFrame* FindJavaScriptFrame(int n);
942
943  private:
944   StackFrameIterator iterator_;
945 };
946
947
948 // Reads all frames on the current stack and copies them into the current
949 // zone memory.
950 Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone);
951
952 } }  // namespace v8::internal
953
954 #endif  // V8_FRAMES_H_