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

#ifndef V8_FRAMES_H_
#define V8_FRAMES_H_

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

12 13
namespace v8 {
namespace internal {
14

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

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

24 25
void SetUpJSCallerSavedCodeData();

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


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

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

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

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

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

55
  InnerPointerToCodeCacheEntry* GetCacheEntry(Address inner_pointer);
56 57

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

  Isolate* isolate_;

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

65
  DISALLOW_COPY_AND_ASSIGN(InnerPointerToCodeCache);
66 67 68
};


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


76 77
class StackHandlerConstants : public AllStatic {
 public:
78
  static const int kNextOffset = 0 * kPointerSize;
79

80
  static const int kSize = kNextOffset + kPointerSize;
81
  static const int kSlotCount = kSize >> kPointerSizeLog2;
82 83 84
};


85 86 87 88 89 90 91 92 93 94 95 96
class StackHandler BASE_EMBEDDED {
 public:
  // Get the address of this stack handler.
  inline Address address() const;

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

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

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

100
#define STACK_FRAME_TYPE_LIST(V)                         \
101 102 103 104 105
  V(ENTRY, EntryFrame)                                   \
  V(ENTRY_CONSTRUCT, EntryConstructFrame)                \
  V(EXIT, ExitFrame)                                     \
  V(JAVA_SCRIPT, JavaScriptFrame)                        \
  V(OPTIMIZED, OptimizedFrame)                           \
106
  V(WASM, WasmFrame)                                     \
107 108
  V(INTERPRETED, InterpretedFrame)                       \
  V(STUB, StubFrame)                                     \
109
  V(STUB_FAILURE_TRAMPOLINE, StubFailureTrampolineFrame) \
110 111 112
  V(INTERNAL, InternalFrame)                             \
  V(CONSTRUCT, ConstructFrame)                           \
  V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
113

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
// Every pointer in a frame has a slot id. On 32-bit platforms, doubles consume
// two slots.
//
// Stack slot indices >= 0 access the callee stack with slot 0 corresponding to
// the callee's saved return address and 1 corresponding to the saved frame
// pointer. Some frames have additional information stored in the fixed header,
// for example JSFunctions store the function context and marker in the fixed
// header, with slot index 2 corresponding to the current function context and 3
// corresponding to the frame marker/JSFunction.
//
//  slot      JS frame
//       +-----------------+--------------------------------
//  -n-1 |   parameter 0   |                            ^
//       |- - - - - - - - -|                            |
//  -n   |                 |                          Caller
//  ...  |       ...       |                       frame slots
//  -2   |  parameter n-1  |                       (slot < 0)
//       |- - - - - - - - -|                            |
//  -1   |   parameter n   |                            v
//  -----+-----------------+--------------------------------
//   0   |   return addr   |   ^                        ^
//       |- - - - - - - - -|   |                        |
//   1   | saved frame ptr | Fixed                      |
//       |- - - - - - - - -| Header <-- frame ptr       |
//   2   | [Constant Pool] |   |                        |
//       |- - - - - - - - -|   |                        |
// 2+cp  |     Context     |   |   if a constant pool   |
//       |- - - - - - - - -|   |    is used, cp = 1,    |
// 3+cp  |JSFunction/Marker|   v   otherwise, cp = 0    |
//       +-----------------+----                        |
// 4+cp  |                 |   ^                      Callee
//       |- - - - - - - - -|   |                   frame slots
//  ...  |                 | Frame slots           (slot >= 0)
//       |- - - - - - - - -|   |                        |
//       |                 |   v                        |
//  -----+-----------------+----- <-- stack ptr -------------
//
151

152 153 154
class StandardFrameConstants : public AllStatic {
 public:
  // Fixed part of the frame consists of return address, caller fp,
155 156 157
  // constant pool (if FLAG_enable_embedded_constant_pool), context, and
  // function. StandardFrame::IterateExpressions assumes that kLastObjectOffset
  // is the last object pointer.
158
  static const int kCPSlotSize =
159
      FLAG_enable_embedded_constant_pool ? kPointerSize : 0;
160
  static const int kFixedFrameSizeFromFp =  2 * kPointerSize + kCPSlotSize;
161
  static const int kFixedFrameSizeAboveFp = kPCOnStackSize + kFPOnStackSize;
162
  static const int kFixedFrameSize =
163 164 165 166
      kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp;
  static const int kFixedSlotCountAboveFp =
      kFixedFrameSizeAboveFp / kPointerSize;
  static const int kFixedSlotCount = kFixedFrameSize / kPointerSize;
167
  static const int kCPSlotCount = kCPSlotSize / kPointerSize;
168 169 170 171 172 173 174 175 176
  static const int kExpressionsOffset = -3 * kPointerSize - kCPSlotSize;
  static const int kMarkerOffset = -2 * kPointerSize - kCPSlotSize;
  static const int kContextOffset = -1 * kPointerSize - kCPSlotSize;
  static const int kConstantPoolOffset = kCPSlotSize ? -1 * kPointerSize : 0;
  static const int kCallerFPOffset = 0 * kPointerSize;
  static const int kCallerPCOffset = +1 * kFPOnStackSize;
  static const int kCallerSPOffset = kCallerPCOffset + 1 * kPCOnStackSize;

