frames.h 47.6 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 "include/v8-initialization.h"
9
#include "src/base/bounds.h"
10
#include "src/codegen/safepoint-table.h"
11
#include "src/common/globals.h"
12
#include "src/handles/handles.h"
13
#include "src/objects/code.h"
14
#include "src/objects/objects.h"
15

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

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

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

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

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

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

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

85 86 87 88
  // 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;

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

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

96 97
#define STACK_FRAME_TYPE_LIST(V)                                          \
  V(ENTRY, EntryFrame)                                                    \
98
  V(CONSTRUCT_ENTRY, ConstructEntryFrame)                                 \
99
  V(EXIT, ExitFrame)                                                      \
100 101 102 103 104 105 106
  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)                     \
107
  V(INTERPRETED, InterpretedFrame)                                        \
108
  V(BASELINE, BaselineFrame)                                              \
109
  V(OPTIMIZED, OptimizedFrame)                                            \
110 111 112
  V(STUB, StubFrame)                                                      \
  V(BUILTIN_CONTINUATION, BuiltinContinuationFrame)                       \
  V(JAVA_SCRIPT_BUILTIN_CONTINUATION, JavaScriptBuiltinContinuationFrame) \
113 114
  V(JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH,                          \
    JavaScriptBuiltinContinuationWithCatchFrame)                          \
115 116 117
  V(INTERNAL, InternalFrame)                                              \
  V(CONSTRUCT, ConstructFrame)                                            \
  V(BUILTIN, BuiltinFrame)                                                \
118 119
  V(BUILTIN_EXIT, BuiltinExitFrame)                                       \
  V(NATIVE, NativeFrame)
120 121

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

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

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

155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
  // 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));
176
    intptr_t type = marker >> kSmiTagSize;
177
    // TODO(petermarshall): There is a bug in the arm simulators that causes
178
    // invalid frame markers.
179 180 181
#if (defined(USE_SIMULATOR) &&                        \
     (V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_ARM)) || \
    V8_TARGET_ARCH_RISCV64
182 183 184 185 186
    if (static_cast<uintptr_t>(type) >= Type::NUMBER_OF_TYPES) {
      // Appease UBSan.
      return Type::NUMBER_OF_TYPES;
    }
#else
187 188 189
    DCHECK_LT(static_cast<uintptr_t>(type), Type::NUMBER_OF_TYPES);
#endif
    return static_cast<Type>(type);
190 191 192 193 194 195 196 197
  }

  // 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) {
198
    return (function_or_marker & kSmiTagMask) == kSmiTag;
199 200
  }

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

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

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

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

257 258 259 260 261
  // 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;

262
  Address constant_pool() const { return *constant_pool_address(); }
263 264
  void set_constant_pool(Address constant_pool) {
    *constant_pool_address() = constant_pool;
265 266
  }

267 268
  Address* pc_address() const { return state_.pc_address; }

269 270 271 272
  Address* constant_pool_address() const {
    return state_.constant_pool_address;
  }

273
  // Get the id of this stack frame.
274
  StackFrameId id() const { return static_cast<StackFrameId>(caller_sp()); }
275

276 277 278
  // Get the top handler from the current stack iterator.
  inline StackHandler* top_handler() const;

279 280 281 282
  // Get the type of this frame.
  virtual Type type() const = 0;

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

286
  // Search for the code associated with this frame.
287
  V8_EXPORT_PRIVATE Code LookupCode() const;
288

289
  virtual void Iterate(RootVisitor* v) const = 0;
290 291
  void IteratePc(RootVisitor* v, Address* pc_address,
                 Address* constant_pool_address, Code holder) const;
292

293 294 295 296 297
  // 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);
298

299 300
  static inline Address ReadPC(Address* pc_address);

301 302 303
  // Resolves pc_address through the resolution address function if one is set.
  static inline Address* ResolveReturnAddressLocation(Address* pc_address);

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

309 310
  Isolate* isolate() const { return isolate_; }

311 312
  void operator=(const StackFrame& original) = delete;

313
 protected:
