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

#ifndef V8_FRAMES_H_
#define V8_FRAMES_H_

8
#include "src/handles.h"
9
#include "src/objects.h"
10
#include "src/objects/code.h"
11
#include "src/safepoint-table.h"
12

13 14
namespace v8 {
namespace internal {
15 16 17
namespace wasm {
class WasmCode;
}
18

19
// Forward declarations.
20
class AbstractCode;
21
class Debug;
22
class ExternalCallbackScope;
23
class InnerPointerToCodeCache;
24
class Isolate;
25
class ObjectVisitor;
26
class RootVisitor;
27
class StackFrameIteratorBase;
28
class StringStream;
29
class ThreadLocalTop;
30
class WasmDebugInfo;
31
class WasmInstanceObject;
32
class WasmModuleObject;
33

34 35
class StackHandlerConstants : public AllStatic {
 public:
36 37
  static const int kNextOffset = 0 * kSystemPointerSize;
  static const int kPaddingOffset = 1 * kSystemPointerSize;
38

39 40
  static const int kSize = kPaddingOffset + kSystemPointerSize;
  static const int kSlotCount = kSize >> kSystemPointerSizeLog2;
41 42
};

43
class StackHandler {
44 45 46 47 48 49 50
 public:
  // Get the address of this stack handler.
  inline Address address() const;

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

51 52 53 54
  // 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;

55 56 57 58
  // Conversion support.
  static inline StackHandler* FromAddress(Address address);

 private:
59
  DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
60 61
};

62 63
#define STACK_FRAME_TYPE_LIST(V)                                          \
  V(ENTRY, EntryFrame)                                                    \
64
  V(CONSTRUCT_ENTRY, ConstructEntryFrame)                                 \
65 66 67 68 69 70
  V(EXIT, ExitFrame)                                                      \
  V(OPTIMIZED, OptimizedFrame)                                            \
  V(WASM_COMPILED, WasmCompiledFrame)                                     \
  V(WASM_TO_JS, WasmToJsFrame)                                            \
  V(JS_TO_WASM, JsToWasmFrame)                                            \
  V(WASM_INTERPRETER_ENTRY, WasmInterpreterEntryFrame)                    \
71
  V(C_WASM_ENTRY, CWasmEntryFrame)                                        \
72
  V(WASM_COMPILE_LAZY, WasmCompileLazyFrame)                              \
73 74 75 76
  V(INTERPRETED, InterpretedFrame)                                        \
  V(STUB, StubFrame)                                                      \
  V(BUILTIN_CONTINUATION, BuiltinContinuationFrame)                       \
  V(JAVA_SCRIPT_BUILTIN_CONTINUATION, JavaScriptBuiltinContinuationFrame) \
77 78
  V(JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH,                          \
    JavaScriptBuiltinContinuationWithCatchFrame)                          \
79 80 81 82
  V(INTERNAL, InternalFrame)                                              \
  V(CONSTRUCT, ConstructFrame)                                            \
  V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)                             \
  V(BUILTIN, BuiltinFrame)                                                \
83 84
  V(BUILTIN_EXIT, BuiltinExitFrame)                                       \
  V(NATIVE, NativeFrame)
85 86

// Abstract base class for all stack frames.
87
class StackFrame {
88 89 90 91 92
 public:
#define DECLARE_TYPE(type, ignore) type,
  enum Type {
    NONE = 0,
    STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
93 94 95 96
    NUMBER_OF_TYPES,
    // Used by FrameScope to indicate that the stack frame is constructed
    // manually and the FrameScope does not need to emit code.
    MANUAL
97 98 99 100 101
  };
#undef DECLARE_TYPE