  static const int kLastObjectOffset = kContextOffset;
177 178 179
};


180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
class ArgumentsAdaptorFrameConstants : public AllStatic {
 public:
  // FP-relative.
  static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;

  static const int kFrameSize =
      StandardFrameConstants::kFixedFrameSize + kPointerSize;
};


class InternalFrameConstants : public AllStatic {
 public:
  // FP-relative.
  static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
};


class ConstructFrameConstants : public AllStatic {
 public:
  // FP-relative.
  static const int kImplicitReceiverOffset =
201
      StandardFrameConstants::kExpressionsOffset - 3 * kPointerSize;
202
  static const int kLengthOffset =
203 204
      StandardFrameConstants::kExpressionsOffset - 2 * kPointerSize;
  static const int kAllocationSiteOffset =
205 206 207 208 209
      StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
  static const int kCodeOffset =
      StandardFrameConstants::kExpressionsOffset - 0 * kPointerSize;

  static const int kFrameSize =
210
      StandardFrameConstants::kFixedFrameSize + 4 * kPointerSize;
211 212 213
};


214 215
class InterpreterFrameConstants : public AllStatic {
 public:
216 217
  // Fixed frame includes new.target and bytecode offset.
  static const int kFixedFrameSize =
218
      StandardFrameConstants::kFixedFrameSize + 3 * kPointerSize;
219
  static const int kFixedFrameSizeFromFp =
220
      StandardFrameConstants::kFixedFrameSizeFromFp + 3 * kPointerSize;
221

222
  // FP-relative.
223 224
  static const int kNewTargetFromFp =
      -StandardFrameConstants::kFixedFrameSizeFromFp - 1 * kPointerSize;
225
  static const int kBytecodeArrayFromFp =
226
      -StandardFrameConstants::kFixedFrameSizeFromFp - 2 * kPointerSize;
227
  static const int kBytecodeOffsetFromFp =
228
      -StandardFrameConstants::kFixedFrameSizeFromFp - 3 * kPointerSize;
229 230
  static const int kRegisterFilePointerFromFp =
      -StandardFrameConstants::kFixedFrameSizeFromFp - 4 * kPointerSize;
231

232 233
  static const int kExpressionsOffset = kRegisterFilePointerFromFp;

234
  // Expression index for {StandardFrame::GetExpressionAddress}.
235 236 237
  static const int kBytecodeArrayExpressionIndex = -2;
  static const int kBytecodeOffsetExpressionIndex = -1;
  static const int kRegisterFileExpressionIndex = 0;
238

239 240
  // Register file pointer relative.
  static const int kLastParamFromRegisterPointer =
241
      StandardFrameConstants::kFixedFrameSize + 4 * kPointerSize;
242 243

