frames.h 47.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
#ifndef V8_EXECUTION_FRAMES_H_
#define V8_EXECUTION_FRAMES_H_
7

8
#include "src/base/bounds.h"
9
#include "src/codegen/safepoint-table.h"
10
#include "src/common/globals.h"
11
#include "src/handles/handles.h"
12
#include "src/objects/code.h"
13
#include "src/objects/objects.h"
14

15 16 17
//
// Frame inheritance hierarchy (please keep in sync with frame-constants.h):
// - CommonFrame
18 19
//   - CommonFrameWithJSLinkage
//     - JavaScriptFrame (aka StandardFrame)
20 21 22
//       - UnoptimizedFrame
//         - InterpretedFrame
//         - BaselineFrame
23 24 25 26 27
//       - OptimizedFrame
//     - TypedFrameWithJSLinkage
//       - BuiltinFrame
//       - JavaScriptBuiltinContinuationFrame
//         - JavaScriptBuiltinContinuationWithCatchFrame
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
//   - TypedFrame
//     - NativeFrame
//     - EntryFrame
//       - ConstructEntryFrame
//     - ExitFrame
//       - BuiltinExitFrame
//     - StubFrame
//       - JsToWasmFrame
//       - CWasmEntryFrame
//     - Internal
//       - ConstructFrame
//       - BuiltinContinuationFrame
//     - WasmFrame
//       - WasmExitFrame
//     - WasmDebugBreakFrame
//     - WasmCompileLazyFrame
//

46 47
namespace v8 {
namespace internal {
48 49
namespace wasm {
class WasmCode;
50
}  // namespace wasm
51

52
// Forward declarations.
53
class AbstractCode;
54
class Debug;
55
class ExternalCallbackScope;
56
class InnerPointerToCodeCache;
57
class Isolate;
58
class ObjectVisitor;
59
class Register;
60
class RootVisitor;
61
class StackFrameIteratorBase;
62
class StringStream;
63
class ThreadLocalTop;
64
class WasmInstanceObject;
65
class WasmModuleObject;
66

67 68
class StackHandlerConstants : public AllStatic {
 public:
69 70
  static const int kNextOffset = 0 * kSystemPointerSize;
  static const int kPaddingOffset = 1 * kSystemPointerSize;
71

72 73
  static const int kSize = kPaddingOffset + kSystemPointerSize;
  static const int kSlotCount = kSize >> kSystemPointerSizeLog2;
74 75
};

76
class StackHandler {
77 78 79 80 81 82 83
 public:
  // Get the address of this stack handler.
  inline Address address() const;

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

84 85 86 87
  // Get the next stack handler, as an Address. This is safe to use even
  // when the next handler is null.
  inline Address next_address() const;

88 89 90 91
  // Conversion support.
  static inline StackHandler* FromAddress(Address address);

 private:
92
  DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
93 94
};

95 96
#define STACK_FRAME_TYPE_LIST(V)                                          \
  V(ENTRY, EntryFrame)                                                    \
97
  V(CONSTRUCT_ENTRY, ConstructEntryFrame)                                 \
98
  V(EXIT, ExitFrame)                                                      \
99 100 101 102 103 104 105
  IF_WASM(V, WASM, WasmFrame)                                             \
  IF_WASM(V, WASM_TO_JS, WasmToJsFrame)                                   \
  IF_WASM(V, JS_TO_WASM, JsToWasmFrame)                                   \
  IF_WASM(V, WASM_DEBUG_BREAK, WasmDebugBreakFrame)                       \
  IF_WASM(V, C_WASM_ENTRY, CWasmEntryFrame)                               \
  IF_WASM(V, WASM_EXIT, WasmExitFrame)                                    \
  IF_WASM(V, WASM_COMPILE_LAZY, WasmCompileLazyFrame)                     \
106
  V(INTERPRETED, InterpretedFrame)                                        \
107
  V(BASELINE, BaselineFrame)                                              \
108
  V(OPTIMIZED, OptimizedFrame)                                            \
109 110 111
  V(STUB, StubFrame)                                                      \
  V(BUILTIN_CONTINUATION, BuiltinContinuationFrame)                       \
  V(JAVA_SCRIPT_BUILTIN_CONTINUATION, JavaScriptBuiltinContinuationFrame) \
112 113
  V(JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH,                          \
    JavaScriptBuiltinContinuationWithCatchFrame)                          \
114 115 116
  V(INTERNAL, InternalFrame)                                              \
  V(CONSTRUCT, ConstructFrame)                                            \
  V(BUILTIN, BuiltinFrame)                                                \
117 118
  V(BUILTIN_EXIT, BuiltinExitFrame)                                       \
  V(NATIVE, NativeFrame)
119 120

// Abstract base class for all stack frames.
121
class StackFrame {
122 123 124 125
 public:
#define DECLARE_TYPE(type, ignore) type,
  enum Type {
    NONE = 0,
126
    STACK_FRAME_TYPE_LIST(DECLARE_TYPE) NUMBER_OF_TYPES,
127 128 129
    // Used by FrameScope to indicate that the stack frame is constructed
    // manually and the FrameScope does not need to emit code.
    MANUAL
130 131 132
  };
#undef DECLARE_TYPE

133
  // Used to mark the outermost JS entry frame.
134 135 136
  //
  // The mark is an opaque value that should be pushed onto the stack directly,
  // carefully crafted to not be interpreted as a tagged pointer.
137
  enum JsFrameMarker {
138 139
    INNER_JSENTRY_FRAME = (0 << kSmiTagSize) | kSmiTag,
    OUTERMOST_JSENTRY_FRAME = (1 << kSmiTagSize) | kSmiTag
140
  };
141 142 143
  STATIC_ASSERT((INNER_JSENTRY_FRAME & kHeapObjectTagMask) != kHeapObjectTag);
  STATIC_ASSERT((OUTERMOST_JSENTRY_FRAME & kHeapObjectTagMask) !=
                kHeapObjectTag);
144

145
  struct State {
146 147
    Address sp = kNullAddress;
    Address fp = kNullAddress;
148
    Address* pc_address = nullptr;
149
    Address callee_fp = kNullAddress;
150 151
    Address* callee_pc_address = nullptr;
    Address* constant_pool_address = nullptr;
152 153
  };

154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
  // Convert a stack frame type to a marker that can be stored on the stack.
  //
  // The marker is an opaque value, not intended to be interpreted in any way
  // except being checked by IsTypeMarker or converted by MarkerToType.
  // It has the same tagging as Smis, so any marker value that does not pass
  // IsTypeMarker can instead be interpreted as a tagged pointer.
  //
  // Note that the marker is not a Smi: Smis on 64-bit architectures are stored
  // in the top 32 bits of a 64-bit value, which in turn makes them expensive
  // (in terms of code/instruction size) to push as immediates onto the stack.
  static int32_t TypeToMarker(Type type) {
    DCHECK_GE(type, 0);
    return (type << kSmiTagSize) | kSmiTag;
  }