  // Opaque data type for identifying stack frames. Used extensively
  // by the debugger.
102 103 104 105 106 107 108
  // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
  // has correct value range (see Issue 830 for more details).
  enum Id {
    ID_MIN_VALUE = kMinInt,
    ID_MAX_VALUE = kMaxInt,
    NO_ID = 0
  };
109

110
  // Used to mark the outermost JS entry frame.
111 112 113
  //
  // The mark is an opaque value that should be pushed onto the stack directly,
  // carefully crafted to not be interpreted as a tagged pointer.
114
  enum JsFrameMarker {
115 116
    INNER_JSENTRY_FRAME = (0 << kSmiTagSize) | kSmiTag,
    OUTERMOST_JSENTRY_FRAME = (1 << kSmiTagSize) | kSmiTag
117
  };
118 119 120
  STATIC_ASSERT((INNER_JSENTRY_FRAME & kHeapObjectTagMask) != kHeapObjectTag);
  STATIC_ASSERT((OUTERMOST_JSENTRY_FRAME & kHeapObjectTagMask) !=
                kHeapObjectTag);
121

122
  struct State {
123 124
    Address sp = kNullAddress;
    Address fp = kNullAddress;
125 126 127
    Address* pc_address = nullptr;
    Address* callee_pc_address = nullptr;
    Address* constant_pool_address = nullptr;
128 129
  };

130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
  // 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));
    return static_cast<Type>(marker >> kSmiTagSize);
  }

  // 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) {
160
    return (function_or_marker & kSmiTagMask) == kSmiTag;
161 162
  }

163 164
  // Copy constructor; it breaks the connection to host iterator
  // (as an iterator usually lives on stack).
165
  StackFrame(const StackFrame& original) V8_NOEXCEPT {
166
    this->state_ = original.state_;
167
    this->iterator_ = nullptr;
168
    this->isolate_ = original.isolate_;
169 170
  }

171 172
  // Type testers.
  bool is_entry() const { return type() == ENTRY; }
173
  bool is_construct_entry() const { return type() == CONSTRUCT_ENTRY; }
174
  bool is_exit() const { return type() == EXIT; }
175
  bool is_optimized() const { return type() == OPTIMIZED; }
176
  bool is_interpreted() const { return type() == INTERPRETED; }
177
  bool is_wasm_compiled() const { return type() == WASM_COMPILED; }
178
  bool is_wasm_compile_lazy() const { return type() == WASM_COMPILE_LAZY; }
179 180
  bool is_wasm_to_js() const { return type() == WASM_TO_JS; }
  bool is_js_to_wasm() const { return type() == JS_TO_WASM; }
181 182 183
  bool is_wasm_interpreter_entry() const {
    return type() == WASM_INTERPRETER_ENTRY;
  }
184
  bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
185
  bool is_builtin() const { return type() == BUILTIN; }
186
  bool is_internal() const { return type() == INTERNAL; }
187 188 189 190 191 192
  bool is_builtin_continuation() const {
    return type() == BUILTIN_CONTINUATION;
  }
  bool is_java_script_builtin_continuation() const {
    return type() == JAVA_SCRIPT_BUILTIN_CONTINUATION;
  }
193 194 195
  bool is_java_script_builtin_with_catch_continuation() const {
    return type() == JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
  }
196
  bool is_construct() const { return type() == CONSTRUCT; }
197
  bool is_builtin_exit() const { return type() == BUILTIN_EXIT; }
198 199
  virtual bool is_standard() const { return false; }

200 201
  bool is_java_script() const {
    Type type = this->type();
202
    return (type == OPTIMIZED) || (type == INTERPRETED) || (type == BUILTIN) ||
203 204
           (type == JAVA_SCRIPT_BUILTIN_CONTINUATION) ||
           (type == JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH);
205
  }
206 207 208 209
  bool is_wasm() const {
    Type type = this->type();
    return type == WASM_COMPILED || type == WASM_INTERPRETER_ENTRY;
  }
210

211 212 213
  // Accessors.
  Address sp() const { return state_.sp; }
  Address fp() const { return state_.fp; }
214
  Address callee_pc() const {
215
    return state_.callee_pc_address ? *state_.callee_pc_address : kNullAddress;
216
  }
217
  Address caller_sp() const { return GetCallerStackPointer(); }
218

