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 namespace v8 {
     32 namespace internal {
     33 
     34 typedef uint32_t RegList;
     35 
     36 // Get the number of registers in a given register list.
     37 int NumRegs(RegList list);
     38 
     39 // Return the code of the n-th saved register available to JavaScript.
     40 int JSCallerSavedCode(int n);
     41 
     42 
     43 // Forward declarations.
     44 class StackFrameIterator;
     45 class Top;
     46 class ThreadLocalTop;
     47 
     48 
     49 class StackHandler BASE_EMBEDDED {
     50  public:
     51   enum State {
     52     ENTRY,
     53     TRY_CATCH,
     54     TRY_FINALLY
     55   };
     56 
     57   // Get the address of this stack handler.
     58   inline Address address() const;
     59 
     60   // Get the next stack handler in the chain.
     61   inline StackHandler* next() const;
     62 
     63   // Tells whether the given address is inside this handler.
     64   inline bool includes(Address address) const;
     65 
     66   // Garbage collection support.
     67   inline void Iterate(ObjectVisitor* v) const;
     68 
     69   // Conversion support.
     70   static inline StackHandler* FromAddress(Address address);
     71 
     72   // Testers
     73   bool is_entry() { return state() == ENTRY; }
     74   bool is_try_catch() { return state() == TRY_CATCH; }
     75   bool is_try_finally() { return state() == TRY_FINALLY; }
     76 
     77   // Garbage collection support.
     78   void Cook(Code* code);
     79   void Uncook(Code* code);
     80 
     81  private:
     82   // Accessors.
     83   inline State state() const;
     84 
     85   inline Address pc() const;
     86   inline void set_pc(Address value);
     87 
     88   DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
     89 };
     90 
     91 
     92 #define STACK_FRAME_TYPE_LIST(V)              \
     93   V(ENTRY,             EntryFrame)            \
     94   V(ENTRY_CONSTRUCT,   EntryConstructFrame)   \
     95   V(EXIT,              ExitFrame)             \
     96   V(JAVA_SCRIPT,       JavaScriptFrame)       \
     97   V(INTERNAL,          InternalFrame)         \
     98   V(CONSTRUCT,         ConstructFrame)        \
     99   V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
    100 
    101 
    102 // Abstract base class for all stack frames.
    103 class StackFrame BASE_EMBEDDED {
    104  public:
    105 #define DECLARE_TYPE(type, ignore) type,
    106   enum Type {
    107     NONE = 0,
    108     STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
    109     NUMBER_OF_TYPES
    110   };
    111 #undef DECLARE_TYPE
    112 
    113   // Opaque data type for identifying stack frames. Used extensively
    114   // by the debugger.
    115   enum Id { NO_ID = 0 };
    116 
    117   // Type testers.
    118   bool is_entry() const { return type() == ENTRY; }
    119   bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
    120   bool is_exit() const { return type() == EXIT; }
    121   bool is_java_script() const { return type() == JAVA_SCRIPT; }
    122   bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
    123   bool is_internal() const { return type() == INTERNAL; }
    124   bool is_construct() const { return type() == CONSTRUCT; }
    125   virtual bool is_standard() const { return false; }
    126 
    127   // Accessors.
    128   Address sp() const { return state_.sp; }
    129   Address fp() const { return state_.fp; }
    130   Address caller_sp() const { return GetCallerStackPointer(); }
    131 
    132   Address pc() const { return *pc_address(); }
    133   void set_pc(Address pc) { *pc_address() = pc; }
    134 
    135   Address* pc_address() const { return state_.pc_address; }
    136 
    137   // Get the id of this stack frame.
    138   Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
    139 
    140   // Checks if this frame includes any stack handlers.
    141   bool HasHandler() const;
    142 
    143   // Get the type of this frame.
    144   virtual Type type() const = 0;
    145 
    146   // Get the code associated with this frame.
    147   virtual Code* code() const = 0;
    148 
    149   // Garbage collection support.
    150   static void CookFramesForThread(ThreadLocalTop* thread);
    151   static void UncookFramesForThread(ThreadLocalTop* thread);
    152 
    153   virtual void Iterate(ObjectVisitor* v) const { }
    154 
    155   // Printing support.
    156   enum PrintMode { OVERVIEW, DETAILS };
    157   virtual void Print(StringStream* accumulator,
    158                      PrintMode mode,
    159                      int index) const { }
    160 
    161  protected:
    162   struct State {
    163     Address sp;
    164     Address fp;
    165     Address* pc_address;
    166   };
    167 
    168   explicit StackFrame(StackFrameIterator* iterator) : iterator_(iterator) { }
    169   virtual ~StackFrame() { }
    170 
    171   // Compute the stack pointer for the calling frame.
    172   virtual Address GetCallerStackPointer() const = 0;
    173 
    174   // Printing support.
    175   static void PrintIndex(StringStream* accumulator,
    176                          PrintMode mode,
    177                          int index);
    178 
    179   // Get the top handler from the current stack iterator.
    180   inline StackHandler* top_handler() const;
    181 
    182   // Compute the stack frame type for the given state.
    183   static Type ComputeType(State* state);
    184 
    185  private:
    186   const StackFrameIterator* iterator_;
    187   State state_;
    188 
    189   // Fill in the state of the calling frame.
    190   virtual void ComputeCallerState(State* state) const = 0;
    191 
    192   // Get the type and the state of the calling frame.
    193   virtual Type GetCallerState(State* state) const;
    194 
    195   // Cooking/uncooking support.
    196   void Cook();
    197   void Uncook();
    198 
    199   friend class StackFrameIterator;
    200   friend class StackHandlerIterator;
    201   friend class SafeStackFrameIterator;
    202 
    203   DISALLOW_IMPLICIT_CONSTRUCTORS(StackFrame);
    204 };
    205 
    206 
    207 // Entry frames are used to enter JavaScript execution from C.
    208 class EntryFrame: public StackFrame {
    209  public:
    210   virtual Type type() const { return ENTRY; }
    211 
    212   virtual Code* code() const;
    213 
    214   // Garbage collection support.
    215   virtual void Iterate(ObjectVisitor* v) const;
    216 
    217   static EntryFrame* cast(StackFrame* frame) {
    218     ASSERT(frame->is_entry());
    219     return static_cast<EntryFrame*>(frame);
    220   }
    221 
    222  protected:
    223   explicit EntryFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
    224 
    225   // The caller stack pointer for entry frames is always zero. The
    226   // real information about the caller frame is available through the
    227   // link to the top exit frame.
    228   virtual Address GetCallerStackPointer() const { return 0; }
    229 
    230  private:
    231   virtual void ComputeCallerState(State* state) const;
    232   virtual Type GetCallerState(State* state) const;
    233 
    234   friend class StackFrameIterator;
    235 };
    236 
    237 
    238 class EntryConstructFrame: public EntryFrame {
    239  public:
    240   virtual Type type() const { return ENTRY_CONSTRUCT; }
    241 
    242   virtual Code* code() const;
    243 
    244   static EntryConstructFrame* cast(StackFrame* frame) {
    245     ASSERT(frame->is_entry_construct());
    246     return static_cast<EntryConstructFrame*>(frame);
    247   }
    248 
    249  protected:
    250   explicit EntryConstructFrame(StackFrameIterator* iterator)
    251       : EntryFrame(iterator) { }
    252 
    253  private:
    254   friend class StackFrameIterator;
    255 };
    256 
    257 
    258 // Exit frames are used to exit JavaScript execution and go to C.
    259 class ExitFrame: public StackFrame {
    260  public:
    261   enum Mode { MODE_NORMAL, MODE_DEBUG };
    262   virtual Type type() const { return EXIT; }
    263 
    264   virtual Code* code() const;
    265 
    266   Object*& code_slot() const;
    267 
    268   // Garbage collection support.
    269   virtual void Iterate(ObjectVisitor* v) const;
    270 
    271   static ExitFrame* cast(StackFrame* frame) {
    272     ASSERT(frame->is_exit());
    273     return static_cast<ExitFrame*>(frame);
    274   }
    275 
    276   // Compute the state and type of an exit frame given a frame
    277   // pointer. Used when constructing the first stack frame seen by an
    278   // iterator and the frames following entry frames.
    279   static Type GetStateForFramePointer(Address fp, State* state);
    280 
    281  protected:
    282   explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
    283 
    284   virtual Address GetCallerStackPointer() const;
    285 
    286  private:
    287   virtual void ComputeCallerState(State* state) const;
    288 
    289   friend class StackFrameIterator;
    290 };
    291 
    292 
    293 class StandardFrame: public StackFrame {
    294  public:
    295   // Testers.
    296   virtual bool is_standard() const { return true; }
    297 
    298   // Accessors.
    299   inline Object* context() const;
    300 
    301   // Access the expressions in the stack frame including locals.
    302   inline Object* GetExpression(int index) const;
    303   inline void SetExpression(int index, Object* value);
    304   int ComputeExpressionsCount() const;
    305 
    306   static StandardFrame* cast(StackFrame* frame) {
    307     ASSERT(frame->is_standard());
    308     return static_cast<StandardFrame*>(frame);
    309   }
    310 
    311  protected:
    312   explicit StandardFrame(StackFrameIterator* iterator)
    313       : StackFrame(iterator) { }
    314 
    315   virtual void ComputeCallerState(State* state) const;
    316 
    317   // Accessors.
    318   inline Address caller_fp() const;
    319   inline Address caller_pc() const;
    320 
    321   // Computes the address of the PC field in the standard frame given
    322   // by the provided frame pointer.
    323   static inline Address ComputePCAddress(Address fp);
    324 
    325   // Iterate over expression stack including stack handlers, locals,
    326   // and parts of the fixed part including context and code fields.
    327   void IterateExpressions(ObjectVisitor* v) const;
    328 
    329   // Returns the address of the n'th expression stack element.
    330   Address GetExpressionAddress(int n) const;
    331 
    332   // Determines if the n'th expression stack element is in a stack
    333   // handler or not. Requires traversing all handlers in this frame.
    334   bool IsExpressionInsideHandler(int n) const;
    335 
    336   // Determines if the standard frame for the given frame pointer is
    337   // an arguments adaptor frame.
    338   static inline bool IsArgumentsAdaptorFrame(Address fp);
    339 
    340   // Determines if the standard frame for the given frame pointer is a
    341   // construct frame.
    342   static inline bool IsConstructFrame(Address fp);
    343 
    344  private:
    345   friend class StackFrame;
    346 };
    347 
    348 
    349 class JavaScriptFrame: public StandardFrame {
    350  public:
    351   virtual Type type() const { return JAVA_SCRIPT; }
    352 
    353   // Accessors.
    354   inline Object* function() const;
    355   inline Object* receiver() const;
    356   inline void set_receiver(Object* value);
    357 
    358   // Access the parameters.
    359   Object* GetParameter(int index) const;
    360   int ComputeParametersCount() const;
    361 
    362   // Temporary way of getting access to the number of parameters
    363   // passed on the stack by the caller. Once argument adaptor frames
    364   // has been introduced on ARM, this number will always match the
    365   // computed parameters count.
    366   int GetProvidedParametersCount() const;
    367 
    368   // Check if this frame is a constructor frame invoked through 'new'.
    369   bool IsConstructor() const;
    370 
    371   // Check if this frame has "adapted" arguments in the sense that the
    372   // actual passed arguments are available in an arguments adaptor
    373   // frame below it on the stack.
    374   inline bool has_adapted_arguments() const;
    375 
    376   // Garbage collection support.
    377   virtual void Iterate(ObjectVisitor* v) const;
    378 
    379   // Printing support.
    380   virtual void Print(StringStream* accumulator,
    381                      PrintMode mode,
    382                      int index) const;
    383 
    384   // Determine the code for the frame.
    385   virtual Code* code() const;
    386 
    387   static JavaScriptFrame* cast(StackFrame* frame) {
    388     ASSERT(frame->is_java_script());
    389     return static_cast<JavaScriptFrame*>(frame);
    390   }
    391 
    392  protected:
    393   explicit JavaScriptFrame(StackFrameIterator* iterator)
    394       : StandardFrame(iterator), disable_heap_access_(false) { }
    395 
    396   virtual Address GetCallerStackPointer() const;
    397 
    398   // When this mode is enabled it is not allowed to access heap objects.
    399   // This is a special mode used when gathering stack samples in profiler.
    400   // A shortcoming is that caller's SP value will be calculated incorrectly
    401   // (see GetCallerStackPointer implementation), but it is not used for stack
    402   // sampling.
    403   void DisableHeapAccess() { disable_heap_access_ = true; }
    404 
    405  private:
    406   bool disable_heap_access_;
    407   inline Object* function_slot_object() const;
    408 
    409   friend class StackFrameIterator;
    410 };
    411 
    412 
    413 // Arguments adaptor frames are automatically inserted below
    414 // JavaScript frames when the actual number of parameters does not
    415 // match the formal number of parameters.
    416 class ArgumentsAdaptorFrame: public JavaScriptFrame {
    417  public:
    418   virtual Type type() const { return ARGUMENTS_ADAPTOR; }
    419 
    420   // Determine the code for the frame.
    421   virtual Code* code() const;
    422 
    423   static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
    424     ASSERT(frame->is_arguments_adaptor());
    425     return static_cast<ArgumentsAdaptorFrame*>(frame);
    426   }
    427 
    428   // Printing support.
    429   virtual void Print(StringStream* accumulator,
    430                      PrintMode mode,
    431                      int index) const;
    432  protected:
    433   explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator)
    434       : JavaScriptFrame(iterator) { }
    435 
    436   virtual Address GetCallerStackPointer() const;
    437 
    438  private:
    439   friend class StackFrameIterator;
    440 };
    441 
    442 
    443 class InternalFrame: public StandardFrame {
    444  public:
    445   virtual Type type() const { return INTERNAL; }
    446 
    447   // Garbage collection support.
    448   virtual void Iterate(ObjectVisitor* v) const;
    449 
    450   // Determine the code for the frame.
    451   virtual Code* code() const;
    452 
    453   static InternalFrame* cast(StackFrame* frame) {
    454     ASSERT(frame->is_internal());
    455     return static_cast<InternalFrame*>(frame);
    456   }
    457 
    458  protected:
    459   explicit InternalFrame(StackFrameIterator* iterator)
    460       : StandardFrame(iterator) { }
    461 
    462   virtual Address GetCallerStackPointer() const;
    463 
    464  private:
    465   friend class StackFrameIterator;
    466 };
    467 
    468 
    469 // Construct frames are special trampoline frames introduced to handle
    470 // function invocations through 'new'.
    471 class ConstructFrame: public InternalFrame {
    472  public:
    473   virtual Type type() const { return CONSTRUCT; }
    474 
    475   static ConstructFrame* cast(StackFrame* frame) {
    476     ASSERT(frame->is_construct());
    477     return static_cast<ConstructFrame*>(frame);
    478   }
    479 
    480  protected:
    481   explicit ConstructFrame(StackFrameIterator* iterator)
    482       : InternalFrame(iterator) { }
    483 
    484  private:
    485   friend class StackFrameIterator;
    486 };
    487 
    488 
    489 class StackFrameIterator BASE_EMBEDDED {
    490  public:
    491   // An iterator that iterates over the current thread's stack.
    492   StackFrameIterator();
    493 
    494   // An iterator that iterates over a given thread's stack.
    495   explicit StackFrameIterator(ThreadLocalTop* thread);
    496 
    497   // An iterator that can start from a given FP address.
    498   // If use_top, then work as usual, if fp isn't NULL, use it,
    499   // otherwise, do nothing.
    500   StackFrameIterator(bool use_top, Address fp, Address sp);
    501 
    502   StackFrame* frame() const {
    503     ASSERT(!done());
    504     return frame_;
    505   }
    506 
    507   bool done() const { return frame_ == NULL; }
    508   void Advance() { (this->*advance_)(); }
    509 
    510   // Go back to the first frame.
    511   void Reset();
    512 
    513  private:
    514 #define DECLARE_SINGLETON(ignore, type) type type##_;
    515   STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
    516 #undef DECLARE_SINGLETON
    517   StackFrame* frame_;
    518   StackHandler* handler_;
    519   ThreadLocalTop* thread_;
    520   Address fp_;
    521   Address sp_;
    522   void (StackFrameIterator::*advance_)();
    523 
    524   StackHandler* handler() const {
    525     ASSERT(!done());
    526     return handler_;
    527   }
    528 
    529   // Get the type-specific frame singleton in a given state.
    530   StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
    531   // A helper function, can return a NULL pointer.
    532   StackFrame* SingletonFor(StackFrame::Type type);
    533 
    534   void AdvanceWithHandler();
    535   void AdvanceWithoutHandler();
    536 
    537   friend class StackFrame;
    538   friend class SafeStackFrameIterator;
    539   DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
    540 };
    541 
    542 
    543 // Iterator that supports iterating through all JavaScript frames.
    544 template<typename Iterator>
    545 class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
    546  public:
    547   JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
    548 
    549   explicit JavaScriptFrameIteratorTemp(ThreadLocalTop* thread) :
    550       iterator_(thread) {
    551     if (!done()) Advance();
    552   }
    553 
    554   // Skip frames until the frame with the given id is reached.
    555   explicit JavaScriptFrameIteratorTemp(StackFrame::Id id);
    556 
    557   JavaScriptFrameIteratorTemp(Address fp, Address sp,
    558                               Address low_bound, Address high_bound) :
    559       iterator_(fp, sp, low_bound, high_bound) {
    560     if (!done()) Advance();
    561   }
    562 
    563   inline JavaScriptFrame* frame() const;
    564 
    565   bool done() const { return iterator_.done(); }
    566   void Advance();
    567 
    568   // Advance to the frame holding the arguments for the current
    569   // frame. This only affects the current frame if it has adapted
    570   // arguments.
    571   void AdvanceToArgumentsFrame();
    572 
    573   // Go back to the first frame.
    574   void Reset();
    575 
    576  private:
    577   Iterator iterator_;
    578 };
    579 
    580 
    581 typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
    582 
    583 
    584 // NOTE: The stack trace frame iterator is an iterator that only
    585 // traverse proper JavaScript frames; that is JavaScript frames that
    586 // have proper JavaScript functions. This excludes the problematic
    587 // functions in runtime.js.
    588 class StackTraceFrameIterator: public JavaScriptFrameIterator {
    589  public:
    590   StackTraceFrameIterator();
    591   void Advance();
    592 
    593  private:
    594   bool IsValidFrame();
    595 };
    596 
    597 
    598 class SafeStackFrameIterator BASE_EMBEDDED {
    599  public:
    600   SafeStackFrameIterator(Address fp, Address sp,
    601                          Address low_bound, Address high_bound);
    602 
    603   StackFrame* frame() const {
    604     ASSERT(is_working_iterator_);
    605     return iterator_.frame();
    606   }
    607 
    608   bool done() const { return iteration_done_ ? true : iterator_.done(); }
    609 
    610   void Advance();
    611   void Reset();
    612 
    613   static bool IsWithinBounds(
    614       Address low_bound, Address high_bound, Address addr) {
    615     return low_bound <= addr && addr <= high_bound;
    616   }
    617 
    618  private:
    619   bool IsValidStackAddress(Address addr) const {
    620     return IsWithinBounds(low_bound_, high_bound_, addr);
    621   }
    622   bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
    623   bool IsValidFrame(StackFrame* frame) const;
    624   bool IsValidCaller(StackFrame* frame);
    625 
    626   Address low_bound_;
    627   Address high_bound_;
    628   const bool is_valid_top_;
    629   const bool is_valid_fp_;
    630   const bool is_working_iterator_;
    631   bool iteration_done_;
    632   StackFrameIterator iterator_;
    633 };
    634 
    635 
    636 #ifdef ENABLE_LOGGING_AND_PROFILING
    637 typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
    638     SafeJavaScriptFrameIterator;
    639 
    640 
    641 class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
    642  public:
    643   explicit SafeStackTraceFrameIterator(Address fp, Address sp,
    644                                        Address low_bound, Address high_bound);
    645   void Advance();
    646 };
    647 #endif
    648 
    649 
    650 class StackFrameLocator BASE_EMBEDDED {
    651  public:
    652   // Find the nth JavaScript frame on the stack. The caller must
    653   // guarantee that such a frame exists.
    654   JavaScriptFrame* FindJavaScriptFrame(int n);
    655 
    656  private:
    657   StackFrameIterator iterator_;
    658 };
    659 
    660 
    661 } }  // namespace v8::internal
    662 
    663 #endif  // V8_FRAMES_H_
    664