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