frames.h 44.3 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4 5 6 7

#ifndef V8_FRAMES_H_
#define V8_FRAMES_H_

8 9 10
#include "src/allocation.h"
#include "src/handles.h"
#include "src/safepoint-table.h"
11

12 13
namespace v8 {
namespace internal {
14

15
#if V8_TARGET_ARCH_ARM64
16 17
typedef uint64_t RegList;
#else
18
typedef uint32_t RegList;
19
#endif
20 21 22 23

// Get the number of registers in a given register list.
int NumRegs(RegList list);

24 25
void SetUpJSCallerSavedCodeData();

26 27 28 29 30
// Return the code of the n-th saved register available to JavaScript.
int JSCallerSavedCode(int n);


// Forward declarations.
31
class ExternalCallbackScope;
32
class StackFrameIteratorBase;
33
class ThreadLocalTop;
34
class Isolate;
35

36
class InnerPointerToCodeCache {
37
 public:
38 39
  struct InnerPointerToCodeCacheEntry {
    Address inner_pointer;
40
    Code* code;
41
    SafepointEntry safepoint_entry;
42 43
  };

44
  explicit InnerPointerToCodeCache(Isolate* isolate) : isolate_(isolate) {
45
    Flush();
46 47
  }

48 49
  Code* GcSafeFindCodeForInnerPointer(Address inner_pointer);
  Code* GcSafeCastToCode(HeapObject* object, Address inner_pointer);
50

51
  void Flush() {
52 53 54
    memset(&cache_[0], 0, sizeof(cache_));
  }

55
  InnerPointerToCodeCacheEntry* GetCacheEntry(Address inner_pointer);
56 57

 private:
58
  InnerPointerToCodeCacheEntry* cache(int index) { return &cache_[index]; }
59 60 61

  Isolate* isolate_;

62 63
  static const int kInnerPointerToCodeCacheSize = 1024;
  InnerPointerToCodeCacheEntry cache_[kInnerPointerToCodeCacheSize];
64

65
  DISALLOW_COPY_AND_ASSIGN(InnerPointerToCodeCache);
66 67 68
};


69 70 71 72 73 74 75
// Every try-block pushes the context register.
class TryBlockConstant : public AllStatic {
 public:
  static const int kElementCount = 1;
};


76 77
class StackHandlerConstants : public AllStatic {
 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 86 87 88 89 90 91 92 93 94 95 96
class StackHandler BASE_EMBEDDED {
 public:
  // Get the address of this stack handler.
  inline Address address() const;

  // Get the next stack handler in the chain.
  inline StackHandler* next() const;

  // Conversion support.
  static inline StackHandler* FromAddress(Address address);

