frames.h 28.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 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
};


101
#define STACK_FRAME_TYPE_LIST(V)                         \
102 103 104 105 106 107 108
  V(ENTRY, EntryFrame)                                   \
  V(ENTRY_CONSTRUCT, EntryConstructFrame)                \
  V(EXIT, ExitFrame)                                     \
  V(JAVA_SCRIPT, JavaScriptFrame)                        \
  V(OPTIMIZED, OptimizedFrame)                           \
  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
class StandardFrameConstants : public AllStatic {
 public:
  // Fixed part of the frame consists of return address, caller fp,
118 119 120
  // constant pool (if FLAG_enable_embedded_constant_pool), context, and
  // function. StandardFrame::IterateExpressions assumes that kLastObjectOffset
  // is the last object pointer.
121
  static const int kCPSlotSize =
122
      FLAG_enable_embedded_constant_pool ? kPointerSize : 0;
123
  static const int kFixedFrameSizeFromFp =  2 * kPointerSize + kCPSlotSize;
124
  static const int kFixedFrameSizeAboveFp = kPCOnStackSize + kFPOnStackSize;
125
  static const int kFixedFrameSize =
126 127 128 129
      kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp;
  static const int kFixedSlotCountAboveFp =
      kFixedFrameSizeAboveFp / kPointerSize;
  static const int kFixedSlotCount = kFixedFrameSize / kPointerSize;
130
  static const int kCPSlotCount = kCPSlotSize / kPointerSize;
131 132 133 134 135 136 137 138 139
  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;
140 141 142
};


143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
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 =
164
      StandardFrameConstants::kExpressionsOffset - 4 * kPointerSize;
165
  static const int kOriginalConstructorOffset =
166
      StandardFrameConstants::kExpressionsOffset - 3 * kPointerSize;
167
  static const int kLengthOffset =
168 169
      StandardFrameConstants::kExpressionsOffset - 2 * kPointerSize;
  static const int kAllocationSiteOffset =
170 171 172 173 174
      StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
  static const int kCodeOffset =
      StandardFrameConstants::kExpressionsOffset - 0 * kPointerSize;

  static const int kFrameSize =
175
      StandardFrameConstants::kFixedFrameSize + 5 * kPointerSize;
176 177 178
};


179 180 181 182 183
class InterpreterFrameConstants : public AllStatic {
 public:
  // Register file pointer relative.
  static const int kLastParamFromRegisterPointer =
      StandardFrameConstants::kFixedFrameSize + kPointerSize;
184
  static const int kFunctionFromRegisterPointer = kPointerSize;
185
  static const int kContextFromRegisterPointer = 2 * kPointerSize;
186 187 188
};


189 190 191 192 193 194 195
// 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)
196 197 198 199
    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
200 201 202 203 204
  };
#undef DECLARE_TYPE

  // Opaque data type for identifying stack frames. Used extensively
  // by the debugger.
205 206 207 208 209 210 211
  // 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
  };
212

213 214 215 216 217 218
  // Used to mark the outermost JS entry frame.
  enum JsFrameMarker {
    INNER_JSENTRY_FRAME = 0,
    OUTERMOST_JSENTRY_FRAME = 1
  };

219
  struct State {
220 221
    State() : sp(NULL), fp(NULL), pc_address(NULL),
              constant_pool_address(NULL) { }
222 223 224
    Address sp;
    Address fp;
    Address* pc_address;
225
    Address* constant_pool_address;
226 227
  };

228 229
  // Copy constructor; it breaks the connection to host iterator
  // (as an iterator usually lives on stack).
230 231 232
  StackFrame(const StackFrame& original) {
    this->state_ = original.state_;
    this->iterator_ = NULL;
233
    this->isolate_ = original.isolate_;
234 235
  }

236 237 238 239
  // 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; }
240
  bool is_optimized() const { return type() == OPTIMIZED; }
241 242
  bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
  bool is_internal() const { return type() == INTERNAL; }
243 244 245
  bool is_stub_failure_trampoline() const {
    return type() == STUB_FAILURE_TRAMPOLINE;
  }
246
  bool is_construct() const { return type() == CONSTRUCT; }
247 248
  virtual bool is_standard() const { return false; }

249 250
  bool is_java_script() const {
    Type type = this->type();
251 252
    return (type == JAVA_SCRIPT) || (type == OPTIMIZED) ||
           (type == INTERPRETED);
253 254
  }

255 256 257
  // Accessors.
  Address sp() const { return state_.sp; }
  Address fp() const { return state_.fp; }
