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
35namespace v8 {
36namespace internal {
37
38typedef uint32_t RegList;
39
40// Get the number of registers in a given register list.
41int NumRegs(RegList list);
42
43// Return the code of the n-th saved register available to JavaScript.
44int JSCallerSavedCode(int n);
45
46
47// Forward declarations.
48class StackFrameIterator;
49class ThreadLocalTop;
50class Isolate;
51
52class InnerPointerToCodeCache {
53 public:
54  struct InnerPointerToCodeCacheEntry {
55    Address inner_pointer;
56    Code* code;
57    SafepointEntry safepoint_entry;
58  };
59
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
67  void Flush() {
68    memset(&cache_[0], 0, sizeof(cache_));
69  }
70
71  InnerPointerToCodeCacheEntry* GetCacheEntry(Address inner_pointer);
72
73 private:
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
85class 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.
143class 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 {
173    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).
181  StackFrame(const StackFrame& original) {
182    this->state_ = original.state_;
183    this->iterator_ = NULL;
184    this->isolate_ = original.isolate_;
185  }
186
187  // Type testers.
188  bool is_entry() const { return type() == ENTRY; }
189  bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
190  bool is_exit() const { return type() == EXIT; }
191  bool is_optimized() const { return type() == OPTIMIZED; }
192  bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
193  bool is_internal() const { return type() == INTERNAL; }
194  bool is_construct() const { return type() == CONSTRUCT; }
195  virtual bool is_standard() const { return false; }
196
197  bool is_java_script() const {
198    Type type = this->type();
199    return (type == JAVA_SCRIPT) || (type == OPTIMIZED);
200  }
201
202  // Accessors.
203  Address sp() const { return state_.sp; }
204  Address fp() const { return state_.fp; }
205  Address caller_sp() const { return GetCallerStackPointer(); }
206
207  Address pc() const { return *pc_address(); }
208  void set_pc(Address pc) { *pc_address() = pc; }
209
210  virtual void SetCallerFp(Address caller_fp) = 0;
211
212  Address* pc_address() const { return state_.pc_address; }
213
214  // Get the id of this stack frame.
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 };
252  virtual void Print(StringStream* accumulator,
253                     PrintMode mode,
254                     int index) const { }
255
256 protected:
257  inline explicit StackFrame(StackFrameIterator* iterator);
258  virtual ~StackFrame() { }
259
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.
299class EntryFrame: public StackFrame {
300 public:
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
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.
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
330class EntryConstructFrame: public EntryFrame {
331 public:
332  virtual Type type() const { return ENTRY_CONSTRUCT; }
333
334  virtual Code* unchecked_code() const;
335
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.
350class ExitFrame: public StackFrame {
351 public:
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
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
387class StandardFrame: public StackFrame {
388 public:
389  // Testers.
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
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
447class FrameSummary BASE_EMBEDDED {
448 public:
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) { }
459  Handle<Object> receiver() { return receiver_; }
460  Handle<JSFunction> function() { return function_; }
461  Handle<Code> code() { return code_; }
462  Address pc() { return code_->address() + offset_; }
463  int offset() { return offset_; }
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
477class JavaScriptFrame: public StandardFrame {
478 public:
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;
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.
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
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
548class OptimizedFrame : public JavaScriptFrame {
549 public:
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.
577class ArgumentsAdaptorFrame: public JavaScriptFrame {
578 public:
579  virtual Type type() const { return ARGUMENTS_ADAPTOR; }
580
581  // Determine the code for the frame.
582  virtual Code* unchecked_code() const;
583
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
606class InternalFrame: public StandardFrame {
607 public:
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
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'.
633class ConstructFrame: public InternalFrame {
634 public:
635  virtual Type type() const { return CONSTRUCT; }
636
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
650class 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
667  StackFrame* frame() const {
668    ASSERT(!done());
669    return frame_;
670  }
671
672  Isolate* isolate() const { return isolate_; }
673
674  bool done() const { return frame_ == NULL; }
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
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.
712template<typename Iterator>
713class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
714 public:
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.
722  explicit JavaScriptFrameIteratorTemp(StackFrame::Id id) { AdvanceToId(id); }
723
724  inline JavaScriptFrameIteratorTemp(Isolate* isolate, StackFrame::Id id);
725
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
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
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
763typedef 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.
770class StackTraceFrameIterator: public JavaScriptFrameIterator {
771 public:
772  StackTraceFrameIterator();
773  explicit StackTraceFrameIterator(Isolate* isolate);
774  void Advance();
775
776 private:
777  bool IsValidFrame();
778};
779
780
781class SafeStackFrameIterator BASE_EMBEDDED {
782 public:
783  SafeStackFrameIterator(Isolate* isolate,
784                         Address fp, Address sp,
785                         Address low_bound, Address high_bound);
786
787  StackFrame* frame() const {
788    ASSERT(is_working_iterator_);
789    return iterator_.frame();
790  }
791
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
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:
807    StackAddressValidator(Address low_bound, Address high_bound)
808        : low_bound_(low_bound), high_bound_(high_bound) { }
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:
819    explicit ExitFrameValidator(const StackAddressValidator& validator)
820        : validator_(validator) { }
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
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
860typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
861    SafeJavaScriptFrameIterator;
862
863
864class 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
873class 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.
886Vector<StackFrame*> CreateStackMap();
887
888} }  // namespace v8::internal
889
890#endif  // V8_FRAMES_H_
891