 private:
97
  DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
98 99
};

100
#define STACK_FRAME_TYPE_LIST(V)                         \
101 102 103 104 105
  V(ENTRY, EntryFrame)                                   \
  V(ENTRY_CONSTRUCT, EntryConstructFrame)                \
  V(EXIT, ExitFrame)                                     \
  V(JAVA_SCRIPT, JavaScriptFrame)                        \
  V(OPTIMIZED, OptimizedFrame)                           \
106
  V(WASM, WasmFrame)                                     \
107 108
  V(WASM_TO_JS, WasmToJsFrame)                           \
  V(JS_TO_WASM, JsToWasmFrame)                           \
109 110
  V(INTERPRETED, InterpretedFrame)                       \
  V(STUB, StubFrame)                                     \
111
  V(STUB_FAILURE_TRAMPOLINE, StubFailureTrampolineFrame) \
112 113
  V(INTERNAL, InternalFrame)                             \
  V(CONSTRUCT, ConstructFrame)                           \
114
  V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)            \
115 116
  V(BUILTIN, BuiltinFrame)                               \
  V(BUILTIN_EXIT, BuiltinExitFrame)
117

118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
// Every pointer in a frame has a slot id. On 32-bit platforms, doubles consume
// two slots.
//
// Stack slot indices >= 0 access the callee stack with slot 0 corresponding to
// the callee's saved return address and 1 corresponding to the saved frame
// pointer. Some frames have additional information stored in the fixed header,
// for example JSFunctions store the function context and marker in the fixed
// header, with slot index 2 corresponding to the current function context and 3
// corresponding to the frame marker/JSFunction.
//
//  slot      JS frame
//       +-----------------+--------------------------------
//  -n-1 |   parameter 0   |                            ^
//       |- - - - - - - - -|                            |
//  -n   |                 |                          Caller
//  ...  |       ...       |                       frame slots
//  -2   |  parameter n-1  |                       (slot < 0)
//       |- - - - - - - - -|                            |
//  -1   |   parameter n   |                            v
//  -----+-----------------+--------------------------------
//   0   |   return addr   |   ^                        ^
//       |- - - - - - - - -|   |                        |
//   1   | saved frame ptr | Fixed                      |
//       |- - - - - - - - -| Header <-- frame ptr       |
//   2   | [Constant Pool] |   |                        |
//       |- - - - - - - - -|   |                        |
144 145 146 147 148
// 2+cp  |Context/Frm. Type|   v   if a constant pool   |
//       |-----------------+----    is used, cp = 1,    |
// 3+cp  |                 |   ^   otherwise, cp = 0    |
//       |- - - - - - - - -|   |                        |
// 4+cp  |                 |   |                      Callee
149 150 151 152 153 154
//       |- - - - - - - - -|   |                   frame slots
//  ...  |                 | Frame slots           (slot >= 0)
//       |- - - - - - - - -|   |                        |
//       |                 |   v                        |
//  -----+-----------------+----- <-- stack ptr -------------
//
155
class CommonFrameConstants : public AllStatic {
156
 public:
157 158 159 160
  static const int kCallerFPOffset = 0 * kPointerSize;
  static const int kCallerPCOffset = kCallerFPOffset + 1 * kFPOnStackSize;
  static const int kCallerSPOffset = kCallerPCOffset + 1 * kPCOnStackSize;

161
  // Fixed part of the frame consists of return address, caller fp,
162 163 164
  // constant pool (if FLAG_enable_embedded_constant_pool), context, and
  // function. StandardFrame::IterateExpressions assumes that kLastObjectOffset
  // is the last object pointer.
165 166 167
  static const int kFixedFrameSizeAboveFp = kPCOnStackSize + kFPOnStackSize;
  static const int kFixedSlotCountAboveFp =
      kFixedFrameSizeAboveFp / kPointerSize;
168 169
  static const int kCPSlotSize =
      FLAG_enable_embedded_constant_pool ? kPointerSize : 0;
170
  static const int kCPSlotCount = kCPSlotSize / kPointerSize;
171
  static const int kConstantPoolOffset = kCPSlotSize ? -1 * kPointerSize : 0;
172 173 174 175
  static const int kContextOrFrameTypeSize = kPointerSize;
  static const int kContextOrFrameTypeOffset =
      -(kCPSlotSize + kContextOrFrameTypeSize);
};
176

177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
// StandardFrames are used for interpreted, full-codegen and optimized
// JavaScript frames. They always have a context below the saved fp/constant
// pool and below that the JSFunction of the executing function.
//
//  slot      JS frame
//       +-----------------+--------------------------------
//  -n-1 |   parameter 0   |                            ^
//       |- - - - - - - - -|                            |
//  -n   |                 |                          Caller
//  ...  |       ...       |                       frame slots
//  -2   |  parameter n-1  |                       (slot < 0)
//       |- - - - - - - - -|                            |
//  -1   |   parameter n   |                            v
//  -----+-----------------+--------------------------------
//   0   |   return addr   |   ^                        ^
//       |- - - - - - - - -|   |                        |
//   1   | saved frame ptr | Fixed                      |
//       |- - - - - - - - -| Header <-- frame ptr       |
//   2   | [Constant Pool] |   |                        |
//       |- - - - - - - - -|   |                        |
// 2+cp  |     Context     |   |   if a constant pool   |
//       |- - - - - - - - -|   |    is used, cp = 1,    |
// 3+cp  |    JSFunction   |   v   otherwise, cp = 0    |
//       +-----------------+----                        |
// 4+cp  |                 |   ^                      Callee
//       |- - - - - - - - -|   |                   frame slots
//  ...  |                 | Frame slots           (slot >= 0)
//       |- - - - - - - - -|   |                        |
//       |                 |   v                        |
//  -----+-----------------+----- <-- stack ptr -------------
//
class StandardFrameConstants : public CommonFrameConstants {
 public:
  static const int kFixedFrameSizeFromFp = 2 * kPointerSize + kCPSlotSize;
  static const int kFixedFrameSize =
      kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp;
  static const int kFixedSlotCountFromFp = kFixedFrameSizeFromFp / kPointerSize;
  static const int kFixedSlotCount = kFixedFrameSize / kPointerSize;
  static const int kContextOffset = kContextOrFrameTypeOffset;
  static const int kFunctionOffset = -2 * kPointerSize - kCPSlotSize;
  static const int kExpressionsOffset = -3 * kPointerSize - kCPSlotSize;
218
  static const int kLastObjectOffset = kContextOffset;
219 220
};

221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
// TypedFrames have a SMI type maker value below the saved FP/constant pool to
// distinguish them from StandardFrames, which have a context in that position
// instead.
//
//  slot      JS frame
//       +-----------------+--------------------------------
//  -n-1 |   parameter 0   |                            ^
//       |- - - - - - - - -|                            |
//  -n   |                 |                          Caller
//  ...  |       ...       |                       frame slots
//  -2   |  parameter n-1  |                       (slot < 0)
//       |- - - - - - - - -|                            |
//  -1   |   parameter n   |                            v
//  -----+-----------------+--------------------------------
//   0   |   return addr   |   ^                        ^
//       |- - - - - - - - -|   |                        |
//   1   | saved frame ptr | Fixed                      |
//       |- - - - - - - - -| Header <-- frame ptr       |
//   2   | [Constant Pool] |   |                        |
//       |- - - - - - - - -|   |                        |
// 2+cp  |Frame Type Marker|   v   if a constant pool   |
//       |-----------------+----    is used, cp = 1,    |
// 3+cp  |                 |   ^   otherwise, cp = 0    |
//       |- - - - - - - - -|   |                        |
// 4+cp  |                 |   |                      Callee
//       |- - - - - - - - -|   |                   frame slots
//  ...  |                 | Frame slots           (slot >= 0)
//       |- - - - - - - - -|   |                        |
//       |                 |   v                        |
//  -----+-----------------+----- <-- stack ptr -------------
//
class TypedFrameConstants : public CommonFrameConstants {
 public:
  static const int kFrameTypeSize = kContextOrFrameTypeSize;
  static const int kFrameTypeOffset = kContextOrFrameTypeOffset;
  static const int kFixedFrameSizeFromFp = kCPSlotSize + kFrameTypeSize;
  static const int kFixedSlotCountFromFp = kFixedFrameSizeFromFp / kPointerSize;
  static const int kFixedFrameSize =
      StandardFrameConstants::kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp;
  static const int kFixedSlotCount = kFixedFrameSize / kPointerSize;
  static const int kFirstPushedFrameValueOffset =
      -StandardFrameConstants::kCPSlotSize - kFrameTypeSize - kPointerSize;
};
264

265 266 267 268 269 270 271 272 273 274 275 276 277
#define TYPED_FRAME_PUSHED_VALUE_OFFSET(x) \
  (TypedFrameConstants::kFirstPushedFrameValueOffset - (x)*kPointerSize)
#define TYPED_FRAME_SIZE(count) \
  (TypedFrameConstants::kFixedFrameSize + (count)*kPointerSize)
#define TYPED_FRAME_SIZE_FROM_SP(count) \
  (TypedFrameConstants::kFixedFrameSizeFromFp + (count)*kPointerSize)
#define DEFINE_TYPED_FRAME_SIZES(count)                                     \
  static const int kFixedFrameSize = TYPED_FRAME_SIZE(count);               \
  static const int kFixedSlotCount = kFixedFrameSize / kPointerSize;        \
  static const int kFixedFrameSizeFromFp = TYPED_FRAME_SIZE_FROM_SP(count); \
  static const int kFixedSlotCountFromFp = kFixedFrameSizeFromFp / kPointerSize

class ArgumentsAdaptorFrameConstants : public TypedFrameConstants {
278 279
 public:
  // FP-relative.
280 281 282
  static const int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
  static const int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
  DEFINE_TYPED_FRAME_SIZES(2);
283 284
};

285 286 287 288 289 290 291 292
class BuiltinFrameConstants : public TypedFrameConstants {
 public:
  // FP-relative.
  static const int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
  static const int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
  DEFINE_TYPED_FRAME_SIZES(2);
};

293
class InternalFrameConstants : public TypedFrameConstants {
294 295
 public:
  // FP-relative.
296 297
  static const int kCodeOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
  DEFINE_TYPED_FRAME_SIZES(1);
298 299
};

300 301 302 303 304 305
class FrameDropperFrameConstants : public InternalFrameConstants {
 public:
  // FP-relative.
  static const int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
  DEFINE_TYPED_FRAME_SIZES(2);
};
306

307
class ConstructFrameConstants : public TypedFrameConstants {
308 309
 public:
  // FP-relative.
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
  static const int kContextOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
  static const int kAllocationSiteOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
  static const int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2);
  static const int kImplicitReceiverOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(3);
  DEFINE_TYPED_FRAME_SIZES(4);
};

class StubFailureTrampolineFrameConstants : public InternalFrameConstants {
 public:
  static const int kArgumentsArgumentsOffset =
      TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
  static const int kArgumentsLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
  static const int kArgumentsPointerOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2);
  static const int kFixedHeaderBottomOffset = kArgumentsPointerOffset;
  DEFINE_TYPED_FRAME_SIZES(3);
325 326
};

