• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
InnerPointerToCodeCache(Isolate * isolate)41   explicit InnerPointerToCodeCache(Isolate* isolate) : isolate_(isolate) {
42     Flush();
43   }
44 
Flush()45   void Flush() {
46     memset(&cache_[0], 0, sizeof(cache_));
47   }
48 
49   InnerPointerToCodeCacheEntry* GetCacheEntry(Address inner_pointer);
50 
51  private:
cache(int index)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.
TypeToMarker(Type type)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.
MarkerToType(intptr_t marker)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.
IsTypeMarker(intptr_t function_or_marker)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).
StackFrame(const StackFrame & original)191   StackFrame(const StackFrame& original) {
192     this->state_ = original.state_;
193     this->iterator_ = nullptr;
194     this->isolate_ = original.isolate_;
195   }
196 
197   // Type testers.
is_entry()198   bool is_entry() const { return type() == ENTRY; }
is_construct_entry()199   bool is_construct_entry() const { return type() == CONSTRUCT_ENTRY; }
is_exit()200   bool is_exit() const { return type() == EXIT; }
is_optimized()201   bool is_optimized() const { return type() == OPTIMIZED; }
is_interpreted()202   bool is_interpreted() const { return type() == INTERPRETED; }
is_wasm_compiled()203   bool is_wasm_compiled() const { return type() == WASM_COMPILED; }
is_wasm_compile_lazy()204   bool is_wasm_compile_lazy() const { return type() == WASM_COMPILE_LAZY; }
is_wasm_to_js()205   bool is_wasm_to_js() const { return type() == WASM_TO_JS; }
is_js_to_wasm()206   bool is_js_to_wasm() const { return type() == JS_TO_WASM; }
is_wasm_interpreter_entry()207   bool is_wasm_interpreter_entry() const {
208     return type() == WASM_INTERPRETER_ENTRY;
209   }
is_arguments_adaptor()210   bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
is_builtin()211   bool is_builtin() const { return type() == BUILTIN; }
is_internal()212   bool is_internal() const { return type() == INTERNAL; }
is_builtin_continuation()213   bool is_builtin_continuation() const {
214     return type() == BUILTIN_CONTINUATION;
215   }
is_java_script_builtin_continuation()216   bool is_java_script_builtin_continuation() const {
217     return type() == JAVA_SCRIPT_BUILTIN_CONTINUATION;
218   }
is_java_script_builtin_with_catch_continuation()219   bool is_java_script_builtin_with_catch_continuation() const {
220     return type() == JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
221   }
is_construct()222   bool is_construct() const { return type() == CONSTRUCT; }
is_builtin_exit()223   bool is_builtin_exit() const { return type() == BUILTIN_EXIT; }
is_standard()224   virtual bool is_standard() const { return false; }
225 
is_java_script()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   }
is_wasm()232   bool is_wasm() const {
233     Type type = this->type();
234     return type == WASM_COMPILED || type == WASM_INTERPRETER_ENTRY;
235   }
236 
237   // Accessors.
sp()238   Address sp() const { return state_.sp; }
fp()239   Address fp() const { return state_.fp; }
callee_pc()240   Address callee_pc() const {
241     return state_.callee_pc_address ? *state_.callee_pc_address : kNullAddress;
242   }
caller_sp()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 
pc()250   Address pc() const { return *pc_address(); }
set_pc(Address pc)251   void set_pc(Address pc) { *pc_address() = pc; }
252 
constant_pool()253   Address constant_pool() const { return *constant_pool_address(); }
set_constant_pool(Address constant_pool)254   void set_constant_pool(Address constant_pool) {
255     *constant_pool_address() = constant_pool;
256   }
257 
pc_address()258   Address* pc_address() const { return state_.pc_address; }
259 
constant_pool_address()260   Address* constant_pool_address() const {
261     return state_.constant_pool_address;
262   }
263 
264   // Get the id of this stack frame.
id()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 
isolate()298   Isolate* isolate() const { return isolate_; }
299 
300   void operator=(const StackFrame& original) = delete;
301 
302  protected:
303   inline explicit StackFrame(StackFrameIteratorBase* iterator);
~StackFrame()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:
type()339   Type type() const override { return NATIVE; }
340 
unchecked_code()341   Code* unchecked_code() const override { return nullptr; }
342 
343   // Garbage collection support.
Iterate(RootVisitor * v)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:
type()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 
cast(StackFrame * frame)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.
GetCallerStackPointer()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:
type()389   Type type() const override { return CONSTRUCT_ENTRY; }
390 
391   Code* unchecked_code() const override;
392 
cast(StackFrame * frame)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:
type()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 
cast(StackFrame * frame)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:
type()447   Type type() const override { return BUILTIN_EXIT; }
448 
cast(StackFrame * frame)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:
FrameSummaryBase(Isolate * isolate,Kind kind)495     FrameSummaryBase(Isolate* isolate, Kind kind)
496         : isolate_(isolate), kind_(kind) {}
isolate()497     Isolate* isolate() const { return isolate_; }
kind()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 
receiver()511     Handle<Object> receiver() const { return receiver_; }
function()512     Handle<JSFunction> function() const { return function_; }
abstract_code()513     Handle<AbstractCode> abstract_code() const { return abstract_code_; }
code_offset()514     int code_offset() const { return code_offset_; }
is_constructor()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;
is_constructor()540     bool is_constructor() const { return false; }
is_subject_to_debugging()541     bool is_subject_to_debugging() const { return true; }
542     int SourcePosition() const;
SourceStatementPosition()543     int SourceStatementPosition() const { return SourcePosition(); }
544     Handle<Script> script() const;
wasm_instance()545     Handle<WasmInstanceObject> wasm_instance() const { return wasm_instance_; }
546     Handle<String> FunctionName() const;
547     Handle<Context> native_context() const;
at_to_number_conversion()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;
code()561     wasm::WasmCode* code() const { return code_; }
code_offset()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);
function_index()575     uint32_t function_index() const { return function_index_; }
code_offset()576     int code_offset() const { return byte_offset_; }
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   }
FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CAST)614   FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CAST)
615 #undef FRAME_SUMMARY_CAST
616 
617   bool IsWasm() const { return IsWasmCompiled() || IsWasmInterpreted(); }
AsWasm()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.
is_standard()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 
cast(StackFrame * frame)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 
cast(StackFrame * frame)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 
PrintFrameKind(StringStream * accumulator)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:
type()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:
type()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:
type()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 
cast(StackFrame * frame)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:
type()916   Type type() const override { return ARGUMENTS_ADAPTOR; }
917 
918   // Determine the code for the frame.
919   Code* unchecked_code() const override;
920 
cast(StackFrame * frame)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:
type()943   Type type() const final { return BUILTIN; }
944 
cast(StackFrame * frame)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:
type()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 
cast(StackFrame * frame)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:
type()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 
cast(StackFrame * frame)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:
type()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:
type()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:
type()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:
type()1077   Type type() const override { return WASM_COMPILE_LAZY; }
1078 
unchecked_code()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 
cast(StackFrame * frame)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:
type()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 
cast(StackFrame * frame)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:
type()1129   Type type() const override { return CONSTRUCT; }
1130 
cast(StackFrame * frame)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:
type()1145   Type type() const override { return BUILTIN_CONTINUATION; }
1146 
cast(StackFrame * frame)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:
type()1161   Type type() const override { return JAVA_SCRIPT_BUILTIN_CONTINUATION; }
1162 
cast(StackFrame * frame)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:
type()1184   Type type() const override {
1185     return JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
1186   }
1187 
cast(StackFrame * frame)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:
isolate()1207   Isolate* isolate() const { return isolate_; }
1208 
done()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 
handler()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 
frame()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 
done()1267   bool done() const { return iterator_.done(); }
1268   void Advance();
AdvanceOneFrame()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);
done()1283   bool done() const { return iterator_.done(); }
1284   void Advance();
AdvanceOneFrame()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 
top_frame_type()1308   StackFrame::Type top_frame_type() const { return top_frame_type_; }
1309 
1310  private:
1311   void AdvanceOneFrame();
1312 
IsValidStackAddress(Address addr)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