219 220 221 222 223
  // If this frame is optimized and was dynamically aligned return its old
  // unaligned frame pointer.  When the frame is deoptimized its FP will shift
  // up one word and become unaligned.
  Address UnpaddedFP() const;

224 225 226
  Address pc() const { return *pc_address(); }
  void set_pc(Address pc) { *pc_address() = pc; }

227
  Address constant_pool() const { return *constant_pool_address(); }
228 229
  void set_constant_pool(Address constant_pool) {
    *constant_pool_address() = constant_pool;
230 231
  }

232 233
  Address* pc_address() const { return state_.pc_address; }

234 235 236 237
  Address* constant_pool_address() const {
    return state_.constant_pool_address;
  }

238
  // Get the id of this stack frame.
239
  Id id() const { return static_cast<Id>(caller_sp()); }
240

241 242 243
  // Get the top handler from the current stack iterator.
  inline StackHandler* top_handler() const;

244 245 246 247
  // Get the type of this frame.
  virtual Type type() const = 0;

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

251
  // Search for the code associated with this frame.
252
  Code LookupCode() const;
253

254 255
  virtual void Iterate(RootVisitor* v) const = 0;
  static void IteratePc(RootVisitor* v, Address* pc_address,
256
                        Address* constant_pool_address, Code holder);
257

258 259 260 261 262
  // 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);
263

264 265 266
  // Resolves pc_address through the resolution address function if one is set.
  static inline Address* ResolveReturnAddressLocation(Address* pc_address);

267 268
  // Printing support.
  enum PrintMode { OVERVIEW, DETAILS };
269 270
  virtual void Print(StringStream* accumulator, PrintMode mode,
                     int index) const;
271

272 273
  Isolate* isolate() const { return isolate_; }

274 275
  void operator=(const StackFrame& original) = delete;

276
 protected:
277
  inline explicit StackFrame(StackFrameIteratorBase* iterator);
278
  virtual ~StackFrame() = default;
279 280 281 282 283

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

  // Compute the stack frame type for the given state.
284
  static Type ComputeType(const StackFrameIteratorBase* iterator, State* state);
285 286 287 288

#ifdef DEBUG
  bool can_access_heap_objects() const;
#endif
289 290

 private:
291
  const StackFrameIteratorBase* iterator_;
292
  Isolate* isolate_;
293
  State state_;
294

295 296
  static ReturnAddressLocationResolver return_address_location_resolver_;

297 298 299
  // Fill in the state of the calling frame.
  virtual void ComputeCallerState(State* state) const = 0;

300
  // Get the type and the state of the calling frame.
301
  virtual Type GetCallerState(State* state) const;
302

303 304
  static const intptr_t kIsolateTag = 1;

305
  friend class StackFrameIterator;
306
  friend class StackFrameIteratorBase;
307
  friend class StackHandlerIterator;
308
  friend class SafeStackFrameIterator;
309 310
};

311 312 313 314
class NativeFrame : public StackFrame {
 public:
  Type type() const override { return NATIVE; }

315
  Code unchecked_code() const override;
316 317 318 319 320 321 322 323 324 325 326 327 328 329

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

 protected:
  inline explicit NativeFrame(StackFrameIteratorBase* iterator);

  Address GetCallerStackPointer() const override;

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

  friend class StackFrameIteratorBase;
};
330 331 332 333

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

336
  Code unchecked_code() const override;
337 338

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

  static EntryFrame* cast(StackFrame* frame) {
342
    DCHECK(frame->is_entry());
343 344 345 346
    return static_cast<EntryFrame*>(frame);
  }

 protected:
347
  inline explicit EntryFrame(StackFrameIteratorBase* iterator);
348 349 350 351

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

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

358
  friend class StackFrameIteratorBase;
359 360
};

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

365
  Code unchecked_code() const override;
366

367 368 369
  static ConstructEntryFrame* cast(StackFrame* frame) {
    DCHECK(frame->is_construct_entry());
    return static_cast<ConstructEntryFrame*>(frame);
370 371 372
  }

 protected:
