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