327 328 329 330 331
// Behaves like an exit frame but with target and new target args.
class BuiltinExitFrameConstants : public CommonFrameConstants {
 public:
  static const int kNewTargetOffset = kCallerPCOffset + 1 * kPointerSize;
  static const int kTargetOffset = kNewTargetOffset + 1 * kPointerSize;
332
  static const int kArgcOffset = kTargetOffset + 1 * kPointerSize;
333
};
334

335 336
class InterpreterFrameConstants : public AllStatic {
 public:
337
  // Fixed frame includes new.target, bytecode array, and bytecode offset.
338
  static const int kFixedFrameSize =
339
      StandardFrameConstants::kFixedFrameSize + 3 * kPointerSize;
340
  static const int kFixedFrameSizeFromFp =
341
      StandardFrameConstants::kFixedFrameSizeFromFp + 3 * kPointerSize;
342

343
  // FP-relative.
344
  static const int kLastParamFromFp = StandardFrameConstants::kCallerSPOffset;
345 346
  static const int kCallerPCOffsetFromFp =
      StandardFrameConstants::kCallerPCOffset;
347 348
  static const int kNewTargetFromFp =
      -StandardFrameConstants::kFixedFrameSizeFromFp - 1 * kPointerSize;
349
  static const int kBytecodeArrayFromFp =
350
      -StandardFrameConstants::kFixedFrameSizeFromFp - 2 * kPointerSize;
351
  static const int kBytecodeOffsetFromFp =
352
      -StandardFrameConstants::kFixedFrameSizeFromFp - 3 * kPointerSize;
353
  static const int kRegisterFileFromFp =
354
      -StandardFrameConstants::kFixedFrameSizeFromFp - 4 * kPointerSize;
355

356
  static const int kExpressionsOffset = kRegisterFileFromFp;
357

358 359 360 361 362
  // Number of fixed slots in addition to a {StandardFrame}.
  static const int kExtraSlotCount =
      InterpreterFrameConstants::kFixedFrameSize / kPointerSize -
      StandardFrameConstants::kFixedFrameSize / kPointerSize;

363
  // Expression index for {StandardFrame::GetExpressionAddress}.
364 365 366
  static const int kBytecodeArrayExpressionIndex = -2;
  static const int kBytecodeOffsetExpressionIndex = -1;
  static const int kRegisterFileExpressionIndex = 0;
367 368
};

369 370 371 372 373 374 375 376 377
inline static int FPOffsetToFrameSlot(int frame_offset) {
  return StandardFrameConstants::kFixedSlotCountAboveFp - 1 -
         frame_offset / kPointerSize;
}

inline static int FrameSlotToFPOffset(int slot) {
  return (StandardFrameConstants::kFixedSlotCountAboveFp - 1 - slot) *
         kPointerSize;
}
378

379 380 381 382 383 384 385
// Abstract base class for all stack frames.
class StackFrame BASE_EMBEDDED {
 public:
#define DECLARE_TYPE(type, ignore) type,
  enum Type {
    NONE = 0,
    STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
386 387 388 389
    NUMBER_OF_TYPES,
    // Used by FrameScope to indicate that the stack frame is constructed
    // manually and the FrameScope does not need to emit code.
    MANUAL
390 391 392 393 394
  };
#undef DECLARE_TYPE