  static const int kBytecodeOffsetFromRegisterPointer = 1 * kPointerSize;
244
  static const int kBytecodeArrayFromRegisterPointer = 2 * kPointerSize;
245 246 247
  static const int kNewTargetFromRegisterPointer = 3 * kPointerSize;
  static const int kFunctionFromRegisterPointer = 4 * kPointerSize;
  static const int kContextFromRegisterPointer = 5 * kPointerSize;
248 249
};

250 251 252 253 254 255 256 257 258
inline static int FPOffsetToFrameSlot(int frame_offset) {
  return StandardFrameConstants::kFixedSlotCountAboveFp - 1 -
         frame_offset / kPointerSize;
}

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

260 261 262 263 264 265 266
// Abstract base class for all stack frames.
class StackFrame BASE_EMBEDDED {
 public:
#define DECLARE_TYPE(type, ignore) type,
  enum Type {
    NONE = 0,
    STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
267 268 269 270
    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
271 272 273 274 275
  };
#undef DECLARE_TYPE

  // Opaque data type for identifying stack frames. Used extensively
  // by the debugger.
276 277 278 279 280 281 282
  // 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
  };
283

284 285 286 287 288 289
  // Used to mark the outermost JS entry frame.
  enum JsFrameMarker {
    INNER_JSENTRY_FRAME = 0,
    OUTERMOST_JSENTRY_FRAME = 1
  };

290
  struct State {
291 292
    State() : sp(NULL), fp(NULL), pc_address(NULL),
              constant_pool_address(NULL) { }
293 294 295
    Address sp;
    Address fp;
    Address* pc_address;
296
    Address* constant_pool_address;
297 298
  };

299 300
  // Copy constructor; it breaks the connection to host iterator
  // (as an iterator usually lives on stack).
301 302 303
  StackFrame(const StackFrame& original) {
    this->state_ = original.state_;
    this->iterator_ = NULL;
304
    this->isolate_ = original.isolate_;
305 306
  }

307 308 309 310
  // Type testers.
  bool is_entry() const { return type() == ENTRY; }
  bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
  bool is_exit() const { return type() == EXIT; }
311
  bool is_optimized() const { return type() == OPTIMIZED; }
312
  bool is_interpreted() const { return type() == INTERPRETED; }
313
  bool is_wasm() const { return type() == WASM; }
314 315
  bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
  bool is_internal() const { return type() == INTERNAL; }
316 317 318
  bool is_stub_failure_trampoline() const {
    return type() == STUB_FAILURE_TRAMPOLINE;
  }
319
  bool is_construct() const { return type() == CONSTRUCT; }
320 321
  virtual bool is_standard() const { return false; }

322 323
  bool is_java_script() const {
    Type type = this->type();
324 325
    return (type == JAVA_SCRIPT) || (type == OPTIMIZED) ||
           (type == INTERPRETED);
326 327
  }

328 329 330
  // Accessors.
  Address sp() const { return state_.sp; }
  Address fp() const { return state_.fp; }
331
  Address caller_sp() const { return GetCallerStackPointer(); }
332

333 334 335 336 337
  // 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;

338 339 340
  Address pc() const { return *pc_address(); }
  void set_pc(Address pc) { *pc_address() = pc; }

341
  Address constant_pool() const { return *constant_pool_address(); }
342 343
  void set_constant_pool(Address constant_pool) {
    *constant_pool_address() = constant_pool;
344 345
  }

346 347
  virtual void SetCallerFp(Address caller_fp) = 0;

348 349 350
  // Manually changes value of fp in this object.
  void UpdateFp(Address fp) { state_.fp = fp; }

351 352
  Address* pc_address() const { return state_.pc_address; }

353 354 355 356
  Address* constant_pool_address() const {
    return state_.constant_pool_address;
  }

357
  // Get the id of this stack frame.
358
  Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
359

360 361 362
  // Get the top handler from the current stack iterator.
  inline StackHandler* top_handler() const;

363 364 365 366
  // Get the type of this frame.
  virtual Type type() const = 0;

