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