  // Convert a marker back to a stack frame type.
  //
  // Unlike the return value of TypeToMarker, this takes an intptr_t, as that is
  // the type of the value on the stack.
  static Type MarkerToType(intptr_t marker) {
    DCHECK(IsTypeMarker(marker));
175
    intptr_t type = marker >> kSmiTagSize;
176
    // TODO(petermarshall): There is a bug in the arm simulators that causes
177
    // invalid frame markers.
178 179 180 181 182 183
#if defined(USE_SIMULATOR) && (V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_ARM)
    if (static_cast<uintptr_t>(type) >= Type::NUMBER_OF_TYPES) {
      // Appease UBSan.
      return Type::NUMBER_OF_TYPES;
    }
#else
184 185 186
    DCHECK_LT(static_cast<uintptr_t>(type), Type::NUMBER_OF_TYPES);
#endif
    return static_cast<Type>(type);
187 188 189 190 191 192 193 194
  }

  // Check if a marker is a stack frame type marker or a tagged pointer.
  //
  // Returns true if the given marker is tagged as a stack frame type marker,
  // and should be converted back to a stack frame type using MarkerToType.
  // Otherwise, the value is a tagged function pointer.
  static bool IsTypeMarker(intptr_t function_or_marker) {
195
    return (function_or_marker & kSmiTagMask) == kSmiTag;
196 197
  }

198 199
  // Copy constructor; it breaks the connection to host iterator
  // (as an iterator usually lives on stack).
200
  StackFrame(const StackFrame& original) V8_NOEXCEPT {
201
    this->state_ = original.state_;
202
    this->iterator_ = nullptr;
203
    this->isolate_ = original.isolate_;
204 205
  }

206 207
  // Type testers.
  bool is_entry() const { return type() == ENTRY; }
208
  bool is_construct_entry() const { return type() == CONSTRUCT_ENTRY; }
209
  bool is_exit() const { return type() == EXIT; }
210
  bool is_optimized() const { return type() == OPTIMIZED; }
211 212 213
  bool is_unoptimized() const {
    STATIC_ASSERT(BASELINE == INTERPRETED + 1);
    return base::IsInRange(type(), INTERPRETED, BASELINE);
214
  }
215
  bool is_interpreted() const { return type() == INTERPRETED; }
216
  bool is_baseline() const { return type() == BASELINE; }
217
#if V8_ENABLE_WEBASSEMBLY
218
  bool is_wasm() const { return this->type() == WASM; }
219
  bool is_c_wasm_entry() const { return type() == C_WASM_ENTRY; }
220
  bool is_wasm_compile_lazy() const { return type() == WASM_COMPILE_LAZY; }
221
  bool is_wasm_debug_break() const { return type() == WASM_DEBUG_BREAK; }
222 223 224
  bool is_wasm_to_js() const { return type() == WASM_TO_JS; }
  bool is_js_to_wasm() const { return type() == JS_TO_WASM; }
#endif  // V8_ENABLE_WEBASSEMBLY
225
  bool is_builtin() const { return type() == BUILTIN; }
226
  bool is_internal() const { return type() == INTERNAL; }
227 228 229 230 231 232
  bool is_builtin_continuation() const {
    return type() == BUILTIN_CONTINUATION;
  }
  bool is_java_script_builtin_continuation() const {
    return type() == JAVA_SCRIPT_BUILTIN_CONTINUATION;
  }
233 234 235
  bool is_java_script_builtin_with_catch_continuation() const {
    return type() == JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
  }
236
  bool is_construct() const { return type() == CONSTRUCT; }
237
  bool is_builtin_exit() const { return type() == BUILTIN_EXIT; }
238

239
  static bool IsJavaScript(Type t) {
240 241
    STATIC_ASSERT(INTERPRETED + 1 == BASELINE);
    STATIC_ASSERT(BASELINE + 1 == OPTIMIZED);
242
    return t >= INTERPRETED && t <= OPTIMIZED;
243
  }
244
  bool is_java_script() const { return IsJavaScript(type()); }
245

246 247 248
  // Accessors.
  Address sp() const { return state_.sp; }
  Address fp() const { return state_.fp; }
249
  Address callee_fp() const { return state_.callee_fp; }
250
  inline Address callee_pc() const;
251
  Address caller_sp() const { return GetCallerStackPointer(); }
252
  inline Address pc() const;
253

254 255 256 257 258
  // Skip authentication of the PC, when using CFI. Used in the profiler, where
  // in certain corner-cases we do not use an address on the stack, which would
  // be signed, as the PC of the frame.
  inline Address unauthenticated_pc() const;

259
  Address constant_pool() const { return *constant_pool_address(); }
260 261
  void set_constant_pool(Address constant_pool) {
    *constant_pool_address() = constant_pool;
262 263
  }

264 265
  Address* pc_address() const { return state_.pc_address; }

266 267 268 269
  Address* constant_pool_address() const {
    return state_.constant_pool_address;
  }

270
  // Get the id of this stack frame.
271
  StackFrameId id() const { return static_cast<StackFrameId>(caller_sp()); }
272

273 274 275
  // Get the top handler from the current stack iterator.
  inline StackHandler* top_handler() const;

276 277 278 279
  // Get the type of this frame.
  virtual Type type() const = 0;