  // Get the code associated with this frame.
367 368 369 370
  // This method could be called during marking phase of GC.
  virtual Code* unchecked_code() const = 0;

  // Get the code associated with this frame.
371
  inline Code* LookupCode() const;
372 373

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

376 377 378
  // Get the code object containing the given pc and fill in the
  // safepoint entry and the number of stack slots. The pc must be at
  // a safepoint.
379 380
  static Code* GetSafepointData(Isolate* isolate,
                                Address pc,
381
                                SafepointEntry* safepoint_entry,
382 383
                                unsigned* stack_slots);

384
  virtual void Iterate(ObjectVisitor* v) const = 0;
385 386
  static void IteratePc(ObjectVisitor* v, Address* pc_address,
                        Address* constant_pool_address, Code* holder);
387

388 389 390 391 392
  // 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);
393

394 395 396
  // Resolves pc_address through the resolution address function if one is set.
  static inline Address* ResolveReturnAddressLocation(Address* pc_address);

397 398 399 400 401 402
  // Printing support.
  enum PrintMode { OVERVIEW, DETAILS };
  virtual void Print(StringStream* accumulator,
                     PrintMode mode,
                     int index) const { }

403 404
  Isolate* isolate() const { return isolate_; }

405
 protected:
406
  inline explicit StackFrame(StackFrameIteratorBase* iterator);
407 408 409 410 411 412 413 414 415 416 417
  virtual ~StackFrame() { }

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

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

  // Compute the stack frame type for the given state.
418
  static Type ComputeType(const StackFrameIteratorBase* iterator, State* state);
419 420 421 422

#ifdef DEBUG
  bool can_access_heap_objects() const;
#endif
423 424

 private:
425
  const StackFrameIteratorBase* iterator_;
426
  Isolate* isolate_;
427
  State state_;
428

429 430
  static ReturnAddressLocationResolver return_address_location_resolver_;

431 432 433
  // Fill in the state of the calling frame.
  virtual void ComputeCallerState(State* state) const = 0;

434
  // Get the type and the state of the calling frame.
435
  virtual Type GetCallerState(State* state) const;
436

437 438
  static const intptr_t kIsolateTag = 1;

439
  friend class StackFrameIterator;
440
  friend class StackFrameIteratorBase;
441
  friend class StackHandlerIterator;
442
  friend class SafeStackFrameIterator;
443

444 445
 private:
  void operator=(const StackFrame& original);
446 447 448 449 450 451
};


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

454
  Code* unchecked_code() const override;
455 456

  // Garbage collection support.
457
  void Iterate(ObjectVisitor* v) const override;
458 459

  static EntryFrame* cast(StackFrame* frame) {
460
    DCHECK(frame->is_entry());
461 462
    return static_cast<EntryFrame*>(frame);
  }
463
  void SetCallerFp(Address caller_fp) override;
464 465

 protected:
466
  inline explicit EntryFrame(StackFrameIteratorBase* iterator);
467 468 469 470

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

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

477
  friend class StackFrameIteratorBase;
478 479 480 481 482
};


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

485
  Code* unchecked_code() const override;
486 487

  static EntryConstructFrame* cast(StackFrame* frame) {
488
    DCHECK(frame->is_entry_construct());
489 490 491 492
    return static_cast<EntryConstructFrame*>(frame);
  }

 protected:
493
  inline explicit EntryConstructFrame(StackFrameIteratorBase* iterator);
494 495

 private:
496
  friend class StackFrameIteratorBase;
497 498 499 500 501 502
};


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

505
  Code* unchecked_code() const override;
506

507 508
  Object*& code_slot() const;

509
  // Garbage collection support.
510
  void Iterate(ObjectVisitor* v) const override;
511

512
  void SetCallerFp(Address caller_fp) override;
513