258
  Address caller_sp() const { return GetCallerStackPointer(); }
259

260 261 262 263 264
  // 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;

265 266 267
  Address pc() const { return *pc_address(); }
  void set_pc(Address pc) { *pc_address() = pc; }

268
  Address constant_pool() const { return *constant_pool_address(); }
269 270
  void set_constant_pool(Address constant_pool) {
    *constant_pool_address() = constant_pool;
271 272
  }

273 274
  virtual void SetCallerFp(Address caller_fp) = 0;

275 276 277
  // Manually changes value of fp in this object.
  void UpdateFp(Address fp) { state_.fp = fp; }

278 279
  Address* pc_address() const { return state_.pc_address; }

280 281 282 283
  Address* constant_pool_address() const {
    return state_.constant_pool_address;
  }

284
  // Get the id of this stack frame.
285
  Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
286

287 288 289
  // Get the top handler from the current stack iterator.
  inline StackHandler* top_handler() const;

290 291 292 293
  // Get the type of this frame.
  virtual Type type() const = 0;

  // Get the code associated with this frame.
294 295 296 297
  // This method could be called during marking phase of GC.
  virtual Code* unchecked_code() const = 0;

  // Get the code associated with this frame.
298
  inline Code* LookupCode() const;
299 300

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

303 304 305
  // 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.
306 307
  static Code* GetSafepointData(Isolate* isolate,
                                Address pc,
308
                                SafepointEntry* safepoint_entry,
309 310
                                unsigned* stack_slots);

311
  virtual void Iterate(ObjectVisitor* v) const = 0;
312 313
  static void IteratePc(ObjectVisitor* v, Address* pc_address,
                        Address* constant_pool_address, Code* holder);
314

315 316 317 318 319
  // 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);
320

321 322 323
  // Resolves pc_address through the resolution address function if one is set.
  static inline Address* ResolveReturnAddressLocation(Address* pc_address);

324 325 326 327 328 329
  // Printing support.
  enum PrintMode { OVERVIEW, DETAILS };
  virtual void Print(StringStream* accumulator,
                     PrintMode mode,
                     int index) const { }

330 331
  Isolate* isolate() const { return isolate_; }

332
 protected:
333
  inline explicit StackFrame(StackFrameIteratorBase* iterator);
334 335 336 337 338 339 340 341 342 343 344
  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.
345
  static Type ComputeType(const StackFrameIteratorBase* iterator, State* state);
346 347 348 349

#ifdef DEBUG
  bool can_access_heap_objects() const;
#endif
350 351

 private:
352
  const StackFrameIteratorBase* iterator_;
353
  Isolate* isolate_;
354
  State state_;
355

356 357
  static ReturnAddressLocationResolver return_address_location_resolver_;

358 359 360
  // Fill in the state of the calling frame.
  virtual void ComputeCallerState(State* state) const = 0;

361
  // Get the type and the state of the calling frame.
362
  virtual Type GetCallerState(State* state) const;
363

364 365
  static const intptr_t kIsolateTag = 1;

366
  friend class StackFrameIterator;
367
  friend class StackFrameIteratorBase;
368
  friend class StackHandlerIterator;
369
  friend class SafeStackFrameIterator;
370

371 372
 private:
  void operator=(const StackFrame& original);
373 374 375 376 377 378 379 380
};


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

381
  virtual Code* unchecked_code() const;
382 383 384 385 386

  // Garbage collection support.
  virtual void Iterate(ObjectVisitor* v) const;

  static EntryFrame* cast(StackFrame* frame) {
387
    DCHECK(frame->is_entry());
388 389
    return static_cast<EntryFrame*>(frame);
  }
390
  virtual void SetCallerFp(Address caller_fp);
391 392

 protected:
393
  inline explicit EntryFrame(StackFrameIteratorBase* iterator);
394 395 396 397 398 399 400

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

 private:
401
  virtual void ComputeCallerState(State* state) const;
402 403
  virtual Type GetCallerState(State* state) const;

404
  friend class StackFrameIteratorBase;
405 406 407 408 409 410 411
};


class EntryConstructFrame: public EntryFrame {
 public:
  virtual Type type() const { return ENTRY_CONSTRUCT; }

412
  virtual Code* unchecked_code() const;
413 414

  static EntryConstructFrame* cast(StackFrame* frame) {
415
    DCHECK(frame->is_entry_construct());
416 417 418 419
    return static_cast<EntryConstructFrame*>(frame);
  }

