• 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     DCHECK(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     DCHECK(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     DCHECK(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     DCHECK(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     DCHECK(frame->is_java_script());
614     return static_cast<JavaScriptFrame*>(frame);
615   }
616 
617   static void PrintFunctionAndOffset(JSFunction* function, Code* code,
618                                      Address pc, FILE* file,
619                                      bool print_line_number);
620 
621   static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
622                        bool print_line_number);
623 
624  protected:
625   inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator);
626 
627   virtual Address GetCallerStackPointer() const;
628 
629   virtual int GetNumberOfIncomingArguments() const;
630 
631   // Garbage collection support. Iterates over incoming arguments,
632   // receiver, and any callee-saved registers.
633   void IterateArguments(ObjectVisitor* v) const;
634 
635  private:
636   inline Object* function_slot_object() const;
637 
638   friend class StackFrameIteratorBase;
639 };
640 
641 
642 class StubFrame : public StandardFrame {
643  public:
type()644   virtual Type type() const { return STUB; }
645 
646   // GC support.
647   virtual void Iterate(ObjectVisitor* v) const;
648 
649   // Determine the code for the frame.
650   virtual Code* unchecked_code() const;
651 
652  protected:
653   inline explicit StubFrame(StackFrameIteratorBase* iterator);
654 
655   virtual Address GetCallerStackPointer() const;
656 
657   virtual int GetNumberOfIncomingArguments() const;
658 
659   friend class StackFrameIteratorBase;
660 };
661 
662 
663 class OptimizedFrame : public JavaScriptFrame {
664  public:
type()665   virtual Type type() const { return OPTIMIZED; }
666 
667   // GC support.
668   virtual void Iterate(ObjectVisitor* v) const;
669 
670   virtual int GetInlineCount();
671 
672   // Return a list with JSFunctions of this frame.
673   // The functions are ordered bottom-to-top (i.e. functions.last()
674   // is the top-most activation)
675   virtual void GetFunctions(List<JSFunction*>* functions);
676 
677   virtual void Summarize(List<FrameSummary>* frames);
678 
679   DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
680 
681  protected:
682   inline explicit OptimizedFrame(StackFrameIteratorBase* iterator);
683 
684  private:
685   JSFunction* LiteralAt(FixedArray* literal_array, int literal_id);
686 
687   friend class StackFrameIteratorBase;
688 };
689 
690 
691 // Arguments adaptor frames are automatically inserted below
692 // JavaScript frames when the actual number of parameters does not
693 // match the formal number of parameters.
694 class ArgumentsAdaptorFrame: public JavaScriptFrame {
695  public:
type()696   virtual Type type() const { return ARGUMENTS_ADAPTOR; }
697 
698   // Determine the code for the frame.
699   virtual Code* unchecked_code() const;
700 
cast(StackFrame * frame)701   static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
702     DCHECK(frame->is_arguments_adaptor());
703     return static_cast<ArgumentsAdaptorFrame*>(frame);
704   }
705 
706   // Printing support.
707   virtual void Print(StringStream* accumulator,
708                      PrintMode mode,
709                      int index) const;
710 
711  protected:
712   inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator);
713 
714   virtual int GetNumberOfIncomingArguments() const;
715 
716   virtual Address GetCallerStackPointer() const;
717 
718  private:
719   friend class StackFrameIteratorBase;
720 };
721 
722 
723 class InternalFrame: public StandardFrame {
724  public:
type()725   virtual Type type() const { return INTERNAL; }
726 
727   // Garbage collection support.
728   virtual void Iterate(ObjectVisitor* v) const;
729 
730   // Determine the code for the frame.
731   virtual Code* unchecked_code() const;
732 
cast(StackFrame * frame)733   static InternalFrame* cast(StackFrame* frame) {
734     DCHECK(frame->is_internal());
735     return static_cast<InternalFrame*>(frame);
736   }
737 
738  protected:
739   inline explicit InternalFrame(StackFrameIteratorBase* iterator);
740 
741   virtual Address GetCallerStackPointer() const;
742 
743  private:
744   friend class StackFrameIteratorBase;
745 };
746 
747 
748 class StubFailureTrampolineFrame: public StandardFrame {
749  public:
750   // sizeof(Arguments) - sizeof(Arguments*) is 3 * kPointerSize), but the
751   // presubmit script complains about using sizeof() on a type.
752   static const int kFirstRegisterParameterFrameOffset =
753       StandardFrameConstants::kMarkerOffset - 3 * kPointerSize;
754 
755   static const int kCallerStackParameterCountFrameOffset =
756       StandardFrameConstants::kMarkerOffset - 2 * kPointerSize;
757 
type()758   virtual Type type() const { return STUB_FAILURE_TRAMPOLINE; }
759 
760   // Get the code associated with this frame.
761   // This method could be called during marking phase of GC.
762   virtual Code* unchecked_code() const;
763 
764   virtual void Iterate(ObjectVisitor* v) const;
765 
766   // Architecture-specific register description.
767   static Register fp_register();
768   static Register context_register();
769   static Register constant_pool_pointer_register();
770 
771  protected:
772   inline explicit StubFailureTrampolineFrame(
773       StackFrameIteratorBase* iterator);
774 
775   virtual Address GetCallerStackPointer() const;
776 
777  private:
778   friend class StackFrameIteratorBase;
779 };
780 
781 
782 // Construct frames are special trampoline frames introduced to handle
783 // function invocations through 'new'.
784 class ConstructFrame: public InternalFrame {
785  public:
type()786   virtual Type type() const { return CONSTRUCT; }
787 
cast(StackFrame * frame)788   static ConstructFrame* cast(StackFrame* frame) {
789     DCHECK(frame->is_construct());
790     return static_cast<ConstructFrame*>(frame);
791   }
792 
793  protected:
794   inline explicit ConstructFrame(StackFrameIteratorBase* iterator);
795 
796  private:
797   friend class StackFrameIteratorBase;
798 };
799 
800 
801 class StackFrameIteratorBase BASE_EMBEDDED {
802  public:
isolate()803   Isolate* isolate() const { return isolate_; }
804 
done()805   bool done() const { return frame_ == NULL; }
806 
807  protected:
808   // An iterator that iterates over a given thread's stack.
809   StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects);
810 
811   Isolate* isolate_;
812 #define DECLARE_SINGLETON(ignore, type) type type##_;
813   STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
814 #undef DECLARE_SINGLETON
815   StackFrame* frame_;
816   StackHandler* handler_;
817   const bool can_access_heap_objects_;
818 
handler()819   StackHandler* handler() const {
820     DCHECK(!done());
821     return handler_;
822   }
823 
824   // Get the type-specific frame singleton in a given state.
825   StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
826   // A helper function, can return a NULL pointer.
827   StackFrame* SingletonFor(StackFrame::Type type);
828 
829  private:
830   friend class StackFrame;
831   DISALLOW_COPY_AND_ASSIGN(StackFrameIteratorBase);
832 };
833 
834 
835 class StackFrameIterator: public StackFrameIteratorBase {
836  public:
837   // An iterator that iterates over the isolate's current thread's stack,
838   explicit StackFrameIterator(Isolate* isolate);
839   // An iterator that iterates over a given thread's stack.
840   StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
841 
frame()842   StackFrame* frame() const {
843     DCHECK(!done());
844     return frame_;
845   }
846   void Advance();
847 
848  private:
849   // Go back to the first frame.
850   void Reset(ThreadLocalTop* top);
851 
852   DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
853 };
854 
855 
856 // Iterator that supports iterating through all JavaScript frames.
857 class JavaScriptFrameIterator BASE_EMBEDDED {
858  public:
859   inline explicit JavaScriptFrameIterator(Isolate* isolate);
860   inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top);
861   // Skip frames until the frame with the given id is reached.
862   JavaScriptFrameIterator(Isolate* isolate, StackFrame::Id id);
863 
864   inline JavaScriptFrame* frame() const;
865 
done()866   bool done() const { return iterator_.done(); }
867   void Advance();
868 
869   // Advance to the frame holding the arguments for the current
870   // frame. This only affects the current frame if it has adapted
871   // arguments.
872   void AdvanceToArgumentsFrame();
873 
874  private:
875   StackFrameIterator iterator_;
876 };
877 
878 
879 // NOTE: The stack trace frame iterator is an iterator that only
880 // traverse proper JavaScript frames; that is JavaScript frames that
881 // have proper JavaScript functions. This excludes the problematic
882 // functions in runtime.js.
883 class StackTraceFrameIterator: public JavaScriptFrameIterator {
884  public:
885   explicit StackTraceFrameIterator(Isolate* isolate);
886   void Advance();
887 
888  private:
889   bool IsValidFrame();
890 };
891 
892 
893 class SafeStackFrameIterator: public StackFrameIteratorBase {
894  public:
895   SafeStackFrameIterator(Isolate* isolate,
896                          Address fp, Address sp,
897                          Address js_entry_sp);
898 
899   inline StackFrame* frame() const;
900   void Advance();
901 
top_frame_type()902   StackFrame::Type top_frame_type() const { return top_frame_type_; }
903 
904  private:
905   void AdvanceOneFrame();
906 
IsValidStackAddress(Address addr)907   bool IsValidStackAddress(Address addr) const {
908     return low_bound_ <= addr && addr <= high_bound_;
909   }
910   bool IsValidFrame(StackFrame* frame) const;
911   bool IsValidCaller(StackFrame* frame);
912   bool IsValidExitFrame(Address fp) const;
913   bool IsValidTop(ThreadLocalTop* top) const;
914 
915   const Address low_bound_;
916   const Address high_bound_;
917   StackFrame::Type top_frame_type_;
918   ExternalCallbackScope* external_callback_scope_;
919 };
920 
921 
922 class StackFrameLocator BASE_EMBEDDED {
923  public:
StackFrameLocator(Isolate * isolate)924   explicit StackFrameLocator(Isolate* isolate) : iterator_(isolate) {}
925 
926   // Find the nth JavaScript frame on the stack. The caller must
927   // guarantee that such a frame exists.
928   JavaScriptFrame* FindJavaScriptFrame(int n);
929 
930  private:
931   StackFrameIterator iterator_;
932 };
933 
934 
935 // Reads all frames on the current stack and copies them into the current
936 // zone memory.
937 Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone);
938 
939 } }  // namespace v8::internal
940 
941 #endif  // V8_FRAMES_H_
942