frames.h 40.7 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 449 450

  friend class StackFrameIteratorBase;
};

451
class StandardFrame;
452

453
class FrameSummary {
454
 public:
455 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
// 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:
481
    JavaScriptFrameSummary(Isolate* isolate, Object receiver,
482
                           JSFunction function, AbstractCode abstract_code,
483
                           int code_offset, bool is_constructor);
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530

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

  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:
531
    WasmCompiledFrameSummary(Isolate*, Handle<WasmInstanceObject>,
532
                             wasm::WasmCode*, int code_offset,
533
                             bool at_to_number_conversion);
534
    uint32_t function_index() const;
535
    wasm::WasmCode* code() const { return code_; }
536 537
    int code_offset() const { return code_offset_; }
    int byte_offset() const;
538
    static int GetWasmSourcePosition(const wasm::WasmCode* code, int offset);
539 540

   private:
541
    wasm::WasmCode* const code_;
542 543
    int code_offset_;
  };
544

545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562
  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
563

564
  ~FrameSummary();
565

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

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

 private:
598 599 600 601 602
#define FRAME_SUMMARY_FIELD(kind, type, field, desc) type field;
  union {
    FrameSummaryBase base_;
    FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_FIELD)
  };
603
};
604

605
class StandardFrame : public StackFrame {
606 607
 public:
  // Testers.
608
  bool is_standard() const override { return true; }
609 610

  // Accessors.
611
  virtual Object receiver() const;
612
  virtual Script script() const;
613
  virtual Object context() const;
614
  virtual int position() const;
615 616

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

621
  // Access the parameters.
622
  virtual Object GetParameter(int index) const;
623 624 625 626 627
  virtual int ComputeParametersCount() const;

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

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

633
  static StandardFrame* cast(StackFrame* frame) {
634
    DCHECK(frame->is_standard());
635 636 637 638
    return static_cast<StandardFrame*>(frame);
  }

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

641
  void ComputeCallerState(State* state) const override;
642 643 644 645 646 647 648 649 650

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

651 652 653 654
  // Computes the address of the constant pool  field in the standard
  // frame given by the provided frame pointer.
  static inline Address ComputeConstantPoolAddress(Address fp);

655 656
  // Iterate over expression stack including stack handlers, locals,
  // and parts of the fixed part including context and code fields.
657
  void IterateExpressions(RootVisitor* v) const;
658 659

  // Returns the address of the n'th expression stack element.
660
  virtual Address GetExpressionAddress(int n) const;
661 662 663 664 665

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

666 667 668
  // Determines if the standard frame for the given frame pointer is a
  // construct frame.
  static inline bool IsConstructFrame(Address fp);
669

670
  // Used by OptimizedFrames and StubFrames.
671
  void IterateCompiledFrame(RootVisitor* v) const;
672

673 674
 private:
  friend class StackFrame;
675
  friend class SafeStackFrameIterator;
676 677
};

678
class JavaScriptFrame : public StandardFrame {
679
 public:
680
  Type type() const override = 0;
681

682
  void Summarize(std::vector<FrameSummary>* frames) const override;
683 684

  // Accessors.
685
  virtual JSFunction function() const;
686 687 688
  Object unchecked_function() const;
  Object receiver() const override;
  Object context() const override;
689
  Script script() const override;
690

691
  inline void set_receiver(Object value);
692 693

