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