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