  // Access the parameters.
694
  inline Address GetParameterSlot(int index) const;
695
  Object GetParameter(int index) const override;
696
  int ComputeParametersCount() const override;
697

698
  // Debugger access.
699
  void SetParameterValue(int index, Object value) const;
700

701
  // Check if this frame is a constructor frame invoked through 'new'.
702
  bool IsConstructor() const override;
703

704 705
  // Determines whether this frame includes inlined activations. To get details
  // about the inlined frames use {GetFunctions} and {Summarize}.
706
  bool HasInlinedFrames() const;
707

708 709 710 711 712
  // 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;

713
  // Garbage collection support.
714
  void Iterate(RootVisitor* v) const override;
715 716

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

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

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

726
  void GetFunctions(std::vector<Handle<SharedFunctionInfo>>* functions) const;
727

728
  // Lookup exception handler for current {pc}, returns -1 if none found. Also
729 730 731
  // 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.
732
  virtual int LookupExceptionHandlerInTable(
733
      int* data, HandlerTable::CatchPrediction* prediction);
734

735 736 737
  // Architecture-specific register description.
  static Register fp_register();
  static Register context_register();
738
  static Register constant_pool_pointer_register();
739

740
  static JavaScriptFrame* cast(StackFrame* frame) {
741
    DCHECK(frame->is_java_script());
742 743 744
    return static_cast<JavaScriptFrame*>(frame);
  }

745
  static void PrintFunctionAndOffset(JSFunction function, AbstractCode code,
746
                                     int code_offset, FILE* file,
747 748 749
                                     bool print_line_number);

  static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
750
                       bool print_line_number);
751

752
  static void CollectFunctionAndOffsetForICStats(JSFunction function,
753
                                                 AbstractCode code,
754 755 756
                                                 int code_offset);
  static void CollectTopFrameForICStats(Isolate* isolate);

757
 protected:
758
  inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator);
759

760
  Address GetCallerStackPointer() const override;
761

762 763
  virtual void PrintFrameKind(StringStream* accumulator) const {}

764
 private:
765
  inline Object function_slot_object() const;
766

767
  friend class StackFrameIteratorBase;
768 769 770
};


771 772
class StubFrame : public StandardFrame {
 public:
773
  Type type() const override { return STUB; }
774 775

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

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

781 782 783 784 785 786
  // 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);

787
 protected:
788
  inline explicit StubFrame(StackFrameIteratorBase* iterator);
789

790
  Address GetCallerStackPointer() const override;
791

792
  friend class StackFrameIteratorBase;
793 794 795
};


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

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

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

808
  void Summarize(std::vector<FrameSummary>* frames) const override;
809

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

814
  DeoptimizationData GetDeoptimizationData(int* deopt_index) const;
815

816
  Object receiver() const override;
817
  int ComputeParametersCount() const override;
818

819 820
  static int StackSlotOffsetRelativeToFp(int slot_index);

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

824

825
 private:
826
  friend class StackFrameIteratorBase;
827

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


832
class InterpretedFrame : public JavaScriptFrame {
833
 public:
834
  Type type() const override { return INTERPRETED; }
835

836 837 838
  // Accessors.
  int position() const override;

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

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

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

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

857
  // Access to the interpreter register file for this frame.
858 859
  Object ReadInterpreterRegister(int register_index) const;
  void WriteInterpreterRegister(int register_index, Object value);
860

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

864 865
  static int GetBytecodeOffset(Address fp);

866 867 868 869 870
  static InterpretedFrame* cast(StackFrame* frame) {
    DCHECK(frame->is_interpreted());
    return static_cast<InterpretedFrame*>(frame);
  }

871 872 873
 protected:
  inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);

874 875
  Address GetExpressionAddress(int n) const override;

876 877 878 879 880
 private:
  friend class StackFrameIteratorBase;
};


881 882 883 884 885
// 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:
886
  Type type() const override { return ARGUMENTS_ADAPTOR; }
887 888

  // Determine the code for the frame.
889
  Code unchecked_code() const override;
890 891

  static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
892
    DCHECK(frame->is_arguments_adaptor());
893 894 895
    return static_cast<ArgumentsAdaptorFrame*>(frame);
  }

896 897
  int ComputeParametersCount() const override;

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

902
 protected:
903
  inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator);
904

905

906 907 908 909 910 911 912 913 914 915 916 917 918 919
 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);
  }
920
  int ComputeParametersCount() const final;
