• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PcToCodeCache(Isolate * isolate)59   explicit PcToCodeCache(Isolate* isolate) : isolate_(isolate) {
60     Flush();
61   }
62 
63   Code* GcSafeFindCodeForPc(Address pc);
64   Code* GcSafeCastToCode(HeapObject* object, Address pc);
65 
Flush()66   void Flush() {
67     memset(&cache_[0], 0, sizeof(cache_));
68   }
69 
70   PcToCodeCacheEntry* GetCacheEntry(Address pc);
71 
72  private:
cache(int index)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
is_entry()108   bool is_entry() { return state() == ENTRY; }
is_try_catch()109   bool is_try_catch() { return state() == TRY_CATCH; }
is_try_finally()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 {
StateState161     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).
StackFrame(const StackFrame & original)169   StackFrame(const StackFrame& original) {
170     this->state_ = original.state_;
171     this->iterator_ = NULL;
172     this->isolate_ = original.isolate_;
173   }
174 
175   // Type testers.
is_entry()176   bool is_entry() const { return type() == ENTRY; }
is_entry_construct()177   bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
is_exit()178   bool is_exit() const { return type() == EXIT; }
is_optimized()179   bool is_optimized() const { return type() == OPTIMIZED; }
is_arguments_adaptor()180   bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
is_internal()181   bool is_internal() const { return type() == INTERNAL; }
is_construct()182   bool is_construct() const { return type() == CONSTRUCT; }
is_standard()183   virtual bool is_standard() const { return false; }
184 
is_java_script()185   bool is_java_script() const {
186     Type type = this->type();
187     return (type == JAVA_SCRIPT) || (type == OPTIMIZED);
188   }
189 
190   // Accessors.
sp()191   Address sp() const { return state_.sp; }
fp()192   Address fp() const { return state_.fp; }
caller_sp()193   Address caller_sp() const { return GetCallerStackPointer(); }
194 
pc()195   Address pc() const { return *pc_address(); }
set_pc(Address pc)196   void set_pc(Address pc) { *pc_address() = pc; }
197 
198   virtual void SetCallerFp(Address caller_fp) = 0;
199 
pc_address()200   Address* pc_address() const { return state_.pc_address; }
201 
202   // Get the id of this stack frame.
id()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.
LookupCode()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 };
Print(StringStream * accumulator,PrintMode mode,int index)237   virtual void Print(StringStream* accumulator,
238                      PrintMode mode,
239                      int index) const { }
240 
241  protected:
242   inline explicit StackFrame(StackFrameIterator* iterator);
~StackFrame()243   virtual ~StackFrame() { }
244 
isolate()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:
type()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 
cast(StackFrame * frame)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:
EntryFrame(StackFrameIterator * iterator)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.
GetCallerStackPointer()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:
type()317   virtual Type type() const { return ENTRY_CONSTRUCT; }
318 
319   virtual Code* unchecked_code() const;
320 
cast(StackFrame * frame)321   static EntryConstructFrame* cast(StackFrame* frame) {
322     ASSERT(frame->is_entry_construct());
323     return static_cast<EntryConstructFrame*>(frame);
324   }
325 
326  protected:
EntryConstructFrame(StackFrameIterator * iterator)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:
type()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 
cast(StackFrame * frame)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:
ExitFrame(StackFrameIterator * iterator)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.
is_standard()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 
cast(StackFrame * frame)388   static StandardFrame* cast(StackFrame* frame) {
389     ASSERT(frame->is_standard());
390     return static_cast<StandardFrame*>(frame);
391   }
392 
393  protected:
StandardFrame(StackFrameIterator * iterator)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:
FrameSummary(Object * receiver,JSFunction * function,Code * code,int offset,bool is_constructor)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) { }
receiver()444   Handle<Object> receiver() { return receiver_; }
function()445   Handle<JSFunction> function() { return function_; }
code()446   Handle<Code> code() { return code_; }
pc()447   Address pc() { return code_->address() + offset_; }
offset()448   int offset() { return offset_; }
is_constructor()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:
type()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;
ComputeParametersCount()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 
cast(StackFrame * frame)503   static JavaScriptFrame* cast(StackFrame* frame) {
504     ASSERT(frame->is_java_script());
505     return static_cast<JavaScriptFrame*>(frame);
506   }
507 
508  protected:
JavaScriptFrame(StackFrameIterator * iterator)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:
type()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:
OptimizedFrame(StackFrameIterator * iterator)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:
type()558   virtual Type type() const { return ARGUMENTS_ADAPTOR; }
559 
560   // Determine the code for the frame.
561   virtual Code* unchecked_code() const;
562 
cast(StackFrame * frame)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:
ArgumentsAdaptorFrame(StackFrameIterator * iterator)573   explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator)
574       : JavaScriptFrame(iterator) { }
575 
GetNumberOfIncomingArguments()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:
type()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 
cast(StackFrame * frame)597   static InternalFrame* cast(StackFrame* frame) {
598     ASSERT(frame->is_internal());
599     return static_cast<InternalFrame*>(frame);
600   }
601 
602  protected:
InternalFrame(StackFrameIterator * iterator)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:
type()617   virtual Type type() const { return CONSTRUCT; }
618 
cast(StackFrame * frame)619   static ConstructFrame* cast(StackFrame* frame) {
620     ASSERT(frame->is_construct());
621     return static_cast<ConstructFrame*>(frame);
622   }
623 
624  protected:
ConstructFrame(StackFrameIterator * iterator)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 
frame()650   StackFrame* frame() const {
651     ASSERT(!done());
652     return frame_;
653   }
654 
isolate()655   Isolate* isolate() const { return isolate_; }
656 
done()657   bool done() const { return frame_ == NULL; }
Advance()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 
handler()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:
JavaScriptFrameIteratorTemp()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.
JavaScriptFrameIteratorTemp(StackFrame::Id id)703   explicit JavaScriptFrameIteratorTemp(StackFrame::Id id) { AdvanceToId(id); }
704 
705   inline JavaScriptFrameIteratorTemp(Isolate* isolate, StackFrame::Id id);
706 
JavaScriptFrameIteratorTemp(Address fp,Address sp,Address low_bound,Address high_bound)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 
JavaScriptFrameIteratorTemp(Isolate * isolate,Address fp,Address sp,Address low_bound,Address high_bound)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 
done()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 
frame()764   StackFrame* frame() const {
765     ASSERT(is_working_iterator_);
766     return iterator_.frame();
767   }
768 
done()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 
IsWithinBounds(Address low_bound,Address high_bound,Address addr)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:
StackAddressValidator(Address low_bound,Address high_bound)784     StackAddressValidator(Address low_bound, Address high_bound)
785         : low_bound_(low_bound), high_bound_(high_bound) { }
IsValid(Address addr)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:
ExitFrameValidator(const StackAddressValidator & validator)796     explicit ExitFrameValidator(const StackAddressValidator& validator)
797         : validator_(validator) { }
ExitFrameValidator(Address low_bound,Address high_bound)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 
IsValidStackAddress(Address addr)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