373
  inline explicit ConstructEntryFrame(StackFrameIteratorBase* iterator);
374 375

 private:
376
  friend class StackFrameIteratorBase;
377 378 379 380 381 382
};


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

385
  Code unchecked_code() const override;
386

387
  Address& code_slot() const;
388

389
  // Garbage collection support.
390
  void Iterate(RootVisitor* v) const override;
391 392

  static ExitFrame* cast(StackFrame* frame) {
393
    DCHECK(frame->is_exit());
394 395 396 397 398 399 400
    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);
401
  static Address ComputeStackPointer(Address fp);
402
  static StackFrame::Type ComputeFrameType(Address fp);
403
  static void FillState(Address fp, Address sp, State* state);
404 405

 protected:
406
  inline explicit ExitFrame(StackFrameIteratorBase* iterator);
407

408
  Address GetCallerStackPointer() const override;
409 410

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

413
  friend class StackFrameIteratorBase;
414 415
};

416 417 418 419 420 421 422 423 424 425 426 427
// 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);
  }

428
  JSFunction function() const;
429
  Object receiver() const;
430 431

  bool IsConstructor() const;
432

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

436 437 438 439
 protected:
  inline explicit BuiltinExitFrame(StackFrameIteratorBase* iterator);

 private:
440
  Object GetParameter(int i) const;
441 442
  int ComputeParametersCount() const;

443 444 445 446
  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;
447 448

  friend class StackFrameIteratorBase;
449
  friend class FrameArrayBuilder;
450 451
};

452
class StandardFrame;
453

454
class FrameSummary {
455
 public:
456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
// Subclasses for the different summary kinds:
#define FRAME_SUMMARY_VARIANTS(F)                                             \
  F(JAVA_SCRIPT, JavaScriptFrameSummary, java_script_summary_, JavaScript)    \
  F(WASM_COMPILED, WasmCompiledFrameSummary, wasm_compiled_summary_,          \
    WasmCompiled)                                                             \
  F(WASM_INTERPRETED, WasmInterpretedFrameSummary, wasm_interpreted_summary_, \
    WasmInterpreted)

#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:
482
    JavaScriptFrameSummary(Isolate* isolate, Object receiver,
483
                           JSFunction function, AbstractCode abstract_code,
484 485
                           int code_offset, bool is_constructor,
                           FixedArray parameters);
486 487 488 489 490 491

    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_; }
492
    Handle<FixedArray> parameters() const { return parameters_; }
493 494 495 496 497 498 499 500 501 502 503 504 505
    bool is_subject_to_debugging() const;
    int SourcePosition() const;
    int SourceStatementPosition() const;
    Handle<Object> script() const;
    Handle<String> FunctionName() const;
    Handle<Context> native_context() const;

   private:
    Handle<Object> receiver_;
    Handle<JSFunction> function_;
    Handle<AbstractCode> abstract_code_;
    int code_offset_;
    bool is_constructor_;
506
    Handle<FixedArray> parameters_;
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
  };

  class WasmFrameSummary : public FrameSummaryBase {
   protected:
    WasmFrameSummary(Isolate*, Kind, Handle<WasmInstanceObject>,
                     bool at_to_number_conversion);

   public:
    Handle<Object> receiver() const;
    uint32_t function_index() const;
    int byte_offset() const;
    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<String> FunctionName() const;
    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_;
  };

  class WasmCompiledFrameSummary : public WasmFrameSummary {
   public:
535
    WasmCompiledFrameSummary(Isolate*, Handle<WasmInstanceObject>,
536
                             wasm::WasmCode*, int code_offset,
537
                             bool at_to_number_conversion);
538
    uint32_t function_index() const;
539
    wasm::WasmCode* code() const { return code_; }
540 541
    int code_offset() const { return code_offset_; }
    int byte_offset() const;
542
    static int GetWasmSourcePosition(const wasm::WasmCode* code, int offset);
543 544

   private:
545
    wasm::WasmCode* const code_;
546 547
    int code_offset_;
  };