314
  inline explicit StackFrame(StackFrameIteratorBase* iterator);
315
  virtual ~StackFrame() = default;
316 317 318 319 320

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

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

#ifdef DEBUG
  bool can_access_heap_objects() const;
#endif
326 327

 private:
328
  const StackFrameIteratorBase* iterator_;
329
  Isolate* isolate_;
330
  State state_;
331

332 333
  static ReturnAddressLocationResolver return_address_location_resolver_;

334 335 336
  // Fill in the state of the calling frame.
  virtual void ComputeCallerState(State* state) const = 0;

337
  // Get the type and the state of the calling frame.
338
  virtual Type GetCallerState(State* state) const;
339

340 341
  static const intptr_t kIsolateTag = 1;

342
  friend class StackFrameIterator;
343
  friend class StackFrameIteratorBase;
344
  friend class StackHandlerIterator;
345
  friend class SafeStackFrameIterator;
346 347
};

348
class CommonFrame;
349

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

#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:
375
    JavaScriptFrameSummary(Isolate* isolate, Object receiver,
376
                           JSFunction function, AbstractCode abstract_code,
377 378
                           int code_offset, bool is_constructor,
                           FixedArray parameters);
379

380
    void EnsureSourcePositionsAvailable();
381
    bool AreSourcePositionsAvailable() const;
382

383 384 385 386 387
    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_; }
388
    Handle<FixedArray> parameters() const { return parameters_; }
389 390 391 392 393 394 395 396 397 398 399 400
    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_;
401
    Handle<FixedArray> parameters_;
402 403
  };

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

410 411
    Handle<Object> receiver() const;
    uint32_t function_index() const;
412 413 414
    wasm::WasmCode* code() const { return code_; }
    int code_offset() const { return code_offset_; }
    V8_EXPORT_PRIVATE int byte_offset() const;
415 416 417 418 419 420 421 422 423 424 425 426
    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_;
427
    wasm::WasmCode* const code_;
428 429
    int code_offset_;
  };
430
#endif  // V8_ENABLE_WEBASSEMBLY
431

432 433 434 435
#define FRAME_SUMMARY_CONS(kind, type, field, desc) \
  FrameSummary(type summ) : field(summ) {}  // NOLINT
  FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CONS)
#undef FRAME_SUMMARY_CONS
436

437
  ~FrameSummary();
438

439 440 441 442
  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);
443

444
  void EnsureSourcePositionsAvailable();
445
  bool AreSourcePositionsAvailable() const;
446

447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
  // 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

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

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

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

487 488
  Address GetCallerStackPointer() const override;

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

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

 protected:
500
  inline explicit CommonFrame(StackFrameIteratorBase* iterator);
501

502
  void ComputeCallerState(State* state) const override;
503 504 505 506 507 508 509 510 511

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

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

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

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

523
  // Used by OptimizedFrames and StubFrames.
524
  void IterateCompiledFrame(RootVisitor* v) const;
525

526 527
 private:
  friend class StackFrame;
528
  friend class SafeStackFrameIterator;
529 530
};

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

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

540
class CommonFrameWithJSLinkage : public CommonFrame {
541
 public:
542 543 544 545 546 547 548 549 550 551 552 553
  // 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;
554

555 556 557
  // 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.
558
  //  - UnoptimizedFrame: Data is the register index holding the context.
559 560 561 562 563 564 565
  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
566
  void Summarize(std::vector<FrameSummary>* frames) const override;
567

568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
 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;

589
  // Accessors.
590
  JSFunction function() const override;
591
  Object unchecked_function() const;
592
  Script script() const;
593 594 595 596
  Object context() const override;
  int GetActualArgumentCount() const override;