  // Opaque data type for identifying stack frames. Used extensively
  // by the debugger.
395 396 397 398 399 400 401
  // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
  // has correct value range (see Issue 830 for more details).
  enum Id {
    ID_MIN_VALUE = kMinInt,
    ID_MAX_VALUE = kMaxInt,
    NO_ID = 0
  };
402

403 404 405 406 407 408
  // Used to mark the outermost JS entry frame.
  enum JsFrameMarker {
    INNER_JSENTRY_FRAME = 0,
    OUTERMOST_JSENTRY_FRAME = 1
  };

409
  struct State {
410 411
    State() : sp(NULL), fp(NULL), pc_address(NULL),
              constant_pool_address(NULL) { }
412 413 414
    Address sp;
    Address fp;
    Address* pc_address;
415
    Address* constant_pool_address;
416 417
  };

418 419
  // Copy constructor; it breaks the connection to host iterator
  // (as an iterator usually lives on stack).
420 421 422
  StackFrame(const StackFrame& original) {
    this->state_ = original.state_;
    this->iterator_ = NULL;
423
    this->isolate_ = original.isolate_;
424 425
  }

426 427 428 429
  // Type testers.
  bool is_entry() const { return type() == ENTRY; }
  bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
  bool is_exit() const { return type() == EXIT; }
430
  bool is_optimized() const { return type() == OPTIMIZED; }
431
  bool is_interpreted() const { return type() == INTERPRETED; }
432
  bool is_wasm() const { return type() == WASM; }
433 434
  bool is_wasm_to_js() const { return type() == WASM_TO_JS; }
  bool is_js_to_wasm() const { return type() == JS_TO_WASM; }
435
  bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
436
  bool is_builtin() const { return type() == BUILTIN; }
437
  bool is_internal() const { return type() == INTERNAL; }
438 439 440
  bool is_stub_failure_trampoline() const {
    return type() == STUB_FAILURE_TRAMPOLINE;
  }
441
  bool is_construct() const { return type() == CONSTRUCT; }
442
  bool is_builtin_exit() const { return type() == BUILTIN_EXIT; }
443 444
  virtual bool is_standard() const { return false; }

445 446
  bool is_java_script() const {
    Type type = this->type();
447
    return (type == JAVA_SCRIPT) || (type == OPTIMIZED) ||
448
           (type == INTERPRETED) || (type == BUILTIN);
449 450
  }

451 452 453
  // Accessors.
  Address sp() const { return state_.sp; }
  Address fp() const { return state_.fp; }
454
  Address caller_sp() const { return GetCallerStackPointer(); }
455

456 457 458 459 460
  // If this frame is optimized and was dynamically aligned return its old
  // unaligned frame pointer.  When the frame is deoptimized its FP will shift
  // up one word and become unaligned.
  Address UnpaddedFP() const;

461 462 463
  Address pc() const { return *pc_address(); }
  void set_pc(Address pc) { *pc_address() = pc; }

464
  Address constant_pool() const { return *constant_pool_address(); }
465 466
  void set_constant_pool(Address constant_pool) {
    *constant_pool_address() = constant_pool;
467 468
  }

469 470
  virtual void SetCallerFp(Address caller_fp) = 0;

471 472 473
  // Manually changes value of fp in this object.
  void UpdateFp(Address fp) { state_.fp = fp; }

474 475
  Address* pc_address() const { return state_.pc_address; }

476 477 478 479
  Address* constant_pool_address() const {
    return state_.constant_pool_address;
  }

480
  // Get the id of this stack frame.
481
  Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
482

483 484 485
  // Get the top handler from the current stack iterator.
  inline StackHandler* top_handler() const;

486 487 488 489
  // Get the type of this frame.
  virtual Type type() const = 0;

  // Get the code associated with this frame.
490 491 492 493
  // This method could be called during marking phase of GC.
  virtual Code* unchecked_code() const = 0;

  // Get the code associated with this frame.
494
  inline Code* LookupCode() const;
495 496

  // Get the code object that contains the given pc.
497
  static inline Code* GetContainingCode(Isolate* isolate, Address pc);
498

499 500 501
  // Get the code object containing the given pc and fill in the
  // safepoint entry and the number of stack slots. The pc must be at
  // a safepoint.
502 503
  static Code* GetSafepointData(Isolate* isolate,
                                Address pc,
504
                                SafepointEntry* safepoint_entry,
505 506
                                unsigned* stack_slots);

507
  virtual void Iterate(ObjectVisitor* v) const = 0;
508 509
  static void IteratePc(ObjectVisitor* v, Address* pc_address,
                        Address* constant_pool_address, Code* holder);
510

511 512 513 514 515
  // Sets a callback function for return-address rewriting profilers
  // to resolve the location of a return address to the location of the
  // profiler's stashed return address.
  static void SetReturnAddressLocationResolver(
      ReturnAddressLocationResolver resolver);
516

517 518 519
  // Resolves pc_address through the resolution address function if one is set.
  static inline Address* ResolveReturnAddressLocation(Address* pc_address);

520 521 522 523 524 525
  // Printing support.
  enum PrintMode { OVERVIEW, DETAILS };
  virtual void Print(StringStream* accumulator,
                     PrintMode mode,
                     int index) const { }

526 527
  Isolate* isolate() const { return isolate_; }

528 529
  void operator=(const StackFrame& original) = delete;

530
 protected:
531
  inline explicit StackFrame(StackFrameIteratorBase* iterator);
532 533 534 535 536 537 538 539 540 541 542
  virtual ~StackFrame() { }

  // Compute the stack pointer for the calling frame.
  virtual Address GetCallerStackPointer() const = 0;

  // Printing support.
  static void PrintIndex(StringStream* accumulator,
                         PrintMode mode,
                         int index);

  // Compute the stack frame type for the given state.
543
  static Type ComputeType(const StackFrameIteratorBase* iterator, State* state);
544 545 546 547

#ifdef DEBUG
  bool can_access_heap_objects() const;
#endif
548 549

 private:
550
  const StackFrameIteratorBase* iterator_;
551
  Isolate* isolate_;
552
  State state_;
553

554 555
  static ReturnAddressLocationResolver return_address_location_resolver_;

556 557 558
  // Fill in the state of the calling frame.
  virtual void ComputeCallerState(State* state) const = 0;

559
  // Get the type and the state of the calling frame.
560
  virtual Type GetCallerState(State* state) const;
561

562 563
  static const intptr_t kIsolateTag = 1;

564
  friend class StackFrameIterator;
565
  friend class StackFrameIteratorBase;
566
  friend class StackHandlerIterator;
567
  friend class SafeStackFrameIterator;
568 569 570 571 572 573
};


// Entry frames are used to enter JavaScript execution from C.
class EntryFrame: public StackFrame {
 public:
574
  Type type() const override { return ENTRY; }
575

576
  Code* unchecked_code() const override;
577 578

  // Garbage collection support.
579
  void Iterate(ObjectVisitor* v) const override;
580 581

  static EntryFrame* cast(StackFrame* frame) {
582
    DCHECK(frame->is_entry());
583 584
    return static_cast<EntryFrame*>(frame);
  }
585
  void SetCallerFp(Address caller_fp) override;
586 587

 protected:
588
  inline explicit EntryFrame(StackFrameIteratorBase* iterator);
589 590 591 592

  // The caller stack pointer for entry frames is always zero. The
  // real information about the caller frame is available through the
  // link to the top exit frame.
593
  Address GetCallerStackPointer() const override { return 0; }
594 595

 private:
596 597
  void ComputeCallerState(State* state) const override;
  Type GetCallerState(State* state) const override;
598

599
  friend class StackFrameIteratorBase;
600 601 602 603 604
};


class EntryConstructFrame: public EntryFrame {
 public:
605
  Type type() const override { return ENTRY_CONSTRUCT; }
606

607
  Code* unchecked_code() const override;
608 609