548

549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
  class WasmInterpretedFrameSummary : public WasmFrameSummary {
   public:
    WasmInterpretedFrameSummary(Isolate*, Handle<WasmInstanceObject>,
                                uint32_t function_index, int byte_offset);
    uint32_t function_index() const { return function_index_; }
    int code_offset() const { return byte_offset_; }
    int byte_offset() const { return byte_offset_; }

   private:
    uint32_t function_index_;
    int byte_offset_;
  };

#undef FRAME_SUMMARY_FIELD
#define FRAME_SUMMARY_CONS(kind, type, field, desc) \
  FrameSummary(type summ) : field(summ) {}  // NOLINT
  FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CONS)
#undef FRAME_SUMMARY_CONS
567

568
  ~FrameSummary();
569

570 571
  static FrameSummary GetTop(const StandardFrame* frame);
  static FrameSummary GetBottom(const StandardFrame* frame);
572
  static FrameSummary GetSingle(const StandardFrame* frame);
573
  static FrameSummary Get(const StandardFrame* frame, int index);
574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599

  // 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<String> FunctionName() 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

  bool IsWasm() const { return IsWasmCompiled() || IsWasmInterpreted(); }
  const WasmFrameSummary& AsWasm() const {
    if (IsWasmCompiled()) return AsWasmCompiled();
    return AsWasmInterpreted();
  }
600 601

 private:
602 603 604 605 606
#define FRAME_SUMMARY_FIELD(kind, type, field, desc) type field;
  union {
    FrameSummaryBase base_;
    FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_FIELD)
  };
607
};
608

609
class StandardFrame : public StackFrame {
610 611
 public:
  // Testers.
612
  bool is_standard() const override { return true; }
613 614

  // Accessors.
615
  virtual Object receiver() const;
616
  virtual Script script() const;
617
  virtual Object context() const;
618
  virtual int position() const;
619 620

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

625
  // Access the parameters.
626
  virtual Object GetParameter(int index) const;
627 628 629 630 631
  virtual int ComputeParametersCount() const;

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

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

637
  static StandardFrame* cast(StackFrame* frame) {
638
    DCHECK(frame->is_standard());
639 640 641 642
    return static_cast<StandardFrame*>(frame);
  }

 protected:
643
  inline explicit StandardFrame(StackFrameIteratorBase* iterator);
644

645
  void ComputeCallerState(State* state) const override;
646 647 648 649 650 651 652 653 654

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

655 656 657 658
  // Computes the address of the constant pool  field in the standard
  // frame given by the provided frame pointer.
  static inline Address ComputeConstantPoolAddress(Address fp);

659 660
  // Iterate over expression stack including stack handlers, locals,
  // and parts of the fixed part including context and code fields.
661
  void IterateExpressions(RootVisitor* v) const;
662 663

  // Returns the address of the n'th expression stack element.
664
  virtual Address GetExpressionAddress(int n) const;
665 666 667 668 669

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

670 671 672
  // Determines if the standard frame for the given frame pointer is a
  // construct frame.
  static inline bool IsConstructFrame(Address fp);
673

674
  // Used by OptimizedFrames and StubFrames.
675
  void IterateCompiledFrame(RootVisitor* v) const;
676

677 678
 private:
  friend class StackFrame;
679
  friend class SafeStackFrameIterator;
680 681
};

682
class JavaScriptFrame : public StandardFrame {
683
 public:
684
  Type type() const override = 0;
685

686
  void Summarize(std::vector<FrameSummary>* frames) const override;
687 688

  // Accessors.
689
  virtual JSFunction function() const;
690 691 692
  Object unchecked_function() const;
  Object receiver() const override;
  Object context() const override;
693
  Script script() const override;
694

695
  inline void set_receiver(Object value);
696 697

