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