Home | History | Annotate | Download | only in src
      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 
     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 
     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 #define STACK_FRAME_TYPE_LIST(V)                         \
    101   V(ENTRY, EntryFrame)                                   \
    102   V(ENTRY_CONSTRUCT, EntryConstructFrame)                \
    103   V(EXIT, ExitFrame)                                     \
    104   V(JAVA_SCRIPT, JavaScriptFrame)                        \
    105   V(OPTIMIZED, OptimizedFrame)                           \
    106   V(WASM, WasmFrame)                                     \
    107   V(WASM_TO_JS, WasmToJsFrame)                           \
    108   V(JS_TO_WASM, JsToWasmFrame)                           \
    109   V(INTERPRETED, InterpretedFrame)                       \
    110   V(STUB, StubFrame)                                     \
    111   V(STUB_FAILURE_TRAMPOLINE, StubFailureTrampolineFrame) \
    112   V(INTERNAL, InternalFrame)                             \
    113   V(CONSTRUCT, ConstructFrame)                           \
    114   V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)            \
    115   V(BUILTIN, BuiltinFrame)
    116 
    117 // Every pointer in a frame has a slot id. On 32-bit platforms, doubles consume
    118 // two slots.
    119 //
    120 // Stack slot indices >= 0 access the callee stack with slot 0 corresponding to
    121 // the callee's saved return address and 1 corresponding to the saved frame
    122 // pointer. Some frames have additional information stored in the fixed header,
    123 // for example JSFunctions store the function context and marker in the fixed
    124 // header, with slot index 2 corresponding to the current function context and 3
    125 // corresponding to the frame marker/JSFunction.
    126 //
    127 //  slot      JS frame
    128 //       +-----------------+--------------------------------
    129 //  -n-1 |   parameter 0   |                            ^
    130 //       |- - - - - - - - -|                            |
    131 //  -n   |                 |                          Caller
    132 //  ...  |       ...       |                       frame slots
    133 //  -2   |  parameter n-1  |                       (slot < 0)
    134 //       |- - - - - - - - -|                            |
    135 //  -1   |   parameter n   |                            v
    136 //  -----+-----------------+--------------------------------
    137 //   0   |   return addr   |   ^                        ^
    138 //       |- - - - - - - - -|   |                        |
    139 //   1   | saved frame ptr | Fixed                      |
    140 //       |- - - - - - - - -| Header <-- frame ptr       |
    141 //   2   | [Constant Pool] |   |                        |
    142 //       |- - - - - - - - -|   |                        |
    143 // 2+cp  |Context/Frm. Type|   v   if a constant pool   |
    144 //       |-----------------+----    is used, cp = 1,    |
    145 // 3+cp  |                 |   ^   otherwise, cp = 0    |
    146 //       |- - - - - - - - -|   |                        |
    147 // 4+cp  |                 |   |                      Callee
    148 //       |- - - - - - - - -|   |                   frame slots
    149 //  ...  |                 | Frame slots           (slot >= 0)
    150 //       |- - - - - - - - -|   |                        |
    151 //       |                 |   v                        |
    152 //  -----+-----------------+----- <-- stack ptr -------------
    153 //
    154 class CommonFrameConstants : public AllStatic {
    155  public:
    156   static const int kCallerFPOffset = 0 * kPointerSize;
    157   static const int kCallerPCOffset = kCallerFPOffset + 1 * kFPOnStackSize;
    158   static const int kCallerSPOffset = kCallerPCOffset + 1 * kPCOnStackSize;
    159 
    160   // Fixed part of the frame consists of return address, caller fp,
    161   // constant pool (if FLAG_enable_embedded_constant_pool), context, and
    162   // function. StandardFrame::IterateExpressions assumes that kLastObjectOffset
    163   // is the last object pointer.
    164   static const int kFixedFrameSizeAboveFp = kPCOnStackSize + kFPOnStackSize;
    165   static const int kFixedSlotCountAboveFp =
    166       kFixedFrameSizeAboveFp / kPointerSize;
    167   static const int kCPSlotSize =
    168       FLAG_enable_embedded_constant_pool ? kPointerSize : 0;
    169   static const int kCPSlotCount = kCPSlotSize / kPointerSize;
    170   static const int kConstantPoolOffset = kCPSlotSize ? -1 * kPointerSize : 0;
    171   static const int kContextOrFrameTypeSize = kPointerSize;
    172   static const int kContextOrFrameTypeOffset =
    173       -(kCPSlotSize + kContextOrFrameTypeSize);
    174 };
    175 
    176 // StandardFrames are used for interpreted, full-codegen and optimized
    177 // JavaScript frames. They always have a context below the saved fp/constant
    178 // pool and below that the JSFunction of the executing function.
    179 //
    180 //  slot      JS frame
    181 //       +-----------------+--------------------------------
    182 //  -n-1 |   parameter 0   |                            ^
    183 //       |- - - - - - - - -|                            |
    184 //  -n   |                 |                          Caller
    185 //  ...  |       ...       |                       frame slots
    186 //  -2   |  parameter n-1  |                       (slot < 0)
    187 //       |- - - - - - - - -|                            |
    188 //  -1   |   parameter n   |                            v
    189 //  -----+-----------------+--------------------------------
    190 //   0   |   return addr   |   ^                        ^
    191 //       |- - - - - - - - -|   |                        |
    192 //   1   | saved frame ptr | Fixed                      |
    193 //       |- - - - - - - - -| Header <-- frame ptr       |
    194 //   2   | [Constant Pool] |   |                        |
    195 //       |- - - - - - - - -|   |                        |
    196 // 2+cp  |     Context     |   |   if a constant pool   |
    197 //       |- - - - - - - - -|   |    is used, cp = 1,    |
    198 // 3+cp  |    JSFunction   |   v   otherwise, cp = 0    |
    199 //       +-----------------+----                        |
    200 // 4+cp  |                 |   ^                      Callee
    201 //       |- - - - - - - - -|   |                   frame slots
    202 //  ...  |                 | Frame slots           (slot >= 0)
    203 //       |- - - - - - - - -|   |                        |
    204 //       |                 |   v                        |
    205 //  -----+-----------------+----- <-- stack ptr -------------
    206 //
    207 class StandardFrameConstants : public CommonFrameConstants {
    208  public:
    209   static const int kFixedFrameSizeFromFp = 2 * kPointerSize + kCPSlotSize;
    210   static const int kFixedFrameSize =
    211       kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp;
    212   static const int kFixedSlotCountFromFp = kFixedFrameSizeFromFp / kPointerSize;
    213   static const int kFixedSlotCount = kFixedFrameSize / kPointerSize;
    214   static const int kContextOffset = kContextOrFrameTypeOffset;
    215   static const int kFunctionOffset = -2 * kPointerSize - kCPSlotSize;
    216   static const int kExpressionsOffset = -3 * kPointerSize - kCPSlotSize;
    217   static const int kLastObjectOffset = kContextOffset;
    218 };
    219 
    220 // TypedFrames have a SMI type maker value below the saved FP/constant pool to
    221 // distinguish them from StandardFrames, which have a context in that position
    222 // instead.
    223 //
    224 //  slot      JS frame
    225 //       +-----------------+--------------------------------
    226 //  -n-1 |   parameter 0   |                            ^
    227 //       |- - - - - - - - -|                            |
    228 //  -n   |                 |                          Caller
    229 //  ...  |       ...       |                       frame slots
    230 //  -2   |  parameter n-1  |                       (slot < 0)
    231 //       |- - - - - - - - -|                            |
    232 //  -1   |   parameter n   |                            v
    233 //  -----+-----------------+--------------------------------
    234 //   0   |   return addr   |   ^                        ^
    235 //       |- - - - - - - - -|   |                        |
    236 //   1   | saved frame ptr | Fixed                      |
    237 //       |- - - - - - - - -| Header <-- frame ptr       |
    238 //   2   | [Constant Pool] |   |                        |
    239 //       |- - - - - - - - -|   |                        |
    240 // 2+cp  |Frame Type Marker|   v   if a constant pool   |
    241 //       |-----------------+----    is used, cp = 1,    |
    242 // 3+cp  |                 |   ^   otherwise, cp = 0    |
    243 //       |- - - - - - - - -|   |                        |
    244 // 4+cp  |                 |   |                      Callee
    245 //       |- - - - - - - - -|   |                   frame slots
    246 //  ...  |                 | Frame slots           (slot >= 0)
    247 //       |- - - - - - - - -|   |                        |
    248 //       |                 |   v                        |
    249 //  -----+-----------------+----- <-- stack ptr -------------
    250 //
    251 class TypedFrameConstants : public CommonFrameConstants {
    252  public:
    253   static const int kFrameTypeSize = kContextOrFrameTypeSize;
    254   static const int kFrameTypeOffset = kContextOrFrameTypeOffset;
    255   static const int kFixedFrameSizeFromFp = kCPSlotSize + kFrameTypeSize;
    256   static const int kFixedSlotCountFromFp = kFixedFrameSizeFromFp / kPointerSize;
    257   static const int kFixedFrameSize =
    258       StandardFrameConstants::kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp;
    259   static const int kFixedSlotCount = kFixedFrameSize / kPointerSize;
    260   static const int kFirstPushedFrameValueOffset =
    261       -StandardFrameConstants::kCPSlotSize - kFrameTypeSize - kPointerSize;
    262 };
    263 
    264 #define TYPED_FRAME_PUSHED_VALUE_OFFSET(x) \
    265   (TypedFrameConstants::kFirstPushedFrameValueOffset - (x)*kPointerSize)
    266 #define TYPED_FRAME_SIZE(count) \
    267   (TypedFrameConstants::kFixedFrameSize + (count)*kPointerSize)
    268 #define TYPED_FRAME_SIZE_FROM_SP(count) \
    269   (TypedFrameConstants::kFixedFrameSizeFromFp + (count)*kPointerSize)
    270 #define DEFINE_TYPED_FRAME_SIZES(count)                                     \
    271   static const int kFixedFrameSize = TYPED_FRAME_SIZE(count);               \
    272   static const int kFixedSlotCount = kFixedFrameSize / kPointerSize;        \
    273   static const int kFixedFrameSizeFromFp = TYPED_FRAME_SIZE_FROM_SP(count); \
    274   static const int kFixedSlotCountFromFp = kFixedFrameSizeFromFp / kPointerSize
    275 
    276 class ArgumentsAdaptorFrameConstants : public TypedFrameConstants {
    277  public:
    278   // FP-relative.
    279   static const int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
    280   static const int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
    281   DEFINE_TYPED_FRAME_SIZES(2);
    282 };
    283 
    284 class BuiltinFrameConstants : public TypedFrameConstants {
    285  public:
    286   // FP-relative.
    287   static const int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
    288   static const int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
    289   DEFINE_TYPED_FRAME_SIZES(2);
    290 };
    291 
    292 class InternalFrameConstants : public TypedFrameConstants {
    293  public:
    294   // FP-relative.
    295   static const int kCodeOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
    296   DEFINE_TYPED_FRAME_SIZES(1);
    297 };
    298 
    299 class FrameDropperFrameConstants : public InternalFrameConstants {
    300  public:
    301   // FP-relative.
    302   static const int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
    303   DEFINE_TYPED_FRAME_SIZES(2);
    304 };
    305 
    306 class ConstructFrameConstants : public TypedFrameConstants {
    307  public:
    308   // FP-relative.
    309   static const int kContextOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
    310   static const int kAllocationSiteOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
    311   static const int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2);
    312   static const int kImplicitReceiverOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(3);
    313   DEFINE_TYPED_FRAME_SIZES(4);
    314 };
    315 
    316 class StubFailureTrampolineFrameConstants : public InternalFrameConstants {
    317  public:
    318   static const int kArgumentsArgumentsOffset =
    319       TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
    320   static const int kArgumentsLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
    321   static const int kArgumentsPointerOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2);
    322   static const int kFixedHeaderBottomOffset = kArgumentsPointerOffset;
    323   DEFINE_TYPED_FRAME_SIZES(3);
    324 };
    325 
    326 
    327 class InterpreterFrameConstants : public AllStatic {
    328  public:
    329   // Fixed frame includes new.target and bytecode offset.
    330   static const int kFixedFrameSize =
    331       StandardFrameConstants::kFixedFrameSize + 3 * kPointerSize;
    332   static const int kFixedFrameSizeFromFp =
    333       StandardFrameConstants::kFixedFrameSizeFromFp + 3 * kPointerSize;
    334 
    335   // FP-relative.
    336   static const int kLastParamFromFp = StandardFrameConstants::kCallerSPOffset;
    337   static const int kCallerPCOffsetFromFp =
    338       StandardFrameConstants::kCallerPCOffset;
    339   static const int kNewTargetFromFp =
    340       -StandardFrameConstants::kFixedFrameSizeFromFp - 1 * kPointerSize;
    341   static const int kBytecodeArrayFromFp =
    342       -StandardFrameConstants::kFixedFrameSizeFromFp - 2 * kPointerSize;
    343   static const int kBytecodeOffsetFromFp =
    344       -StandardFrameConstants::kFixedFrameSizeFromFp - 3 * kPointerSize;
    345   static const int kRegisterFileFromFp =
    346       -StandardFrameConstants::kFixedFrameSizeFromFp - 4 * kPointerSize;
    347 
    348   static const int kExpressionsOffset = kRegisterFileFromFp;
    349 
    350   // Expression index for {StandardFrame::GetExpressionAddress}.
    351   static const int kBytecodeArrayExpressionIndex = -2;
    352   static const int kBytecodeOffsetExpressionIndex = -1;
    353   static const int kRegisterFileExpressionIndex = 0;
    354 };
    355 
    356 inline static int FPOffsetToFrameSlot(int frame_offset) {
    357   return StandardFrameConstants::kFixedSlotCountAboveFp - 1 -
    358          frame_offset / kPointerSize;
    359 }
    360 
    361 inline static int FrameSlotToFPOffset(int slot) {
    362   return (StandardFrameConstants::kFixedSlotCountAboveFp - 1 - slot) *
    363          kPointerSize;
    364 }
    365 
    366 // Abstract base class for all stack frames.
    367 class StackFrame BASE_EMBEDDED {
    368  public:
    369 #define DECLARE_TYPE(type, ignore) type,
    370   enum Type {
    371     NONE = 0,
    372     STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
    373     NUMBER_OF_TYPES,
    374     // Used by FrameScope to indicate that the stack frame is constructed
    375     // manually and the FrameScope does not need to emit code.
    376     MANUAL
    377   };
    378 #undef DECLARE_TYPE
    379 
    380   // Opaque data type for identifying stack frames. Used extensively
    381   // by the debugger.
    382   // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
    383   // has correct value range (see Issue 830 for more details).
    384   enum Id {
    385     ID_MIN_VALUE = kMinInt,
    386     ID_MAX_VALUE = kMaxInt,
    387     NO_ID = 0
    388   };
    389 
    390   // Used to mark the outermost JS entry frame.
    391   enum JsFrameMarker {
    392     INNER_JSENTRY_FRAME = 0,
    393     OUTERMOST_JSENTRY_FRAME = 1
    394   };
    395 
    396   struct State {
    397     State() : sp(NULL), fp(NULL), pc_address(NULL),
    398               constant_pool_address(NULL) { }
    399     Address sp;
    400     Address fp;
    401     Address* pc_address;
    402     Address* constant_pool_address;
    403   };
    404 
    405   // Copy constructor; it breaks the connection to host iterator
    406   // (as an iterator usually lives on stack).
    407   StackFrame(const StackFrame& original) {
    408     this->state_ = original.state_;
    409     this->iterator_ = NULL;
    410     this->isolate_ = original.isolate_;
    411   }
    412 
    413   // Type testers.
    414   bool is_entry() const { return type() == ENTRY; }
    415   bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
    416   bool is_exit() const { return type() == EXIT; }
    417   bool is_optimized() const { return type() == OPTIMIZED; }
    418   bool is_interpreted() const { return type() == INTERPRETED; }
    419   bool is_wasm() const { return type() == WASM; }
    420   bool is_wasm_to_js() const { return type() == WASM_TO_JS; }
    421   bool is_js_to_wasm() const { return type() == JS_TO_WASM; }
    422   bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
    423   bool is_builtin() const { return type() == BUILTIN; }
    424   bool is_internal() const { return type() == INTERNAL; }
    425   bool is_stub_failure_trampoline() const {
    426     return type() == STUB_FAILURE_TRAMPOLINE;
    427   }
    428   bool is_construct() const { return type() == CONSTRUCT; }
    429   virtual bool is_standard() const { return false; }
    430 
    431   bool is_java_script() const {
    432     Type type = this->type();
    433     return (type == JAVA_SCRIPT) || (type == OPTIMIZED) ||
    434            (type == INTERPRETED) || (type == BUILTIN);
    435   }
    436 
    437   // Accessors.
    438   Address sp() const { return state_.sp; }
    439   Address fp() const { return state_.fp; }
    440   Address caller_sp() const { return GetCallerStackPointer(); }
    441 
    442   // If this frame is optimized and was dynamically aligned return its old
    443   // unaligned frame pointer.  When the frame is deoptimized its FP will shift
    444   // up one word and become unaligned.
    445   Address UnpaddedFP() const;
    446 
    447   Address pc() const { return *pc_address(); }
    448   void set_pc(Address pc) { *pc_address() = pc; }
    449 
    450   Address constant_pool() const { return *constant_pool_address(); }
    451   void set_constant_pool(Address constant_pool) {
    452     *constant_pool_address() = constant_pool;
    453   }
    454 
    455   virtual void SetCallerFp(Address caller_fp) = 0;
    456 
    457   // Manually changes value of fp in this object.
    458   void UpdateFp(Address fp) { state_.fp = fp; }
    459 
    460   Address* pc_address() const { return state_.pc_address; }
    461 
    462   Address* constant_pool_address() const {
    463     return state_.constant_pool_address;
    464   }
    465 
    466   // Get the id of this stack frame.
    467   Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
    468 
    469   // Get the top handler from the current stack iterator.
    470   inline StackHandler* top_handler() const;
    471 
    472   // Get the type of this frame.
    473   virtual Type type() const = 0;
    474 
    475   // Get the code associated with this frame.
    476   // This method could be called during marking phase of GC.
    477   virtual Code* unchecked_code() const = 0;
    478 
    479   // Get the code associated with this frame.
    480   inline Code* LookupCode() const;
    481 
    482   // Get the code object that contains the given pc.
    483   static inline Code* GetContainingCode(Isolate* isolate, Address pc);
    484 
    485   // Get the code object containing the given pc and fill in the
    486   // safepoint entry and the number of stack slots. The pc must be at
    487   // a safepoint.
    488   static Code* GetSafepointData(Isolate* isolate,
    489                                 Address pc,
    490                                 SafepointEntry* safepoint_entry,
    491                                 unsigned* stack_slots);
    492 
    493   virtual void Iterate(ObjectVisitor* v) const = 0;
    494   static void IteratePc(ObjectVisitor* v, Address* pc_address,
    495                         Address* constant_pool_address, Code* holder);
    496 
    497   // Sets a callback function for return-address rewriting profilers
    498   // to resolve the location of a return address to the location of the
    499   // profiler's stashed return address.
    500   static void SetReturnAddressLocationResolver(
    501       ReturnAddressLocationResolver resolver);
    502 
    503   // Resolves pc_address through the resolution address function if one is set.
    504   static inline Address* ResolveReturnAddressLocation(Address* pc_address);
    505 
    506   // Printing support.
    507   enum PrintMode { OVERVIEW, DETAILS };
    508   virtual void Print(StringStream* accumulator,
    509                      PrintMode mode,
    510                      int index) const { }
    511 
    512   Isolate* isolate() const { return isolate_; }
    513 
    514  protected:
    515   inline explicit StackFrame(StackFrameIteratorBase* iterator);
    516   virtual ~StackFrame() { }
    517 
    518   // Compute the stack pointer for the calling frame.
    519   virtual Address GetCallerStackPointer() const = 0;
    520 
    521   // Printing support.
    522   static void PrintIndex(StringStream* accumulator,
    523                          PrintMode mode,
    524                          int index);
    525 
    526   // Compute the stack frame type for the given state.
    527   static Type ComputeType(const StackFrameIteratorBase* iterator, State* state);
    528 
    529 #ifdef DEBUG
    530   bool can_access_heap_objects() const;
    531 #endif
    532 
    533  private:
    534   const StackFrameIteratorBase* iterator_;
    535   Isolate* isolate_;
    536   State state_;
    537 
    538   static ReturnAddressLocationResolver return_address_location_resolver_;
    539 
    540   // Fill in the state of the calling frame.
    541   virtual void ComputeCallerState(State* state) const = 0;
    542 
    543   // Get the type and the state of the calling frame.
    544   virtual Type GetCallerState(State* state) const;
    545 
    546   static const intptr_t kIsolateTag = 1;
    547 
    548   friend class StackFrameIterator;
    549   friend class StackFrameIteratorBase;
    550   friend class StackHandlerIterator;
    551   friend class SafeStackFrameIterator;
    552 
    553  private:
    554   void operator=(const StackFrame& original);
    555 };
    556 
    557 
    558 // Entry frames are used to enter JavaScript execution from C.
    559 class EntryFrame: public StackFrame {
    560  public:
    561   Type type() const override { return ENTRY; }
    562 
    563   Code* unchecked_code() const override;
    564 
    565   // Garbage collection support.
    566   void Iterate(ObjectVisitor* v) const override;
    567 
    568   static EntryFrame* cast(StackFrame* frame) {
    569     DCHECK(frame->is_entry());
    570     return static_cast<EntryFrame*>(frame);
    571   }
    572   void SetCallerFp(Address caller_fp) override;
    573 
    574  protected:
    575   inline explicit EntryFrame(StackFrameIteratorBase* iterator);
    576 
    577   // The caller stack pointer for entry frames is always zero. The
    578   // real information about the caller frame is available through the
    579   // link to the top exit frame.
    580   Address GetCallerStackPointer() const override { return 0; }
    581 
    582  private:
    583   void ComputeCallerState(State* state) const override;
    584   Type GetCallerState(State* state) const override;
    585 
    586   friend class StackFrameIteratorBase;
    587 };
    588 
    589 
    590 class EntryConstructFrame: public EntryFrame {
    591  public:
    592   Type type() const override { return ENTRY_CONSTRUCT; }
    593 
    594   Code* unchecked_code() const override;
    595 
    596   static EntryConstructFrame* cast(StackFrame* frame) {
    597     DCHECK(frame->is_entry_construct());
    598     return static_cast<EntryConstructFrame*>(frame);
    599   }
    600 
    601  protected:
    602   inline explicit EntryConstructFrame(StackFrameIteratorBase* iterator);
    603 
    604  private:
    605   friend class StackFrameIteratorBase;
    606 };
    607 
    608 
    609 // Exit frames are used to exit JavaScript execution and go to C.
    610 class ExitFrame: public StackFrame {
    611  public:
    612   Type type() const override { return EXIT; }
    613 
    614   Code* unchecked_code() const override;
    615 
    616   Object*& code_slot() const;
    617 
    618   // Garbage collection support.
    619   void Iterate(ObjectVisitor* v) const override;
    620 
    621   void SetCallerFp(Address caller_fp) override;
    622 
    623   static ExitFrame* cast(StackFrame* frame) {
    624     DCHECK(frame->is_exit());
    625     return static_cast<ExitFrame*>(frame);
    626   }
    627 
    628   // Compute the state and type of an exit frame given a frame
    629   // pointer. Used when constructing the first stack frame seen by an
    630   // iterator and the frames following entry frames.
    631   static Type GetStateForFramePointer(Address fp, State* state);
    632   static Address ComputeStackPointer(Address fp);
    633   static void FillState(Address fp, Address sp, State* state);
    634 
    635  protected:
    636   inline explicit ExitFrame(StackFrameIteratorBase* iterator);
    637 
    638   Address GetCallerStackPointer() const override;
    639 
    640  private:
    641   void ComputeCallerState(State* state) const override;
    642 
    643   friend class StackFrameIteratorBase;
    644 };
    645 
    646 class JavaScriptFrame;
    647 
    648 class FrameSummary BASE_EMBEDDED {
    649  public:
    650   // Mode for JavaScriptFrame::Summarize. Exact summary is required to produce
    651   // an exact stack trace. It will trigger an assertion failure if that is not
    652   // possible, e.g., because of missing deoptimization information. The
    653   // approximate mode should produce a summary even without deoptimization
    654   // information, but it might miss frames.
    655   enum Mode { kExactSummary, kApproximateSummary };
    656 
    657   FrameSummary(Object* receiver, JSFunction* function,
    658                AbstractCode* abstract_code, int code_offset,
    659                bool is_constructor, Mode mode = kExactSummary);
    660 
    661   static FrameSummary GetFirst(JavaScriptFrame* frame);
    662 
    663   Handle<Object> receiver() { return receiver_; }
    664   Handle<JSFunction> function() { return function_; }
    665   Handle<AbstractCode> abstract_code() { return abstract_code_; }
    666   int code_offset() { return code_offset_; }
    667   bool is_constructor() { return is_constructor_; }
    668 
    669   void Print();
    670 
    671  private:
    672   Handle<Object> receiver_;
    673   Handle<JSFunction> function_;
    674   Handle<AbstractCode> abstract_code_;
    675   int code_offset_;
    676   bool is_constructor_;
    677 };
    678 
    679 class StandardFrame : public StackFrame {
    680  public:
    681   // Testers.
    682   bool is_standard() const override { return true; }
    683 
    684   // Accessors.
    685   inline Object* context() const;
    686 
    687   // Access the expressions in the stack frame including locals.
    688   inline Object* GetExpression(int index) const;
    689   inline void SetExpression(int index, Object* value);
    690   int ComputeExpressionsCount() const;
    691 
    692   void SetCallerFp(Address caller_fp) override;
    693 
    694   static StandardFrame* cast(StackFrame* frame) {
    695     DCHECK(frame->is_standard());
    696     return static_cast<StandardFrame*>(frame);
    697   }
    698 
    699  protected:
    700   inline explicit StandardFrame(StackFrameIteratorBase* iterator);
    701 
    702   void ComputeCallerState(State* state) const override;
    703 
    704   // Accessors.
    705   inline Address caller_fp() const;
    706   inline Address caller_pc() const;
    707 
    708   // Computes the address of the PC field in the standard frame given
    709   // by the provided frame pointer.
    710   static inline Address ComputePCAddress(Address fp);
    711 
    712   // Computes the address of the constant pool  field in the standard
    713   // frame given by the provided frame pointer.
    714   static inline Address ComputeConstantPoolAddress(Address fp);
    715 
    716   // Iterate over expression stack including stack handlers, locals,
    717   // and parts of the fixed part including context and code fields.
    718   void IterateExpressions(ObjectVisitor* v) const;
    719 
    720   // Returns the address of the n'th expression stack element.
    721   virtual Address GetExpressionAddress(int n) const;
    722 
    723   // Determines if the standard frame for the given frame pointer is
    724   // an arguments adaptor frame.
    725   static inline bool IsArgumentsAdaptorFrame(Address fp);
    726 
    727   // Determines if the standard frame for the given frame pointer is a
    728   // construct frame.
    729   static inline bool IsConstructFrame(Address fp);
    730 
    731   // Used by OptimizedFrames and StubFrames.
    732   void IterateCompiledFrame(ObjectVisitor* v) const;
    733 
    734  private:
    735   friend class StackFrame;
    736   friend class SafeStackFrameIterator;
    737 };
    738 
    739 class JavaScriptFrame : public StandardFrame {
    740  public:
    741   Type type() const override { return JAVA_SCRIPT; }
    742 
    743   // Build a list with summaries for this frame including all inlined frames.
    744   virtual void Summarize(
    745       List<FrameSummary>* frames,
    746       FrameSummary::Mode mode = FrameSummary::kExactSummary) const;
    747 
    748   // Accessors.
    749   virtual JSFunction* function() const;
    750   virtual Object* receiver() const;
    751 
    752   inline void set_receiver(Object* value);
    753 
    754   // Access the parameters.
    755   inline Address GetParameterSlot(int index) const;
    756   inline Object* GetParameter(int index) const;
    757   inline int ComputeParametersCount() const {
    758     return GetNumberOfIncomingArguments();
    759   }
    760 
    761   // Access the operand stack.
    762   inline Address GetOperandSlot(int index) const;
    763   inline Object* GetOperand(int index) const;
    764   inline int ComputeOperandsCount() const;
    765 
    766   // Generator support to preserve operand stack.
    767   void SaveOperandStack(FixedArray* store) const;
    768 
    769   // Debugger access.
    770   void SetParameterValue(int index, Object* value) const;
    771 
    772   // Check if this frame is a constructor frame invoked through 'new'.
    773   bool IsConstructor() const;
    774 
    775   // Determines whether this frame includes inlined activations. To get details
    776   // about the inlined frames use {GetFunctions} and {Summarize}.
    777   bool HasInlinedFrames() const;
    778 
    779   // Check if this frame has "adapted" arguments in the sense that the
    780   // actual passed arguments are available in an arguments adaptor
    781   // frame below it on the stack.
    782   inline bool has_adapted_arguments() const;
    783   int GetArgumentsLength() const;
    784 
    785   // Garbage collection support.
    786   void Iterate(ObjectVisitor* v) const override;
    787 
    788   // Printing support.
    789   void Print(StringStream* accumulator, PrintMode mode,
    790              int index) const override;
    791 
    792   // Determine the code for the frame.
    793   Code* unchecked_code() const override;
    794 
    795   // Return a list with JSFunctions of this frame.
    796   virtual void GetFunctions(List<JSFunction*>* functions) const;
    797 
    798   // Lookup exception handler for current {pc}, returns -1 if none found. Also
    799   // returns data associated with the handler site specific to the frame type:
    800   //  - JavaScriptFrame : Data is the stack depth at entry of the try-block.
    801   //  - OptimizedFrame  : Data is the stack slot count of the entire frame.
    802   //  - InterpretedFrame: Data is the register index holding the context.
    803   virtual int LookupExceptionHandlerInTable(
    804       int* data, HandlerTable::CatchPrediction* prediction);
    805 
    806   // Architecture-specific register description.
    807   static Register fp_register();
    808   static Register context_register();
    809   static Register constant_pool_pointer_register();
    810 
    811   static JavaScriptFrame* cast(StackFrame* frame) {
    812     DCHECK(frame->is_java_script());
    813     return static_cast<JavaScriptFrame*>(frame);
    814   }
    815 
    816   static void PrintFunctionAndOffset(JSFunction* function, Code* code,
    817                                      Address pc, FILE* file,
    818                                      bool print_line_number);
    819 
    820   static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
    821                        bool print_line_number);
    822 
    823  protected:
    824   inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator);
    825 
    826   Address GetCallerStackPointer() const override;
    827 
    828   virtual int GetNumberOfIncomingArguments() const;
    829 
    830   // Garbage collection support. Iterates over incoming arguments,
    831   // receiver, and any callee-saved registers.
    832   void IterateArguments(ObjectVisitor* v) const;
    833 
    834  private:
    835   inline Object* function_slot_object() const;
    836 
    837   friend class StackFrameIteratorBase;
    838 };
    839 
    840 
    841 class StubFrame : public StandardFrame {
    842  public:
    843   Type type() const override { return STUB; }
    844 
    845   // GC support.
    846   void Iterate(ObjectVisitor* v) const override;
    847 
    848   // Determine the code for the frame.
    849   Code* unchecked_code() const override;
    850 
    851  protected:
    852   inline explicit StubFrame(StackFrameIteratorBase* iterator);
    853 
    854   Address GetCallerStackPointer() const override;
    855 
    856   virtual int GetNumberOfIncomingArguments() const;
    857 
    858   friend class StackFrameIteratorBase;
    859 };
    860 
    861 
    862 class OptimizedFrame : public JavaScriptFrame {
    863  public:
    864   Type type() const override { return OPTIMIZED; }
    865 
    866   // GC support.
    867   void Iterate(ObjectVisitor* v) const override;
    868 
    869   // Return a list with JSFunctions of this frame.
    870   // The functions are ordered bottom-to-top (i.e. functions.last()
    871   // is the top-most activation)
    872   void GetFunctions(List<JSFunction*>* functions) const override;
    873 
    874   void Summarize(
    875       List<FrameSummary>* frames,
    876       FrameSummary::Mode mode = FrameSummary::kExactSummary) const override;
    877 
    878   // Lookup exception handler for current {pc}, returns -1 if none found.
    879   int LookupExceptionHandlerInTable(
    880       int* data, HandlerTable::CatchPrediction* prediction) override;
    881 
    882   DeoptimizationInputData* GetDeoptimizationData(int* deopt_index) const;
    883 
    884   static int StackSlotOffsetRelativeToFp(int slot_index);
    885 
    886  protected:
    887   inline explicit OptimizedFrame(StackFrameIteratorBase* iterator);
    888 
    889  private:
    890   friend class StackFrameIteratorBase;
    891 
    892   Object* StackSlotAt(int index) const;
    893 };
    894 
    895 
    896 class InterpretedFrame : public JavaScriptFrame {
    897  public:
    898   Type type() const override { return INTERPRETED; }
    899 
    900   // Lookup exception handler for current {pc}, returns -1 if none found.
    901   int LookupExceptionHandlerInTable(
    902       int* data, HandlerTable::CatchPrediction* prediction) override;
    903 
    904   // Returns the current offset into the bytecode stream.
    905   int GetBytecodeOffset() const;
    906 
    907   // Updates the current offset into the bytecode stream, mainly used for stack
    908   // unwinding to continue execution at a different bytecode offset.
    909   void PatchBytecodeOffset(int new_offset);
    910 
    911   // Returns the frame's current bytecode array.
    912   BytecodeArray* GetBytecodeArray() const;
    913 
    914   // Updates the frame's BytecodeArray with |bytecode_array|. Used by the
    915   // debugger to swap execution onto a BytecodeArray patched with breakpoints.
    916   void PatchBytecodeArray(BytecodeArray* bytecode_array);
    917 
    918   // Access to the interpreter register file for this frame.
    919   Object* ReadInterpreterRegister(int register_index) const;
    920   void WriteInterpreterRegister(int register_index, Object* value);
    921 
    922   // Build a list with summaries for this frame including all inlined frames.
    923   void Summarize(
    924       List<FrameSummary>* frames,
    925       FrameSummary::Mode mode = FrameSummary::kExactSummary) const override;
    926 
    927  protected:
    928   inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);
    929 
    930   Address GetExpressionAddress(int n) const override;
    931 
    932  private:
    933   friend class StackFrameIteratorBase;
    934 };
    935 
    936 
    937 // Arguments adaptor frames are automatically inserted below
    938 // JavaScript frames when the actual number of parameters does not
    939 // match the formal number of parameters.
    940 class ArgumentsAdaptorFrame: public JavaScriptFrame {
    941  public:
    942   Type type() const override { return ARGUMENTS_ADAPTOR; }
    943 
    944   // Determine the code for the frame.
    945   Code* unchecked_code() const override;
    946 
    947   static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
    948     DCHECK(frame->is_arguments_adaptor());
    949     return static_cast<ArgumentsAdaptorFrame*>(frame);
    950   }
    951 
    952   // Printing support.
    953   void Print(StringStream* accumulator, PrintMode mode,
    954              int index) const override;
    955 
    956   static int GetLength(Address fp);
    957 
    958  protected:
    959   inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator);
    960 
    961   int GetNumberOfIncomingArguments() const override;
    962 
    963  private:
    964   friend class StackFrameIteratorBase;
    965 };
    966 
    967 // Builtin frames are built for builtins with JavaScript linkage, such as
    968 // various standard library functions (i.e. Math.asin, Math.floor, etc.).
    969 class BuiltinFrame final : public JavaScriptFrame {
    970  public:
    971   Type type() const final { return BUILTIN; }
    972 
    973   static BuiltinFrame* cast(StackFrame* frame) {
    974     DCHECK(frame->is_builtin());
    975     return static_cast<BuiltinFrame*>(frame);
    976   }
    977 
    978   // Printing support.
    979   void Print(StringStream* accumulator, PrintMode mode, int index) const final;
    980 
    981  protected:
    982   inline explicit BuiltinFrame(StackFrameIteratorBase* iterator);
    983 
    984   int GetNumberOfIncomingArguments() const final;
    985 
    986  private:
    987   friend class StackFrameIteratorBase;
    988 };
    989 
    990 class WasmFrame : public StandardFrame {
    991  public:
    992   Type type() const override { return WASM; }
    993 
    994   // GC support.
    995   void Iterate(ObjectVisitor* v) const override;
    996 
    997   // Printing support.
    998   void Print(StringStream* accumulator, PrintMode mode,
    999              int index) const override;
   1000 
   1001   // Determine the code for the frame.
   1002   Code* unchecked_code() const override;
   1003 
   1004   Object* wasm_obj();
   1005   uint32_t function_index();
   1006 
   1007   static WasmFrame* cast(StackFrame* frame) {
   1008     DCHECK(frame->is_wasm());
   1009     return static_cast<WasmFrame*>(frame);
   1010   }
   1011 
   1012  protected:
   1013   inline explicit WasmFrame(StackFrameIteratorBase* iterator);
   1014 
   1015   Address GetCallerStackPointer() const override;
   1016 
   1017  private:
   1018   friend class StackFrameIteratorBase;
   1019 };
   1020 
   1021 class WasmToJsFrame : public StubFrame {
   1022  public:
   1023   Type type() const override { return WASM_TO_JS; }
   1024 
   1025  protected:
   1026   inline explicit WasmToJsFrame(StackFrameIteratorBase* iterator);
   1027 
   1028  private:
   1029   friend class StackFrameIteratorBase;
   1030 };
   1031 
   1032 class JsToWasmFrame : public StubFrame {
   1033  public:
   1034   Type type() const override { return JS_TO_WASM; }
   1035 
   1036  protected:
   1037   inline explicit JsToWasmFrame(StackFrameIteratorBase* iterator);
   1038 
   1039  private:
   1040   friend class StackFrameIteratorBase;
   1041 };
   1042 
   1043 class InternalFrame: public StandardFrame {
   1044  public:
   1045   Type type() const override { return INTERNAL; }
   1046 
   1047   // Garbage collection support.
   1048   void Iterate(ObjectVisitor* v) const override;
   1049 
   1050   // Determine the code for the frame.
   1051   Code* unchecked_code() const override;
   1052 
   1053   static InternalFrame* cast(StackFrame* frame) {
   1054     DCHECK(frame->is_internal());
   1055     return static_cast<InternalFrame*>(frame);
   1056   }
   1057 
   1058  protected:
   1059   inline explicit InternalFrame(StackFrameIteratorBase* iterator);
   1060 
   1061   Address GetCallerStackPointer() const override;
   1062 
   1063  private:
   1064   friend class StackFrameIteratorBase;
   1065 };
   1066 
   1067 
   1068 class StubFailureTrampolineFrame: public StandardFrame {
   1069  public:
   1070   Type type() const override { return STUB_FAILURE_TRAMPOLINE; }
   1071 
   1072   // Get the code associated with this frame.
   1073   // This method could be called during marking phase of GC.
   1074   Code* unchecked_code() const override;
   1075 
   1076   void Iterate(ObjectVisitor* v) const override;
   1077 
   1078   // Architecture-specific register description.
   1079   static Register fp_register();
   1080   static Register context_register();
   1081   static Register constant_pool_pointer_register();
   1082 
   1083  protected:
   1084   inline explicit StubFailureTrampolineFrame(
   1085       StackFrameIteratorBase* iterator);
   1086 
   1087   Address GetCallerStackPointer() const override;
   1088 
   1089  private:
   1090   friend class StackFrameIteratorBase;
   1091 };
   1092 
   1093 
   1094 // Construct frames are special trampoline frames introduced to handle
   1095 // function invocations through 'new'.
   1096 class ConstructFrame: public InternalFrame {
   1097  public:
   1098   Type type() const override { return CONSTRUCT; }
   1099 
   1100   static ConstructFrame* cast(StackFrame* frame) {
   1101     DCHECK(frame->is_construct());
   1102     return static_cast<ConstructFrame*>(frame);
   1103   }
   1104 
   1105  protected:
   1106   inline explicit ConstructFrame(StackFrameIteratorBase* iterator);
   1107 
   1108  private:
   1109   friend class StackFrameIteratorBase;
   1110 };
   1111 
   1112 
   1113 class StackFrameIteratorBase BASE_EMBEDDED {
   1114  public:
   1115   Isolate* isolate() const { return isolate_; }
   1116 
   1117   bool done() const { return frame_ == NULL; }
   1118 
   1119  protected:
   1120   // An iterator that iterates over a given thread's stack.
   1121   StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects);
   1122 
   1123   Isolate* isolate_;
   1124 #define DECLARE_SINGLETON(ignore, type) type type##_;
   1125   STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
   1126 #undef DECLARE_SINGLETON
   1127   StackFrame* frame_;
   1128   StackHandler* handler_;
   1129   const bool can_access_heap_objects_;
   1130 
   1131   StackHandler* handler() const {
   1132     DCHECK(!done());
   1133     return handler_;
   1134   }
   1135 
   1136   // Get the type-specific frame singleton in a given state.
   1137   StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
   1138   // A helper function, can return a NULL pointer.
   1139   StackFrame* SingletonFor(StackFrame::Type type);
   1140 
   1141  private:
   1142   friend class StackFrame;
   1143   DISALLOW_COPY_AND_ASSIGN(StackFrameIteratorBase);
   1144 };
   1145 
   1146 
   1147 class StackFrameIterator: public StackFrameIteratorBase {
   1148  public:
   1149   // An iterator that iterates over the isolate's current thread's stack,
   1150   explicit StackFrameIterator(Isolate* isolate);
   1151   // An iterator that iterates over a given thread's stack.
   1152   StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
   1153 
   1154   StackFrame* frame() const {
   1155     DCHECK(!done());
   1156     return frame_;
   1157   }
   1158   void Advance();
   1159 
   1160  private:
   1161   // Go back to the first frame.
   1162   void Reset(ThreadLocalTop* top);
   1163 
   1164   DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
   1165 };
   1166 
   1167 // Iterator that supports iterating through all JavaScript frames.
   1168 class JavaScriptFrameIterator BASE_EMBEDDED {
   1169  public:
   1170   inline explicit JavaScriptFrameIterator(Isolate* isolate);
   1171   inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top);
   1172   // Skip frames until the frame with the given id is reached.
   1173   JavaScriptFrameIterator(Isolate* isolate, StackFrame::Id id);
   1174 
   1175   inline JavaScriptFrame* frame() const;
   1176 
   1177   bool done() const { return iterator_.done(); }
   1178   void Advance();
   1179 
   1180   // Advance to the frame holding the arguments for the current
   1181   // frame. This only affects the current frame if it has adapted
   1182   // arguments.
   1183   void AdvanceToArgumentsFrame();
   1184 
   1185  private:
   1186   StackFrameIterator iterator_;
   1187 };
   1188 
   1189 // NOTE: The stack trace frame iterator is an iterator that only traverse proper
   1190 // JavaScript frames that have proper JavaScript functions and WASM frames.
   1191 // This excludes the problematic functions in runtime.js.
   1192 class StackTraceFrameIterator BASE_EMBEDDED {
   1193  public:
   1194   explicit StackTraceFrameIterator(Isolate* isolate);
   1195   bool done() const { return iterator_.done(); }
   1196   void Advance();
   1197 
   1198   inline StandardFrame* frame() const;
   1199 
   1200   inline bool is_javascript() const;
   1201   inline bool is_wasm() const;
   1202   inline JavaScriptFrame* javascript_frame() const;
   1203   inline WasmFrame* wasm_frame() const;
   1204 
   1205  private:
   1206   StackFrameIterator iterator_;
   1207   bool IsValidFrame(StackFrame* frame) const;
   1208 };
   1209 
   1210 
   1211 class SafeStackFrameIterator: public StackFrameIteratorBase {
   1212  public:
   1213   SafeStackFrameIterator(Isolate* isolate,
   1214                          Address fp, Address sp,
   1215                          Address js_entry_sp);
   1216 
   1217   inline StackFrame* frame() const;
   1218   void Advance();
   1219 
   1220   StackFrame::Type top_frame_type() const { return top_frame_type_; }
   1221 
   1222  private:
   1223   void AdvanceOneFrame();
   1224 
   1225   bool IsValidStackAddress(Address addr) const {
   1226     return low_bound_ <= addr && addr <= high_bound_;
   1227   }
   1228   bool IsValidFrame(StackFrame* frame) const;
   1229   bool IsValidCaller(StackFrame* frame);
   1230   bool IsValidExitFrame(Address fp) const;
   1231   bool IsValidTop(ThreadLocalTop* top) const;
   1232 
   1233   const Address low_bound_;
   1234   const Address high_bound_;
   1235   StackFrame::Type top_frame_type_;
   1236   ExternalCallbackScope* external_callback_scope_;
   1237 };
   1238 
   1239 
   1240 class StackFrameLocator BASE_EMBEDDED {
   1241  public:
   1242   explicit StackFrameLocator(Isolate* isolate) : iterator_(isolate) {}
   1243 
   1244   // Find the nth JavaScript frame on the stack. The caller must
   1245   // guarantee that such a frame exists.
   1246   JavaScriptFrame* FindJavaScriptFrame(int n);
   1247 
   1248  private:
   1249   StackFrameIterator iterator_;
   1250 };
   1251 
   1252 
   1253 // Reads all frames on the current stack and copies them into the current
   1254 // zone memory.
   1255 Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone);
   1256 
   1257 }  // namespace internal
   1258 }  // namespace v8
   1259 
   1260 #endif  // V8_FRAMES_H_
   1261