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