  static EntryConstructFrame* cast(StackFrame* frame) {
610
    DCHECK(frame->is_entry_construct());
611 612 613 614
    return static_cast<EntryConstructFrame*>(frame);
  }

 protected:
615
  inline explicit EntryConstructFrame(StackFrameIteratorBase* iterator);
616 617

 private:
618
  friend class StackFrameIteratorBase;
619 620 621 622 623 624
};


// Exit frames are used to exit JavaScript execution and go to C.
class ExitFrame: public StackFrame {
 public:
625
  Type type() const override { return EXIT; }
626

627
  Code* unchecked_code() const override;
628

629 630
  Object*& code_slot() const;

631
  // Garbage collection support.
632
  void Iterate(ObjectVisitor* v) const override;
633

634
  void SetCallerFp(Address caller_fp) override;
635

636
  static ExitFrame* cast(StackFrame* frame) {
637
    DCHECK(frame->is_exit());
638 639 640 641 642 643 644
    return static_cast<ExitFrame*>(frame);
  }

  // Compute the state and type of an exit frame given a frame
  // pointer. Used when constructing the first stack frame seen by an
  // iterator and the frames following entry frames.
  static Type GetStateForFramePointer(Address fp, State* state);
645
  static Address ComputeStackPointer(Address fp);
646
  static StackFrame::Type ComputeFrameType(Address fp);
647
  static void FillState(Address fp, Address sp, State* state);
648 649

 protected:
650
  inline explicit ExitFrame(StackFrameIteratorBase* iterator);
651

652
  Address GetCallerStackPointer() const override;
653 654

 private:
655
  void ComputeCallerState(State* state) const override;
656

657
  friend class StackFrameIteratorBase;
658 659
};

660 661 662 663 664 665 666 667 668 669 670 671
// Builtin exit frames are a special case of exit frames, which are used
// whenever C++ builtins (e.g., Math.acos) are called. Their main purpose is
// to allow such builtins to appear in stack traces.
class BuiltinExitFrame : public ExitFrame {
 public:
  Type type() const override { return BUILTIN_EXIT; }

  static BuiltinExitFrame* cast(StackFrame* frame) {
    DCHECK(frame->is_builtin_exit());
    return static_cast<BuiltinExitFrame*>(frame);
  }

672 673 674 675
  JSFunction* function() const;
  Object* receiver() const;

  bool IsConstructor() const;
676

677 678 679
  void Print(StringStream* accumulator, PrintMode mode,
             int index) const override;

680 681 682 683
 protected:
  inline explicit BuiltinExitFrame(StackFrameIteratorBase* iterator);

 private:
684 685 686 687 688
  Object* GetParameter(int i) const;
  int ComputeParametersCount() const;

  inline Object* receiver_slot_object() const;
  inline Object* argc_slot_object() const;
689 690
  inline Object* target_slot_object() const;
  inline Object* new_target_slot_object() const;
691 692 693 694

  friend class StackFrameIteratorBase;
};

695 696
class JavaScriptFrame;

697 698
class FrameSummary BASE_EMBEDDED {
 public:
699 700
  // Mode for JavaScriptFrame::Summarize. Exact summary is required to produce
  // an exact stack trace. It will trigger an assertion failure if that is not
701 702 703 704 705
  // possible, e.g., because of missing deoptimization information. The
  // approximate mode should produce a summary even without deoptimization
  // information, but it might miss frames.
  enum Mode { kExactSummary, kApproximateSummary };

706 707
  FrameSummary(Object* receiver, JSFunction* function,
               AbstractCode* abstract_code, int code_offset,
708
               bool is_constructor, Mode mode = kExactSummary);
709

710 711
  static FrameSummary GetFirst(JavaScriptFrame* frame);

712 713 714 715 716
  Handle<Object> receiver() const { return receiver_; }
  Handle<JSFunction> function() const { return function_; }
  Handle<AbstractCode> abstract_code() const { return abstract_code_; }
  int code_offset() const { return code_offset_; }
  bool is_constructor() const { return is_constructor_; }
717 718 719 720 721 722 723 724 725 726

  void Print();

 private:
  Handle<Object> receiver_;
  Handle<JSFunction> function_;
  Handle<AbstractCode> abstract_code_;
  int code_offset_;
  bool is_constructor_;
};
727

728
class StandardFrame : public StackFrame {
729 730
 public:
  // Testers.
731
  bool is_standard() const override { return true; }
732 733

  // Accessors.
734 735 736
  virtual Object* receiver() const;
  virtual Script* script() const;
  virtual Object* context() const;
737
  virtual int position() const;
738 739 740 741 742 743

  // Access the expressions in the stack frame including locals.
  inline Object* GetExpression(int index) const;
  inline void SetExpression(int index, Object* value);
  int ComputeExpressionsCount() const;

744 745 746 747
  // Access the parameters.
  virtual Object* GetParameter(int index) const;
  virtual int ComputeParametersCount() const;

748
  void SetCallerFp(Address caller_fp) override;
749

750 751 752
  // Check if this frame is a constructor frame invoked through 'new'.
  virtual bool IsConstructor() const;

753
  static StandardFrame* cast(StackFrame* frame) {
754
    DCHECK(frame->is_standard());
755 756 757 758
    return static_cast<StandardFrame*>(frame);
  }

 protected:
759
  inline explicit StandardFrame(StackFrameIteratorBase* iterator);
760

761
  void ComputeCallerState(State* state) const override;
762 763 764 765 766 767 768 769 770

  // Accessors.
  inline Address caller_fp() const;
  inline Address caller_pc() const;

  // Computes the address of the PC field in the standard frame given
  // by the provided frame pointer.
  static inline Address ComputePCAddress(Address fp);

771 772 773 774
  // Computes the address of the constant pool  field in the standard
  // frame given by the provided frame pointer.
  static inline Address ComputeConstantPoolAddress(Address fp);

775 776 777 778 779
  // Iterate over expression stack including stack handlers, locals,
  // and parts of the fixed part including context and code fields.
  void IterateExpressions(ObjectVisitor* v) const;

  // Returns the address of the n'th expression stack element.
780
  virtual Address GetExpressionAddress(int n) const;
781 782 783 784 785