514
  static ExitFrame* cast(StackFrame* frame) {
515
    DCHECK(frame->is_exit());
516 517 518 519 520 521 522
    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);
523 524
  static Address ComputeStackPointer(Address fp);
  static void FillState(Address fp, Address sp, State* state);
525 526

 protected:
527
  inline explicit ExitFrame(StackFrameIteratorBase* iterator);
528

529
  Address GetCallerStackPointer() const override;
530 531

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

534
  friend class StackFrameIteratorBase;
535 536 537 538 539 540
};


class StandardFrame: public StackFrame {
 public:
  // Testers.
541
  bool is_standard() const override { return true; }
542 543 544 545 546 547 548 549 550

  // Accessors.
  inline Object* context() const;

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

551
  void SetCallerFp(Address caller_fp) override;
552

553
  static StandardFrame* cast(StackFrame* frame) {
554
    DCHECK(frame->is_standard());
555 556 557 558
    return static_cast<StandardFrame*>(frame);
  }

 protected:
559
  inline explicit StandardFrame(StackFrameIteratorBase* iterator);
560

561
  void ComputeCallerState(State* state) const override;
562 563 564 565 566 567 568 569 570

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

571 572 573 574
  // Computes the address of the constant pool  field in the standard
  // frame given by the provided frame pointer.
  static inline Address ComputeConstantPoolAddress(Address fp);

575 576 577 578 579
  // Iterate over expression stack including stack handlers, locals,
  // and parts of the fixed part including context and code fields.
  void IterateExpressions(ObjectVisitor* v) const;

  // Returns the address of the n'th expression stack element.
580
  virtual Address GetExpressionAddress(int n) const;
581 582 583 584 585

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

586 587 588
  // Determines if the standard frame for the given frame pointer is a
  // construct frame.
  static inline bool IsConstructFrame(Address fp);
589

590 591 592
  // Used by OptimizedFrames and StubFrames.
  void IterateCompiledFrame(ObjectVisitor* v) const;

593 594
 private:
  friend class StackFrame;
595
  friend class SafeStackFrameIterator;
596 597 598
};


599 600
class FrameSummary BASE_EMBEDDED {
 public:
601 602
  FrameSummary(Object* receiver, JSFunction* function,
               AbstractCode* abstract_code, int code_offset,
603 604
               bool is_constructor);

605 606
  Handle<Object> receiver() { return receiver_; }
  Handle<JSFunction> function() { return function_; }
607 608
  Handle<AbstractCode> abstract_code() { return abstract_code_; }
  int code_offset() { return code_offset_; }
609 610 611 612 613 614 615
  bool is_constructor() { return is_constructor_; }

  void Print();

 private:
  Handle<Object> receiver_;
  Handle<JSFunction> function_;
616 617
  Handle<AbstractCode> abstract_code_;
  int code_offset_;
618 619 620
  bool is_constructor_;
};

621
class JavaScriptFrame : public StandardFrame {
622
 public:
623
  Type type() const override { return JAVA_SCRIPT; }
624 625

  // Accessors.
626
  inline JSFunction* function() const;
627 628 629 630
  inline Object* receiver() const;
  inline void set_receiver(Object* value);

  // Access the parameters.
631 632 633 634 635
  inline Address GetParameterSlot(int index) const;
  inline Object* GetParameter(int index) const;
  inline int ComputeParametersCount() const {
    return GetNumberOfIncomingArguments();
  }
636

637 638 639 640 641
  // Access the operand stack.
  inline Address GetOperandSlot(int index) const;
  inline Object* GetOperand(int index) const;
  inline int ComputeOperandsCount() const;

642 643 644
  // Generator support to preserve operand stack.
  void SaveOperandStack(FixedArray* store) const;
  void RestoreOperandStack(FixedArray* store);
645

646 647 648
  // Debugger access.
  void SetParameterValue(int index, Object* value) const;

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

652 653
  // Determines whether this frame includes inlined activations. To get details
  // about the inlined frames use {GetFunctions} and {Summarize}.
654
  bool HasInlinedFrames() const;
655

656 657 658 659
  // 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;
660
  int GetArgumentsLength() const;
661

662
  // Garbage collection support.
663
  void Iterate(ObjectVisitor* v) const override;
664 665

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

