Home | History | Annotate | Download | only in src
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_FRAMES_H_
     29 #define V8_FRAMES_H_
     30 
     31 #include "allocation.h"
     32 #include "handles.h"
     33 #include "safepoint-table.h"
     34 
     35 namespace v8 {
     36 namespace internal {
     37 
     38 typedef uint32_t RegList;
     39 
     40 // Get the number of registers in a given register list.
     41 int NumRegs(RegList list);
     42 
     43 // Return the code of the n-th saved register available to JavaScript.
     44 int JSCallerSavedCode(int n);
     45 
     46 
     47 // Forward declarations.
     48 class StackFrameIterator;
     49 class ThreadLocalTop;
     50 class Isolate;
     51 
     52 class InnerPointerToCodeCache {
     53  public:
     54   struct InnerPointerToCodeCacheEntry {
     55     Address inner_pointer;
     56     Code* code;
     57     SafepointEntry safepoint_entry;
     58   };
     59 
     60   explicit InnerPointerToCodeCache(Isolate* isolate) : isolate_(isolate) {
     61     Flush();
     62   }
     63 
     64   Code* GcSafeFindCodeForInnerPointer(Address inner_pointer);
     65   Code* GcSafeCastToCode(HeapObject* object, Address inner_pointer);
     66 
     67   void Flush() {
     68     memset(&cache_[0], 0, sizeof(cache_));
     69   }
     70 
     71   InnerPointerToCodeCacheEntry* GetCacheEntry(Address inner_pointer);
     72 
     73  private:
     74   InnerPointerToCodeCacheEntry* cache(int index) { return &cache_[index]; }
     75 
     76   Isolate* isolate_;
     77 
     78   static const int kInnerPointerToCodeCacheSize = 1024;
     79   InnerPointerToCodeCacheEntry cache_[kInnerPointerToCodeCacheSize];
     80 
     81   DISALLOW_COPY_AND_ASSIGN(InnerPointerToCodeCache);
     82 };
     83 
     84 
     85 class StackHandler BASE_EMBEDDED {
     86  public:
     87   enum Kind {
     88     JS_ENTRY,
     89     CATCH,
     90     FINALLY,
     91     LAST_KIND = FINALLY
     92   };
     93 
     94   static const int kKindWidth = 2;
     95   STATIC_ASSERT(LAST_KIND < (1 << kKindWidth));
     96   static const int kIndexWidth = 32 - kKindWidth;
     97   class KindField: public BitField<StackHandler::Kind, 0, kKindWidth> {};
     98   class IndexField: public BitField<unsigned, kKindWidth, kIndexWidth> {};
     99 
    100   // Get the address of this stack handler.
    101   inline Address address() const;
    102 
    103   // Get the next stack handler in the chain.
    104   inline StackHandler* next() const;
    105 
    106   // Tells whether the given address is inside this handler.
    107   inline bool includes(Address address) const;
    108 
    109   // Garbage collection support.
    110   inline void Iterate(ObjectVisitor* v, Code* holder) const;
    111 
    112   // Conversion support.
    113   static inline StackHandler* FromAddress(Address address);
    114 
    115   // Testers
    116   inline bool is_js_entry() const;
    117   inline bool is_catch() const;
    118   inline bool is_finally() const;
    119 
    120  private:
    121   // Accessors.
    122   inline Kind kind() const;
    123 
    124   inline Object** context_address() const;
    125   inline Object** code_address() const;
    126 
    127   DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
    128 };
    129 
    130 
    131 #define STACK_FRAME_TYPE_LIST(V)              \
    132   V(ENTRY,             EntryFrame)            \
    133   V(ENTRY_CONSTRUCT,   EntryConstructFrame)   \
    134   V(EXIT,              ExitFrame)             \
    135   V(JAVA_SCRIPT,       JavaScriptFrame)       \
    136   V(OPTIMIZED,         OptimizedFrame)        \
    137   V(INTERNAL,          InternalFrame)         \
    138   V(CONSTRUCT,         ConstructFrame)        \
    139   V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
    140 
    141 
    142 // Abstract base class for all stack frames.
    143 class StackFrame BASE_EMBEDDED {
    144  public:
    145 #define DECLARE_TYPE(type, ignore) type,
    146   enum Type {
    147     NONE = 0,
    148     STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
    149     NUMBER_OF_TYPES,
    150     // Used by FrameScope to indicate that the stack frame is constructed
    151     // manually and the FrameScope does not need to emit code.
    152     MANUAL
    153   };
    154 #undef DECLARE_TYPE
    155 
    156   // Opaque data type for identifying stack frames. Used extensively
    157   // by the debugger.
    158   // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
    159   // has correct value range (see Issue 830 for more details).
    160   enum Id {
    161     ID_MIN_VALUE = kMinInt,
    162     ID_MAX_VALUE = kMaxInt,
    163     NO_ID = 0
    164   };
    165 
    166   // Used to mark the outermost JS entry frame.
    167   enum JsFrameMarker {
    168     INNER_JSENTRY_FRAME = 0,
    169     OUTERMOST_JSENTRY_FRAME = 1
    170   };
    171 
    172   struct State {
    173     State() : sp(NULL), fp(NULL), pc_address(NULL) { }
    174     Address sp;
    175     Address fp;
    176     Address* pc_address;
    177   };
    178 
    179   // Copy constructor; it breaks the connection to host iterator
    180   // (as an iterator usually lives on stack).
    181   StackFrame(const StackFrame& original) {
    182     this->state_ = original.state_;
    183     this->iterator_ = NULL;
    184     this->isolate_ = original.isolate_;
    185   }
    186 
    187   // Type testers.
    188   bool is_entry() const { return type() == ENTRY; }
    189   bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
    190   bool is_exit() const { return type() == EXIT; }
    191   bool is_optimized() const { return type() == OPTIMIZED; }
    192   bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
    193   bool is_internal() const { return type() == INTERNAL; }
    194   bool is_construct() const { return type() == CONSTRUCT; }
    195   virtual bool is_standard() const { return false; }
    196 
    197   bool is_java_script() const {
    198     Type type = this->type();
    199     return (type == JAVA_SCRIPT) || (type == OPTIMIZED);
    200   }
    201 
    202   // Accessors.
    203   Address sp() const { return state_.sp; }
    204   Address fp() const { return state_.fp; }
    205   Address caller_sp() const { return GetCallerStackPointer(); }
    206 
    207   Address pc() const { return *pc_address(); }
    208   void set_pc(Address pc) { *pc_address() = pc; }
    209 
    210   virtual void SetCallerFp(Address caller_fp) = 0;
    211 
    212   Address* pc_address() const { return state_.pc_address; }
    213 
    214   // Get the id of this stack frame.
    215   Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
    216 
    217   // Checks if this frame includes any stack handlers.
    218   bool HasHandler() const;
    219 
    220   // Get the type of this frame.
    221   virtual Type type() const = 0;
    222 
    223   // Get the code associated with this frame.
    224   // This method could be called during marking phase of GC.
    225   virtual Code* unchecked_code() const = 0;
    226 
    227   // Get the code associated with this frame.
    228   inline Code* LookupCode() const;
    229 
    230   // Get the code object that contains the given pc.
    231   static inline Code* GetContainingCode(Isolate* isolate, Address pc);
    232 
    233   // Get the code object containing the given pc and fill in the
    234   // safepoint entry and the number of stack slots. The pc must be at
    235   // a safepoint.
    236   static Code* GetSafepointData(Isolate* isolate,
    237                                 Address pc,
    238                                 SafepointEntry* safepoint_entry,
    239                                 unsigned* stack_slots);
    240 
    241   virtual void Iterate(ObjectVisitor* v) const = 0;
    242   static void IteratePc(ObjectVisitor* v, Address* pc_address, Code* holder);
    243 
    244   // Sets a callback function for return-address rewriting profilers
    245   // to resolve the location of a return address to the location of the
    246   // profiler's stashed return address.
    247   static void SetReturnAddressLocationResolver(
    248       ReturnAddressLocationResolver resolver);
    249 
    250   // Printing support.
    251   enum PrintMode { OVERVIEW, DETAILS };
    252   virtual void Print(StringStream* accumulator,
    253                      PrintMode mode,
    254                      int index) const { }
    255 
    256  protected:
    257   inline explicit StackFrame(StackFrameIterator* iterator);
    258   virtual ~StackFrame() { }
    259 
    260   Isolate* isolate() const { return isolate_; }
    261 
    262   // Compute the stack pointer for the calling frame.
    263   virtual Address GetCallerStackPointer() const = 0;
    264 
    265   // Printing support.
    266   static void PrintIndex(StringStream* accumulator,
    267                          PrintMode mode,
    268                          int index);
    269 
    270   // Get the top handler from the current stack iterator.
    271   inline StackHandler* top_handler() const;
    272 
    273   // Compute the stack frame type for the given state.
    274   static Type ComputeType(Isolate* isolate, State* state);
    275 
    276  private:
    277   const StackFrameIterator* iterator_;
    278   Isolate* isolate_;
    279   State state_;
    280 
    281   // Fill in the state of the calling frame.
    282   virtual void ComputeCallerState(State* state) const = 0;
    283 
    284   // Get the type and the state of the calling frame.
    285   virtual Type GetCallerState(State* state) const;
    286 
    287   static const intptr_t kIsolateTag = 1;
    288 
    289   friend class StackFrameIterator;
    290   friend class StackHandlerIterator;
    291   friend class SafeStackFrameIterator;
    292 
    293  private:
    294   void operator=(const StackFrame& original);
    295 };
    296 
    297 
    298 // Entry frames are used to enter JavaScript execution from C.
    299 class EntryFrame: public StackFrame {
    300  public:
    301   virtual Type type() const { return ENTRY; }
    302 
    303   virtual Code* unchecked_code() const;
    304 
    305   // Garbage collection support.
    306   virtual void Iterate(ObjectVisitor* v) const;
    307 
    308   static EntryFrame* cast(StackFrame* frame) {
    309     ASSERT(frame->is_entry());
    310     return static_cast<EntryFrame*>(frame);
    311   }
    312   virtual void SetCallerFp(Address caller_fp);
    313 
    314  protected:
    315   inline explicit EntryFrame(StackFrameIterator* iterator);
    316 
    317   // The caller stack pointer for entry frames is always zero. The
    318   // real information about the caller frame is available through the
    319   // link to the top exit frame.
    320   virtual Address GetCallerStackPointer() const { return 0; }
    321 
    322  private:
    323   virtual void ComputeCallerState(State* state) const;
    324   virtual Type GetCallerState(State* state) const;
    325 
    326   friend class StackFrameIterator;
    327 };
    328 
    329 
    330 class EntryConstructFrame: public EntryFrame {
    331  public:
    332   virtual Type type() const { return ENTRY_CONSTRUCT; }
    333 
    334   virtual Code* unchecked_code() const;
    335 
    336   static EntryConstructFrame* cast(StackFrame* frame) {
    337     ASSERT(frame->is_entry_construct());
    338     return static_cast<EntryConstructFrame*>(frame);
    339   }
    340 
    341  protected:
    342   inline explicit EntryConstructFrame(StackFrameIterator* iterator);
    343 
    344  private:
    345   friend class StackFrameIterator;
    346 };
    347 
    348 
    349 // Exit frames are used to exit JavaScript execution and go to C.
    350 class ExitFrame: public StackFrame {
    351  public:
    352   virtual Type type() const { return EXIT; }
    353 
    354   virtual Code* unchecked_code() const;
    355 
    356   Object*& code_slot() const;
    357 
    358   // Garbage collection support.
    359   virtual void Iterate(ObjectVisitor* v) const;
    360 
    361   virtual void SetCallerFp(Address caller_fp);
    362 
    363   static ExitFrame* cast(StackFrame* frame) {
    364     ASSERT(frame->is_exit());
    365     return static_cast<ExitFrame*>(frame);
    366   }
    367 
    368   // Compute the state and type of an exit frame given a frame
    369   // pointer. Used when constructing the first stack frame seen by an
    370   // iterator and the frames following entry frames.
    371   static Type GetStateForFramePointer(Address fp, State* state);
    372   static Address ComputeStackPointer(Address fp);
    373   static void FillState(Address fp, Address sp, State* state);
    374 
    375  protected:
    376   inline explicit ExitFrame(StackFrameIterator* iterator);
    377 
    378   virtual Address GetCallerStackPointer() const;
    379 
    380  private:
    381   virtual void ComputeCallerState(State* state) const;
    382 
    383   friend class StackFrameIterator;
    384 };
    385 
    386 
    387 class StandardFrame: public StackFrame {
    388  public:
    389   // Testers.
    390   virtual bool is_standard() const { return true; }
    391 
    392   // Accessors.
    393   inline Object* context() const;
    394 
    395   // Access the expressions in the stack frame including locals.
    396   inline Object* GetExpression(int index) const;
    397   inline void SetExpression(int index, Object* value);
    398   int ComputeExpressionsCount() const;
    399   static Object* GetExpression(Address fp, int index);
    400 
    401   virtual void SetCallerFp(Address caller_fp);
    402 
    403   static StandardFrame* cast(StackFrame* frame) {
    404     ASSERT(frame->is_standard());
    405     return static_cast<StandardFrame*>(frame);
    406   }
    407 
    408  protected:
    409   inline explicit StandardFrame(StackFrameIterator* iterator);
    410 
    411   virtual void ComputeCallerState(State* state) const;
    412 
    413   // Accessors.
    414   inline Address caller_fp() const;
    415   inline Address caller_pc() const;
    416 
    417   // Computes the address of the PC field in the standard frame given
    418   // by the provided frame pointer.
    419   static inline Address ComputePCAddress(Address fp);
    420 
    421   // Iterate over expression stack including stack handlers, locals,
    422   // and parts of the fixed part including context and code fields.
    423   void IterateExpressions(ObjectVisitor* v) const;
    424 
    425   // Returns the address of the n'th expression stack element.
    426   Address GetExpressionAddress(int n) const;
    427   static Address GetExpressionAddress(Address fp, int n);
    428 
    429   // Determines if the n'th expression stack element is in a stack
    430   // handler or not. Requires traversing all handlers in this frame.
    431   bool IsExpressionInsideHandler(int n) const;
    432 
    433   // Determines if the standard frame for the given frame pointer is
    434   // an arguments adaptor frame.
    435   static inline bool IsArgumentsAdaptorFrame(Address fp);
    436 
    437   // Determines if the standard frame for the given frame pointer is a
    438   // construct frame.
    439   static inline bool IsConstructFrame(Address fp);
    440 
    441  private:
    442   friend class StackFrame;
    443   friend class StackFrameIterator;
    444 };
    445 
    446 
    447 class FrameSummary BASE_EMBEDDED {
    448  public:
    449   FrameSummary(Object* receiver,
    450                JSFunction* function,
    451                Code* code,
    452                int offset,
    453                bool is_constructor)
    454       : receiver_(receiver),
    455         function_(function),
    456         code_(code),
    457         offset_(offset),
    458         is_constructor_(is_constructor) { }
    459   Handle<Object> receiver() { return receiver_; }
    460   Handle<JSFunction> function() { return function_; }
    461   Handle<Code> code() { return code_; }
    462   Address pc() { return code_->address() + offset_; }
    463   int offset() { return offset_; }
    464   bool is_constructor() { return is_constructor_; }
    465 
    466   void Print();
    467 
    468  private:
    469   Handle<Object> receiver_;
    470   Handle<JSFunction> function_;
    471   Handle<Code> code_;
    472   int offset_;
    473   bool is_constructor_;
    474 };
    475 
    476 
    477 class JavaScriptFrame: public StandardFrame {
    478  public:
    479   virtual Type type() const { return JAVA_SCRIPT; }
    480 
    481   // Accessors.
    482   inline Object* function() const;
    483   inline Object* receiver() const;
    484   inline void set_receiver(Object* value);
    485 
    486   // Access the parameters.
    487   inline Address GetParameterSlot(int index) const;
    488   inline Object* GetParameter(int index) const;
    489   inline int ComputeParametersCount() const {
    490     return GetNumberOfIncomingArguments();
    491   }
    492 
    493   // Check if this frame is a constructor frame invoked through 'new'.
    494   bool IsConstructor() const;
    495 
    496   // Check if this frame has "adapted" arguments in the sense that the
    497   // actual passed arguments are available in an arguments adaptor
    498   // frame below it on the stack.
    499   inline bool has_adapted_arguments() const;
    500   int GetArgumentsLength() const;
    501 
    502   // Garbage collection support.
    503   virtual void Iterate(ObjectVisitor* v) const;
    504 
    505   // Printing support.
    506   virtual void Print(StringStream* accumulator,
    507                      PrintMode mode,
    508                      int index) const;
    509 
    510   // Determine the code for the frame.
    511   virtual Code* unchecked_code() const;
    512 
    513   // Returns the levels of inlining for this frame.
    514   virtual int GetInlineCount() { return 1; }
    515 
    516   // Return a list with JSFunctions of this frame.
    517   virtual void GetFunctions(List<JSFunction*>* functions);
    518 
    519   // Build a list with summaries for this frame including all inlined frames.
    520   virtual void Summarize(List<FrameSummary>* frames);
    521 
    522   static JavaScriptFrame* cast(StackFrame* frame) {
    523     ASSERT(frame->is_java_script());
    524     return static_cast<JavaScriptFrame*>(frame);
    525   }
    526 
    527   static void PrintTop(FILE* file, bool print_args, bool print_line_number);
    528 
    529  protected:
    530   inline explicit JavaScriptFrame(StackFrameIterator* iterator);
    531 
    532   virtual Address GetCallerStackPointer() const;
    533 
    534   virtual int GetNumberOfIncomingArguments() const;
    535 
    536   // Garbage collection support. Iterates over incoming arguments,
    537   // receiver, and any callee-saved registers.
    538   void IterateArguments(ObjectVisitor* v) const;
    539 
    540  private:
    541   inline Object* function_slot_object() const;
    542 
    543   friend class StackFrameIterator;
    544   friend class StackTracer;
    545 };
    546 
    547 
    548 class OptimizedFrame : public JavaScriptFrame {
    549  public:
    550   virtual Type type() const { return OPTIMIZED; }
    551 
    552   // GC support.
    553   virtual void Iterate(ObjectVisitor* v) const;
    554 
    555   virtual int GetInlineCount();
    556 
    557   // Return a list with JSFunctions of this frame.
    558   // The functions are ordered bottom-to-top (i.e. functions.last()
    559   // is the top-most activation)
    560   virtual void GetFunctions(List<JSFunction*>* functions);
    561 
    562   virtual void Summarize(List<FrameSummary>* frames);
    563 
    564   DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
    565 
    566  protected:
    567   inline explicit OptimizedFrame(StackFrameIterator* iterator);
    568 
    569  private:
    570   friend class StackFrameIterator;
    571 };
    572 
    573 
    574 // Arguments adaptor frames are automatically inserted below
    575 // JavaScript frames when the actual number of parameters does not
    576 // match the formal number of parameters.
    577 class ArgumentsAdaptorFrame: public JavaScriptFrame {
    578  public:
    579   virtual Type type() const { return ARGUMENTS_ADAPTOR; }
    580 
    581   // Determine the code for the frame.
    582   virtual Code* unchecked_code() const;
    583 
    584   static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
    585     ASSERT(frame->is_arguments_adaptor());
    586     return static_cast<ArgumentsAdaptorFrame*>(frame);
    587   }
    588 
    589   // Printing support.
    590   virtual void Print(StringStream* accumulator,
    591                      PrintMode mode,
    592                      int index) const;
    593 
    594  protected:
    595   inline explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator);
    596 
    597   virtual int GetNumberOfIncomingArguments() const;
    598 
    599   virtual Address GetCallerStackPointer() const;
    600 
    601  private:
    602   friend class StackFrameIterator;
    603 };
    604 
    605 
    606 class InternalFrame: public StandardFrame {
    607  public:
    608   virtual Type type() const { return INTERNAL; }
    609 
    610   // Garbage collection support.
    611   virtual void Iterate(ObjectVisitor* v) const;
    612 
    613   // Determine the code for the frame.
    614   virtual Code* unchecked_code() const;
    615 
    616   static InternalFrame* cast(StackFrame* frame) {
    617     ASSERT(frame->is_internal());
    618     return static_cast<InternalFrame*>(frame);
    619   }
    620 
    621  protected:
    622   inline explicit InternalFrame(StackFrameIterator* iterator);
    623 
    624   virtual Address GetCallerStackPointer() const;
    625 
    626  private:
    627   friend class StackFrameIterator;
    628 };
    629 
    630 
    631 // Construct frames are special trampoline frames introduced to handle
    632 // function invocations through 'new'.
    633 class ConstructFrame: public InternalFrame {
    634  public:
    635   virtual Type type() const { return CONSTRUCT; }
    636 
    637   static ConstructFrame* cast(StackFrame* frame) {
    638     ASSERT(frame->is_construct());
    639     return static_cast<ConstructFrame*>(frame);
    640   }
    641 
    642  protected:
    643   inline explicit ConstructFrame(StackFrameIterator* iterator);
    644 
    645  private:
    646   friend class StackFrameIterator;
    647 };
    648 
    649 
    650 class StackFrameIterator BASE_EMBEDDED {
    651  public:
    652   // An iterator that iterates over the current thread's stack,
    653   // and uses current isolate.
    654   StackFrameIterator();
    655 
    656   // An iterator that iterates over the isolate's current thread's stack,
    657   explicit StackFrameIterator(Isolate* isolate);
    658 
    659   // An iterator that iterates over a given thread's stack.
    660   StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
    661 
    662   // An iterator that can start from a given FP address.
    663   // If use_top, then work as usual, if fp isn't NULL, use it,
    664   // otherwise, do nothing.
    665   StackFrameIterator(Isolate* isolate, bool use_top, Address fp, Address sp);
    666 
    667   StackFrame* frame() const {
    668     ASSERT(!done());
    669     return frame_;
    670   }
    671 
    672   Isolate* isolate() const { return isolate_; }
    673 
    674   bool done() const { return frame_ == NULL; }
    675   void Advance() { (this->*advance_)(); }
    676 
    677   // Go back to the first frame.
    678   void Reset();
    679 
    680  private:
    681   Isolate* isolate_;
    682 #define DECLARE_SINGLETON(ignore, type) type type##_;
    683   STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
    684 #undef DECLARE_SINGLETON
    685   StackFrame* frame_;
    686   StackHandler* handler_;
    687   ThreadLocalTop* thread_;
    688   Address fp_;
    689   Address sp_;
    690   void (StackFrameIterator::*advance_)();
    691 
    692   StackHandler* handler() const {
    693     ASSERT(!done());
    694     return handler_;
    695   }
    696 
    697   // Get the type-specific frame singleton in a given state.
    698   StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
    699   // A helper function, can return a NULL pointer.
    700   StackFrame* SingletonFor(StackFrame::Type type);
    701 
    702   void AdvanceWithHandler();
    703   void AdvanceWithoutHandler();
    704 
    705   friend class StackFrame;
    706   friend class SafeStackFrameIterator;
    707   DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
    708 };
    709 
    710 
    711 // Iterator that supports iterating through all JavaScript frames.
    712 template<typename Iterator>
    713 class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
    714  public:
    715   JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
    716 
    717   inline explicit JavaScriptFrameIteratorTemp(Isolate* isolate);
    718 
    719   inline JavaScriptFrameIteratorTemp(Isolate* isolate, ThreadLocalTop* top);
    720 
    721   // Skip frames until the frame with the given id is reached.
    722   explicit JavaScriptFrameIteratorTemp(StackFrame::Id id) { AdvanceToId(id); }
    723 
    724   inline JavaScriptFrameIteratorTemp(Isolate* isolate, StackFrame::Id id);
    725 
    726   JavaScriptFrameIteratorTemp(Address fp,
    727                               Address sp,
    728                               Address low_bound,
    729                               Address high_bound) :
    730       iterator_(fp, sp, low_bound, high_bound) {
    731     if (!done()) Advance();
    732   }
    733 
    734   JavaScriptFrameIteratorTemp(Isolate* isolate,
    735                               Address fp,
    736                               Address sp,
    737                               Address low_bound,
    738                               Address high_bound) :
    739       iterator_(isolate, fp, sp, low_bound, high_bound) {
    740     if (!done()) Advance();
    741   }
    742 
    743   inline JavaScriptFrame* frame() const;
    744 
    745   bool done() const { return iterator_.done(); }
    746   void Advance();
    747 
    748   // Advance to the frame holding the arguments for the current
    749   // frame. This only affects the current frame if it has adapted
    750   // arguments.
    751   void AdvanceToArgumentsFrame();
    752 
    753   // Go back to the first frame.
    754   void Reset();
    755 
    756  private:
    757   inline void AdvanceToId(StackFrame::Id id);
    758 
    759   Iterator iterator_;
    760 };
    761 
    762 
    763 typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
    764 
    765 
    766 // NOTE: The stack trace frame iterator is an iterator that only
    767 // traverse proper JavaScript frames; that is JavaScript frames that
    768 // have proper JavaScript functions. This excludes the problematic
    769 // functions in runtime.js.
    770 class StackTraceFrameIterator: public JavaScriptFrameIterator {
    771  public:
    772   StackTraceFrameIterator();
    773   explicit StackTraceFrameIterator(Isolate* isolate);
    774   void Advance();
    775 
    776  private:
    777   bool IsValidFrame();
    778 };
    779 
    780 
    781 class SafeStackFrameIterator BASE_EMBEDDED {
    782  public:
    783   SafeStackFrameIterator(Isolate* isolate,
    784                          Address fp, Address sp,
    785                          Address low_bound, Address high_bound);
    786 
    787   StackFrame* frame() const {
    788     ASSERT(is_working_iterator_);
    789     return iterator_.frame();
    790   }
    791 
    792   bool done() const { return iteration_done_ ? true : iterator_.done(); }
    793 
    794   void Advance();
    795   void Reset();
    796 
    797   static bool is_active(Isolate* isolate);
    798 
    799   static bool IsWithinBounds(
    800       Address low_bound, Address high_bound, Address addr) {
    801     return low_bound <= addr && addr <= high_bound;
    802   }
    803 
    804  private:
    805   class StackAddressValidator {
    806    public:
    807     StackAddressValidator(Address low_bound, Address high_bound)
    808         : low_bound_(low_bound), high_bound_(high_bound) { }
    809     bool IsValid(Address addr) const {
    810       return IsWithinBounds(low_bound_, high_bound_, addr);
    811     }
    812    private:
    813     Address low_bound_;
    814     Address high_bound_;
    815   };
    816 
    817   class ExitFrameValidator {
    818    public:
    819     explicit ExitFrameValidator(const StackAddressValidator& validator)
    820         : validator_(validator) { }
    821     ExitFrameValidator(Address low_bound, Address high_bound)
    822         : validator_(low_bound, high_bound) { }
    823     bool IsValidFP(Address fp);
    824    private:
    825     StackAddressValidator validator_;
    826   };
    827 
    828   bool IsValidStackAddress(Address addr) const {
    829     return stack_validator_.IsValid(addr);
    830   }
    831   bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
    832   bool IsValidFrame(StackFrame* frame) const;
    833   bool IsValidCaller(StackFrame* frame);
    834   static bool IsValidTop(Isolate* isolate,
    835                          Address low_bound, Address high_bound);
    836 
    837   // This is a nasty hack to make sure the active count is incremented
    838   // before the constructor for the embedded iterator is invoked. This
    839   // is needed because the constructor will start looking at frames
    840   // right away and we need to make sure it doesn't start inspecting
    841   // heap objects.
    842   class ActiveCountMaintainer BASE_EMBEDDED {
    843    public:
    844     explicit ActiveCountMaintainer(Isolate* isolate);
    845     ~ActiveCountMaintainer();
    846    private:
    847     Isolate* isolate_;
    848   };
    849 
    850   ActiveCountMaintainer maintainer_;
    851   StackAddressValidator stack_validator_;
    852   const bool is_valid_top_;
    853   const bool is_valid_fp_;
    854   const bool is_working_iterator_;
    855   bool iteration_done_;
    856   StackFrameIterator iterator_;
    857 };
    858 
    859 
    860 typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
    861     SafeJavaScriptFrameIterator;
    862 
    863 
    864 class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
    865  public:
    866   explicit SafeStackTraceFrameIterator(Isolate* isolate,
    867                                        Address fp, Address sp,
    868                                        Address low_bound, Address high_bound);
    869   void Advance();
    870 };
    871 
    872 
    873 class StackFrameLocator BASE_EMBEDDED {
    874  public:
    875   // Find the nth JavaScript frame on the stack. The caller must
    876   // guarantee that such a frame exists.
    877   JavaScriptFrame* FindJavaScriptFrame(int n);
    878 
    879  private:
    880   StackFrameIterator iterator_;
    881 };
    882 
    883 
    884 // Reads all frames on the current stack and copies them into the current
    885 // zone memory.
    886 Vector<StackFrame*> CreateStackMap();
    887 
    888 } }  // namespace v8::internal
    889 
    890 #endif  // V8_FRAMES_H_
    891