  // Determines if the standard frame for the given frame pointer is
  // an arguments adaptor frame.
  static inline bool IsArgumentsAdaptorFrame(Address fp);

786 787 788
  // Determines if the standard frame for the given frame pointer is a
  // construct frame.
  static inline bool IsConstructFrame(Address fp);
789

790 791 792
  // Used by OptimizedFrames and StubFrames.
  void IterateCompiledFrame(ObjectVisitor* v) const;

793 794
 private:
  friend class StackFrame;
795
  friend class SafeStackFrameIterator;
796 797
};

798
class JavaScriptFrame : public StandardFrame {
799
 public:
800
  Type type() const override { return JAVA_SCRIPT; }
801

802 803 804 805 806 807 808
  // Build a list with summaries for this frame including all inlined frames.
  virtual void Summarize(
      List<FrameSummary>* frames,
      FrameSummary::Mode mode = FrameSummary::kExactSummary) const;

  // Accessors.
  virtual JSFunction* function() const;
809 810 811
  Object* receiver() const override;
  Object* context() const override;
  Script* script() const override;
812

813 814 815
  inline void set_receiver(Object* value);

  // Access the parameters.
816
  inline Address GetParameterSlot(int index) const;
817 818
  Object* GetParameter(int index) const override;
  int ComputeParametersCount() const override;
819

820 821 822 823 824
  // Access the operand stack.
  inline Address GetOperandSlot(int index) const;
  inline Object* GetOperand(int index) const;
  inline int ComputeOperandsCount() const;

825 826
  // Generator support to preserve operand stack.
  void SaveOperandStack(FixedArray* store) const;
827

828 829 830
  // Debugger access.
  void SetParameterValue(int index, Object* value) const;

831
  // Check if this frame is a constructor frame invoked through 'new'.
832
  bool IsConstructor() const override;
833

834 835
  // Determines whether this frame includes inlined activations. To get details
  // about the inlined frames use {GetFunctions} and {Summarize}.
836
  bool HasInlinedFrames() const;
837

838 839 840 841
  // Check if this frame has "adapted" arguments in the sense that the
  // actual passed arguments are available in an arguments adaptor
  // frame below it on the stack.
  inline bool has_adapted_arguments() const;
842
  int GetArgumentsLength() const;
843

844
  // Garbage collection support.
845
  void Iterate(ObjectVisitor* v) const override;
846 847

  // Printing support.
848 849
  void Print(StringStream* accumulator, PrintMode mode,
             int index) const override;
850 851

  // Determine the code for the frame.
852
  Code* unchecked_code() const override;
853

854
  // Return a list with JSFunctions of this frame.
855
  virtual void GetFunctions(List<JSFunction*>* functions) const;
856

857
  // Lookup exception handler for current {pc}, returns -1 if none found. Also
858 859 860 861
  // returns data associated with the handler site specific to the frame type:
  //  - JavaScriptFrame : Data is the stack depth at entry of the try-block.
  //  - OptimizedFrame  : Data is the stack slot count of the entire frame.
  //  - InterpretedFrame: Data is the register index holding the context.
862
  virtual int LookupExceptionHandlerInTable(
863
      int* data, HandlerTable::CatchPrediction* prediction);
864

865 866 867
  // Architecture-specific register description.
  static Register fp_register();
  static Register context_register();
868
  static Register constant_pool_pointer_register();
869

870
  static JavaScriptFrame* cast(StackFrame* frame) {
871
    DCHECK(frame->is_java_script());
872 873 874
    return static_cast<JavaScriptFrame*>(frame);
  }

875 876
  static void PrintFunctionAndOffset(JSFunction* function, AbstractCode* code,
                                     int code_offset, FILE* file,
877 878 879
                                     bool print_line_number);

  static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
880
                       bool print_line_number);
881

882
 protected:
883
  inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator);
884

885
  Address GetCallerStackPointer() const override;
886

887 888
  virtual int GetNumberOfIncomingArguments() const;

889 890 891 892
  // Garbage collection support. Iterates over incoming arguments,
  // receiver, and any callee-saved registers.
  void IterateArguments(ObjectVisitor* v) const;

893 894
  virtual void PrintFrameKind(StringStream* accumulator) const {}

895
 private:
896 897
  inline Object* function_slot_object() const;

898
  friend class StackFrameIteratorBase;
899 900 901
};


902 903
class StubFrame : public StandardFrame {
 public:
904
  Type type() const override { return STUB; }
905 906

  // GC support.
907
  void Iterate(ObjectVisitor* v) const override;
908 909

  // Determine the code for the frame.
910
  Code* unchecked_code() const override;
911 912

 protected:
913
  inline explicit StubFrame(StackFrameIteratorBase* iterator);
914

915
  Address GetCallerStackPointer() const override;
916 917 918

  virtual int GetNumberOfIncomingArguments() const;

919
  friend class StackFrameIteratorBase;
920 921 922
};


923
class OptimizedFrame : public JavaScriptFrame {
924
 public:
925
  Type type() const override { return OPTIMIZED; }
926 927

  // GC support.
928
  void Iterate(ObjectVisitor* v) const override;
929 930 931 932

  // Return a list with JSFunctions of this frame.
  // The functions are ordered bottom-to-top (i.e. functions.last()
  // is the top-most activation)
933
  void GetFunctions(List<JSFunction*>* functions) const override;
934

935 936 937
  void Summarize(
      List<FrameSummary>* frames,
      FrameSummary::Mode mode = FrameSummary::kExactSummary) const override;
938

939
  // Lookup exception handler for current {pc}, returns -1 if none found.
940
  int LookupExceptionHandlerInTable(
941
      int* data, HandlerTable::CatchPrediction* prediction) override;
942

943
  DeoptimizationInputData* GetDeoptimizationData(int* deopt_index) const;
944

945 946
  static int StackSlotOffsetRelativeToFp(int slot_index);

947
 protected:
948
  inline explicit OptimizedFrame(StackFrameIteratorBase* iterator);
949 950

 private:
951
  friend class StackFrameIteratorBase;
952 953

  Object* StackSlotAt(int index) const;
954 955 956
};


957
class InterpretedFrame : public JavaScriptFrame {
958
 public:
959
  Type type() const override { return INTERPRETED; }
960

961 962 963
  // Accessors.
  int position() const override;

964
  // Lookup exception handler for current {pc}, returns -1 if none found.
965
  int LookupExceptionHandlerInTable(
966
      int* data, HandlerTable::CatchPrediction* prediction) override;
967 968 969 970 971 972 973 974