  inline void set_receiver(Object value);
597

598
  // Debugger access.
599
  void SetParameterValue(int index, Object value) const;
600

601
  // Check if this frame is a constructor frame invoked through 'new'.
602
  bool IsConstructor() const override;
603

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

608
  // Garbage collection support.
609
  void Iterate(RootVisitor* v) const override;
610 611

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

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

618
  void GetFunctions(std::vector<Handle<SharedFunctionInfo>>* functions) const;
619

620 621 622
  // Architecture-specific register description.
  static Register fp_register();
  static Register context_register();
623
  static Register constant_pool_pointer_register();
624

625
  static JavaScriptFrame* cast(StackFrame* frame) {
626
    DCHECK(frame->is_java_script());
627 628 629
    return static_cast<JavaScriptFrame*>(frame);
  }

630
  static void PrintFunctionAndOffset(JSFunction function, AbstractCode code,
631
                                     int code_offset, FILE* file,
632 633 634
                                     bool print_line_number);

  static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
635
                       bool print_line_number);
636

637
  static void CollectFunctionAndOffsetForICStats(JSFunction function,
638
                                                 AbstractCode code,
639 640
                                                 int code_offset);

641
 protected:
642
  inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator);
643

644
  Address GetCallerStackPointer() const override;
645

646 647
  virtual void PrintFrameKind(StringStream* accumulator) const {}

648
 private:
649
  inline Object function_slot_object() const;
650

651
  friend class StackFrameIteratorBase;
652 653
};

654
class NativeFrame : public TypedFrame {
655
 public:
656
  Type type() const override { return NATIVE; }
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 721 722 723
  // 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.
724
  void Iterate(RootVisitor* v) const override;
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 759 760 761
  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;
762
  bool IsConstructor() const;
763 764 765 766 767 768 769 770

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

 protected:
  inline explicit BuiltinExitFrame(StackFrameIteratorBase* iterator);

 private:
771 772
  Object GetParameter(int i) const;
  int ComputeParametersCount() const;
773 774 775 776 777 778 779

  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;
780
  friend class StackTraceBuilder;
781 782 783 784 785 786
};

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

787
  // Determine the code for the frame.
788
  Code unchecked_code() const override;
789

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

794
 protected:
795
  inline explicit StubFrame(StackFrameIteratorBase* iterator);
796

797
 private:
798
  friend class StackFrameIteratorBase;
799 800
};

801
class OptimizedFrame : public JavaScriptFrame {
802
 public:
803
  Type type() const override { return OPTIMIZED; }
804 805

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

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

813
  void Summarize(std::vector<FrameSummary>* frames) const override;
814

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

819
  DeoptimizationData GetDeoptimizationData(int* deopt_index) const;
820

821
  int ComputeParametersCount() const override;
822

823 824
  static int StackSlotOffsetRelativeToFp(int slot_index);

825
 protected:
826
  inline explicit OptimizedFrame(StackFrameIteratorBase* iterator);
827 828

 private:
829
  friend class StackFrameIteratorBase;
830

831
  Object StackSlotAt(int index) const;
832 833
};

834 835 836 837
// 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 {
838
 public:
839 840 841
  // Accessors.
  int position() const override;

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

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

849
  // Returns the frame's current bytecode array.
850
  BytecodeArray GetBytecodeArray() const;
851

852
  // Access to the interpreter register file for this frame.
853
  Object ReadInterpreterRegister(int register_index) const;
854

855
  // Build a list with summaries for this frame including all inlined frames.
856
  void Summarize(std::vector<FrameSummary>* frames) const override;
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 883 884 885
  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);
886

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

  static int GetBytecodeOffset(Address fp);
897

898 899 900 901 902 903 904
 protected:
  inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};

905
class BaselineFrame : public UnoptimizedFrame {
906
 public:
907
  Type type() const override { return BASELINE; }
908 909 910 911 912 913

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

  intptr_t GetPCForBytecodeOffset(int lookup_offset) const;

914 915
  void PatchContext(Context value);

916 917 918
  static BaselineFrame* cast(StackFrame* frame) {
    DCHECK(frame->is_baseline());
    return static_cast<BaselineFrame*>(frame);
919 920 921
  }

 protected:
922
  inline explicit BaselineFrame(StackFrameIteratorBase* iterator);
923 924 925 926 927

 private:
  friend class StackFrameIteratorBase;
};

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

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

  JSFunction function() const override;
  int ComputeParametersCount() const override;
