Home | History | Annotate | Download | only in src
      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   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 {
    205     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).
    215   StackFrame(const StackFrame& original) {
    216     this->state_ = original.state_;
    217     this->iterator_ = NULL;
    218     this->isolate_ = original.isolate_;
    219   }
    220 
    221   // Type testers.
    222   bool is_entry() const { return type() == ENTRY; }
    223   bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
    224   bool is_exit() const { return type() == EXIT; }
    225   bool is_optimized() const { return type() == OPTIMIZED; }
    226   bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
    227   bool is_internal() const { return type() == INTERNAL; }
    228   bool is_stub_failure_trampoline() const {
    229     return type() == STUB_FAILURE_TRAMPOLINE;
    230   }
    231   bool is_construct() const { return type() == CONSTRUCT; }
    232   virtual bool is_standard() const { return false; }
    233 
    234   bool is_java_script() const {
    235     Type type = this->type();
    236     return (type == JAVA_SCRIPT) || (type == OPTIMIZED);
    237   }
    238 
    239   // Accessors.
    240   Address sp() const { return state_.sp; }
    241   Address fp() const { return state_.fp; }
    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 
    249   Address pc() const { return *pc_address(); }
    250   void set_pc(Address pc) { *pc_address() = pc; }
    251 
    252   Address constant_pool() const { return *constant_pool_address(); }
    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.
    260   void UpdateFp(Address fp) { state_.fp = fp; }
    261 
    262   Address* pc_address() const { return state_.pc_address; }
    263 
    264   Address* constant_pool_address() const {
    265     return state_.constant_pool_address;
    266   }
    267 
    268   // Get the id of this stack frame.
    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 };
    310   virtual void Print(StringStream* accumulator,
    311                      PrintMode mode,
    312                      int index) const { }
    313 
    314   Isolate* isolate() const { return isolate_; }
    315 
    316  protected:
    317   inline explicit StackFrame(StackFrameIteratorBase* iterator);
    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:
    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 
    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.
    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:
    397   virtual Type type() const { return ENTRY_CONSTRUCT; }
    398 
    399   virtual Code* unchecked_code() const;
    400 
    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:
    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 
    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.
    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 
    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:
    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) { }
    532   Handle<Object> receiver() { return receiver_; }
    533   Handle<JSFunction> function() { return function_; }
    534   Handle<Code> code() { return code_; }
    535   Address pc() { return code_->address() + offset_; }
    536   int offset() { return offset_; }
    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:
    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;
    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.
    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 
    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:
    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:
    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:
    696   virtual Type type() const { return ARGUMENTS_ADAPTOR; }
    697 
    698   // Determine the code for the frame.
    699   virtual Code* unchecked_code() const;
    700 
    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:
    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 
    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 
    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:
    786   virtual Type type() const { return CONSTRUCT; }
    787 
    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:
    803   Isolate* isolate() const { return isolate_; }
    804 
    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 
    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 
    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 
    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 
    902   StackFrame::Type top_frame_type() const { return top_frame_type_; }
    903 
    904  private:
    905   void AdvanceOneFrame();
    906 
    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:
    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