921 922 923 924

 protected:
  inline explicit BuiltinFrame(StackFrameIteratorBase* iterator);

925
  void PrintFrameKind(StringStream* accumulator) const override;
926 927

 private:
928
  friend class StackFrameIteratorBase;
929 930
};

931
class WasmCompiledFrame final : public StandardFrame {
932
 public:
933
  Type type() const override { return WASM_COMPILED; }
934 935

  // GC support.
936
  void Iterate(RootVisitor* v) const override;
937 938 939 940 941

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

942 943 944 945
  // 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);

946
  // Determine the code for the frame.
947
  Code unchecked_code() const override;
948

949
  // Accessors.
950
  WasmInstanceObject wasm_instance() const;
951
  wasm::WasmCode* wasm_code() const;
952
  uint32_t function_index() const;
953
  Script script() const override;
954
  int position() const override;
955
  bool at_to_number_conversion() const;
956

957
  void Summarize(std::vector<FrameSummary>* frames) const override;
958 959 960 961 962 963 964 965 966 967 968 969 970

  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;
971
  WasmModuleObject module_object() const;
972 973
};

974
class WasmInterpreterEntryFrame final : public StandardFrame {
975 976 977 978
 public:
  Type type() const override { return WASM_INTERPRETER_ENTRY; }

  // GC support.
979
  void Iterate(RootVisitor* v) const override;
980 981 982 983 984

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

985
  void Summarize(std::vector<FrameSummary>* frames) const override;
986 987

  // Determine the code for the frame.
988
  Code unchecked_code() const override;
989 990

  // Accessors.
991
  WasmDebugInfo debug_info() const;
992
  WasmInstanceObject wasm_instance() const;
993

994
  Script script() const override;
995
  int position() const override;
996
  Object context() const override;
997 998 999 1000

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

1003
 protected:
1004
  inline explicit WasmInterpreterEntryFrame(StackFrameIteratorBase* iterator);
1005 1006 1007 1008 1009

  Address GetCallerStackPointer() const override;

 private:
  friend class StackFrameIteratorBase;
1010
  WasmModuleObject module_object() const;
1011 1012
};

1013
class WasmToJsFrame : public StubFrame {
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
 public:
  Type type() const override { return WASM_TO_JS; }

 protected:
  inline explicit WasmToJsFrame(StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};

1024
class JsToWasmFrame : public StubFrame {
1025 1026 1027 1028 1029
 public:
  Type type() const override { return JS_TO_WASM; }

 protected:
  inline explicit JsToWasmFrame(StackFrameIteratorBase* iterator);
1030 1031 1032 1033 1034

 private:
  friend class StackFrameIteratorBase;
};

1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
class CWasmEntryFrame : public StubFrame {
 public:
  Type type() const override { return C_WASM_ENTRY; }

 protected:
  inline explicit CWasmEntryFrame(StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};

1046 1047 1048 1049
class WasmCompileLazyFrame : public StandardFrame {
 public:
  Type type() const override { return WASM_COMPILE_LAZY; }

1050
  Code unchecked_code() const override;
1051
  WasmInstanceObject wasm_instance() const;
1052
  FullObjectSlot wasm_instance_slot() const;
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070

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

1071 1072
class InternalFrame: public StandardFrame {
 public:
1073
  Type type() const override { return INTERNAL; }
1074

1075
  // Garbage collection support.
1076
  void Iterate(RootVisitor* v) const override;
1077 1078

  // Determine the code for the frame.
1079
  Code unchecked_code() const override;
1080 1081

  static InternalFrame* cast(StackFrame* frame) {
1082
    DCHECK(frame->is_internal());
1083 1084 1085 1086
    return static_cast<InternalFrame*>(frame);
  }

 protected:
1087
  inline explicit InternalFrame(StackFrameIteratorBase* iterator);
1088

1089
  Address GetCallerStackPointer() const override;
1090 1091