  // Get the code associated with this frame.
280
  // This method could be called during marking phase of GC.
281
  virtual Code unchecked_code() const = 0;
282

283
  // Search for the code associated with this frame.
284
  V8_EXPORT_PRIVATE Code LookupCode() const;
285

286
  virtual void Iterate(RootVisitor* v) const = 0;
287 288
  void IteratePc(RootVisitor* v, Address* pc_address,
                 Address* constant_pool_address, Code holder) const;
289

290 291 292 293 294
  // 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);
295

296 297
  static inline Address ReadPC(Address* pc_address);

298 299 300
  // Resolves pc_address through the resolution address function if one is set.
  static inline Address* ResolveReturnAddressLocation(Address* pc_address);

301 302
  // Printing support.
  enum PrintMode { OVERVIEW, DETAILS };
303 304
  virtual void Print(StringStream* accumulator, PrintMode mode,
                     int index) const;
305

306 307
  Isolate* isolate() const { return isolate_; }

308 309
  void operator=(const StackFrame& original) = delete;

310
 protected:
311
  inline explicit StackFrame(StackFrameIteratorBase* iterator);
312
  virtual ~StackFrame() = default;
313 314 315 316 317

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

  // Compute the stack frame type for the given state.
318
  static Type ComputeType(const StackFrameIteratorBase* iterator, State* state);
319 320 321 322

#ifdef DEBUG
  bool can_access_heap_objects() const;
#endif
323 324

 private:
325
  const StackFrameIteratorBase* iterator_;
326
  Isolate* isolate_;
327
  State state_;
328

329 330
  static ReturnAddressLocationResolver return_address_location_resolver_;

331 332 333
  // Fill in the state of the calling frame.
  virtual void ComputeCallerState(State* state) const = 0;

334
  // Get the type and the state of the calling frame.
335
  virtual Type GetCallerState(State* state) const;
336

337 338
  static const intptr_t kIsolateTag = 1;

339
  friend class StackFrameIterator;
340
  friend class StackFrameIteratorBase;
341
  friend class StackHandlerIterator;
342
  friend class SafeStackFrameIterator;
343 344
};

345
class CommonFrame;
346

347
class V8_EXPORT_PRIVATE FrameSummary {
348
 public:
349
// Subclasses for the different summary kinds:
350 351
#define FRAME_SUMMARY_VARIANTS(F)                                          \
  F(JAVA_SCRIPT, JavaScriptFrameSummary, java_script_summary_, JavaScript) \
352
  IF_WASM(F, WASM, WasmFrameSummary, wasm_summary_, Wasm)
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371

#define FRAME_SUMMARY_KIND(kind, type, field, desc) kind,
  enum Kind { FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_KIND) };
#undef FRAME_SUMMARY_KIND

  class FrameSummaryBase {
   public:
    FrameSummaryBase(Isolate* isolate, Kind kind)
        : isolate_(isolate), kind_(kind) {}
    Isolate* isolate() const { return isolate_; }
    Kind kind() const { return kind_; }

   private:
    Isolate* isolate_;
    Kind kind_;
  };

  class JavaScriptFrameSummary : public FrameSummaryBase {
   public:
372
    JavaScriptFrameSummary(Isolate* isolate, Object receiver,
373
                           JSFunction function, AbstractCode abstract_code,
374 375
                           int code_offset, bool is_constructor,
                           FixedArray parameters);
376

377
    void EnsureSourcePositionsAvailable();
378
    bool AreSourcePositionsAvailable() const;
379

380 381 382 383 384
    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_; }
385
    Handle<FixedArray> parameters() const { return parameters_; }
386 387 388 389 390 391 392 393 394 395 396 397
    bool is_subject_to_debugging() const;
    int SourcePosition() const;
    int SourceStatementPosition() const;
    Handle<Object> script() const;
    Handle<Context> native_context() const;

   private:
    Handle<Object> receiver_;
    Handle<JSFunction> function_;
    Handle<AbstractCode> abstract_code_;
    int code_offset_;
    bool is_constructor_;
398
    Handle<FixedArray> parameters_;
399 400
  };

401
#if V8_ENABLE_WEBASSEMBLY
402 403
  class WasmFrameSummary : public FrameSummaryBase {
   public:
404 405 406
    WasmFrameSummary(Isolate*, Handle<WasmInstanceObject>, wasm::WasmCode*,
                     int code_offset, bool at_to_number_conversion);

407 408
    Handle<Object> receiver() const;
    uint32_t function_index() const;
409 410 411
    wasm::WasmCode* code() const { return code_; }
    int code_offset() const { return code_offset_; }
    V8_EXPORT_PRIVATE int byte_offset() const;
412 413 414 415 416 417 418 419 420 421 422 423
    bool is_constructor() const { return false; }
    bool is_subject_to_debugging() const { return true; }
    int SourcePosition() const;
    int SourceStatementPosition() const { return SourcePosition(); }
    Handle<Script> script() const;
    Handle<WasmInstanceObject> wasm_instance() const { return wasm_instance_; }
    Handle<Context> native_context() const;
    bool at_to_number_conversion() const { return at_to_number_conversion_; }

   private:
    Handle<WasmInstanceObject> wasm_instance_;
    bool at_to_number_conversion_;
424
    wasm::WasmCode* const code_;
425 426
    int code_offset_;
  };
427
#endif  // V8_ENABLE_WEBASSEMBLY
428

429 430 431 432
#define FRAME_SUMMARY_CONS(kind, type, field, desc) \
  FrameSummary(type summ) : field(summ) {}  // NOLINT
  FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CONS)
#undef FRAME_SUMMARY_CONS
433

434
  ~FrameSummary();
435

436 437 438 439
  static FrameSummary GetTop(const CommonFrame* frame);
  static FrameSummary GetBottom(const CommonFrame* frame);
  static FrameSummary GetSingle(const CommonFrame* frame);
  static FrameSummary Get(const CommonFrame* frame, int index);
440

441
  void EnsureSourcePositionsAvailable();
442
  bool AreSourcePositionsAvailable() const;