  // Access the parameters.
698
  inline Address GetParameterSlot(int index) const;
699
  Object GetParameter(int index) const override;
700
  int ComputeParametersCount() const override;
701
  Handle<FixedArray> GetParameters() const;
702

703
  // Debugger access.
704
  void SetParameterValue(int index, Object value) const;
705

706
  // Check if this frame is a constructor frame invoked through 'new'.
707
  bool IsConstructor() const override;
708

709 710
  // Determines whether this frame includes inlined activations. To get details
  // about the inlined frames use {GetFunctions} and {Summarize}.
711
  bool HasInlinedFrames() const;
712

713 714 715 716 717
  // Check if this frame has "adapted" arguments in the sense that the
  // actual passed arguments are available in an arguments adaptor
  // frame below it on the stack.
  inline bool has_adapted_arguments() const;

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

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

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

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

731
  void GetFunctions(std::vector<Handle<SharedFunctionInfo>>* functions) const;
732

733
  // Lookup exception handler for current {pc}, returns -1 if none found. Also
734 735 736
  // returns data associated with the handler site specific to the frame type:
  //  - OptimizedFrame  : Data is the stack slot count of the entire frame.
  //  - InterpretedFrame: Data is the register index holding the context.
737
  virtual int LookupExceptionHandlerInTable(
738
      int* data, HandlerTable::CatchPrediction* prediction);
739

740 741 742
  // Architecture-specific register description.
  static Register fp_register();
  static Register context_register();
743
  static Register constant_pool_pointer_register();
744

745
  static JavaScriptFrame* cast(StackFrame* frame) {
746
    DCHECK(frame->is_java_script());
747 748 749
    return static_cast<JavaScriptFrame*>(frame);
  }

750
  static void PrintFunctionAndOffset(JSFunction function, AbstractCode code,
751
                                     int code_offset, FILE* file,
752 753 754
                                     bool print_line_number);

  static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
755
                       bool print_line_number);
756

757
  static void CollectFunctionAndOffsetForICStats(JSFunction function,
758
                                                 AbstractCode code,
759 760 761
                                                 int code_offset);
  static void CollectTopFrameForICStats(Isolate* isolate);

762
 protected:
763
  inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator);
764

765
  Address GetCallerStackPointer() const override;
766

767 768
  virtual void PrintFrameKind(StringStream* accumulator) const {}

769
 private:
770
  inline Object function_slot_object() const;
771

772
  friend class StackFrameIteratorBase;
773 774 775
};


776 777
class StubFrame : public StandardFrame {
 public:
778
  Type type() const override { return STUB; }
779 780

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

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

786 787 788 789 790 791
  // Lookup exception handler for current {pc}, returns -1 if none found. Only
  // TurboFan stub frames are supported. Also returns data associated with the
  // handler site:
  //  - TurboFan stub: Data is the stack slot count of the entire frame.
  int LookupExceptionHandlerInTable(int* data);

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

795
  Address GetCallerStackPointer() const override;
796

797
  friend class StackFrameIteratorBase;
798 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
  Object receiver() const override;
822
  int ComputeParametersCount() const override;
823

824 825
  static int StackSlotOffsetRelativeToFp(int slot_index);

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

829

830
 private:
831
  friend class StackFrameIteratorBase;
832

833
  Object StackSlotAt(int index) const;
834 835 836
};


837
class InterpretedFrame : public JavaScriptFrame {
838
 public:
839
  Type type() const override { return INTERPRETED; }
840

841 842 843
  // Accessors.
  int position() const override;

844
  // Lookup exception handler for current {pc}, returns -1 if none found.
845
  int LookupExceptionHandlerInTable(
846
      int* data, HandlerTable::CatchPrediction* prediction) override;
847 848 849 850 851 852 853 854

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

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

855
  // Returns the frame's current bytecode array.
856
  BytecodeArray GetBytecodeArray() const;
857

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

862
  // Access to the interpreter register file for this frame.
863 864
  Object ReadInterpreterRegister(int register_index) const;
  void WriteInterpreterRegister(int register_index, Object value);
865

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

869 870
  static int GetBytecodeOffset(Address fp);

871 872 873 874 875
  static InterpretedFrame* cast(StackFrame* frame) {
    DCHECK(frame->is_interpreted());
    return static_cast<InterpretedFrame*>(frame);
  }

876 877 878
 protected:
  inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);