  // Determine the code for the frame.
670
  Code* unchecked_code() const override;
671

672
  // Return a list with JSFunctions of this frame.
673
  virtual void GetFunctions(List<JSFunction*>* functions) const;
674 675 676 677

  // Build a list with summaries for this frame including all inlined frames.
  virtual void Summarize(List<FrameSummary>* frames);

678
  // Lookup exception handler for current {pc}, returns -1 if none found. Also
679 680 681 682
  // returns data associated with the handler site specific to the frame type:
  //  - JavaScriptFrame : Data is the stack depth at entry of the try-block.
  //  - OptimizedFrame  : Data is the stack slot count of the entire frame.
  //  - InterpretedFrame: Data is the register index holding the context.
683
  virtual int LookupExceptionHandlerInTable(
684
      int* data, HandlerTable::CatchPrediction* prediction);
685

686 687 688
  // Architecture-specific register description.
  static Register fp_register();
  static Register context_register();
689
  static Register constant_pool_pointer_register();
690

691
  static JavaScriptFrame* cast(StackFrame* frame) {
692
    DCHECK(frame->is_java_script());
693 694 695
    return static_cast<JavaScriptFrame*>(frame);
  }

696 697 698 699 700
  static void PrintFunctionAndOffset(JSFunction* function, Code* code,
                                     Address pc, FILE* file,
                                     bool print_line_number);

  static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
701
                       bool print_line_number);
702

703
 protected:
704
  inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator);
705

706
  Address GetCallerStackPointer() const override;
707

708 709
  virtual int GetNumberOfIncomingArguments() const;

710 711 712 713
  // Garbage collection support. Iterates over incoming arguments,
  // receiver, and any callee-saved registers.
  void IterateArguments(ObjectVisitor* v) const;

714
 private:
715 716
  inline Object* function_slot_object() const;

717
  friend class StackFrameIteratorBase;
718 719 720
};


721 722
class StubFrame : public StandardFrame {
 public:
723
  Type type() const override { return STUB; }
724 725

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

  // Determine the code for the frame.
729
  Code* unchecked_code() const override;
730 731

 protected:
732
  inline explicit StubFrame(StackFrameIteratorBase* iterator);
733

734
  Address GetCallerStackPointer() const override;
735 736 737

  virtual int GetNumberOfIncomingArguments() const;

738
  friend class StackFrameIteratorBase;
739 740 741
};


742
class OptimizedFrame : public JavaScriptFrame {
743
 public:
744
  Type type() const override { return OPTIMIZED; }
745 746

  // GC support.
747
  void Iterate(ObjectVisitor* v) const override;
748 749 750 751

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

754
  void Summarize(List<FrameSummary>* frames) override;
755

756
  // Lookup exception handler for current {pc}, returns -1 if none found.
757
  int LookupExceptionHandlerInTable(
758
      int* data, HandlerTable::CatchPrediction* prediction) override;
759

760
  DeoptimizationInputData* GetDeoptimizationData(int* deopt_index) const;
761

762 763
  static int StackSlotOffsetRelativeToFp(int slot_index);

764
 protected:
765
  inline explicit OptimizedFrame(StackFrameIteratorBase* iterator);
766 767

 private:
768
  friend class StackFrameIteratorBase;
769 770

  Object* StackSlotAt(int index) const;
771 772 773
};