443

444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
  // Dispatched accessors.
  Handle<Object> receiver() const;
  int code_offset() const;
  bool is_constructor() const;
  bool is_subject_to_debugging() const;
  Handle<Object> script() const;
  int SourcePosition() const;
  int SourceStatementPosition() const;
  Handle<Context> native_context() const;

#define FRAME_SUMMARY_CAST(kind_, type, field, desc)      \
  bool Is##desc() const { return base_.kind() == kind_; } \
  const type& As##desc() const {                          \
    DCHECK_EQ(base_.kind(), kind_);                       \
    return field;                                         \
  }
  FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CAST)
#undef FRAME_SUMMARY_CAST

463
 private:
464 465 466 467 468
#define FRAME_SUMMARY_FIELD(kind, type, field, desc) type field;
  union {
    FrameSummaryBase base_;
    FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_FIELD)
  };
469
#undef FRAME_SUMMARY_FIELD
470
};
471

472
class CommonFrame : public StackFrame {
473 474
 public:
  // Accessors.
475 476
  virtual Object context()
      const;  // TODO(victorgomes): CommonFrames don't have context.
477
  virtual int position() const;
478 479

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

484 485
  Address GetCallerStackPointer() const override;

486
  // Build a list with summaries for this frame including all inlined frames.
487 488
  // The functions are ordered bottom-to-top (i.e. summaries.last() is the
  // top-most activation; caller comes before callee).
489
  virtual void Summarize(std::vector<FrameSummary>* frames) const;
490

491 492 493
  static CommonFrame* cast(StackFrame* frame) {
    // It is always safe to cast to common.
    return static_cast<CommonFrame*>(frame);
494 495 496
  }

 protected:
497
  inline explicit CommonFrame(StackFrameIteratorBase* iterator);
498

499
  void ComputeCallerState(State* state) const override;
500 501 502 503 504 505 506 507 508

  // 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);

509 510 511 512
  // Computes the address of the constant pool  field in the standard
  // frame given by the provided frame pointer.
  static inline Address ComputeConstantPoolAddress(Address fp);

513 514
  // Iterate over expression stack including stack handlers, locals,
  // and parts of the fixed part including context and code fields.
515
  void IterateExpressions(RootVisitor* v) const;
516 517

  // Returns the address of the n'th expression stack element.
518
  virtual Address GetExpressionAddress(int n) const;
519

520
  // Used by OptimizedFrames and StubFrames.
521
  void IterateCompiledFrame(RootVisitor* v) const;
522

523 524
 private:
  friend class StackFrame;
525
  friend class SafeStackFrameIterator;
526 527
};

528 529
class TypedFrame : public CommonFrame {
 public:
530
  Code unchecked_code() const override { return {}; }
531 532 533 534 535 536
  void Iterate(RootVisitor* v) const override { IterateCompiledFrame(v); }

 protected:
  inline explicit TypedFrame(StackFrameIteratorBase* iterator);
};

537
class CommonFrameWithJSLinkage : public CommonFrame {
538
 public:
539 540 541 542 543 544 545 546 547 548 549 550
  // Accessors.
  virtual JSFunction function() const = 0;

  // Access the parameters.
  virtual Object receiver() const;
  virtual Object GetParameter(int index) const;
  virtual int ComputeParametersCount() const;
  Handle<FixedArray> GetParameters() const;
  virtual int GetActualArgumentCount() const;

  // Determine the code for the frame.
  Code unchecked_code() const override;
551

552 553 554
  // Lookup exception handler for current {pc}, returns -1 if none found. Also
  // returns data associated with the handler site specific to the frame type:
  //  - OptimizedFrame  : Data is not used and will not return a value.
555
  //  - UnoptimizedFrame: Data is the register index holding the context.
556 557 558 559 560 561 562
  virtual int LookupExceptionHandlerInTable(
      int* data, HandlerTable::CatchPrediction* prediction);

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

  // Summarize Frame
563
  void Summarize(std::vector<FrameSummary>* frames) const override;
564

565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
 protected:
  inline explicit CommonFrameWithJSLinkage(StackFrameIteratorBase* iterator);

  // Determines if the standard frame for the given frame pointer is a
  // construct frame.
  static inline bool IsConstructFrame(Address fp);
  inline Address GetParameterSlot(int index) const;
};

class TypedFrameWithJSLinkage : public CommonFrameWithJSLinkage {
 public:
  void Iterate(RootVisitor* v) const override;

 protected:
  inline explicit TypedFrameWithJSLinkage(StackFrameIteratorBase* iterator);
};

class JavaScriptFrame : public CommonFrameWithJSLinkage {
 public:
  Type type() const override = 0;

586
  // Accessors.
587
  JSFunction function() const override;
588
  Object unchecked_function() const;
589
  Script script() const;
590 591 592 593
  Object context() const override;
  int GetActualArgumentCount() const override;

  inline void set_receiver(Object value);
594

595
  // Debugger access.
596
  void SetParameterValue(int index, Object value) const;
597

598
  // Check if this frame is a constructor frame invoked through 'new'.
599
  bool IsConstructor() const override;
600

601 602
  // Determines whether this frame includes inlined activations. To get details
  // about the inlined frames use {GetFunctions} and {Summarize}.
603
  bool HasInlinedFrames() const;
604

605
  // Garbage collection support.
606
  void Iterate(RootVisitor* v) const override;
607 608

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

612
  // Return a list with {SharedFunctionInfo} objects of this frame.
613
  virtual void GetFunctions(std::vector<SharedFunctionInfo>* functions) const;
614

615
  void GetFunctions(std::vector<Handle<SharedFunctionInfo>>* functions) const;
616

617 618 619
  // Architecture-specific register description.
  static Register fp_register();
  static Register context_register();
620
  static Register constant_pool_pointer_register();
621

622
  static JavaScriptFrame* cast(StackFrame* frame) {
623
    DCHECK(frame->is_java_script());
624 625 626
    return static_cast<JavaScriptFrame*>(frame);
  }

627
  static void PrintFunctionAndOffset(JSFunction function, AbstractCode code,
628
                                     int code_offset, FILE* file,
629 630 631
                                     bool print_line_number);

