Home | History | Annotate | Download | only in src
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_FRAMES_H_
      6 #define V8_FRAMES_H_
      7 
      8 #include "src/handles.h"
      9 #include "src/objects.h"
     10 #include "src/objects/code.h"
     11 #include "src/safepoint-table.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 namespace wasm {
     16 class WasmCode;
     17 }
     18 
     19 // Forward declarations.
     20 class AbstractCode;
     21 class Debug;
     22 class ExternalCallbackScope;
     23 class Isolate;
     24 class ObjectVisitor;
     25 class RootVisitor;
     26 class StackFrameIteratorBase;
     27 class StringStream;
     28 class ThreadLocalTop;
     29 class WasmDebugInfo;
     30 class WasmInstanceObject;
     31 class WasmModuleObject;
     32 
     33 class InnerPointerToCodeCache {
     34  public:
     35   struct InnerPointerToCodeCacheEntry {
     36     Address inner_pointer;
     37     Code* code;
     38     SafepointEntry safepoint_entry;
     39   };
     40 
     41   explicit InnerPointerToCodeCache(Isolate* isolate) : isolate_(isolate) {
     42     Flush();
     43   }
     44 
     45   void Flush() {
     46     memset(&cache_[0], 0, sizeof(cache_));
     47   }
     48 
     49   InnerPointerToCodeCacheEntry* GetCacheEntry(Address inner_pointer);
     50 
     51  private:
     52   InnerPointerToCodeCacheEntry* cache(int index) { return &cache_[index]; }
     53 
     54   Isolate* isolate_;
     55 
     56   static const int kInnerPointerToCodeCacheSize = 1024;
     57   InnerPointerToCodeCacheEntry cache_[kInnerPointerToCodeCacheSize];
     58 
     59   DISALLOW_COPY_AND_ASSIGN(InnerPointerToCodeCache);
     60 };
     61 
     62 
     63 class StackHandlerConstants : public AllStatic {
     64  public:
     65   static const int kNextOffset = 0 * kPointerSize;
     66   static const int kPaddingOffset = 1 * kPointerSize;
     67 
     68   static const int kSize = kPaddingOffset + kPointerSize;
     69   static const int kSlotCount = kSize >> kPointerSizeLog2;
     70 };
     71 
     72 
     73 class StackHandler BASE_EMBEDDED {
     74  public:
     75   // Get the address of this stack handler.
     76   inline Address address() const;
     77 
     78   // Get the next stack handler in the chain.
     79   inline StackHandler* next() const;
     80 
     81   // Conversion support.
     82   static inline StackHandler* FromAddress(Address address);
     83 
     84  private:
     85   DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
     86 };
     87 
     88 #define STACK_FRAME_TYPE_LIST(V)                                          \
     89   V(ENTRY, EntryFrame)                                                    \
     90   V(CONSTRUCT_ENTRY, ConstructEntryFrame)                                 \
     91   V(EXIT, ExitFrame)                                                      \
     92   V(OPTIMIZED, OptimizedFrame)                                            \
     93   V(WASM_COMPILED, WasmCompiledFrame)                                     \
     94   V(WASM_TO_JS, WasmToJsFrame)                                            \
     95   V(JS_TO_WASM, JsToWasmFrame)                                            \
     96   V(WASM_INTERPRETER_ENTRY, WasmInterpreterEntryFrame)                    \
     97   V(C_WASM_ENTRY, CWasmEntryFrame)                                        \
     98   V(WASM_COMPILE_LAZY, WasmCompileLazyFrame)                              \
     99   V(INTERPRETED, InterpretedFrame)                                        \
    100   V(STUB, StubFrame)                                                      \
    101   V(BUILTIN_CONTINUATION, BuiltinContinuationFrame)                       \
    102   V(JAVA_SCRIPT_BUILTIN_CONTINUATION, JavaScriptBuiltinContinuationFrame) \
    103   V(JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH,                          \
    104     JavaScriptBuiltinContinuationWithCatchFrame)                          \
    105   V(INTERNAL, InternalFrame)                                              \
    106   V(CONSTRUCT, ConstructFrame)                                            \
    107   V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)                             \
    108   V(BUILTIN, BuiltinFrame)                                                \
    109   V(BUILTIN_EXIT, BuiltinExitFrame)                                       \
    110   V(NATIVE, NativeFrame)
    111 
    112 // Abstract base class for all stack frames.
    113 class StackFrame BASE_EMBEDDED {
    114  public:
    115 #define DECLARE_TYPE(type, ignore) type,
    116   enum Type {
    117     NONE = 0,
    118     STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
    119     NUMBER_OF_TYPES,
    120     // Used by FrameScope to indicate that the stack frame is constructed
    121     // manually and the FrameScope does not need to emit code.
    122     MANUAL
    123   };
    124 #undef DECLARE_TYPE
    125 
    126   // Opaque data type for identifying stack frames. Used extensively
    127   // by the debugger.
    128   // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
    129   // has correct value range (see Issue 830 for more details).
    130   enum Id {
    131     ID_MIN_VALUE = kMinInt,
    132     ID_MAX_VALUE = kMaxInt,
    133     NO_ID = 0
    134   };
    135 
    136   // Used to mark the outermost JS entry frame.
    137   //
    138   // The mark is an opaque value that should be pushed onto the stack directly,
    139   // carefully crafted to not be interpreted as a tagged pointer.
    140   enum JsFrameMarker {
    141     INNER_JSENTRY_FRAME = (0 << kSmiTagSize) | kSmiTag,
    142     OUTERMOST_JSENTRY_FRAME = (1 << kSmiTagSize) | kSmiTag
    143   };
    144   STATIC_ASSERT((INNER_JSENTRY_FRAME & kHeapObjectTagMask) != kHeapObjectTag);
    145   STATIC_ASSERT((OUTERMOST_JSENTRY_FRAME & kHeapObjectTagMask) !=
    146                 kHeapObjectTag);
    147 
    148   struct State {
    149     Address sp = kNullAddress;
    150     Address fp = kNullAddress;
    151     Address* pc_address = nullptr;
    152     Address* callee_pc_address = nullptr;
    153     Address* constant_pool_address = nullptr;
    154   };
    155 
    156   // Convert a stack frame type to a marker that can be stored on the stack.
    157   //
    158   // The marker is an opaque value, not intended to be interpreted in any way
    159   // except being checked by IsTypeMarker or converted by MarkerToType.
    160   // It has the same tagging as Smis, so any marker value that does not pass
    161   // IsTypeMarker can instead be interpreted as a tagged pointer.
    162   //
    163   // Note that the marker is not a Smi: Smis on 64-bit architectures are stored
    164   // in the top 32 bits of a 64-bit value, which in turn makes them expensive
    165   // (in terms of code/instruction size) to push as immediates onto the stack.
    166   static int32_t TypeToMarker(Type type) {
    167     DCHECK_GE(type, 0);
    168     return (type << kSmiTagSize) | kSmiTag;
    169   }
    170 
    171   // Convert a marker back to a stack frame type.
    172   //
    173   // Unlike the return value of TypeToMarker, this takes an intptr_t, as that is
    174   // the type of the value on the stack.
    175   static Type MarkerToType(intptr_t marker) {
    176     DCHECK(IsTypeMarker(marker));
    177     return static_cast<Type>(marker >> kSmiTagSize);
    178   }
    179 
    180   // Check if a marker is a stack frame type marker or a tagged pointer.
    181   //
    182   // Returns true if the given marker is tagged as a stack frame type marker,
    183   // and should be converted back to a stack frame type using MarkerToType.
    184   // Otherwise, the value is a tagged function pointer.
    185   static bool IsTypeMarker(intptr_t function_or_marker) {
    186     return (function_or_marker & kSmiTagMask) == kSmiTag;
    187   }
    188 
    189   // Copy constructor; it breaks the connection to host iterator
    190   // (as an iterator usually lives on stack).
    191   StackFrame(const StackFrame& original) {
    192     this->state_ = original.state_;
    193     this->iterator_ = nullptr;
    194     this->isolate_ = original.isolate_;
    195   }
    196 
    197   // Type testers.
    198   bool is_entry() const { return type() == ENTRY; }
    199   bool is_construct_entry() const { return type() == CONSTRUCT_ENTRY; }
    200   bool is_exit() const { return type() == EXIT; }
    201   bool is_optimized() const { return type() == OPTIMIZED; }
    202   bool is_interpreted() const { return type() == INTERPRETED; }
    203   bool is_wasm_compiled() const { return type() == WASM_COMPILED; }
    204   bool is_wasm_compile_lazy() const { return type() == WASM_COMPILE_LAZY; }
    205   bool is_wasm_to_js() const { return type() == WASM_TO_JS; }
    206   bool is_js_to_wasm() const { return type() == JS_TO_WASM; }
    207   bool is_wasm_interpreter_entry() const {
    208     return type() == WASM_INTERPRETER_ENTRY;
    209   }
    210   bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
    211   bool is_builtin() const { return type() == BUILTIN; }
    212   bool is_internal() const { return type() == INTERNAL; }
    213   bool is_builtin_continuation() const {
    214     return type() == BUILTIN_CONTINUATION;
    215   }
    216   bool is_java_script_builtin_continuation() const {
    217     return type() == JAVA_SCRIPT_BUILTIN_CONTINUATION;
    218   }
    219   bool is_java_script_builtin_with_catch_continuation() const {
    220     return type() == JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
    221   }
    222   bool is_construct() const { return type() == CONSTRUCT; }
    223   bool is_builtin_exit() const { return type() == BUILTIN_EXIT; }
    224   virtual bool is_standard() const { return false; }
    225 
    226   bool is_java_script() const {
    227     Type type = this->type();
    228     return (type == OPTIMIZED) || (type == INTERPRETED) || (type == BUILTIN) ||
    229            (type == JAVA_SCRIPT_BUILTIN_CONTINUATION) ||
    230            (type == JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH);
    231   }
    232   bool is_wasm() const {
    233     Type type = this->type();
    234     return type == WASM_COMPILED || type == WASM_INTERPRETER_ENTRY;
    235   }
    236 
    237   // Accessors.
    238   Address sp() const { return state_.sp; }
    239   Address fp() const { return state_.fp; }
    240   Address callee_pc() const {
    241     return state_.callee_pc_address ? *state_.callee_pc_address : kNullAddress;
    242   }
    243   Address caller_sp() const { return GetCallerStackPointer(); }
    244 
    245   // If this frame is optimized and was dynamically aligned return its old
    246   // unaligned frame pointer.  When the frame is deoptimized its FP will shift
    247   // up one word and become unaligned.
    248   Address UnpaddedFP() const;
    249 
    250   Address pc() const { return *pc_address(); }
    251   void set_pc(Address pc) { *pc_address() = pc; }
    252 
    253   Address constant_pool() const { return *constant_pool_address(); }
    254   void set_constant_pool(Address constant_pool) {
    255     *constant_pool_address() = constant_pool;
    256   }
    257 
    258   Address* pc_address() const { return state_.pc_address; }
    259 
    260   Address* constant_pool_address() const {
    261     return state_.constant_pool_address;
    262   }
    263 
    264   // Get the id of this stack frame.
    265   Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
    266 
    267   // Get the top handler from the current stack iterator.
    268   inline StackHandler* top_handler() const;
    269 
    270   // Get the type of this frame.
    271   virtual Type type() const = 0;
    272 
    273   // Get the code associated with this frame.
    274   // This method could be called during marking phase of GC.
    275   virtual Code* unchecked_code() const = 0;
    276 
    277   // Search for the code associated with this frame.
    278   Code* LookupCode() const;
    279 
    280   virtual void Iterate(RootVisitor* v) const = 0;
    281   static void IteratePc(RootVisitor* v, Address* pc_address,
    282                         Address* constant_pool_address, Code* holder);
    283 
    284   // Sets a callback function for return-address rewriting profilers
    285   // to resolve the location of a return address to the location of the
    286   // profiler's stashed return address.
    287   static void SetReturnAddressLocationResolver(
    288       ReturnAddressLocationResolver resolver);
    289 
    290   // Resolves pc_address through the resolution address function if one is set.
    291   static inline Address* ResolveReturnAddressLocation(Address* pc_address);
    292 
    293   // Printing support.
    294   enum PrintMode { OVERVIEW, DETAILS };
    295   virtual void Print(StringStream* accumulator, PrintMode mode,
    296                      int index) const;
    297 
    298   Isolate* isolate() const { return isolate_; }
    299 
    300   void operator=(const StackFrame& original) = delete;
    301 
    302  protected:
    303   inline explicit StackFrame(StackFrameIteratorBase* iterator);
    304   virtual ~StackFrame() { }
    305 
    306   // Compute the stack pointer for the calling frame.
    307   virtual Address GetCallerStackPointer() const = 0;
    308 
    309   // Compute the stack frame type for the given state.
    310   static Type ComputeType(const StackFrameIteratorBase* iterator, State* state);
    311 
    312 #ifdef DEBUG
    313   bool can_access_heap_objects() const;
    314 #endif
    315 
    316  private:
    317   const StackFrameIteratorBase* iterator_;
    318   Isolate* isolate_;
    319   State state_;
    320 
    321   static ReturnAddressLocationResolver return_address_location_resolver_;
    322 
    323   // Fill in the state of the calling frame.
    324   virtual void ComputeCallerState(State* state) const = 0;
    325 
    326   // Get the type and the state of the calling frame.
    327   virtual Type GetCallerState(State* state) const;
    328 
    329   static const intptr_t kIsolateTag = 1;
    330 
    331   friend class StackFrameIterator;
    332   friend class StackFrameIteratorBase;
    333   friend class StackHandlerIterator;
    334   friend class SafeStackFrameIterator;
    335 };
    336 
    337 class NativeFrame : public StackFrame {
    338  public:
    339   Type type() const override { return NATIVE; }
    340 
    341   Code* unchecked_code() const override { return nullptr; }
    342 
    343   // Garbage collection support.
    344   void Iterate(RootVisitor* v) const override {}
    345 
    346  protected:
    347   inline explicit NativeFrame(StackFrameIteratorBase* iterator);
    348 
    349   Address GetCallerStackPointer() const override;
    350 
    351  private:
    352   void ComputeCallerState(State* state) const override;
    353 
    354   friend class StackFrameIteratorBase;
    355 };
    356 
    357 // Entry frames are used to enter JavaScript execution from C.
    358 class EntryFrame: public StackFrame {
    359  public:
    360   Type type() const override { return ENTRY; }
    361 
    362   Code* unchecked_code() const override;
    363 
    364   // Garbage collection support.
    365   void Iterate(RootVisitor* v) const override;
    366 
    367   static EntryFrame* cast(StackFrame* frame) {
    368     DCHECK(frame->is_entry());
    369     return static_cast<EntryFrame*>(frame);
    370   }
    371 
    372  protected:
    373   inline explicit EntryFrame(StackFrameIteratorBase* iterator);
    374 
    375   // The caller stack pointer for entry frames is always zero. The
    376   // real information about the caller frame is available through the
    377   // link to the top exit frame.
    378   Address GetCallerStackPointer() const override { return 0; }
    379 
    380  private:
    381   void ComputeCallerState(State* state) const override;
    382   Type GetCallerState(State* state) const override;
    383 
    384   friend class StackFrameIteratorBase;
    385 };
    386 
    387 class ConstructEntryFrame : public EntryFrame {
    388  public:
    389   Type type() const override { return CONSTRUCT_ENTRY; }
    390 
    391   Code* unchecked_code() const override;
    392 
    393   static ConstructEntryFrame* cast(StackFrame* frame) {
    394     DCHECK(frame->is_construct_entry());
    395     return static_cast<ConstructEntryFrame*>(frame);
    396   }
    397 
    398  protected:
    399   inline explicit ConstructEntryFrame(StackFrameIteratorBase* iterator);
    400 
    401  private:
    402   friend class StackFrameIteratorBase;
    403 };
    404 
    405 
    406 // Exit frames are used to exit JavaScript execution and go to C.
    407 class ExitFrame: public StackFrame {
    408  public:
    409   Type type() const override { return EXIT; }
    410 
    411   Code* unchecked_code() const override;
    412 
    413   Object*& code_slot() const;
    414 
    415   // Garbage collection support.
    416   void Iterate(RootVisitor* v) const override;
    417 
    418   static ExitFrame* cast(StackFrame* frame) {
    419     DCHECK(frame->is_exit());
    420     return static_cast<ExitFrame*>(frame);
    421   }
    422 
    423   // Compute the state and type of an exit frame given a frame
    424   // pointer. Used when constructing the first stack frame seen by an
    425   // iterator and the frames following entry frames.
    426   static Type GetStateForFramePointer(Address fp, State* state);
    427   static Address ComputeStackPointer(Address fp);
    428   static StackFrame::Type ComputeFrameType(Address fp);
    429   static void FillState(Address fp, Address sp, State* state);
    430 
    431  protected:
    432   inline explicit ExitFrame(StackFrameIteratorBase* iterator);
    433 
    434   Address GetCallerStackPointer() const override;
    435 
    436  private:
    437   void ComputeCallerState(State* state) const override;
    438 
    439   friend class StackFrameIteratorBase;
    440 };
    441 
    442 // Builtin exit frames are a special case of exit frames, which are used
    443 // whenever C++ builtins (e.g., Math.acos) are called. Their main purpose is
    444 // to allow such builtins to appear in stack traces.
    445 class BuiltinExitFrame : public ExitFrame {
    446  public:
    447   Type type() const override { return BUILTIN_EXIT; }
    448 
    449   static BuiltinExitFrame* cast(StackFrame* frame) {
    450     DCHECK(frame->is_builtin_exit());
    451     return static_cast<BuiltinExitFrame*>(frame);
    452   }
    453 
    454   JSFunction* function() const;
    455   Object* receiver() const;
    456 
    457   bool IsConstructor() const;
    458 
    459   void Print(StringStream* accumulator, PrintMode mode,
    460              int index) const override;
    461 
    462  protected:
    463   inline explicit BuiltinExitFrame(StackFrameIteratorBase* iterator);
    464 
    465  private:
    466   Object* GetParameter(int i) const;
    467   int ComputeParametersCount() const;
    468 
    469   inline Object* receiver_slot_object() const;
    470   inline Object* argc_slot_object() const;
    471   inline Object* target_slot_object() const;
    472   inline Object* new_target_slot_object() const;
    473 
    474   friend class StackFrameIteratorBase;
    475 };
    476 
    477 class StandardFrame;
    478 
    479 class FrameSummary BASE_EMBEDDED {
    480  public:
    481 // Subclasses for the different summary kinds:
    482 #define FRAME_SUMMARY_VARIANTS(F)                                             \
    483   F(JAVA_SCRIPT, JavaScriptFrameSummary, java_script_summary_, JavaScript)    \
    484   F(WASM_COMPILED, WasmCompiledFrameSummary, wasm_compiled_summary_,          \
    485     WasmCompiled)                                                             \
    486   F(WASM_INTERPRETED, WasmInterpretedFrameSummary, wasm_interpreted_summary_, \
    487     WasmInterpreted)
    488 
    489 #define FRAME_SUMMARY_KIND(kind, type, field, desc) kind,
    490   enum Kind { FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_KIND) };
    491 #undef FRAME_SUMMARY_KIND
    492 
    493   class FrameSummaryBase {
    494    public:
    495     FrameSummaryBase(Isolate* isolate, Kind kind)
    496         : isolate_(isolate), kind_(kind) {}
    497     Isolate* isolate() const { return isolate_; }
    498     Kind kind() const { return kind_; }
    499 
    500    private:
    501     Isolate* isolate_;
    502     Kind kind_;
    503   };
    504 
    505   class JavaScriptFrameSummary : public FrameSummaryBase {
    506    public:
    507     JavaScriptFrameSummary(Isolate* isolate, Object* receiver,
    508                            JSFunction* function, AbstractCode* abstract_code,
    509                            int code_offset, bool is_constructor);
    510 
    511     Handle<Object> receiver() const { return receiver_; }
    512     Handle<JSFunction> function() const { return function_; }
    513     Handle<AbstractCode> abstract_code() const { return abstract_code_; }
    514     int code_offset() const { return code_offset_; }
    515     bool is_constructor() const { return is_constructor_; }
    516     bool is_subject_to_debugging() const;
    517     int SourcePosition() const;
    518     int SourceStatementPosition() const;
    519     Handle<Object> script() const;
    520     Handle<String> FunctionName() const;
    521     Handle<Context> native_context() const;
    522 
    523    private:
    524     Handle<Object> receiver_;
    525     Handle<JSFunction> function_;
    526     Handle<AbstractCode> abstract_code_;
    527     int code_offset_;
    528     bool is_constructor_;
    529   };
    530 
    531   class WasmFrameSummary : public FrameSummaryBase {
    532    protected:
    533     WasmFrameSummary(Isolate*, Kind, Handle<WasmInstanceObject>,
    534                      bool at_to_number_conversion);
    535 
    536    public:
    537     Handle<Object> receiver() const;
    538     uint32_t function_index() const;
    539     int byte_offset() const;
    540     bool is_constructor() const { return false; }
    541     bool is_subject_to_debugging() const { return true; }
    542     int SourcePosition() const;
    543     int SourceStatementPosition() const { return SourcePosition(); }
    544     Handle<Script> script() const;
    545     Handle<WasmInstanceObject> wasm_instance() const { return wasm_instance_; }
    546     Handle<String> FunctionName() const;
    547     Handle<Context> native_context() const;
    548     bool at_to_number_conversion() const { return at_to_number_conversion_; }
    549 
    550    private:
    551     Handle<WasmInstanceObject> wasm_instance_;
    552     bool at_to_number_conversion_;
    553   };
    554 
    555   class WasmCompiledFrameSummary : public WasmFrameSummary {
    556    public:
    557     WasmCompiledFrameSummary(Isolate*, Handle<WasmInstanceObject>,
    558                              wasm::WasmCode*, int code_offset,
    559                              bool at_to_number_conversion);
    560     uint32_t function_index() const;
    561     wasm::WasmCode* code() const { return code_; }
    562     int code_offset() const { return code_offset_; }
    563     int byte_offset() const;
    564     static int GetWasmSourcePosition(const wasm::WasmCode* code, int offset);
    565 
    566    private:
    567     wasm::WasmCode* const code_;
    568     int code_offset_;
    569   };
    570 
    571   class WasmInterpretedFrameSummary : public WasmFrameSummary {
    572    public:
    573     WasmInterpretedFrameSummary(Isolate*, Handle<WasmInstanceObject>,
    574                                 uint32_t function_index, int byte_offset);
    575     uint32_t function_index() const { return function_index_; }
    576     int code_offset() const { return byte_offset_; }
    577     int byte_offset() const { return byte_offset_; }
    578 
    579    private:
    580     uint32_t function_index_;
    581     int byte_offset_;
    582   };
    583 
    584 #undef FRAME_SUMMARY_FIELD
    585 #define FRAME_SUMMARY_CONS(kind, type, field, desc) \
    586   FrameSummary(type summ) : field(summ) {}  // NOLINT
    587   FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CONS)
    588 #undef FRAME_SUMMARY_CONS
    589 
    590   ~FrameSummary();
    591 
    592   static FrameSummary GetTop(const StandardFrame* frame);
    593   static FrameSummary GetBottom(const StandardFrame* frame);
    594   static FrameSummary GetSingle(const StandardFrame* frame);
    595   static FrameSummary Get(const StandardFrame* frame, int index);
    596 
    597   // Dispatched accessors.
    598   Handle<Object> receiver() const;
    599   int code_offset() const;
    600   bool is_constructor() const;
    601   bool is_subject_to_debugging() const;
    602   Handle<Object> script() const;
    603   int SourcePosition() const;
    604   int SourceStatementPosition() const;
    605   Handle<String> FunctionName() const;
    606   Handle<Context> native_context() const;
    607 
    608 #define FRAME_SUMMARY_CAST(kind_, type, field, desc)      \
    609   bool Is##desc() const { return base_.kind() == kind_; } \
    610   const type& As##desc() const {                          \
    611     DCHECK_EQ(base_.kind(), kind_);                       \
    612     return field;                                         \
    613   }
    614   FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CAST)
    615 #undef FRAME_SUMMARY_CAST
    616 
    617   bool IsWasm() const { return IsWasmCompiled() || IsWasmInterpreted(); }
    618   const WasmFrameSummary& AsWasm() const {
    619     if (IsWasmCompiled()) return AsWasmCompiled();
    620     return AsWasmInterpreted();
    621   }
    622 
    623  private:
    624 #define FRAME_SUMMARY_FIELD(kind, type, field, desc) type field;
    625   union {
    626     FrameSummaryBase base_;
    627     FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_FIELD)
    628   };
    629 };
    630 
    631 class StandardFrame : public StackFrame {
    632  public:
    633   // Testers.
    634   bool is_standard() const override { return true; }
    635 
    636   // Accessors.
    637   virtual Object* receiver() const;
    638   virtual Script* script() const;
    639   virtual Object* context() const;
    640   virtual int position() const;
    641 
    642   // Access the expressions in the stack frame including locals.
    643   inline Object* GetExpression(int index) const;
    644   inline void SetExpression(int index, Object* value);
    645   int ComputeExpressionsCount() const;
    646 
    647   // Access the parameters.
    648   virtual Object* GetParameter(int index) const;
    649   virtual int ComputeParametersCount() const;
    650 
    651   // Check if this frame is a constructor frame invoked through 'new'.
    652   virtual bool IsConstructor() const;
    653 
    654   // Build a list with summaries for this frame including all inlined frames.
    655   // The functions are ordered bottom-to-top (i.e. summaries.last() is the
    656   // top-most activation; caller comes before callee).
    657   virtual void Summarize(std::vector<FrameSummary>* frames) const;
    658 
    659   static StandardFrame* cast(StackFrame* frame) {
    660     DCHECK(frame->is_standard());
    661     return static_cast<StandardFrame*>(frame);
    662   }
    663 
    664  protected:
    665   inline explicit StandardFrame(StackFrameIteratorBase* iterator);
    666 
    667   void ComputeCallerState(State* state) const override;
    668 
    669   // Accessors.
    670   inline Address caller_fp() const;
    671   inline Address caller_pc() const;
    672 
    673   // Computes the address of the PC field in the standard frame given
    674   // by the provided frame pointer.
    675   static inline Address ComputePCAddress(Address fp);
    676 
    677   // Computes the address of the constant pool  field in the standard
    678   // frame given by the provided frame pointer.
    679   static inline Address ComputeConstantPoolAddress(Address fp);
    680 
    681   // Iterate over expression stack including stack handlers, locals,
    682   // and parts of the fixed part including context and code fields.
    683   void IterateExpressions(RootVisitor* v) const;
    684 
    685   // Returns the address of the n'th expression stack element.
    686   virtual Address GetExpressionAddress(int n) const;
    687 
    688   // Determines if the standard frame for the given frame pointer is
    689   // an arguments adaptor frame.
    690   static inline bool IsArgumentsAdaptorFrame(Address fp);
    691 
    692   // Determines if the standard frame for the given frame pointer is a
    693   // construct frame.
    694   static inline bool IsConstructFrame(Address fp);
    695 
    696   // Used by OptimizedFrames and StubFrames.
    697   void IterateCompiledFrame(RootVisitor* v) const;
    698 
    699  private:
    700   friend class StackFrame;
    701   friend class SafeStackFrameIterator;
    702 };
    703 
    704 class JavaScriptFrame : public StandardFrame {
    705  public:
    706   Type type() const override = 0;
    707 
    708   void Summarize(std::vector<FrameSummary>* frames) const override;
    709 
    710   // Accessors.
    711   virtual JSFunction* function() const;
    712   Object* unchecked_function() const;
    713   Object* receiver() const override;
    714   Object* context() const override;
    715   Script* script() const override;
    716 
    717   inline void set_receiver(Object* value);
    718 
    719   // Access the parameters.
    720   inline Address GetParameterSlot(int index) const;
    721   Object* GetParameter(int index) const override;
    722   int ComputeParametersCount() const override;
    723 
    724   // Debugger access.
    725   void SetParameterValue(int index, Object* value) const;
    726 
    727   // Check if this frame is a constructor frame invoked through 'new'.
    728   bool IsConstructor() const override;
    729 
    730   // Determines whether this frame includes inlined activations. To get details
    731   // about the inlined frames use {GetFunctions} and {Summarize}.
    732   bool HasInlinedFrames() const;
    733 
    734   // Check if this frame has "adapted" arguments in the sense that the
    735   // actual passed arguments are available in an arguments adaptor
    736   // frame below it on the stack.
    737   inline bool has_adapted_arguments() const;
    738 
    739   // Garbage collection support.
    740   void Iterate(RootVisitor* v) const override;
    741 
    742   // Printing support.
    743   void Print(StringStream* accumulator, PrintMode mode,
    744              int index) const override;
    745 
    746   // Determine the code for the frame.
    747   Code* unchecked_code() const override;
    748 
    749   // Return a list with {SharedFunctionInfo} objects of this frame.
    750   virtual void GetFunctions(std::vector<SharedFunctionInfo*>* functions) const;
    751 
    752   void GetFunctions(std::vector<Handle<SharedFunctionInfo>>* functions) const;
    753 
    754   // Lookup exception handler for current {pc}, returns -1 if none found. Also
    755   // returns data associated with the handler site specific to the frame type:
    756   //  - OptimizedFrame  : Data is the stack slot count of the entire frame.
    757   //  - InterpretedFrame: Data is the register index holding the context.
    758   virtual int LookupExceptionHandlerInTable(
    759       int* data, HandlerTable::CatchPrediction* prediction);
    760 
    761   // Architecture-specific register description.
    762   static Register fp_register();
    763   static Register context_register();
    764   static Register constant_pool_pointer_register();
    765 
    766   static JavaScriptFrame* cast(StackFrame* frame) {
    767     DCHECK(frame->is_java_script());
    768     return static_cast<JavaScriptFrame*>(frame);
    769   }
    770 
    771   static void PrintFunctionAndOffset(JSFunction* function, AbstractCode* code,
    772                                      int code_offset, FILE* file,
    773                                      bool print_line_number);
    774 
    775   static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
    776                        bool print_line_number);
    777 
    778   static void CollectFunctionAndOffsetForICStats(JSFunction* function,
    779                                                  AbstractCode* code,
    780                                                  int code_offset);
    781   static void CollectTopFrameForICStats(Isolate* isolate);
    782 
    783  protected:
    784   inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator);
    785 
    786   Address GetCallerStackPointer() const override;
    787 
    788   virtual int GetNumberOfIncomingArguments() const;
    789 
    790   virtual void PrintFrameKind(StringStream* accumulator) const {}
    791 
    792  private:
    793   inline Object* function_slot_object() const;
    794 
    795   friend class StackFrameIteratorBase;
    796 };
    797 
    798 
    799 class StubFrame : public StandardFrame {
    800  public:
    801   Type type() const override { return STUB; }
    802 
    803   // GC support.
    804   void Iterate(RootVisitor* v) const override;
    805 
    806   // Determine the code for the frame.
    807   Code* unchecked_code() const override;
    808 
    809   // Lookup exception handler for current {pc}, returns -1 if none found. Only
    810   // TurboFan stub frames are supported. Also returns data associated with the
    811   // handler site:
    812   //  - TurboFan stub: Data is the stack slot count of the entire frame.
    813   int LookupExceptionHandlerInTable(int* data);
    814 
    815  protected:
    816   inline explicit StubFrame(StackFrameIteratorBase* iterator);
    817 
    818   Address GetCallerStackPointer() const override;
    819 
    820   virtual int GetNumberOfIncomingArguments() const;
    821 
    822   friend class StackFrameIteratorBase;
    823 };
    824 
    825 
    826 class OptimizedFrame : public JavaScriptFrame {
    827  public:
    828   Type type() const override { return OPTIMIZED; }
    829 
    830   // GC support.
    831   void Iterate(RootVisitor* v) const override;
    832 
    833   // Return a list with {SharedFunctionInfo} objects of this frame.
    834   // The functions are ordered bottom-to-top (i.e. functions.last()
    835   // is the top-most activation)
    836   void GetFunctions(std::vector<SharedFunctionInfo*>* functions) const override;
    837 
    838   void Summarize(std::vector<FrameSummary>* frames) const override;
    839 
    840   // Lookup exception handler for current {pc}, returns -1 if none found.
    841   int LookupExceptionHandlerInTable(
    842       int* data, HandlerTable::CatchPrediction* prediction) override;
    843 
    844   DeoptimizationData* GetDeoptimizationData(int* deopt_index) const;
    845 
    846   Object* receiver() const override;
    847 
    848   static int StackSlotOffsetRelativeToFp(int slot_index);
    849 
    850  protected:
    851   inline explicit OptimizedFrame(StackFrameIteratorBase* iterator);
    852 
    853   int GetNumberOfIncomingArguments() const override;
    854 
    855  private:
    856   friend class StackFrameIteratorBase;
    857 
    858   Object* StackSlotAt(int index) const;
    859 };
    860 
    861 
    862 class InterpretedFrame : public JavaScriptFrame {
    863  public:
    864   Type type() const override { return INTERPRETED; }
    865 
    866   // Accessors.
    867   int position() const override;
    868 
    869   // Lookup exception handler for current {pc}, returns -1 if none found.
    870   int LookupExceptionHandlerInTable(
    871       int* data, HandlerTable::CatchPrediction* prediction) override;
    872 
    873   // Returns the current offset into the bytecode stream.
    874   int GetBytecodeOffset() const;
    875 
    876   // Updates the current offset into the bytecode stream, mainly used for stack
    877   // unwinding to continue execution at a different bytecode offset.
    878   void PatchBytecodeOffset(int new_offset);
    879 
    880   // Returns the frame's current bytecode array.
    881   BytecodeArray* GetBytecodeArray() const;
    882 
    883   // Updates the frame's BytecodeArray with |bytecode_array|. Used by the
    884   // debugger to swap execution onto a BytecodeArray patched with breakpoints.
    885   void PatchBytecodeArray(BytecodeArray* bytecode_array);
    886 
    887   // Access to the interpreter register file for this frame.
    888   Object* ReadInterpreterRegister(int register_index) const;
    889   void WriteInterpreterRegister(int register_index, Object* value);
    890 
    891   // Build a list with summaries for this frame including all inlined frames.
    892   void Summarize(std::vector<FrameSummary>* frames) const override;
    893 
    894   static int GetBytecodeOffset(Address fp);
    895 
    896   static InterpretedFrame* cast(StackFrame* frame) {
    897     DCHECK(frame->is_interpreted());
    898     return static_cast<InterpretedFrame*>(frame);
    899   }
    900 
    901  protected:
    902   inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);
    903 
    904   Address GetExpressionAddress(int n) const override;
    905 
    906  private:
    907   friend class StackFrameIteratorBase;
    908 };
    909 
    910 
    911 // Arguments adaptor frames are automatically inserted below
    912 // JavaScript frames when the actual number of parameters does not
    913 // match the formal number of parameters.
    914 class ArgumentsAdaptorFrame: public JavaScriptFrame {
    915  public:
    916   Type type() const override { return ARGUMENTS_ADAPTOR; }
    917 
    918   // Determine the code for the frame.
    919   Code* unchecked_code() const override;
    920 
    921   static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
    922     DCHECK(frame->is_arguments_adaptor());
    923     return static_cast<ArgumentsAdaptorFrame*>(frame);
    924   }
    925 
    926   // Printing support.
    927   void Print(StringStream* accumulator, PrintMode mode,
    928              int index) const override;
    929 
    930  protected:
    931   inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator);
    932 
    933   int GetNumberOfIncomingArguments() const override;
    934 
    935  private:
    936   friend class StackFrameIteratorBase;
    937 };
    938 
    939 // Builtin frames are built for builtins with JavaScript linkage, such as
    940 // various standard library functions (i.e. Math.asin, Math.floor, etc.).
    941 class BuiltinFrame final : public JavaScriptFrame {
    942  public:
    943   Type type() const final { return BUILTIN; }
    944 
    945   static BuiltinFrame* cast(StackFrame* frame) {
    946     DCHECK(frame->is_builtin());
    947     return static_cast<BuiltinFrame*>(frame);
    948   }
    949 
    950  protected:
    951   inline explicit BuiltinFrame(StackFrameIteratorBase* iterator);
    952 
    953   int GetNumberOfIncomingArguments() const final;
    954   void PrintFrameKind(StringStream* accumulator) const override;
    955 
    956  private:
    957   friend class StackFrameIteratorBase;
    958 };
    959 
    960 class WasmCompiledFrame final : public StandardFrame {
    961  public:
    962   Type type() const override { return WASM_COMPILED; }
    963 
    964   // GC support.
    965   void Iterate(RootVisitor* v) const override;
    966 
    967   // Printing support.
    968   void Print(StringStream* accumulator, PrintMode mode,
    969              int index) const override;
    970 
    971   // Lookup exception handler for current {pc}, returns -1 if none found. Also
    972   // returns the stack slot count of the entire frame.
    973   int LookupExceptionHandlerInTable(int* data);
    974 
    975   // Determine the code for the frame.
    976   Code* unchecked_code() const override;
    977 
    978   // Accessors.
    979   WasmInstanceObject* wasm_instance() const;
    980   wasm::WasmCode* wasm_code() const;
    981   uint32_t function_index() const;
    982   Script* script() const override;
    983   int position() const override;
    984   bool at_to_number_conversion() const;
    985 
    986   void Summarize(std::vector<FrameSummary>* frames) const override;
    987 
    988   static WasmCompiledFrame* cast(StackFrame* frame) {
    989     DCHECK(frame->is_wasm_compiled());
    990     return static_cast<WasmCompiledFrame*>(frame);
    991   }
    992 
    993  protected:
    994   inline explicit WasmCompiledFrame(StackFrameIteratorBase* iterator);
    995 
    996   Address GetCallerStackPointer() const override;
    997 
    998  private:
    999   friend class StackFrameIteratorBase;
   1000   WasmModuleObject* module_object() const;
   1001 };
   1002 
   1003 class WasmInterpreterEntryFrame final : public StandardFrame {
   1004  public:
   1005   Type type() const override { return WASM_INTERPRETER_ENTRY; }
   1006 
   1007   // GC support.
   1008   void Iterate(RootVisitor* v) const override;
   1009 
   1010   // Printing support.
   1011   void Print(StringStream* accumulator, PrintMode mode,
   1012              int index) const override;
   1013 
   1014   void Summarize(std::vector<FrameSummary>* frames) const override;
   1015 
   1016   // Determine the code for the frame.
   1017   Code* unchecked_code() const override;
   1018 
   1019   // Accessors.
   1020   WasmDebugInfo* debug_info() const;
   1021   WasmInstanceObject* wasm_instance() const;
   1022 
   1023   Script* script() const override;
   1024   int position() const override;
   1025   Object* context() const override;
   1026 
   1027   static WasmInterpreterEntryFrame* cast(StackFrame* frame) {
   1028     DCHECK(frame->is_wasm_interpreter_entry());
   1029     return static_cast<WasmInterpreterEntryFrame*>(frame);
   1030   }
   1031 
   1032  protected:
   1033   inline explicit WasmInterpreterEntryFrame(StackFrameIteratorBase* iterator);
   1034 
   1035   Address GetCallerStackPointer() const override;
   1036 
   1037  private:
   1038   friend class StackFrameIteratorBase;
   1039   WasmModuleObject* module_object() const;
   1040 };
   1041 
   1042 class WasmToJsFrame : public StubFrame {
   1043  public:
   1044   Type type() const override { return WASM_TO_JS; }
   1045 
   1046  protected:
   1047   inline explicit WasmToJsFrame(StackFrameIteratorBase* iterator);
   1048 
   1049  private:
   1050   friend class StackFrameIteratorBase;
   1051 };
   1052 
   1053 class JsToWasmFrame : public StubFrame {
   1054  public:
   1055   Type type() const override { return JS_TO_WASM; }
   1056 
   1057  protected:
   1058   inline explicit JsToWasmFrame(StackFrameIteratorBase* iterator);
   1059 
   1060  private:
   1061   friend class StackFrameIteratorBase;
   1062 };
   1063 
   1064 class CWasmEntryFrame : public StubFrame {
   1065  public:
   1066   Type type() const override { return C_WASM_ENTRY; }
   1067 
   1068  protected:
   1069   inline explicit CWasmEntryFrame(StackFrameIteratorBase* iterator);
   1070 
   1071  private:
   1072   friend class StackFrameIteratorBase;
   1073 };
   1074 
   1075 class WasmCompileLazyFrame : public StandardFrame {
   1076  public:
   1077   Type type() const override { return WASM_COMPILE_LAZY; }
   1078 
   1079   Code* unchecked_code() const override { return nullptr; }
   1080   WasmInstanceObject* wasm_instance() const;
   1081   Object** wasm_instance_slot() const;
   1082 
   1083   // Garbage collection support.
   1084   void Iterate(RootVisitor* v) const override;
   1085 
   1086   static WasmCompileLazyFrame* cast(StackFrame* frame) {
   1087     DCHECK(frame->is_wasm_compile_lazy());
   1088     return static_cast<WasmCompileLazyFrame*>(frame);
   1089   }
   1090 
   1091  protected:
   1092   inline explicit WasmCompileLazyFrame(StackFrameIteratorBase* iterator);
   1093 
   1094   Address GetCallerStackPointer() const override;
   1095 
   1096  private:
   1097   friend class StackFrameIteratorBase;
   1098 };
   1099 
   1100 class InternalFrame: public StandardFrame {
   1101  public:
   1102   Type type() const override { return INTERNAL; }
   1103 
   1104   // Garbage collection support.
   1105   void Iterate(RootVisitor* v) const override;
   1106 
   1107   // Determine the code for the frame.
   1108   Code* unchecked_code() const override;
   1109 
   1110   static InternalFrame* cast(StackFrame* frame) {
   1111     DCHECK(frame->is_internal());
   1112     return static_cast<InternalFrame*>(frame);
   1113   }
   1114 
   1115  protected:
   1116   inline explicit InternalFrame(StackFrameIteratorBase* iterator);
   1117 
   1118   Address GetCallerStackPointer() const override;
   1119 
   1120  private:
   1121   friend class StackFrameIteratorBase;
   1122 };
   1123 
   1124 
   1125 // Construct frames are special trampoline frames introduced to handle
   1126 // function invocations through 'new'.
   1127 class ConstructFrame: public InternalFrame {
   1128  public:
   1129   Type type() const override { return CONSTRUCT; }
   1130 
   1131   static ConstructFrame* cast(StackFrame* frame) {
   1132     DCHECK(frame->is_construct());
   1133     return static_cast<ConstructFrame*>(frame);
   1134   }
   1135 
   1136  protected:
   1137   inline explicit ConstructFrame(StackFrameIteratorBase* iterator);
   1138 
   1139  private:
   1140   friend class StackFrameIteratorBase;
   1141 };
   1142 
   1143 class BuiltinContinuationFrame : public InternalFrame {
   1144  public:
   1145   Type type() const override { return BUILTIN_CONTINUATION; }
   1146 
   1147   static BuiltinContinuationFrame* cast(StackFrame* frame) {
   1148     DCHECK(frame->is_builtin_continuation());
   1149     return static_cast<BuiltinContinuationFrame*>(frame);
   1150   }
   1151 
   1152  protected:
   1153   inline explicit BuiltinContinuationFrame(StackFrameIteratorBase* iterator);
   1154 
   1155  private:
   1156   friend class StackFrameIteratorBase;
   1157 };
   1158 
   1159 class JavaScriptBuiltinContinuationFrame : public JavaScriptFrame {
   1160  public:
   1161   Type type() const override { return JAVA_SCRIPT_BUILTIN_CONTINUATION; }
   1162 
   1163   static JavaScriptBuiltinContinuationFrame* cast(StackFrame* frame) {
   1164     DCHECK(frame->is_java_script_builtin_continuation());
   1165     return static_cast<JavaScriptBuiltinContinuationFrame*>(frame);
   1166   }
   1167 
   1168   int ComputeParametersCount() const override;
   1169   intptr_t GetSPToFPDelta() const;
   1170 
   1171   Object* context() const override;
   1172 
   1173  protected:
   1174   inline explicit JavaScriptBuiltinContinuationFrame(
   1175       StackFrameIteratorBase* iterator);
   1176 
   1177  private:
   1178   friend class StackFrameIteratorBase;
   1179 };
   1180 
   1181 class JavaScriptBuiltinContinuationWithCatchFrame
   1182     : public JavaScriptBuiltinContinuationFrame {
   1183  public:
   1184   Type type() const override {
   1185     return JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
   1186   }
   1187 
   1188   static JavaScriptBuiltinContinuationWithCatchFrame* cast(StackFrame* frame) {
   1189     DCHECK(frame->is_java_script_builtin_with_catch_continuation());
   1190     return static_cast<JavaScriptBuiltinContinuationWithCatchFrame*>(frame);
   1191   }
   1192 
   1193   // Patch in the exception object at the appropriate location into the stack
   1194   // frame.
   1195   void SetException(Object* exception);
   1196 
   1197  protected:
   1198   inline explicit JavaScriptBuiltinContinuationWithCatchFrame(
   1199       StackFrameIteratorBase* iterator);
   1200 
   1201  private:
   1202   friend class StackFrameIteratorBase;
   1203 };
   1204 
   1205 class StackFrameIteratorBase BASE_EMBEDDED {
   1206  public:
   1207   Isolate* isolate() const { return isolate_; }
   1208 
   1209   bool done() const { return frame_ == nullptr; }
   1210 
   1211  protected:
   1212   // An iterator that iterates over a given thread's stack.
   1213   StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects);
   1214 
   1215   Isolate* isolate_;
   1216 #define DECLARE_SINGLETON(ignore, type) type type##_;
   1217   STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
   1218 #undef DECLARE_SINGLETON
   1219   StackFrame* frame_;
   1220   StackHandler* handler_;
   1221   const bool can_access_heap_objects_;
   1222 
   1223   StackHandler* handler() const {
   1224     DCHECK(!done());
   1225     return handler_;
   1226   }
   1227 
   1228   // Get the type-specific frame singleton in a given state.
   1229   StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
   1230   // A helper function, can return a nullptr pointer.
   1231   StackFrame* SingletonFor(StackFrame::Type type);
   1232 
   1233  private:
   1234   friend class StackFrame;
   1235   DISALLOW_COPY_AND_ASSIGN(StackFrameIteratorBase);
   1236 };
   1237 
   1238 
   1239 class StackFrameIterator: public StackFrameIteratorBase {
   1240  public:
   1241   // An iterator that iterates over the isolate's current thread's stack,
   1242   explicit StackFrameIterator(Isolate* isolate);
   1243   // An iterator that iterates over a given thread's stack.
   1244   StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
   1245 
   1246   StackFrame* frame() const {
   1247     DCHECK(!done());
   1248     return frame_;
   1249   }
   1250   void Advance();
   1251 
   1252  private:
   1253   // Go back to the first frame.
   1254   void Reset(ThreadLocalTop* top);
   1255 
   1256   DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
   1257 };
   1258 
   1259 // Iterator that supports iterating through all JavaScript frames.
   1260 class JavaScriptFrameIterator BASE_EMBEDDED {
   1261  public:
   1262   inline explicit JavaScriptFrameIterator(Isolate* isolate);
   1263   inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top);
   1264 
   1265   inline JavaScriptFrame* frame() const;
   1266 
   1267   bool done() const { return iterator_.done(); }
   1268   void Advance();
   1269   void AdvanceOneFrame() { iterator_.Advance(); }
   1270 
   1271  private:
   1272   StackFrameIterator iterator_;
   1273 };
   1274 
   1275 // NOTE: The stack trace frame iterator is an iterator that only traverse proper
   1276 // JavaScript frames that have proper JavaScript functions and WebAssembly
   1277 // frames.
   1278 class StackTraceFrameIterator BASE_EMBEDDED {
   1279  public:
   1280   explicit StackTraceFrameIterator(Isolate* isolate);
   1281   // Skip frames until the frame with the given id is reached.
   1282   StackTraceFrameIterator(Isolate* isolate, StackFrame::Id id);
   1283   bool done() const { return iterator_.done(); }
   1284   void Advance();
   1285   void AdvanceOneFrame() { iterator_.Advance(); }
   1286 
   1287   inline StandardFrame* frame() const;
   1288 
   1289   inline bool is_javascript() const;
   1290   inline bool is_wasm() const;
   1291   inline JavaScriptFrame* javascript_frame() const;
   1292 
   1293  private:
   1294   StackFrameIterator iterator_;
   1295   bool IsValidFrame(StackFrame* frame) const;
   1296 };
   1297 
   1298 
   1299 class SafeStackFrameIterator: public StackFrameIteratorBase {
   1300  public:
   1301   SafeStackFrameIterator(Isolate* isolate,
   1302                          Address fp, Address sp,
   1303                          Address js_entry_sp);
   1304 
   1305   inline StackFrame* frame() const;
   1306   void Advance();
   1307 
   1308   StackFrame::Type top_frame_type() const { return top_frame_type_; }
   1309 
   1310  private:
   1311   void AdvanceOneFrame();
   1312 
   1313   bool IsValidStackAddress(Address addr) const {
   1314     return low_bound_ <= addr && addr <= high_bound_;
   1315   }
   1316   bool IsValidFrame(StackFrame* frame) const;
   1317   bool IsValidCaller(StackFrame* frame);
   1318   bool IsValidExitFrame(Address fp) const;
   1319   bool IsValidTop(ThreadLocalTop* top) const;
   1320 
   1321   const Address low_bound_;
   1322   const Address high_bound_;
   1323   StackFrame::Type top_frame_type_;
   1324   ExternalCallbackScope* external_callback_scope_;
   1325 };
   1326 }  // namespace internal
   1327 }  // namespace v8
   1328 
   1329 #endif  // V8_FRAMES_H_
   1330