  // Returns the current offset into the bytecode stream.
  int GetBytecodeOffset() const;

  // Updates the current offset into the bytecode stream, mainly used for stack
  // unwinding to continue execution at a different bytecode offset.
  void PatchBytecodeOffset(int new_offset);

975
  // Returns the frame's current bytecode array.
976
  BytecodeArray* GetBytecodeArray() const;
977

978 979
  // Updates the frame's BytecodeArray with |bytecode_array|. Used by the
  // debugger to swap execution onto a BytecodeArray patched with breakpoints.
980
  void PatchBytecodeArray(BytecodeArray* bytecode_array);
981

982
  // Access to the interpreter register file for this frame.
983 984
  Object* ReadInterpreterRegister(int register_index) const;
  void WriteInterpreterRegister(int register_index, Object* value);
985

986
  // Build a list with summaries for this frame including all inlined frames.
987 988 989
  void Summarize(
      List<FrameSummary>* frames,
      FrameSummary::Mode mode = FrameSummary::kExactSummary) const override;
990

991 992
  static int GetBytecodeOffset(Address fp);

993 994 995
 protected:
  inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);

996 997
  Address GetExpressionAddress(int n) const override;

998 999 1000 1001 1002
 private:
  friend class StackFrameIteratorBase;
};


1003 1004 1005 1006 1007
// Arguments adaptor frames are automatically inserted below
// JavaScript frames when the actual number of parameters does not
// match the formal number of parameters.
class ArgumentsAdaptorFrame: public JavaScriptFrame {
 public:
1008
  Type type() const override { return ARGUMENTS_ADAPTOR; }
1009 1010

  // Determine the code for the frame.
1011
  Code* unchecked_code() const override;
1012 1013

  static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
1014
    DCHECK(frame->is_arguments_adaptor());
1015 1016 1017 1018
    return static_cast<ArgumentsAdaptorFrame*>(frame);
  }

  // Printing support.
1019 1020
  void Print(StringStream* accumulator, PrintMode mode,
             int index) const override;
1021

1022 1023
  static int GetLength(Address fp);

1024
 protected:
1025
  inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator);
1026

1027
  int GetNumberOfIncomingArguments() const override;
1028

1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047
 private:
  friend class StackFrameIteratorBase;
};

// Builtin frames are built for builtins with JavaScript linkage, such as
// various standard library functions (i.e. Math.asin, Math.floor, etc.).
class BuiltinFrame final : public JavaScriptFrame {
 public:
  Type type() const final { return BUILTIN; }

  static BuiltinFrame* cast(StackFrame* frame) {
    DCHECK(frame->is_builtin());
    return static_cast<BuiltinFrame*>(frame);
  }

 protected:
  inline explicit BuiltinFrame(StackFrameIteratorBase* iterator);

  int GetNumberOfIncomingArguments() const final;
1048
  void PrintFrameKind(StringStream* accumulator) const override;
1049 1050

 private:
1051
  friend class StackFrameIteratorBase;
1052 1053
};

1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
class WasmFrame : public StandardFrame {
 public:
  Type type() const override { return WASM; }

  // GC support.
  void Iterate(ObjectVisitor* v) const override;

  // Printing support.
  void Print(StringStream* accumulator, PrintMode mode,
             int index) const override;

1065 1066 1067 1068
  // Lookup exception handler for current {pc}, returns -1 if none found. Also
  // returns the stack slot count of the entire frame.
  int LookupExceptionHandlerInTable(int* data);

1069 1070 1071
  // Determine the code for the frame.
  Code* unchecked_code() const override;

1072 1073 1074 1075
  // Accessors.
  Object* wasm_obj() const;
  uint32_t function_index() const;
  Script* script() const override;
1076
  int position() const override;
1077

1078 1079 1080 1081 1082
  static WasmFrame* cast(StackFrame* frame) {
    DCHECK(frame->is_wasm());
    return static_cast<WasmFrame*>(frame);
  }

1083 1084 1085 1086 1087 1088 1089
 protected:
  inline explicit WasmFrame(StackFrameIteratorBase* iterator);

  Address GetCallerStackPointer() const override;

 private:
  friend class StackFrameIteratorBase;
1090 1091
};

1092
class WasmToJsFrame : public StubFrame {
1093 1094 1095 1096 1097 1098 1099 1100 1101 1102
 public:
  Type type() const override { return WASM_TO_JS; }

 protected:
  inline explicit WasmToJsFrame(StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};

1103
class JsToWasmFrame : public StubFrame {
1104 1105 1106 1107 1108 1109 1110 1111
 public:
  Type type() const override { return JS_TO_WASM; }

 protected:
  inline explicit JsToWasmFrame(StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
1112
};
1113 1114 1115

class InternalFrame: public StandardFrame {
 public:
1116
  Type type() const override { return INTERNAL; }
1117

1118
  // Garbage collection support.
1119
  void Iterate(ObjectVisitor* v) const override;
1120 1121

  // Determine the code for the frame.
1122
  Code* unchecked_code() const override;
1123 1124

  static InternalFrame* cast(StackFrame* frame) {
1125
    DCHECK(frame->is_internal());
1126 1127 1128 1129
    return static_cast<InternalFrame*>(frame);
  }

 protected:
1130
  inline explicit InternalFrame(StackFrameIteratorBase* iterator);
1131

1132
  Address GetCallerStackPointer() const override;
1133 1134

 private:
1135
  friend class StackFrameIteratorBase;
1136 1137 1138
};


1139
class StubFailureTrampolineFrame: public StandardFrame {
1140
 public:
1141
  Type type() const override { return STUB_FAILURE_TRAMPOLINE; }
1142

1143 1144
  // Get the code associated with this frame.
  // This method could be called during marking phase of GC.
1145
  Code* unchecked_code() const override;
1146

1147
  void Iterate(ObjectVisitor* v) const override;
1148

1149 1150 1151
  // Architecture-specific register description.
  static Register fp_register();
  static Register context_register();
1152
  static Register constant_pool_pointer_register();
1153

1154 1155
 protected:
  inline explicit StubFailureTrampolineFrame(
1156
      StackFrameIteratorBase* iterator);
1157

1158
  Address GetCallerStackPointer() const override;
1159

1160
 private:
1161
  friend class StackFrameIteratorBase;
1162 1163 1164
};


1165 1166 1167 1168
// Construct frames are special trampoline frames introduced to handle
// function invocations through 'new'.
class ConstructFrame: public InternalFrame {
 public:
1169
  Type type() const override { return CONSTRUCT; }
1170 1171