  static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
632
                       bool print_line_number);
633

634
  static void CollectFunctionAndOffsetForICStats(JSFunction function,
635
                                                 AbstractCode code,
636 637
                                                 int code_offset);

638
 protected:
639
  inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator);
640

641
  Address GetCallerStackPointer() const override;
642

643 644
  virtual void PrintFrameKind(StringStream* accumulator) const {}

645
 private:
646
  inline Object function_slot_object() const;
647

648
  friend class StackFrameIteratorBase;
649 650
};

651
class NativeFrame : public TypedFrame {
652
 public:
653
  Type type() const override { return NATIVE; }
654

655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720
  // Garbage collection support.
  void Iterate(RootVisitor* v) const override {}

 protected:
  inline explicit NativeFrame(StackFrameIteratorBase* iterator);

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

  friend class StackFrameIteratorBase;
};

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

  Code unchecked_code() const override;

  // Garbage collection support.
  void Iterate(RootVisitor* v) const override;

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

 protected:
  inline explicit EntryFrame(StackFrameIteratorBase* iterator);

  // 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.
  Address GetCallerStackPointer() const override { return 0; }

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

  friend class StackFrameIteratorBase;
};

class ConstructEntryFrame : public EntryFrame {
 public:
  Type type() const override { return CONSTRUCT_ENTRY; }

  Code unchecked_code() const override;

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

 protected:
  inline explicit ConstructEntryFrame(StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};

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

  // Garbage collection support.
721
  void Iterate(RootVisitor* v) const override;
722

723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758
  static ExitFrame* cast(StackFrame* frame) {
    DCHECK(frame->is_exit());
    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);
  static Address ComputeStackPointer(Address fp);
  static StackFrame::Type ComputeFrameType(Address fp);
  static void FillState(Address fp, Address sp, State* state);

 protected:
  inline explicit ExitFrame(StackFrameIteratorBase* iterator);

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

  friend class StackFrameIteratorBase;
};

// 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);
  }

  JSFunction function() const;
  Object receiver() const;
759
  bool IsConstructor() const;
760 761 762 763 764 765 766 767

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

 protected:
  inline explicit BuiltinExitFrame(StackFrameIteratorBase* iterator);

 private:
768 769
  Object GetParameter(int i) const;
  int ComputeParametersCount() const;
770 771 772 773 774 775 776

  inline Object receiver_slot_object() const;
  inline Object argc_slot_object() const;
  inline Object target_slot_object() const;
  inline Object new_target_slot_object() const;

  friend class StackFrameIteratorBase;
777
  friend class StackTraceBuilder;
778 779 780 781 782 783
};

class StubFrame : public TypedFrame {
 public:
  Type type() const override { return STUB; }

784
  // Determine the code for the frame.
785
  Code unchecked_code() const override;
786

787
  // Lookup exception handler for current {pc}, returns -1 if none found. Only
788 789
  // TurboFan stub frames are supported.
  int LookupExceptionHandlerInTable();
790

791
 protected:
792
  inline explicit StubFrame(StackFrameIteratorBase* iterator);
793

794
 private:
795
  friend class StackFrameIteratorBase;
796 797
};

798
class OptimizedFrame : public JavaScriptFrame {
799
 public:
800
  Type type() const override { return OPTIMIZED; }
801 802

  // GC support.
803
  void Iterate(RootVisitor* v) const override;
804

805
  // Return a list with {SharedFunctionInfo} objects of this frame.
806 807
  // The functions are ordered bottom-to-top (i.e. functions.last()
  // is the top-most activation)
808
  void GetFunctions(std::vector<SharedFunctionInfo>* functions) const override;
809

810
  void Summarize(std::vector<FrameSummary>* frames) const override;
811

812
  // Lookup exception handler for current {pc}, returns -1 if none found.
813
  int LookupExceptionHandlerInTable(
814
      int* data, HandlerTable::CatchPrediction* prediction) override;
815

816
  DeoptimizationData GetDeoptimizationData(int* deopt_index) const;
817

818
  int ComputeParametersCount() const override;
819

820 821
  static int StackSlotOffsetRelativeToFp(int slot_index);

822
 protected:
823
  inline explicit OptimizedFrame(StackFrameIteratorBase* iterator);
824 825

 private:
826
  friend class StackFrameIteratorBase;
827

828
  Object StackSlotAt(int index) const;
829 830
};

831 832 833 834
// An unoptimized frame is a JavaScript frame that is executing bytecode. It
// may be executing it using the interpreter, or via baseline code compiled from
// the bytecode.
class UnoptimizedFrame : public JavaScriptFrame {
835
 public:
836 837 838
  // Accessors.
  int position() const override;

839
  // Lookup exception handler for current {pc}, returns -1 if none found.
840
  int LookupExceptionHandlerInTable(
841
      int* data, HandlerTable::CatchPrediction* prediction) override;
842 843

  // Returns the current offset into the bytecode stream.
844
  virtual int GetBytecodeOffset() const = 0;
845

846
  // Returns the frame's current bytecode array.
847
  BytecodeArray GetBytecodeArray() const;
848

849
  // Access to the interpreter register file for this frame.
850
  Object ReadInterpreterRegister(int register_index) const;
851

852
  // Build a list with summaries for this frame including all inlined frames.
853
  void Summarize(std::vector<FrameSummary>* frames) const override;
854

855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882
  static UnoptimizedFrame* cast(StackFrame* frame) {
    DCHECK(frame->is_unoptimized());
    return static_cast<UnoptimizedFrame*>(frame);
  }

 protected:
  inline explicit UnoptimizedFrame(StackFrameIteratorBase* iterator);

  Address GetExpressionAddress(int n) const override;

 private:
  friend class StackFrameIteratorBase;
};

class InterpretedFrame : public UnoptimizedFrame {
 public:
  Type type() const override { return INTERPRETED; }

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