774
class InterpretedFrame : public JavaScriptFrame {
775
 public:
776
  Type type() const override { return INTERPRETED; }
777

778
  // Lookup exception handler for current {pc}, returns -1 if none found.
779
  int LookupExceptionHandlerInTable(
780
      int* data, HandlerTable::CatchPrediction* prediction) override;
781 782 783 784 785 786 787 788

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

789 790
  // Returns the frame's current bytecode array.
  Object* GetBytecodeArray() const;
791

792 793 794
  // Updates the frame's BytecodeArray with |bytecode_array|. Used by the
  // debugger to swap execution onto a BytecodeArray patched with breakpoints.
  void PatchBytecodeArray(Object* bytecode_array);
795

796 797 798
  // Access to the interpreter register file for this frame.
  Object* GetInterpreterRegister(int register_index) const;

799 800 801
  // Build a list with summaries for this frame including all inlined frames.
  void Summarize(List<FrameSummary>* frames) override;

802 803 804
 protected:
  inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);

805 806
  Address GetExpressionAddress(int n) const override;

807 808 809 810 811
 private:
  friend class StackFrameIteratorBase;
};


812 813 814 815 816
// 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:
817
  Type type() const override { return ARGUMENTS_ADAPTOR; }
818 819

  // Determine the code for the frame.
820
  Code* unchecked_code() const override;
821 822

  static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
823
    DCHECK(frame->is_arguments_adaptor());
824 825 826 827
    return static_cast<ArgumentsAdaptorFrame*>(frame);
  }

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

831 832
  static int GetLength(Address fp);

833
 protected:
834
  inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator);
835

836
  int GetNumberOfIncomingArguments() const override;
837

838
  Address GetCallerStackPointer() const override;
839 840

 private:
841
  friend class StackFrameIteratorBase;
842 843
};

844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865
class WasmFrame : public StandardFrame {
 public:
  Type type() const override { return WASM; }

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

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

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

 protected:
  inline explicit WasmFrame(StackFrameIteratorBase* iterator);

  Address GetCallerStackPointer() const override;

 private:
  friend class StackFrameIteratorBase;
};
866 867 868

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

871
  // Garbage collection support.
872
  void Iterate(ObjectVisitor* v) const override;
873 874

  // Determine the code for the frame.
875
  Code* unchecked_code() const override;
876 877

  static InternalFrame* cast(StackFrame* frame) {
878
    DCHECK(frame->is_internal());
879 880 881 882
    return static_cast<InternalFrame*>(frame);
  }

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

885
  Address GetCallerStackPointer() const override;
886 887

 private:
888
  friend class StackFrameIteratorBase;
889 890 891
};


892
class StubFailureTrampolineFrame: public StandardFrame {
893
 public:
894 895 896 897 898 899 900 901
  // sizeof(Arguments) - sizeof(Arguments*) is 3 * kPointerSize), but the
  // presubmit script complains about using sizeof() on a type.
  static const int kFirstRegisterParameterFrameOffset =
      StandardFrameConstants::kMarkerOffset - 3 * kPointerSize;

  static const int kCallerStackParameterCountFrameOffset =
      StandardFrameConstants::kMarkerOffset - 2 * kPointerSize;

902
  Type type() const override { return STUB_FAILURE_TRAMPOLINE; }
903

904 905
  // Get the code associated with this frame.
  // This method could be called during marking phase of GC.
906
  Code* unchecked_code() const override;
907

908
  void Iterate(ObjectVisitor* v) const override;
909

910 911 912
  // Architecture-specific register description.
  static Register fp_register();
  static Register context_register();
913
  static Register constant_pool_pointer_register();
914

915 916
 protected:
  inline explicit StubFailureTrampolineFrame(
917
      StackFrameIteratorBase* iterator);
918

919
  Address GetCallerStackPointer() const override;
920

921
 private:
922
  friend class StackFrameIteratorBase;
923 924 925
};


926 927 928 929
// Construct frames are special trampoline frames introduced to handle
// function invocations through 'new'.
class ConstructFrame: public InternalFrame {
 public:
930
  Type type() const override { return CONSTRUCT; }
931 932

  static ConstructFrame* cast(StackFrame* frame) {
933
    DCHECK(frame->is_construct());
934 935 936 937
    return static_cast<ConstructFrame*>(frame);
  }