 private:
1092
  friend class StackFrameIteratorBase;
1093 1094 1095
};


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

  static ConstructFrame* cast(StackFrame* frame) {
1103
    DCHECK(frame->is_construct());
1104 1105 1106 1107
    return static_cast<ConstructFrame*>(frame);
  }

 protected:
1108
  inline explicit ConstructFrame(StackFrameIteratorBase* iterator);
1109 1110

 private:
1111
  friend class StackFrameIteratorBase;
1112 1113
};

1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139
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;
1140
  intptr_t GetSPToFPDelta() const;
1141

1142
  Object context() const override;
1143

1144 1145 1146 1147 1148 1149 1150
 protected:
  inline explicit JavaScriptBuiltinContinuationFrame(
      StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};
1151

1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
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.
1166
  void SetException(Object exception);
1167 1168 1169 1170 1171 1172 1173 1174 1175

 protected:
  inline explicit JavaScriptBuiltinContinuationWithCatchFrame(
      StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};

1176
class StackFrameIteratorBase {
1177
 public:
1178 1179
  Isolate* isolate() const { return isolate_; }

1180
  bool done() const { return frame_ == nullptr; }
1181

1182 1183 1184
 protected:
  // An iterator that iterates over a given thread's stack.
  StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects);
1185

1186
  Isolate* isolate_;
1187 1188 1189 1190 1191
#define DECLARE_SINGLETON(ignore, type) type type##_;
  STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
#undef DECLARE_SINGLETON
  StackFrame* frame_;
  StackHandler* handler_;
1192
  const bool can_access_heap_objects_;
1193 1194

  StackHandler* handler() const {
1195
    DCHECK(!done());
1196 1197 1198 1199 1200
    return handler_;
  }

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

1204
 private:
1205
  friend class StackFrame;
1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217
  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 {
1218
    DCHECK(!done());
1219 1220 1221 1222 1223 1224 1225 1226
    return frame_;
  }
  void Advance();

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

1227
  DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
1228 1229 1230
};

// Iterator that supports iterating through all JavaScript frames.
1231
class JavaScriptFrameIterator {
1232
 public:
1233 1234
  inline explicit JavaScriptFrameIterator(Isolate* isolate);
  inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top);
1235

1236 1237 1238 1239
  inline JavaScriptFrame* frame() const;

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

1242
 private:
1243
  StackFrameIterator iterator_;
1244 1245
};

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

1258 1259 1260 1261 1262 1263
  inline StandardFrame* frame() const;

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

1264
 private:
1265 1266
  StackFrameIterator iterator_;
  bool IsValidFrame(StackFrame* frame) const;
1267 1268 1269
};


1270
class SafeStackFrameIterator: public StackFrameIteratorBase {
1271
 public:
1272 1273
  SafeStackFrameIterator(Isolate* isolate,
                         Address fp, Address sp,
1274
                         Address js_entry_sp);
1275

1276
  inline StackFrame* frame() const;
1277 1278
  void Advance();

1279 1280
  StackFrame::Type top_frame_type() const { return top_frame_type_; }

1281
 private:
1282 1283
  void AdvanceOneFrame();

1284
  bool IsValidStackAddress(Address addr) const {
1285
    return low_bound_ <= addr && addr <= high_bound_;
1286
  }
1287 1288
  bool IsValidFrame(StackFrame* frame) const;
  bool IsValidCaller(StackFrame* frame);
1289 1290
  bool IsValidExitFrame(Address fp) const;
  bool IsValidTop(ThreadLocalTop* top) const;
1291

1292 1293
  const Address low_bound_;
  const Address high_bound_;
1294
  StackFrame::Type top_frame_type_;
1295
  ExternalCallbackScope* external_callback_scope_;
1296
};
1297 1298
}  // namespace internal
}  // namespace v8
1299 1300

#endif  // V8_FRAMES_H_