 protected:
420
  inline explicit EntryConstructFrame(StackFrameIteratorBase* iterator);
421 422

 private:
423
  friend class StackFrameIteratorBase;
424 425 426 427 428 429 430 431
};


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

432
  virtual Code* unchecked_code() const;
433

434 435
  Object*& code_slot() const;

436
  // Garbage collection support.
437 438
  virtual void Iterate(ObjectVisitor* v) const;

439 440
  virtual void SetCallerFp(Address caller_fp);

441
  static ExitFrame* cast(StackFrame* frame) {
442
    DCHECK(frame->is_exit());
443 444 445 446 447 448 449
    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);
450 451
  static Address ComputeStackPointer(Address fp);
  static void FillState(Address fp, Address sp, State* state);
452 453

 protected:
454
  inline explicit ExitFrame(StackFrameIteratorBase* iterator);
455 456 457 458

  virtual Address GetCallerStackPointer() const;

 private:
459
  virtual void ComputeCallerState(State* state) const;
460

461
  friend class StackFrameIteratorBase;
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
};


class StandardFrame: public StackFrame {
 public:
  // Testers.
  virtual bool is_standard() const { return true; }

  // 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;
477
  static Object* GetExpression(Address fp, int index);
478

479 480
  virtual void SetCallerFp(Address caller_fp);

481
  static StandardFrame* cast(StackFrame* frame) {
482
    DCHECK(frame->is_standard());
483 484 485 486
    return static_cast<StandardFrame*>(frame);
  }

 protected:
487
  inline explicit StandardFrame(StackFrameIteratorBase* iterator);
488

489
  virtual void ComputeCallerState(State* state) const;
490 491 492 493 494 495 496 497 498

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

499 500 501 502
  // Computes the address of the constant pool  field in the standard
  // frame given by the provided frame pointer.
  static inline Address ComputeConstantPoolAddress(Address fp);

503 504 505 506 507 508
  // 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.
  Address GetExpressionAddress(int n) const;
509
  static Address GetExpressionAddress(Address fp, int n);
510 511 512 513 514

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

515 516 517
  // Determines if the standard frame for the given frame pointer is a
  // construct frame.
  static inline bool IsConstructFrame(Address fp);
518

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

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


528 529
class FrameSummary BASE_EMBEDDED {
 public:
530 531 532
  FrameSummary(Object* receiver, JSFunction* function, Code* code, int offset,
               bool is_constructor);

533 534 535
  Handle<Object> receiver() { return receiver_; }
  Handle<JSFunction> function() { return function_; }
  Handle<Code> code() { return code_; }
536
  Address pc() { return code_->address() + offset_; }
537 538 539 540 541 542 543 544 545 546 547 548 549 550
  int offset() { return offset_; }
  bool is_constructor() { return is_constructor_; }

  void Print();

 private:
  Handle<Object> receiver_;
  Handle<JSFunction> function_;
  Handle<Code> code_;
  int offset_;
  bool is_constructor_;
};


551 552 553 554 555
class JavaScriptFrame: public StandardFrame {
 public:
  virtual Type type() const { return JAVA_SCRIPT; }

  // Accessors.
556
  inline JSFunction* function() const;
557 558 559 560
  inline Object* receiver() const;
  inline void set_receiver(Object* value);

  // Access the parameters.
561 562 563 564 565
  inline Address GetParameterSlot(int index) const;
  inline Object* GetParameter(int index) const;
  inline int ComputeParametersCount() const {
    return GetNumberOfIncomingArguments();
  }
566

567 568 569 570 571
  // Access the operand stack.
  inline Address GetOperandSlot(int index) const;
  inline Object* GetOperand(int index) const;
  inline int ComputeOperandsCount() const;

572 573 574
  // Generator support to preserve operand stack.
  void SaveOperandStack(FixedArray* store) const;
  void RestoreOperandStack(FixedArray* store);
575

576 577 578
  // Debugger access.
  void SetParameterValue(int index, Object* value) const;

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

582 583 584 585
  // Determines whether this frame includes inlined activations. To get details
  // about the inlined frames use {GetFunctions} and {Summarize}.
  bool HasInlinedFrames();

586 587 588 589
  // Returns the original constructor function that was used in the constructor
  // call to this frame. Note that this is only valid on constructor frames.
  Object* GetOriginalConstructor() const;

590 591 592 593
  // 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;
594
  int GetArgumentsLength() const;
595

596
  // Garbage collection support.
597 598 599 600 601 602 603 604
  virtual void Iterate(ObjectVisitor* v) const;

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