879 880
  Address GetExpressionAddress(int n) const override;

881 882 883 884 885
 private:
  friend class StackFrameIteratorBase;
};


886 887 888 889 890
// Arguments adaptor frames are automatically inserted below
// JavaScript frames when the actual number of parameters does not
// match the formal number of parameters.
class ArgumentsAdaptorFrame: public JavaScriptFrame {
 public:
891
  Type type() const override { return ARGUMENTS_ADAPTOR; }
892 893

  // Determine the code for the frame.
894
  Code unchecked_code() const override;
895 896

  static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
897
    DCHECK(frame->is_arguments_adaptor());
898 899 900
    return static_cast<ArgumentsAdaptorFrame*>(frame);
  }

901 902
  int ComputeParametersCount() const override;

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

907
 protected:
908
  inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator);
909

910

911 912 913 914 915 916 917 918 919 920 921 922 923 924
 private:
  friend class StackFrameIteratorBase;
};

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

  static BuiltinFrame* cast(StackFrame* frame) {
    DCHECK(frame->is_builtin());
    return static_cast<BuiltinFrame*>(frame);
  }
925
  int ComputeParametersCount() const final;
926 927 928 929

 protected:
  inline explicit BuiltinFrame(StackFrameIteratorBase* iterator);

930
  void PrintFrameKind(StringStream* accumulator) const override;
931 932

 private:
933
  friend class StackFrameIteratorBase;
934 935
};

936
class WasmCompiledFrame final : public StandardFrame {
937
 public:
938
  Type type() const override { return WASM_COMPILED; }
939 940

  // GC support.
941
  void Iterate(RootVisitor* v) const override;
942 943 944 945 946

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

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

951
  // Determine the code for the frame.
952
  Code unchecked_code() const override;
953

954
  // Accessors.
955
  WasmInstanceObject wasm_instance() const;
956
  wasm::WasmCode* wasm_code() const;
957
  uint32_t function_index() const;
958
  Script script() const override;
959
  int position() const override;
960
  bool at_to_number_conversion() const;
961

962
  void Summarize(std::vector<FrameSummary>* frames) const override;
963 964 965 966 967 968 969 970 971 972 973 974 975

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

 protected:
  inline explicit WasmCompiledFrame(StackFrameIteratorBase* iterator);

  Address GetCallerStackPointer() const override;

 private:
  friend class StackFrameIteratorBase;
976
  WasmModuleObject module_object() const;
977 978
};

979
class WasmInterpreterEntryFrame final : public StandardFrame {
980 981 982 983
 public:
  Type type() const override { return WASM_INTERPRETER_ENTRY; }

  // GC support.
984
  void Iterate(RootVisitor* v) const override;
985 986 987 988 989

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

990
  void Summarize(std::vector<FrameSummary>* frames) const override;
991 992

  // Determine the code for the frame.
993
  Code unchecked_code() const override;
994 995

  // Accessors.
996
  WasmDebugInfo debug_info() const;
997
  WasmInstanceObject wasm_instance() const;
998

999
  Script script() const override;
1000
  int position() const override;
1001
  Object context() const override;
1002 1003 1004 1005

  static WasmInterpreterEntryFrame* cast(StackFrame* frame) {
    DCHECK(frame->is_wasm_interpreter_entry());
    return static_cast<WasmInterpreterEntryFrame*>(frame);
1006 1007
  }

1008
 protected:
1009
  inline explicit WasmInterpreterEntryFrame(StackFrameIteratorBase* iterator);
1010 1011 1012 1013 1014

  Address GetCallerStackPointer() const override;

 private:
  friend class StackFrameIteratorBase;
1015
  WasmModuleObject module_object() const;
1016 1017
};

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

 protected:
  inline explicit WasmToJsFrame(StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};

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

 protected:
  inline explicit JsToWasmFrame(StackFrameIteratorBase* iterator);