 protected:
938
  inline explicit ConstructFrame(StackFrameIteratorBase* iterator);
939 940

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


945
class StackFrameIteratorBase BASE_EMBEDDED {
946
 public:
947 948
  Isolate* isolate() const { return isolate_; }

949
  bool done() const { return frame_ == NULL; }
950

951 952 953
 protected:
  // An iterator that iterates over a given thread's stack.
  StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects);
954

955
  Isolate* isolate_;
956 957 958 959 960
#define DECLARE_SINGLETON(ignore, type) type type##_;
  STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
#undef DECLARE_SINGLETON
  StackFrame* frame_;
  StackHandler* handler_;
961
  const bool can_access_heap_objects_;
962 963

  StackHandler* handler() const {
964
    DCHECK(!done());
965 966 967 968 969
    return handler_;
  }

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

973
 private:
974
  friend class StackFrame;
975 976 977 978 979 980 981 982 983 984 985 986
  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 {
987
    DCHECK(!done());
988 989 990 991 992 993 994 995
    return frame_;
  }
  void Advance();

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

996
  DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
997 998 999
};

// Iterator that supports iterating through all JavaScript frames.
1000
class JavaScriptFrameIterator BASE_EMBEDDED {
1001
 public:
1002 1003
  inline explicit JavaScriptFrameIterator(Isolate* isolate);
  inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top);
1004
  // Skip frames until the frame with the given id is reached.
1005
  JavaScriptFrameIterator(Isolate* isolate, StackFrame::Id id);
1006

1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017
  inline JavaScriptFrame* frame() const;

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

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

 private:
1018
  StackFrameIterator iterator_;
1019 1020 1021 1022 1023 1024 1025 1026
};

// NOTE: The stack trace frame iterator is an iterator that only
// traverse proper JavaScript frames; that is JavaScript frames that
// have proper JavaScript functions. This excludes the problematic
// functions in runtime.js.
class StackTraceFrameIterator: public JavaScriptFrameIterator {
 public:
1027
  explicit StackTraceFrameIterator(Isolate* isolate);
1028
  void Advance();
1029 1030 1031

 private:
  bool IsValidFrame();
1032 1033 1034
};


1035
class SafeStackFrameIterator: public StackFrameIteratorBase {
1036
 public:
1037 1038
  SafeStackFrameIterator(Isolate* isolate,
                         Address fp, Address sp,
1039
                         Address js_entry_sp);
1040

1041
  inline StackFrame* frame() const;
1042 1043
  void Advance();

1044 1045
  StackFrame::Type top_frame_type() const { return top_frame_type_; }

1046
 private:
1047 1048
  void AdvanceOneFrame();

1049
  bool IsValidStackAddress(Address addr) const {
1050
    return low_bound_ <= addr && addr <= high_bound_;
1051
  }
1052 1053
  bool IsValidFrame(StackFrame* frame) const;
  bool IsValidCaller(StackFrame* frame);
1054 1055
  bool IsValidExitFrame(Address fp) const;
  bool IsValidTop(ThreadLocalTop* top) const;
1056

1057 1058
  const Address low_bound_;
  const Address high_bound_;
1059
  StackFrame::Type top_frame_type_;
1060
  ExternalCallbackScope* external_callback_scope_;
1061 1062 1063 1064 1065
};


class StackFrameLocator BASE_EMBEDDED {
 public:
1066 1067
  explicit StackFrameLocator(Isolate* isolate) : iterator_(isolate) {}

1068 1069 1070 1071 1072 1073 1074 1075 1076
  // Find the nth JavaScript frame on the stack. The caller must
  // guarantee that such a frame exists.
  JavaScriptFrame* FindJavaScriptFrame(int n);

 private:
  StackFrameIterator iterator_;
};


1077 1078
// Reads all frames on the current stack and copies them into the current
// zone memory.
1079
Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone);
1080

1081 1082
}  // namespace internal
}  // namespace v8
1083 1084

#endif  // V8_FRAMES_H_