  // 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);

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

884 885 886 887
  static InterpretedFrame* cast(StackFrame* frame) {
    DCHECK(frame->is_interpreted());
    return static_cast<InterpretedFrame*>(frame);
  }
888 889 890 891 892 893
  static const InterpretedFrame* cast(const StackFrame* frame) {
    DCHECK(frame->is_interpreted());
    return static_cast<const InterpretedFrame*>(frame);
  }

  static int GetBytecodeOffset(Address fp);
894

895 896 897 898 899 900 901
 protected:
  inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};

902
class BaselineFrame : public UnoptimizedFrame {
903
 public:
904
  Type type() const override { return BASELINE; }
905 906 907 908 909 910

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

  intptr_t GetPCForBytecodeOffset(int lookup_offset) const;

911 912
  void PatchContext(Context value);

913 914 915
  static BaselineFrame* cast(StackFrame* frame) {
    DCHECK(frame->is_baseline());
    return static_cast<BaselineFrame*>(frame);
916 917 918
  }

 protected:
919
  inline explicit BaselineFrame(StackFrameIteratorBase* iterator);
920 921 922 923 924

 private:
  friend class StackFrameIteratorBase;
};

925 926
// Builtin frames are built for builtins with JavaScript linkage, such as
// various standard library functions (i.e. Math.asin, Math.floor, etc.).
927
class BuiltinFrame final : public TypedFrameWithJSLinkage {
928 929 930 931 932 933 934
 public:
  Type type() const final { return BUILTIN; }

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

  JSFunction function() const override;
  int ComputeParametersCount() const override;
938 939 940 941

 protected:
  inline explicit BuiltinFrame(StackFrameIteratorBase* iterator);

942
 private:
943
  friend class StackFrameIteratorBase;
944 945
};

946
#if V8_ENABLE_WEBASSEMBLY
947
class WasmFrame : public TypedFrame {
948
 public:
949
  Type type() const override { return WASM; }
950 951 952 953 954

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

955 956
  // Lookup exception handler for current {pc}, returns -1 if none found.
  int LookupExceptionHandlerInTable();
957

958
  // Accessors.
959
  V8_EXPORT_PRIVATE WasmInstanceObject wasm_instance() const;
960
  V8_EXPORT_PRIVATE wasm::NativeModule* native_module() const;
961
  wasm::WasmCode* wasm_code() const;
962
  int function_index() const;
963
  Script script() const;
964
  // Byte position in the module, or asm.js source position.
965
  int position() const override;
966
  Object context() const override;
967
  bool at_to_number_conversion() const;
968 969
  // Byte offset in the function.
  int byte_offset() const;
970
  bool is_inspectable() const;
971

972
  void Summarize(std::vector<FrameSummary>* frames) const override;
973

974 975 976
  static WasmFrame* cast(StackFrame* frame) {
    DCHECK(frame->is_wasm());
    return static_cast<WasmFrame*>(frame);
977 978 979
  }

 protected:
980
  inline explicit WasmFrame(StackFrameIteratorBase* iterator);
981 982 983

 private:
  friend class StackFrameIteratorBase;
984
  WasmModuleObject module_object() const;
985 986
};

987
class WasmExitFrame : public WasmFrame {
988 989 990 991 992 993 994 995 996 997 998
 public:
  Type type() const override { return WASM_EXIT; }
  static Address ComputeStackPointer(Address fp);

 protected:
  inline explicit WasmExitFrame(StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};

999
class WasmDebugBreakFrame final : public TypedFrame {
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
 public:
  Type type() const override { return WASM_DEBUG_BREAK; }

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

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

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

 protected:
  inline explicit WasmDebugBreakFrame(StackFrameIteratorBase*);

 private:
  friend class StackFrameIteratorBase;
};

1021
class WasmToJsFrame : public StubFrame {
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031
 public:
  Type type() const override { return WASM_TO_JS; }

 protected:
  inline explicit WasmToJsFrame(StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};

1032
class JsToWasmFrame : public StubFrame {
1033 1034 1035
 public:
  Type type() const override { return JS_TO_WASM; }

1036 1037
  void Iterate(RootVisitor* v) const override;

1038 1039
 protected:
  inline explicit JsToWasmFrame(StackFrameIteratorBase* iterator);
1040 1041 1042 1043 1044

 private:
  friend class StackFrameIteratorBase;
};

1045 1046 1047 1048 1049 1050 1051 1052 1053
class CWasmEntryFrame : public StubFrame {
 public:
  Type type() const override { return C_WASM_ENTRY; }

 protected:
  inline explicit CWasmEntryFrame(StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
1054
  Type GetCallerState(State* state) const override;
1055 1056
};

1057
class WasmCompileLazyFrame : public TypedFrame {
1058 1059 1060
 public:
  Type type() const override { return WASM_COMPILE_LAZY; }

1061
  WasmInstanceObject wasm_instance() const;
1062
  FullObjectSlot wasm_instance_slot() const;
1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077

  // Garbage collection support.
  void Iterate(RootVisitor* v) const override;

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

 protected:
  inline explicit WasmCompileLazyFrame(StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};
1078
#endif  // V8_ENABLE_WEBASSEMBLY
1079

1080
class InternalFrame : public TypedFrame {
1081
 public:
1082
  Type type() const override { return INTERNAL; }
1083

1084
  // Garbage collection support.
1085
  void Iterate(RootVisitor* v) const override;
1086 1087

  static InternalFrame* cast(StackFrame* frame) {
1088
    DCHECK(frame->is_internal());
1089 1090 1091 1092
    return static_cast<InternalFrame*>(frame);
  }

 protected:
1093
  inline explicit InternalFrame(StackFrameIteratorBase* iterator);
1094 1095

 private:
1096
  friend class StackFrameIteratorBase;
1097 1098
};

1099 1100
// Construct frames are special trampoline frames introduced to handle
// function invocations through 'new'.
1101
class ConstructFrame : public InternalFrame {
1102
 public:
1103
  Type type() const override { return CONSTRUCT; }
1104 1105

  static ConstructFrame* cast(StackFrame* frame) {
1106
    DCHECK(frame->is_construct());
1107 1108 1109 1110
    return static_cast<ConstructFrame*>(frame);
  }

