• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
InnerPointerToCodeCache(Isolate * isolate)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 
Flush()67   void Flush() {
68     memset(&cache_[0], 0, sizeof(cache_));
69   }
70 
71   InnerPointerToCodeCacheEntry* GetCacheEntry(Address inner_pointer);
72 
73  private:
cache(int index)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 {
StateState173     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).
StackFrame(const StackFrame & original)181   StackFrame(const StackFrame& original) {
182     this->state_ = original.state_;
183     this->iterator_ = NULL;
184     this->isolate_ = original.isolate_;
185   }
186 
187   // Type testers.
is_entry()188   bool is_entry() const { return type() == ENTRY; }
is_entry_construct()189   bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
is_exit()190   bool is_exit() const { return type() == EXIT; }
is_optimized()191   bool is_optimized() const { return type() == OPTIMIZED; }
is_arguments_adaptor()192   bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
is_internal()193   bool is_internal() const { return type() == INTERNAL; }
is_construct()194   bool is_construct() const { return type() == CONSTRUCT; }
is_standard()195   virtual bool is_standard() const { return false; }
196 
is_java_script()197   bool is_java_script() const {
198     Type type = this->type();
199     return (type == JAVA_SCRIPT) || (type == OPTIMIZED);
200   }
201 
202   // Accessors.
sp()203   Address sp() const { return state_.sp; }
fp()204   Address fp() const { return state_.fp; }
caller_sp()205   Address caller_sp() const { return GetCallerStackPointer(); }
206 
pc()207   Address pc() const { return *pc_address(); }
set_pc(Address pc)208   void set_pc(Address pc) { *pc_address() = pc; }
209 
210   virtual void SetCallerFp(Address caller_fp) = 0;
211 
pc_address()212   Address* pc_address() const { return state_.pc_address; }
213 
214   // Get the id of this stack frame.
id()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 };
Print(StringStream * accumulator,PrintMode mode,int index)252   virtual void Print(StringStream* accumulator,
253                      PrintMode mode,
254                      int index) const { }
255 
256  protected:
257   inline explicit StackFrame(StackFrameIterator* iterator);
~StackFrame()258   virtual ~StackFrame() { }
259 
isolate()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:
type()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 
cast(StackFrame * frame)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.
GetCallerStackPointer()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:
type()332   virtual Type type() const { return ENTRY_CONSTRUCT; }
333 
334   virtual Code* unchecked_code() const;
335 
cast(StackFrame * frame)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:
type()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 
cast(StackFrame * frame)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.
is_standard()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 
cast(StackFrame * frame)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:
FrameSummary(Object * receiver,JSFunction * function,Code * code,int offset,bool is_constructor)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) { }
receiver()459   Handle<Object> receiver() { return receiver_; }
function()460   Handle<JSFunction> function() { return function_; }
code()461   Handle<Code> code() { return code_; }
pc()462   Address pc() { return code_->address() + offset_; }
offset()463   int offset() { return offset_; }
is_constructor()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:
type()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;
ComputeParametersCount()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.
GetInlineCount()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 
cast(StackFrame * frame)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:
type()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:
type()579   virtual Type type() const { return ARGUMENTS_ADAPTOR; }
580 
581   // Determine the code for the frame.
582   virtual Code* unchecked_code() const;
583 
cast(StackFrame * frame)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:
type()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 
cast(StackFrame * frame)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:
type()635   virtual Type type() const { return CONSTRUCT; }
636 
cast(StackFrame * frame)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 
frame()667   StackFrame* frame() const {
668     ASSERT(!done());
669     return frame_;
670   }
671 
isolate()672   Isolate* isolate() const { return isolate_; }
673 
done()674   bool done() const { return frame_ == NULL; }
Advance()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 
handler()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:
JavaScriptFrameIteratorTemp()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.
JavaScriptFrameIteratorTemp(StackFrame::Id id)722   explicit JavaScriptFrameIteratorTemp(StackFrame::Id id) { AdvanceToId(id); }
723 
724   inline JavaScriptFrameIteratorTemp(Isolate* isolate, StackFrame::Id id);
725 
JavaScriptFrameIteratorTemp(Address fp,Address sp,Address low_bound,Address high_bound)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 
JavaScriptFrameIteratorTemp(Isolate * isolate,Address fp,Address sp,Address low_bound,Address high_bound)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 
done()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 
frame()787   StackFrame* frame() const {
788     ASSERT(is_working_iterator_);
789     return iterator_.frame();
790   }
791 
done()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 
IsWithinBounds(Address low_bound,Address high_bound,Address addr)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:
StackAddressValidator(Address low_bound,Address high_bound)807     StackAddressValidator(Address low_bound, Address high_bound)
808         : low_bound_(low_bound), high_bound_(high_bound) { }
IsValid(Address addr)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:
ExitFrameValidator(const StackAddressValidator & validator)819     explicit ExitFrameValidator(const StackAddressValidator& validator)
820         : validator_(validator) { }
ExitFrameValidator(Address low_bound,Address high_bound)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 
IsValidStackAddress(Address addr)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