  static ConstructFrame* cast(StackFrame* frame) {
1172
    DCHECK(frame->is_construct());
1173 1174 1175 1176
    return static_cast<ConstructFrame*>(frame);
  }

 protected:
1177
  inline explicit ConstructFrame(StackFrameIteratorBase* iterator);
1178 1179

 private:
1180
  friend class StackFrameIteratorBase;
1181 1182 1183
};


1184
class StackFrameIteratorBase BASE_EMBEDDED {
1185
 public:
1186 1187
  Isolate* isolate() const { return isolate_; }

1188
  bool done() const { return frame_ == NULL; }
1189

1190 1191 1192
 protected:
  // An iterator that iterates over a given thread's stack.
  StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects);
1193

1194
  Isolate* isolate_;
1195 1196 1197 1198 1199
#define DECLARE_SINGLETON(ignore, type) type type##_;
  STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
#undef DECLARE_SINGLETON
  StackFrame* frame_;
  StackHandler* handler_;
1200
  const bool can_access_heap_objects_;
1201 1202

  StackHandler* handler() const {
1203
    DCHECK(!done());
1204 1205 1206 1207 1208
    return handler_;
  }

  // Get the type-specific frame singleton in a given state.
  StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
1209 1210 1211
  // A helper function, can return a NULL pointer.
  StackFrame* SingletonFor(StackFrame::Type type);

1212
 private:
1213
  friend class StackFrame;
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225
  DISALLOW_COPY_AND_ASSIGN(StackFrameIteratorBase);
};


class StackFrameIterator: public StackFrameIteratorBase {
 public:
  // An iterator that iterates over the isolate's current thread's stack,
  explicit StackFrameIterator(Isolate* isolate);
  // An iterator that iterates over a given thread's stack.
  StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);

  StackFrame* frame() const {
1226
    DCHECK(!done());
1227 1228 1229 1230 1231 1232 1233 1234
    return frame_;
  }
  void Advance();

 private:
  // Go back to the first frame.
  void Reset(ThreadLocalTop* top);

1235
  DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
1236 1237 1238
};

// Iterator that supports iterating through all JavaScript frames.
1239
class JavaScriptFrameIterator BASE_EMBEDDED {
1240
 public:
1241 1242
  inline explicit JavaScriptFrameIterator(Isolate* isolate);
  inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top);
1243
  // Skip frames until the frame with the given id is reached.
1244
  JavaScriptFrameIterator(Isolate* isolate, StackFrame::Id id);
1245

1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256
  inline JavaScriptFrame* frame() const;

  bool done() const { return iterator_.done(); }
  void Advance();

  // Advance to the frame holding the arguments for the current
  // frame. This only affects the current frame if it has adapted
  // arguments.
  void AdvanceToArgumentsFrame();

 private:
1257
  StackFrameIterator iterator_;
1258 1259
};

1260 1261 1262 1263
// NOTE: The stack trace frame iterator is an iterator that only traverse proper
// JavaScript frames that have proper JavaScript functions and WASM frames.
// This excludes the problematic functions in runtime.js.
class StackTraceFrameIterator BASE_EMBEDDED {
1264
 public:
1265
  explicit StackTraceFrameIterator(Isolate* isolate);
1266
  StackTraceFrameIterator(Isolate* isolate, StackFrame::Id id);
1267
  bool done() const { return iterator_.done(); }
1268
  void Advance();
1269

1270 1271 1272 1273 1274 1275 1276
  inline StandardFrame* frame() const;

  inline bool is_javascript() const;
  inline bool is_wasm() const;
  inline JavaScriptFrame* javascript_frame() const;
  inline WasmFrame* wasm_frame() const;

1277 1278 1279 1280 1281
  // Advance to the frame holding the arguments for the current
  // frame. This only affects the current frame if it is a javascript frame and
  // has adapted arguments.
  void AdvanceToArgumentsFrame();

1282
 private:
1283 1284
  StackFrameIterator iterator_;
  bool IsValidFrame(StackFrame* frame) const;
1285 1286 1287
};


1288
class SafeStackFrameIterator: public StackFrameIteratorBase {
1289
 public:
1290 1291
  SafeStackFrameIterator(Isolate* isolate,
                         Address fp, Address sp,
1292
                         Address js_entry_sp);
1293

1294
  inline StackFrame* frame() const;
1295 1296
  void Advance();

1297 1298
  StackFrame::Type top_frame_type() const { return top_frame_type_; }

1299
 private:
1300 1301
  void AdvanceOneFrame();

1302
  bool IsValidStackAddress(Address addr) const {
1303
    return low_bound_ <= addr && addr <= high_bound_;
1304
  }
1305 1306
  bool IsValidFrame(StackFrame* frame) const;
  bool IsValidCaller(StackFrame* frame);
1307 1308
  bool IsValidExitFrame(Address fp) const;
  bool IsValidTop(ThreadLocalTop* top) const;
1309

1310 1311
  const Address low_bound_;
  const Address high_bound_;
1312
  StackFrame::Type top_frame_type_;
1313
  ExternalCallbackScope* external_callback_scope_;
1314 1315 1316 1317 1318
};


class StackFrameLocator BASE_EMBEDDED {
 public:
1319 1320
  explicit StackFrameLocator(Isolate* isolate) : iterator_(isolate) {}

1321 1322 1323 1324 1325 1326 1327 1328 1329
  // Find the nth JavaScript frame on the stack. The caller must
  // guarantee that such a frame exists.
  JavaScriptFrame* FindJavaScriptFrame(int n);

 private:
  StackFrameIterator iterator_;
};


1330 1331
// Reads all frames on the current stack and copies them into the current
// zone memory.
1332
Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone);
1333

1334 1335
}  // namespace internal
}  // namespace v8
1336 1337

#endif  // V8_FRAMES_H_