941 942 943 944

 protected:
  inline explicit BuiltinFrame(StackFrameIteratorBase* iterator);

945
 private:
946
  friend class StackFrameIteratorBase;
947 948
};

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

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

958 959
  // Lookup exception handler for current {pc}, returns -1 if none found.
  int LookupExceptionHandlerInTable();
960

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

975
  void Summarize(std::vector<FrameSummary>* frames) const override;
976

977 978 979
  static WasmFrame* cast(StackFrame* frame) {
    DCHECK(frame->is_wasm());
    return static_cast<WasmFrame*>(frame);
980 981 982
  }

 protected:
983
  inline explicit WasmFrame(StackFrameIteratorBase* iterator);
984 985 986

 private:
  friend class StackFrameIteratorBase;
987
  WasmModuleObject module_object() const;
988 989
};

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

 protected:
  inline explicit WasmExitFrame(StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};

1002
class WasmDebugBreakFrame final : public TypedFrame {
1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
 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;
};

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

 protected:
  inline explicit WasmToJsFrame(StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};

1035
class JsToWasmFrame : public StubFrame {
1036 1037 1038
 public:
  Type type() const override { return JS_TO_WASM; }

1039 1040
  void Iterate(RootVisitor* v) const override;

1041 1042
 protected:
  inline explicit JsToWasmFrame(StackFrameIteratorBase* iterator);
1043 1044 1045 1046 1047

 private:
  friend class StackFrameIteratorBase;
};

1048 1049 1050 1051 1052 1053 1054 1055 1056
class CWasmEntryFrame : public StubFrame {
 public:
  Type type() const override { return C_WASM_ENTRY; }

 protected:
  inline explicit CWasmEntryFrame(StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
1057
  Type GetCallerState(State* state) const override;
1058 1059
};

1060
class WasmCompileLazyFrame : public TypedFrame {
1061 1062 1063
 public:
  Type type() const override { return WASM_COMPILE_LAZY; }

1064
  WasmInstanceObject wasm_instance() const;
1065
  FullObjectSlot wasm_instance_slot() const;
1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080

  // 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;
};
1081
#endif  // V8_ENABLE_WEBASSEMBLY
1082

1083
class InternalFrame : public TypedFrame {
1084
 public:
1085
  Type type() const override { return INTERNAL; }
1086

1087
  // Garbage collection support.
1088
  void Iterate(RootVisitor* v) const override;
1089 1090

  static InternalFrame* cast(StackFrame* frame) {
1091
    DCHECK(frame->is_internal());
1092 1093 1094 1095
    return static_cast<InternalFrame*>(frame);
  }

 protected:
1096
  inline explicit InternalFrame(StackFrameIteratorBase* iterator);
1097 1098

 private:
1099
  friend class StackFrameIteratorBase;
1100 1101
};

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

  static ConstructFrame* cast(StackFrame* frame) {
1109
    DCHECK(frame->is_construct());
1110 1111 1112 1113
    return static_cast<ConstructFrame*>(frame);
  }

 protected:
1114
  inline explicit ConstructFrame(StackFrameIteratorBase* iterator);
1115 1116

 private:
1117
  friend class StackFrameIteratorBase;
1118 1119
};

1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
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;
};

1136
class JavaScriptBuiltinContinuationFrame : public TypedFrameWithJSLinkage {
1137 1138 1139 1140 1141 1142 1143 1144
 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);
  }

1145
  JSFunction function() const override;
1146
  int ComputeParametersCount() const override;
1147
  intptr_t GetSPToFPDelta() const;
1148

1149
  Object context() const override;
1150

1151 1152 1153 1154 1155 1156 1157
 protected:
  inline explicit JavaScriptBuiltinContinuationFrame(
      StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};
1158

1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172
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.
1173
  void SetException(Object exception);
1174 1175 1176 1177 1178 1179 1180 1181 1182

 protected:
  inline explicit JavaScriptBuiltinContinuationWithCatchFrame(
      StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};

