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    ASSERT(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    ASSERT(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    ASSERT(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    ASSERT(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    ASSERT(frame->is_java_script());
614    return static_cast<JavaScriptFrame*>(frame);
615  }
616
617  static void PrintTop(Isolate* isolate,
618                       FILE* file,
619                       bool print_args,
620                       bool print_line_number);
621
622 protected:
623  inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator);
624
625  virtual Address GetCallerStackPointer() const;
626
627  virtual int GetNumberOfIncomingArguments() const;
628
629  // Garbage collection support. Iterates over incoming arguments,
630  // receiver, and any callee-saved registers.
631  void IterateArguments(ObjectVisitor* v) const;
632
633 private:
634  inline Object* function_slot_object() const;
635
636  friend class StackFrameIteratorBase;
637};
638
639
640class StubFrame : public StandardFrame {
641 public:
642  virtual Type type() const { return STUB; }
643
644  // GC support.
645  virtual void Iterate(ObjectVisitor* v) const;
646
647  // Determine the code for the frame.
648  virtual Code* unchecked_code() const;
649
650 protected:
651  inline explicit StubFrame(StackFrameIteratorBase* iterator);
652
653  virtual Address GetCallerStackPointer() const;
654
655  virtual int GetNumberOfIncomingArguments() const;
656
657  friend class StackFrameIteratorBase;
658};
659
660
661class OptimizedFrame : public JavaScriptFrame {
662 public:
663  virtual Type type() const { return OPTIMIZED; }
664
665  // GC support.
666  virtual void Iterate(ObjectVisitor* v) const;
667
668  virtual int GetInlineCount();
669
670  // Return a list with JSFunctions of this frame.
671  // The functions are ordered bottom-to-top (i.e. functions.last()
672  // is the top-most activation)
673  virtual void GetFunctions(List<JSFunction*>* functions);
674
675  virtual void Summarize(List<FrameSummary>* frames);
676
677  DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
678
679 protected:
680  inline explicit OptimizedFrame(StackFrameIteratorBase* iterator);
681
682 private:
683  JSFunction* LiteralAt(FixedArray* literal_array, int literal_id);
684
685  friend class StackFrameIteratorBase;
686};
687
688
689// Arguments adaptor frames are automatically inserted below
690// JavaScript frames when the actual number of parameters does not
691// match the formal number of parameters.
692class ArgumentsAdaptorFrame: public JavaScriptFrame {
693 public:
694  virtual Type type() const { return ARGUMENTS_ADAPTOR; }
695
696  // Determine the code for the frame.
697  virtual Code* unchecked_code() const;
698
699  static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
700    ASSERT(frame->is_arguments_adaptor());
701    return static_cast<ArgumentsAdaptorFrame*>(frame);
702  }
703
704  // Printing support.
705  virtual void Print(StringStream* accumulator,
706                     PrintMode mode,
707                     int index) const;
708
709 protected:
710  inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator);
711
712  virtual int GetNumberOfIncomingArguments() const;
713
714  virtual Address GetCallerStackPointer() const;
715
716 private:
717  friend class StackFrameIteratorBase;
718};
719
720
721class InternalFrame: public StandardFrame {
722 public:
723  virtual Type type() const { return INTERNAL; }
724
725  // Garbage collection support.
726  virtual void Iterate(ObjectVisitor* v) const;
727
728  // Determine the code for the frame.
729  virtual Code* unchecked_code() const;
730
731  static InternalFrame* cast(StackFrame* frame) {
732    ASSERT(frame->is_internal());
733    return static_cast<InternalFrame*>(frame);
734  }
735
736 protected:
737  inline explicit InternalFrame(StackFrameIteratorBase* iterator);
738
739  virtual Address GetCallerStackPointer() const;
740
741 private:
742  friend class StackFrameIteratorBase;
743};
744
745
746class StubFailureTrampolineFrame: public StandardFrame {
747 public:
748  // sizeof(Arguments) - sizeof(Arguments*) is 3 * kPointerSize), but the
749  // presubmit script complains about using sizeof() on a type.
750  static const int kFirstRegisterParameterFrameOffset =
751      StandardFrameConstants::kMarkerOffset - 3 * kPointerSize;
752
753  static const int kCallerStackParameterCountFrameOffset =
754      StandardFrameConstants::kMarkerOffset - 2 * kPointerSize;
755
756  virtual Type type() const { return STUB_FAILURE_TRAMPOLINE; }
757
758  // Get the code associated with this frame.
759  // This method could be called during marking phase of GC.
760  virtual Code* unchecked_code() const;
761
762  virtual void Iterate(ObjectVisitor* v) const;
763
764  // Architecture-specific register description.
765  static Register fp_register();
766  static Register context_register();
767  static Register constant_pool_pointer_register();
768
769 protected:
770  inline explicit StubFailureTrampolineFrame(
771      StackFrameIteratorBase* iterator);
772
773  virtual Address GetCallerStackPointer() const;
774
775 private:
776  friend class StackFrameIteratorBase;
777};
778
779
780// Construct frames are special trampoline frames introduced to handle
781// function invocations through 'new'.
782class ConstructFrame: public InternalFrame {
783 public:
784  virtual Type type() const { return CONSTRUCT; }
785
786  static ConstructFrame* cast(StackFrame* frame) {
787    ASSERT(frame->is_construct());
788    return static_cast<ConstructFrame*>(frame);
789  }
790
791 protected:
792  inline explicit ConstructFrame(StackFrameIteratorBase* iterator);
793
794 private:
795  friend class StackFrameIteratorBase;
796};
797
798
799class StackFrameIteratorBase BASE_EMBEDDED {
800 public:
801  Isolate* isolate() const { return isolate_; }
802
803  bool done() const { return frame_ == NULL; }
804
805 protected:
806  // An iterator that iterates over a given thread's stack.
807  StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects);
808
809  Isolate* isolate_;
810#define DECLARE_SINGLETON(ignore, type) type type##_;
811  STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
812#undef DECLARE_SINGLETON
813  StackFrame* frame_;
814  StackHandler* handler_;
815  const bool can_access_heap_objects_;
816
817  StackHandler* handler() const {
818    ASSERT(!done());
819    return handler_;
820  }
821
822  // Get the type-specific frame singleton in a given state.
823  StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
824  // A helper function, can return a NULL pointer.
825  StackFrame* SingletonFor(StackFrame::Type type);
826
827 private:
828  friend class StackFrame;
829  DISALLOW_COPY_AND_ASSIGN(StackFrameIteratorBase);
830};
831
832
833class StackFrameIterator: public StackFrameIteratorBase {
834 public:
835  // An iterator that iterates over the isolate's current thread's stack,
836  explicit StackFrameIterator(Isolate* isolate);
837  // An iterator that iterates over a given thread's stack.
838  StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
839
840  StackFrame* frame() const {
841    ASSERT(!done());
842    return frame_;
843  }
844  void Advance();
845
846 private:
847  // Go back to the first frame.
848  void Reset(ThreadLocalTop* top);
849
850  DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
851};
852
853
854// Iterator that supports iterating through all JavaScript frames.
855class JavaScriptFrameIterator BASE_EMBEDDED {
856 public:
857  inline explicit JavaScriptFrameIterator(Isolate* isolate);
858  inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top);
859  // Skip frames until the frame with the given id is reached.
860  JavaScriptFrameIterator(Isolate* isolate, StackFrame::Id id);
861
862  inline JavaScriptFrame* frame() const;
863
864  bool done() const { return iterator_.done(); }
865  void Advance();
866
867  // Advance to the frame holding the arguments for the current
868  // frame. This only affects the current frame if it has adapted
869  // arguments.
870  void AdvanceToArgumentsFrame();
871
872 private:
873  StackFrameIterator iterator_;
874};
875
876
877// NOTE: The stack trace frame iterator is an iterator that only
878// traverse proper JavaScript frames; that is JavaScript frames that
879// have proper JavaScript functions. This excludes the problematic
880// functions in runtime.js.
881class StackTraceFrameIterator: public JavaScriptFrameIterator {
882 public:
883  explicit StackTraceFrameIterator(Isolate* isolate);
884  void Advance();
885
886 private:
887  bool IsValidFrame();
888};
889
890
891class SafeStackFrameIterator: public StackFrameIteratorBase {
892 public:
893  SafeStackFrameIterator(Isolate* isolate,
894                         Address fp, Address sp,
895                         Address js_entry_sp);
896
897  inline StackFrame* frame() const;
898  void Advance();
899
900  StackFrame::Type top_frame_type() const { return top_frame_type_; }
901
902 private:
903  void AdvanceOneFrame();
904
905  bool IsValidStackAddress(Address addr) const {
906    return low_bound_ <= addr && addr <= high_bound_;
907  }
908  bool IsValidFrame(StackFrame* frame) const;
909  bool IsValidCaller(StackFrame* frame);
910  bool IsValidExitFrame(Address fp) const;
911  bool IsValidTop(ThreadLocalTop* top) const;
912
913  const Address low_bound_;
914  const Address high_bound_;
915  StackFrame::Type top_frame_type_;
916  ExternalCallbackScope* external_callback_scope_;
917};
918
919
920class StackFrameLocator BASE_EMBEDDED {
921 public:
922  explicit StackFrameLocator(Isolate* isolate) : iterator_(isolate) {}
923
924  // Find the nth JavaScript frame on the stack. The caller must
925  // guarantee that such a frame exists.
926  JavaScriptFrame* FindJavaScriptFrame(int n);
927
928 private:
929  StackFrameIterator iterator_;
930};
931
932
933// Reads all frames on the current stack and copies them into the current
934// zone memory.
935Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone);
936
937} }  // namespace v8::internal
938
939#endif  // V8_FRAMES_H_
940