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