 protected:
1111
  inline explicit ConstructFrame(StackFrameIteratorBase* iterator);
1112 1113

 private:
1114
  friend class StackFrameIteratorBase;
1115 1116
};

1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132
class BuiltinContinuationFrame : public InternalFrame {
 public:
  Type type() const override { return BUILTIN_CONTINUATION; }

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

 protected:
  inline explicit BuiltinContinuationFrame(StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};

1133
class JavaScriptBuiltinContinuationFrame : public TypedFrameWithJSLinkage {
1134 1135 1136 1137 1138 1139 1140 1141
 public:
  Type type() const override { return JAVA_SCRIPT_BUILTIN_CONTINUATION; }

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

1142
  JSFunction function() const override;
1143
  int ComputeParametersCount() const override;
1144
  intptr_t GetSPToFPDelta() const;
1145

1146
  Object context() const override;
1147

1148 1149 1150 1151 1152 1153 1154
 protected:
  inline explicit JavaScriptBuiltinContinuationFrame(
      StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};
1155

1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169
class JavaScriptBuiltinContinuationWithCatchFrame
    : public JavaScriptBuiltinContinuationFrame {
 public:
  Type type() const override {
    return JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
  }

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

  // Patch in the exception object at the appropriate location into the stack
  // frame.
1170
  void SetException(Object exception);
1171 1172 1173 1174 1175 1176 1177 1178 1179

 protected:
  inline explicit JavaScriptBuiltinContinuationWithCatchFrame(
      StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};

1180
class StackFrameIteratorBase {
1181
 public:
1182 1183 1184
  StackFrameIteratorBase(const StackFrameIteratorBase&) = delete;
  StackFrameIteratorBase& operator=(const StackFrameIteratorBase&) = delete;

1185 1186
  Isolate* isolate() const { return isolate_; }

1187
  bool done() const { return frame_ == nullptr; }
1188

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

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

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

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

1211
 private:
1212
  friend class StackFrame;
1213 1214
};

1215
class StackFrameIterator : public StackFrameIteratorBase {
1216 1217
 public:
  // An iterator that iterates over the isolate's current thread's stack,
1218
  V8_EXPORT_PRIVATE explicit StackFrameIterator(Isolate* isolate);
1219
  // An iterator that iterates over a given thread's stack.
1220
  V8_EXPORT_PRIVATE StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
1221

1222 1223 1224
  StackFrameIterator(const StackFrameIterator&) = delete;
  StackFrameIterator& operator=(const StackFrameIterator&) = delete;

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

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

// Iterator that supports iterating through all JavaScript frames.
1238
class JavaScriptFrameIterator {
1239
 public:
1240 1241
  inline explicit JavaScriptFrameIterator(Isolate* isolate);
  inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top);
1242

1243 1244 1245
  inline JavaScriptFrame* frame() const;

  bool done() const { return iterator_.done(); }
1246
  V8_EXPORT_PRIVATE void Advance();
1247
  void AdvanceOneFrame() { iterator_.Advance(); }
1248
  inline JavaScriptFrame* Reframe();
1249

1250
 private:
1251
  StackFrameIterator iterator_;
1252 1253
};

1254
// NOTE: The stack trace frame iterator is an iterator that only traverse proper
1255 1256
// JavaScript frames that have proper JavaScript functions and WebAssembly
// frames.
1257
class V8_EXPORT_PRIVATE StackTraceFrameIterator {
1258
 public:
1259
  explicit StackTraceFrameIterator(Isolate* isolate);
1260
  // Skip frames until the frame with the given id is reached.
1261
  StackTraceFrameIterator(Isolate* isolate, StackFrameId id);
1262
  bool done() const { return iterator_.done(); }
1263
  void Advance();
1264
  void AdvanceOneFrame() { iterator_.Advance(); }
1265
  int FrameFunctionCount() const;
1266

1267
  inline CommonFrame* frame() const;
1268
  inline CommonFrame* Reframe();
1269 1270

  inline bool is_javascript() const;
1271
#if V8_ENABLE_WEBASSEMBLY
1272
  inline bool is_wasm() const;
1273
#endif  // V8_ENABLE_WEBASSEMBLY
1274 1275
  inline JavaScriptFrame* javascript_frame() const;

1276
 private:
1277 1278
  StackFrameIterator iterator_;
  bool IsValidFrame(StackFrame* frame) const;
1279 1280
};

1281
class SafeStackFrameIterator : public StackFrameIteratorBase {
1282
 public:
1283 1284
  SafeStackFrameIterator(Isolate* isolate, Address pc, Address fp, Address sp,
                         Address lr, Address js_entry_sp);
1285

1286
  inline StackFrame* frame() const;
1287 1288
  void Advance();

1289
  StackFrame::Type top_frame_type() const { return top_frame_type_; }
1290
  Address top_context_address() const { return top_context_address_; }
1291

1292
 private:
1293 1294
  void AdvanceOneFrame();

1295
  bool IsValidStackAddress(Address addr) const {
1296
    return low_bound_ <= addr && addr <= high_bound_;
1297
  }
1298 1299
  bool IsValidFrame(StackFrame* frame) const;
  bool IsValidCaller(StackFrame* frame);
1300 1301
  bool IsValidExitFrame(Address fp) const;
  bool IsValidTop(ThreadLocalTop* top) const;
1302

1303 1304 1305 1306 1307 1308 1309 1310
  // Returns true if the pc points to a bytecode handler and the frame pointer
  // doesn't seem to be a bytecode handler's frame, which implies that the
  // bytecode handler has an elided frame. This is not precise and might give
  // false negatives since it relies on checks to the frame's type marker,
  // which might be uninitialized.
  bool IsNoFrameBytecodeHandlerPc(Isolate* isolate, Address pc,
                                  Address fp) const;

1311 1312
  const Address low_bound_;
  const Address high_bound_;
1313
  StackFrame::Type top_frame_type_;
1314
  Address top_context_address_;
1315
  ExternalCallbackScope* external_callback_scope_;
1316
  Address top_link_register_;
1317
};
1318 1319 1320 1321 1322 1323 1324 1325

// Frame layout helper classes. Used by the deoptimizer and instruction
// selector.
// -------------------------------------------------------------------------

// How to calculate the frame layout information. Precise, when all information
// is available during deoptimization. Conservative, when an overapproximation
// is fine.
1326 1327 1328 1329 1330 1331 1332
// TODO(jgruber): Investigate whether the conservative kind can be removed. It
// seems possible: 1. is_topmost should be known through the outer_state chain
// of FrameStateDescriptor; 2. the deopt_kind may be a property of the bailout
// id; 3. for continuation_mode, we only care whether it is a mode with catch,
// and that is likewise known at compile-time.
// There is nothing specific blocking this, the investigation just requires time
// and it is not that important to get the exact frame height at compile-time.
1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345
enum class FrameInfoKind {
  kPrecise,
  kConservative,
};

// Used by the deoptimizer. Corresponds to frame kinds:
enum class BuiltinContinuationMode {
  STUB,                        // BuiltinContinuationFrame
  JAVASCRIPT,                  // JavaScriptBuiltinContinuationFrame
  JAVASCRIPT_WITH_CATCH,       // JavaScriptBuiltinContinuationWithCatchFrame
  JAVASCRIPT_HANDLE_EXCEPTION  // JavaScriptBuiltinContinuationWithCatchFrame
};

1346
class UnoptimizedFrameInfo {
1347
 public:
1348
  static UnoptimizedFrameInfo Precise(int parameters_count_with_receiver,
1349 1350
                                      int translation_height, bool is_topmost,
                                      bool pad_arguments) {
1351
    return {parameters_count_with_receiver, translation_height, is_topmost,
1352
            pad_arguments, FrameInfoKind::kPrecise};
1353 1354
  }

1355
  static UnoptimizedFrameInfo Conservative(int parameters_count_with_receiver,
1356
                                           int locals_count) {
1357
    return {parameters_count_with_receiver, locals_count, false, true,
1358 1359 1360
            FrameInfoKind::kConservative};
  }

1361 1362
  static uint32_t GetStackSizeForAdditionalArguments(int parameters_count);

1363 1364 1365 1366 1367 1368 1369 1370 1371
  uint32_t register_stack_slot_count() const {
    return register_stack_slot_count_;
  }
  uint32_t frame_size_in_bytes_without_fixed() const {
    return frame_size_in_bytes_without_fixed_;
  }
  uint32_t frame_size_in_bytes() const { return frame_size_in_bytes_; }

 private:
1372
  UnoptimizedFrameInfo(int parameters_count_with_receiver,
1373
                       int translation_height, bool is_topmost,
1374
                       bool pad_arguments, FrameInfoKind frame_info_kind);
1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387

  uint32_t register_stack_slot_count_;
  uint32_t frame_size_in_bytes_without_fixed_;
  uint32_t frame_size_in_bytes_;
};

class ConstructStubFrameInfo {
 public:
  static ConstructStubFrameInfo Precise(int translation_height,
                                        bool is_topmost) {
    return {translation_height, is_topmost, FrameInfoKind::kPrecise};
  }

1388 1389 1390 1391
  static ConstructStubFrameInfo Conservative(int parameters_count) {
    return {parameters_count, false, FrameInfoKind::kConservative};
  }

1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424
  uint32_t frame_size_in_bytes_without_fixed() const {
    return frame_size_in_bytes_without_fixed_;
  }
  uint32_t frame_size_in_bytes() const { return frame_size_in_bytes_; }

 private:
  ConstructStubFrameInfo(int translation_height, bool is_topmost,
                         FrameInfoKind frame_info_kind);

  uint32_t frame_size_in_bytes_without_fixed_;
  uint32_t frame_size_in_bytes_;
};

// Used by BuiltinContinuationFrameInfo.
class CallInterfaceDescriptor;
class RegisterConfiguration;

class BuiltinContinuationFrameInfo {
 public:
  static BuiltinContinuationFrameInfo Precise(
      int translation_height,
      const CallInterfaceDescriptor& continuation_descriptor,
      const RegisterConfiguration* register_config, bool is_topmost,
      DeoptimizeKind deopt_kind, BuiltinContinuationMode continuation_mode) {
    return {translation_height,
            continuation_descriptor,
            register_config,
            is_topmost,
            deopt_kind,
            continuation_mode,
            FrameInfoKind::kPrecise};
  }

1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439
  static BuiltinContinuationFrameInfo Conservative(
      int parameters_count,
      const CallInterfaceDescriptor& continuation_descriptor,
      const RegisterConfiguration* register_config) {
    // It doesn't matter what we pass as is_topmost, deopt_kind and
    // continuation_mode; these values are ignored in conservative mode.
    return {parameters_count,
            continuation_descriptor,
            register_config,
            false,
            DeoptimizeKind::kEager,
            BuiltinContinuationMode::STUB,
            FrameInfoKind::kConservative};
  }

1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466
  bool frame_has_result_stack_slot() const {
    return frame_has_result_stack_slot_;
  }
  uint32_t translated_stack_parameter_count() const {
    return translated_stack_parameter_count_;
  }
  uint32_t stack_parameter_count() const { return stack_parameter_count_; }
  uint32_t frame_size_in_bytes() const { return frame_size_in_bytes_; }
  uint32_t frame_size_in_bytes_above_fp() const {
    return frame_size_in_bytes_above_fp_;
  }

 private:
  BuiltinContinuationFrameInfo(
      int translation_height,
      const CallInterfaceDescriptor& continuation_descriptor,
      const RegisterConfiguration* register_config, bool is_topmost,
      DeoptimizeKind deopt_kind, BuiltinContinuationMode continuation_mode,
      FrameInfoKind frame_info_kind);

  bool frame_has_result_stack_slot_;
  uint32_t translated_stack_parameter_count_;
  uint32_t stack_parameter_count_;
  uint32_t frame_size_in_bytes_;
  uint32_t frame_size_in_bytes_above_fp_;
};

1467 1468
}  // namespace internal
}  // namespace v8
1469

1470
#endif  // V8_EXECUTION_FRAMES_H_