1035 1036 1037 1038 1039

 private:
  friend class StackFrameIteratorBase;
};

1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050
class CWasmEntryFrame : public StubFrame {
 public:
  Type type() const override { return C_WASM_ENTRY; }

 protected:
  inline explicit CWasmEntryFrame(StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};

1051 1052 1053 1054
class WasmCompileLazyFrame : public StandardFrame {
 public:
  Type type() const override { return WASM_COMPILE_LAZY; }

1055
  Code unchecked_code() const override;
1056
  WasmInstanceObject wasm_instance() const;
1057
  FullObjectSlot wasm_instance_slot() const;
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075

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

  Address GetCallerStackPointer() const override;

 private:
  friend class StackFrameIteratorBase;
};

1076 1077
class InternalFrame: public StandardFrame {
 public:
1078
  Type type() const override { return INTERNAL; }
1079

1080
  // Garbage collection support.
1081
  void Iterate(RootVisitor* v) const override;
1082 1083

  // Determine the code for the frame.
1084
  Code unchecked_code() const override;
1085 1086

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

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

1094
  Address GetCallerStackPointer() const override;
1095 1096

 private:
1097
  friend class StackFrameIteratorBase;
1098 1099 1100
};


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

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

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

 private:
1116
  friend class StackFrameIteratorBase;
1117 1118
};

1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144
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;
};

class JavaScriptBuiltinContinuationFrame : public JavaScriptFrame {
 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);
  }

  int ComputeParametersCount() const override;
1145
  intptr_t GetSPToFPDelta() const;
1146

1147
  Object context() const override;
1148

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

 private:
  friend class StackFrameIteratorBase;
};
1156

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

 protected:
  inline explicit JavaScriptBuiltinContinuationWithCatchFrame(
      StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};

1181
class StackFrameIteratorBase {
1182
 public:
1183 1184
  Isolate* isolate() const { return isolate_; }

1185
  bool done() const { return frame_ == nullptr; }
1186

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

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

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

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

1209
 private:
1210
  friend class StackFrame;
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222
  DISALLOW_COPY_AND_ASSIGN(StackFrameIteratorBase);
};


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

  StackFrame* frame() const {
1223
    DCHECK(!done());
1224 1225 1226 1227 1228 1229 1230 1231
    return frame_;
  }
  void Advance();

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

1232
  DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
1233 1234 1235
};

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

1241 1242 1243 1244
  inline JavaScriptFrame* frame() const;

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

1247
 private:
1248
  StackFrameIterator iterator_;
1249 1250
};

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

1263 1264 1265 1266 1267 1268
  inline StandardFrame* frame() const;

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

1269
 private:
1270 1271
  StackFrameIterator iterator_;
  bool IsValidFrame(StackFrame* frame) const;
1272 1273 1274
};


1275
class SafeStackFrameIterator: public StackFrameIteratorBase {
1276
 public:
1277 1278
  SafeStackFrameIterator(Isolate* isolate,
                         Address fp, Address sp,
1279
                         Address js_entry_sp);
1280

1281
  inline StackFrame* frame() const;
1282 1283
  void Advance();

1284 1285
  StackFrame::Type top_frame_type() const { return top_frame_type_; }

1286
 private:
1287 1288
  void AdvanceOneFrame();

1289
  bool IsValidStackAddress(Address addr) const {
1290
    return low_bound_ <= addr && addr <= high_bound_;
1291
  }
1292 1293
  bool IsValidFrame(StackFrame* frame) const;
  bool IsValidCaller(StackFrame* frame);
1294 1295
  bool IsValidExitFrame(Address fp) const;
  bool IsValidTop(ThreadLocalTop* top) const;
1296

1297 1298
  const Address low_bound_;
  const Address high_bound_;
1299
  StackFrame::Type top_frame_type_;
1300
  ExternalCallbackScope* external_callback_scope_;
1301
};
1302 1303
}  // namespace internal
}  // namespace v8
1304 1305

#endif  // V8_FRAMES_H_