  // Determine the code for the frame.
605
  virtual Code* unchecked_code() const;
606

607 608 609 610 611 612
  // Return a list with JSFunctions of this frame.
  virtual void GetFunctions(List<JSFunction*>* functions);

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

613 614
  // Lookup exception handler for current {pc}, returns -1 if none found. Also
  // returns the expected number of stack slots at the handler site.
615 616
  virtual int LookupExceptionHandlerInTable(
      int* stack_slots, HandlerTable::CatchPrediction* prediction);
617

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

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

628 629 630 631 632
  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,
633
                       bool print_line_number);
634

635
 protected:
636
  inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator);
637 638 639

  virtual Address GetCallerStackPointer() const;

640 641
  virtual int GetNumberOfIncomingArguments() const;

642 643 644 645
  // Garbage collection support. Iterates over incoming arguments,
  // receiver, and any callee-saved registers.
  void IterateArguments(ObjectVisitor* v) const;

646
 private:
647 648
  inline Object* function_slot_object() const;

649
  friend class StackFrameIteratorBase;
650 651 652
};


653 654 655 656 657 658 659 660 661 662 663
class StubFrame : public StandardFrame {
 public:
  virtual Type type() const { return STUB; }

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

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

 protected:
664
  inline explicit StubFrame(StackFrameIteratorBase* iterator);
665 666 667 668 669

  virtual Address GetCallerStackPointer() const;

  virtual int GetNumberOfIncomingArguments() const;

670
  friend class StackFrameIteratorBase;
671 672 673
};


674
class OptimizedFrame : public JavaScriptFrame {
675 676 677 678 679 680 681 682 683 684 685 686 687
 public:
  virtual Type type() const { return OPTIMIZED; }

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

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

  virtual void Summarize(List<FrameSummary>* frames);

688 689
  // Lookup exception handler for current {pc}, returns -1 if none found. Also
  // returns the expected number of stack slots at the handler site.
690 691
  virtual int LookupExceptionHandlerInTable(
      int* stack_slots, HandlerTable::CatchPrediction* prediction);
692

693 694
  DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);

695 696
  static int StackSlotOffsetRelativeToFp(int slot_index);

697
 protected:
698
  inline explicit OptimizedFrame(StackFrameIteratorBase* iterator);
699 700

 private:
701
  friend class StackFrameIteratorBase;
702 703

  Object* StackSlotAt(int index) const;
704 705 706
};


707 708 709 710 711 712 713 714 715 716 717
class InterpretedFrame : public JavaScriptFrame {
  virtual Type type() const { return INTERPRETED; }

 protected:
  inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);

 private:
  friend class StackFrameIteratorBase;
};


718 719 720 721 722 723 724 725
// 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:
  virtual Type type() const { return ARGUMENTS_ADAPTOR; }

  // Determine the code for the frame.
726
  virtual Code* unchecked_code() const;
727 728

  static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
729
    DCHECK(frame->is_arguments_adaptor());
730 731 732 733 734 735 736
    return static_cast<ArgumentsAdaptorFrame*>(frame);
  }

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

738
 protected:
739
  inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator);
740

741
  virtual int GetNumberOfIncomingArguments() const;
742

743 744 745
  virtual Address GetCallerStackPointer() const;

 private:
746
  friend class StackFrameIteratorBase;
747 748 749 750 751 752 753
};


class InternalFrame: public StandardFrame {
 public:
  virtual Type type() const { return INTERNAL; }

754
  // Garbage collection support.
755 756 757
  virtual void Iterate(ObjectVisitor* v) const;

  // Determine the code for the frame.
758
  virtual Code* unchecked_code() const;
759 760

  static InternalFrame* cast(StackFrame* frame) {
761
    DCHECK(frame->is_internal());
762 763 764 765
    return static_cast<InternalFrame*>(frame);
  }

 protected:
766
  inline explicit InternalFrame(StackFrameIteratorBase* iterator);
767 768 769 770

  virtual Address GetCallerStackPointer() const;

 private:
771
  friend class StackFrameIteratorBase;
772 773 774
};