1183
class StackFrameIteratorBase {
1184
 public:
1185 1186 1187
  StackFrameIteratorBase(const StackFrameIteratorBase&) = delete;
  StackFrameIteratorBase& operator=(const StackFrameIteratorBase&) = delete;

1188 1189
  Isolate* isolate() const { return isolate_; }

1190
  bool done() const { return frame_ == nullptr; }
1191

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

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

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

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

1214
 private:
1215
  friend class StackFrame;
1216 1217
};

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

1225 1226 1227
  StackFrameIterator(const StackFrameIterator&) = delete;
  StackFrameIterator& operator=(const StackFrameIterator&) = delete;

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

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

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

1246 1247 1248
  inline JavaScriptFrame* frame() const;

  bool done() const { return iterator_.done(); }
1249
  V8_EXPORT_PRIVATE void Advance();
1250
  void AdvanceOneFrame() { iterator_.Advance(); }
1251
  inline JavaScriptFrame* Reframe();
1252

1253
 private:
1254
  StackFrameIterator iterator_;
1255 1256
};

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

1270
  inline CommonFrame* frame() const;
1271
  inline CommonFrame* Reframe();
1272 1273

  inline bool is_javascript() const;
1274
#if V8_ENABLE_WEBASSEMBLY
1275
  inline bool is_wasm() const;
1276
#endif  // V8_ENABLE_WEBASSEMBLY
1277 1278
  inline JavaScriptFrame* javascript_frame() const;

1279 1280 1281 1282
  // Use this instead of FrameSummary::GetTop(javascript_frame) to keep
  // filtering behavior consistent with the rest of StackTraceFrameIterator.
  FrameSummary GetTopValidFrame() const;

1283
 private:
1284
  StackFrameIterator iterator_;
1285 1286
  static bool IsValidFrame(StackFrame* frame);
  static bool IsValidJSFunction(JSFunction f);
1287 1288
};

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

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

1297
  StackFrame::Type top_frame_type() const { return top_frame_type_; }
1298
  Address top_context_address() const { return top_context_address_; }
1299

1300
 private:
1301 1302
  void AdvanceOneFrame();

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

1311 1312 1313 1314 1315 1316 1317 1318
  // 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;

1319 1320
  const Address low_bound_;
  const Address high_bound_;
1321
  StackFrame::Type top_frame_type_;
1322
  Address top_context_address_;
1323
  ExternalCallbackScope* external_callback_scope_;
1324
  Address top_link_register_;
1325
};
1326 1327 1328 1329 1330 1331 1332 1333

// 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.
1334 1335 1336 1337 1338 1339 1340
// 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.
1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353
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
};

1354
class UnoptimizedFrameInfo {
1355
 public:
1356
  static UnoptimizedFrameInfo Precise(int parameters_count_with_receiver,
1357 1358
                                      int translation_height, bool is_topmost,
                                      bool pad_arguments) {
1359
    return {parameters_count_with_receiver, translation_height, is_topmost,
1360
            pad_arguments, FrameInfoKind::kPrecise};
1361 1362
  }

1363
  static UnoptimizedFrameInfo Conservative(int parameters_count_with_receiver,
1364
                                           int locals_count) {
1365
    return {parameters_count_with_receiver, locals_count, false, true,
1366 1367 1368
            FrameInfoKind::kConservative};
  }

1369 1370
  static uint32_t GetStackSizeForAdditionalArguments(int parameters_count);

1371 1372 1373 1374 1375 1376 1377 1378 1379
  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:
1380
  UnoptimizedFrameInfo(int parameters_count_with_receiver,
1381
                       int translation_height, bool is_topmost,
1382
                       bool pad_arguments, FrameInfoKind frame_info_kind);
1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395

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

1396 1397 1398 1399
  static ConstructStubFrameInfo Conservative(int parameters_count) {
    return {parameters_count, false, FrameInfoKind::kConservative};
  }

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 1425 1426 1427 1428 1429 1430 1431 1432
  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};
  }

1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447
  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};
  }

1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474
  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_;
};

1475 1476
}  // namespace internal
}  // namespace v8
1477

1478
#endif  // V8_EXECUTION_FRAMES_H_