775
class StubFailureTrampolineFrame: public StandardFrame {
776
 public:
777 778 779 780 781 782 783 784
  // 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;

785 786
  virtual Type type() const { return STUB_FAILURE_TRAMPOLINE; }

787 788 789 790
  // Get the code associated with this frame.
  // This method could be called during marking phase of GC.
  virtual Code* unchecked_code() const;

791 792
  virtual void Iterate(ObjectVisitor* v) const;

793 794 795
  // Architecture-specific register description.
  static Register fp_register();
  static Register context_register();
796
  static Register constant_pool_pointer_register();
797

798 799
 protected:
  inline explicit StubFailureTrampolineFrame(
800
      StackFrameIteratorBase* iterator);
801

802 803
  virtual Address GetCallerStackPointer() const;

804
 private:
805
  friend class StackFrameIteratorBase;
806 807 808
};


809 810 811 812 813 814 815
// Construct frames are special trampoline frames introduced to handle
// function invocations through 'new'.
class ConstructFrame: public InternalFrame {
 public:
  virtual Type type() const { return CONSTRUCT; }

  static ConstructFrame* cast(StackFrame* frame) {
816
    DCHECK(frame->is_construct());
817 818 819 820
    return static_cast<ConstructFrame*>(frame);
  }

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

 private:
824
  friend class StackFrameIteratorBase;
825 826 827
};


828
class StackFrameIteratorBase BASE_EMBEDDED {
829
 public:
830 831
  Isolate* isolate() const { return isolate_; }

832
  bool done() const { return frame_ == NULL; }
833

834 835 836
 protected:
  // An iterator that iterates over a given thread's stack.
  StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects);
837

838
  Isolate* isolate_;
839 840 841 842 843
#define DECLARE_SINGLETON(ignore, type) type type##_;
  STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
#undef DECLARE_SINGLETON
  StackFrame* frame_;
  StackHandler* handler_;
844
  const bool can_access_heap_objects_;
845 846

  StackHandler* handler() const {
847
    DCHECK(!done());
848 849 850 851 852
    return handler_;
  }

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

856
 private:
857
  friend class StackFrame;
858 859 860 861 862 863 864 865 866 867 868 869
  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 {
870
    DCHECK(!done());
871 872 873 874 875 876 877 878
    return frame_;
  }
  void Advance();

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

879
  DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
880 881 882 883
};


// Iterator that supports iterating through all JavaScript frames.
884
class JavaScriptFrameIterator BASE_EMBEDDED {
885
 public:
886 887
  inline explicit JavaScriptFrameIterator(Isolate* isolate);
  inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top);
888
  // Skip frames until the frame with the given id is reached.
889
  JavaScriptFrameIterator(Isolate* isolate, StackFrame::Id id);
890

891 892 893 894 895 896 897 898 899 900 901
  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:
902
  StackFrameIterator iterator_;
903 904 905 906 907 908 909 910 911
};


// 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:
912
  explicit StackTraceFrameIterator(Isolate* isolate);
913
  void Advance();
914 915 916

 private:
  bool IsValidFrame();
917 918 919
};


920
class SafeStackFrameIterator: public StackFrameIteratorBase {
921
 public:
922 923
  SafeStackFrameIterator(Isolate* isolate,
                         Address fp, Address sp,
924
                         Address js_entry_sp);
925

926
  inline StackFrame* frame() const;
927 928
  void Advance();

929 930
  StackFrame::Type top_frame_type() const { return top_frame_type_; }

931
 private:
932 933
  void AdvanceOneFrame();

934
  bool IsValidStackAddress(Address addr) const {
935
    return low_bound_ <= addr && addr <= high_bound_;
936
  }
937 938
  bool IsValidFrame(StackFrame* frame) const;
  bool IsValidCaller(StackFrame* frame);
939 940
  bool IsValidExitFrame(Address fp) const;
  bool IsValidTop(ThreadLocalTop* top) const;
941

942 943
  const Address low_bound_;
  const Address high_bound_;
944
  StackFrame::Type top_frame_type_;
945
  ExternalCallbackScope* external_callback_scope_;
946 947 948 949 950
};


class StackFrameLocator BASE_EMBEDDED {
 public:
951 952
  explicit StackFrameLocator(Isolate* isolate) : iterator_(isolate) {}

953 954 955 956 957 958 959 960 961
  // Find the nth JavaScript frame on the stack. The caller must
  // guarantee that such a frame exists.
  JavaScriptFrame* FindJavaScriptFrame(int n);

 private:
  StackFrameIterator iterator_;
};


962 963
// Reads all frames on the current stack and copies them into the current
// zone memory.
964
Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone);
965

966 967
}  // namespace internal
}  // namespace v8
968 969

#endif  // V8_FRAMES_H_