• 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_EXECUTION_FRAMES_H_
6 #define V8_EXECUTION_FRAMES_H_
7 
8 #include "include/v8-initialization.h"
9 #include "src/base/bounds.h"
10 #include "src/codegen/safepoint-table.h"
11 #include "src/common/globals.h"
12 #include "src/handles/handles.h"
13 #include "src/objects/code.h"
14 #include "src/objects/objects.h"
15 
16 //
17 // Frame inheritance hierarchy (please keep in sync with frame-constants.h):
18 // - CommonFrame
19 //   - CommonFrameWithJSLinkage
20 //     - JavaScriptFrame (aka StandardFrame)
21 //       - UnoptimizedFrame
22 //         - InterpretedFrame
23 //         - BaselineFrame
24 //       - OptimizedFrame
25 //     - TypedFrameWithJSLinkage
26 //       - BuiltinFrame
27 //       - JavaScriptBuiltinContinuationFrame
28 //         - JavaScriptBuiltinContinuationWithCatchFrame
29 //   - TypedFrame
30 //     - NativeFrame
31 //     - EntryFrame
32 //       - ConstructEntryFrame
33 //     - ExitFrame
34 //       - BuiltinExitFrame
35 //     - StubFrame
36 //       - JsToWasmFrame
37 //       - CWasmEntryFrame
38 //     - Internal
39 //       - ConstructFrame
40 //       - BuiltinContinuationFrame
41 //     - WasmFrame
42 //       - WasmExitFrame
43 //     - WasmDebugBreakFrame
44 //     - WasmCompileLazyFrame
45 //
46 
47 namespace v8 {
48 namespace internal {
49 namespace wasm {
50 class WasmCode;
51 struct JumpBuffer;
52 class StackMemory;
53 }  // namespace wasm
54 
55 class AbstractCode;
56 class Debug;
57 class ExternalCallbackScope;
58 class InnerPointerToCodeCache;
59 class Isolate;
60 class ObjectVisitor;
61 class Register;
62 class RootVisitor;
63 class StackFrameInfo;
64 class StackFrameIteratorBase;
65 class StringStream;
66 class ThreadLocalTop;
67 class WasmInstanceObject;
68 class WasmModuleObject;
69 
70 class StackHandlerConstants : public AllStatic {
71  public:
72   static const int kNextOffset = 0 * kSystemPointerSize;
73   static const int kPaddingOffset = 1 * kSystemPointerSize;
74 
75   static const int kSize = kPaddingOffset + kSystemPointerSize;
76   static const int kSlotCount = kSize >> kSystemPointerSizeLog2;
77 };
78 
79 class StackHandler {
80  public:
81   // Get the address of this stack handler.
82   inline Address address() const;
83 
84   // Get the next stack handler in the chain.
85   inline StackHandler* next() const;
86 
87   // Get the next stack handler, as an Address. This is safe to use even
88   // when the next handler is null.
89   inline Address next_address() const;
90 
91   // Conversion support.
92   static inline StackHandler* FromAddress(Address address);
93 
94  private:
95   DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
96 };
97 
98 #define STACK_FRAME_TYPE_LIST(V)                                          \
99   V(ENTRY, EntryFrame)                                                    \
100   V(CONSTRUCT_ENTRY, ConstructEntryFrame)                                 \
101   V(EXIT, ExitFrame)                                                      \
102   IF_WASM(V, WASM, WasmFrame)                                             \
103   IF_WASM(V, WASM_TO_JS, WasmToJsFrame)                                   \
104   IF_WASM(V, JS_TO_WASM, JsToWasmFrame)                                   \
105   IF_WASM(V, STACK_SWITCH, StackSwitchFrame)                              \
106   IF_WASM(V, WASM_DEBUG_BREAK, WasmDebugBreakFrame)                       \
107   IF_WASM(V, C_WASM_ENTRY, CWasmEntryFrame)                               \
108   IF_WASM(V, WASM_EXIT, WasmExitFrame)                                    \
109   IF_WASM(V, WASM_COMPILE_LAZY, WasmCompileLazyFrame)                     \
110   V(INTERPRETED, InterpretedFrame)                                        \
111   V(BASELINE, BaselineFrame)                                              \
112   V(OPTIMIZED, OptimizedFrame)                                            \
113   V(STUB, StubFrame)                                                      \
114   V(BUILTIN_CONTINUATION, BuiltinContinuationFrame)                       \
115   V(JAVA_SCRIPT_BUILTIN_CONTINUATION, JavaScriptBuiltinContinuationFrame) \
116   V(JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH,                          \
117     JavaScriptBuiltinContinuationWithCatchFrame)                          \
118   V(INTERNAL, InternalFrame)                                              \
119   V(CONSTRUCT, ConstructFrame)                                            \
120   V(BUILTIN, BuiltinFrame)                                                \
121   V(BUILTIN_EXIT, BuiltinExitFrame)                                       \
122   V(NATIVE, NativeFrame)
123 
124 // Abstract base class for all stack frames.
125 class StackFrame {
126  public:
127 #define DECLARE_TYPE(type, ignore) type,
128   enum Type {
129     NO_FRAME_TYPE = 0,
130     STACK_FRAME_TYPE_LIST(DECLARE_TYPE) NUMBER_OF_TYPES,
131     // Used by FrameScope to indicate that the stack frame is constructed
132     // manually and the FrameScope does not need to emit code.
133     MANUAL
134   };
135 #undef DECLARE_TYPE
136 
137   // Used to mark the outermost JS entry frame.
138   //
139   // The mark is an opaque value that should be pushed onto the stack directly,
140   // carefully crafted to not be interpreted as a tagged pointer.
141   enum JsFrameMarker {
142     INNER_JSENTRY_FRAME = (0 << kSmiTagSize) | kSmiTag,
143     OUTERMOST_JSENTRY_FRAME = (1 << kSmiTagSize) | kSmiTag
144   };
145   STATIC_ASSERT((INNER_JSENTRY_FRAME & kHeapObjectTagMask) != kHeapObjectTag);
146   STATIC_ASSERT((OUTERMOST_JSENTRY_FRAME & kHeapObjectTagMask) !=
147                 kHeapObjectTag);
148 
149   struct State {
150     Address sp = kNullAddress;
151     Address fp = kNullAddress;
152     Address* pc_address = nullptr;
153     Address callee_fp = kNullAddress;
154     Address* callee_pc_address = nullptr;
155     Address* constant_pool_address = nullptr;
156   };
157 
158   // Convert a stack frame type to a marker that can be stored on the stack.
159   //
160   // The marker is an opaque value, not intended to be interpreted in any way
161   // except being checked by IsTypeMarker or converted by MarkerToType.
162   // It has the same tagging as Smis, so any marker value that does not pass
163   // IsTypeMarker can instead be interpreted as a tagged pointer.
164   //
165   // Note that the marker is not a Smi: Smis on 64-bit architectures are stored
166   // in the top 32 bits of a 64-bit value, which in turn makes them expensive
167   // (in terms of code/instruction size) to push as immediates onto the stack.
TypeToMarker(Type type)168   static int32_t TypeToMarker(Type type) {
169     DCHECK_GE(type, 0);
170     return (type << kSmiTagSize) | kSmiTag;
171   }
172 
173   // Convert a marker back to a stack frame type.
174   //
175   // Unlike the return value of TypeToMarker, this takes an intptr_t, as that is
176   // the type of the value on the stack.
MarkerToType(intptr_t marker)177   static Type MarkerToType(intptr_t marker) {
178     DCHECK(IsTypeMarker(marker));
179     intptr_t type = marker >> kSmiTagSize;
180     // TODO(petermarshall): There is a bug in the arm simulators that causes
181     // invalid frame markers.
182 #if (defined(USE_SIMULATOR) &&                        \
183      (V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_ARM)) || \
184     V8_TARGET_ARCH_RISCV64
185     if (static_cast<uintptr_t>(type) >= Type::NUMBER_OF_TYPES) {
186       // Appease UBSan.
187       return Type::NUMBER_OF_TYPES;
188     }
189 #else
190     DCHECK_LT(static_cast<uintptr_t>(type), Type::NUMBER_OF_TYPES);
191 #endif
192     return static_cast<Type>(type);
193   }
194 
195   // Check if a marker is a stack frame type marker or a tagged pointer.
196   //
197   // Returns true if the given marker is tagged as a stack frame type marker,
198   // and should be converted back to a stack frame type using MarkerToType.
199   // Otherwise, the value is a tagged function pointer.
IsTypeMarker(intptr_t function_or_marker)200   static bool IsTypeMarker(intptr_t function_or_marker) {
201     return (function_or_marker & kSmiTagMask) == kSmiTag;
202   }
203 
204   // Copy constructor; it breaks the connection to host iterator
205   // (as an iterator usually lives on stack).
StackFrame(const StackFrame & original)206   StackFrame(const StackFrame& original) V8_NOEXCEPT {
207     this->state_ = original.state_;
208     this->iterator_ = nullptr;
209     this->isolate_ = original.isolate_;
210   }
211 
212   // Type testers.
is_entry()213   bool is_entry() const { return type() == ENTRY; }
is_construct_entry()214   bool is_construct_entry() const { return type() == CONSTRUCT_ENTRY; }
is_exit()215   bool is_exit() const { return type() == EXIT; }
is_optimized()216   bool is_optimized() const { return type() == OPTIMIZED; }
is_unoptimized()217   bool is_unoptimized() const {
218     STATIC_ASSERT(BASELINE == INTERPRETED + 1);
219     return base::IsInRange(type(), INTERPRETED, BASELINE);
220   }
is_interpreted()221   bool is_interpreted() const { return type() == INTERPRETED; }
is_baseline()222   bool is_baseline() const { return type() == BASELINE; }
223 #if V8_ENABLE_WEBASSEMBLY
is_wasm()224   bool is_wasm() const { return this->type() == WASM; }
is_c_wasm_entry()225   bool is_c_wasm_entry() const { return type() == C_WASM_ENTRY; }
is_wasm_compile_lazy()226   bool is_wasm_compile_lazy() const { return type() == WASM_COMPILE_LAZY; }
is_wasm_debug_break()227   bool is_wasm_debug_break() const { return type() == WASM_DEBUG_BREAK; }
is_wasm_to_js()228   bool is_wasm_to_js() const { return type() == WASM_TO_JS; }
is_js_to_wasm()229   bool is_js_to_wasm() const { return type() == JS_TO_WASM; }
230 #endif  // V8_ENABLE_WEBASSEMBLY
is_builtin()231   bool is_builtin() const { return type() == BUILTIN; }
is_internal()232   bool is_internal() const { return type() == INTERNAL; }
is_builtin_continuation()233   bool is_builtin_continuation() const {
234     return type() == BUILTIN_CONTINUATION;
235   }
is_java_script_builtin_continuation()236   bool is_java_script_builtin_continuation() const {
237     return type() == JAVA_SCRIPT_BUILTIN_CONTINUATION;
238   }
is_java_script_builtin_with_catch_continuation()239   bool is_java_script_builtin_with_catch_continuation() const {
240     return type() == JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
241   }
is_construct()242   bool is_construct() const { return type() == CONSTRUCT; }
is_builtin_exit()243   bool is_builtin_exit() const { return type() == BUILTIN_EXIT; }
244 
IsJavaScript(Type t)245   static bool IsJavaScript(Type t) {
246     STATIC_ASSERT(INTERPRETED + 1 == BASELINE);
247     STATIC_ASSERT(BASELINE + 1 == OPTIMIZED);
248     return t >= INTERPRETED && t <= OPTIMIZED;
249   }
is_java_script()250   bool is_java_script() const { return IsJavaScript(type()); }
251 
252   // Accessors.
sp()253   Address sp() const { return state_.sp; }
fp()254   Address fp() const { return state_.fp; }
callee_fp()255   Address callee_fp() const { return state_.callee_fp; }
256   inline Address callee_pc() const;
caller_sp()257   Address caller_sp() const { return GetCallerStackPointer(); }
258   inline Address pc() const;
259 
260   // Skip authentication of the PC, when using CFI. Used in the profiler, where
261   // in certain corner-cases we do not use an address on the stack, which would
262   // be signed, as the PC of the frame.
263   inline Address unauthenticated_pc() const;
264 
constant_pool()265   Address constant_pool() const { return *constant_pool_address(); }
set_constant_pool(Address constant_pool)266   void set_constant_pool(Address constant_pool) {
267     *constant_pool_address() = constant_pool;
268   }
269 
pc_address()270   Address* pc_address() const { return state_.pc_address; }
271 
constant_pool_address()272   Address* constant_pool_address() const {
273     return state_.constant_pool_address;
274   }
275 
276   // Get the id of this stack frame.
id()277   StackFrameId id() const { return static_cast<StackFrameId>(caller_sp()); }
278 
279   // Get the top handler from the current stack iterator.
280   inline StackHandler* top_handler() const;
281 
282   // Get the type of this frame.
283   virtual Type type() const = 0;
284 
285   // Get the code associated with this frame.
286   // This method could be called during marking phase of GC.
287   virtual Code unchecked_code() const = 0;
288 
289   // Search for the code associated with this frame.
290   V8_EXPORT_PRIVATE Code LookupCode() const;
291 
292   virtual void Iterate(RootVisitor* v) const = 0;
293   void IteratePc(RootVisitor* v, Address* pc_address,
294                  Address* constant_pool_address, Code holder) const;
295 
296   // Sets a callback function for return-address rewriting profilers
297   // to resolve the location of a return address to the location of the
298   // profiler's stashed return address.
299   static void SetReturnAddressLocationResolver(
300       ReturnAddressLocationResolver resolver);
301 
302   static inline Address ReadPC(Address* pc_address);
303 
304   // Resolves pc_address through the resolution address function if one is set.
305   static inline Address* ResolveReturnAddressLocation(Address* pc_address);
306 
307   // Printing support.
308   enum PrintMode { OVERVIEW, DETAILS };
309   virtual void Print(StringStream* accumulator, PrintMode mode,
310                      int index) const;
311 
isolate()312   Isolate* isolate() const { return isolate_; }
313 
314   void operator=(const StackFrame& original) = delete;
315 
316  protected:
317   inline explicit StackFrame(StackFrameIteratorBase* iterator);
318   virtual ~StackFrame() = default;
319 
320   // Compute the stack pointer for the calling frame.
321   virtual Address GetCallerStackPointer() const = 0;
322 
323   // Compute the stack frame type for the given state.
324   static Type ComputeType(const StackFrameIteratorBase* iterator, State* state);
325 
326 #ifdef DEBUG
327   bool can_access_heap_objects() const;
328 #endif
329 
330  private:
331   const StackFrameIteratorBase* iterator_;
332   Isolate* isolate_;
333   State state_;
334 
335   static ReturnAddressLocationResolver return_address_location_resolver_;
336 
337   // Fill in the state of the calling frame.
338   virtual void ComputeCallerState(State* state) const = 0;
339 
340   // Get the type and the state of the calling frame.
341   virtual Type GetCallerState(State* state) const;
342 
343   static const intptr_t kIsolateTag = 1;
344 
345   friend class StackFrameIterator;
346   friend class StackFrameIteratorBase;
347   friend class StackHandlerIterator;
348   friend class SafeStackFrameIterator;
349 };
350 
351 class CommonFrame;
352 
353 class V8_EXPORT_PRIVATE FrameSummary {
354  public:
355 // Subclasses for the different summary kinds:
356 #define FRAME_SUMMARY_VARIANTS(F)                                          \
357   F(JAVA_SCRIPT, JavaScriptFrameSummary, java_script_summary_, JavaScript) \
358   IF_WASM(F, WASM, WasmFrameSummary, wasm_summary_, Wasm)
359 
360 #define FRAME_SUMMARY_KIND(kind, type, field, desc) kind,
361   enum Kind { FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_KIND) };
362 #undef FRAME_SUMMARY_KIND
363 
364   class FrameSummaryBase {
365    public:
FrameSummaryBase(Isolate * isolate,Kind kind)366     FrameSummaryBase(Isolate* isolate, Kind kind)
367         : isolate_(isolate), kind_(kind) {}
isolate()368     Isolate* isolate() const { return isolate_; }
kind()369     Kind kind() const { return kind_; }
370 
371    private:
372     Isolate* isolate_;
373     Kind kind_;
374   };
375 
376   class JavaScriptFrameSummary : public FrameSummaryBase {
377    public:
378     JavaScriptFrameSummary(Isolate* isolate, Object receiver,
379                            JSFunction function, AbstractCode abstract_code,
380                            int code_offset, bool is_constructor,
381                            FixedArray parameters);
382 
383     void EnsureSourcePositionsAvailable();
384     bool AreSourcePositionsAvailable() const;
385 
receiver()386     Handle<Object> receiver() const { return receiver_; }
function()387     Handle<JSFunction> function() const { return function_; }
abstract_code()388     Handle<AbstractCode> abstract_code() const { return abstract_code_; }
code_offset()389     int code_offset() const { return code_offset_; }
is_constructor()390     bool is_constructor() const { return is_constructor_; }
parameters()391     Handle<FixedArray> parameters() const { return parameters_; }
392     bool is_subject_to_debugging() const;
393     int SourcePosition() const;
394     int SourceStatementPosition() const;
395     Handle<Object> script() const;
396     Handle<Context> native_context() const;
397     Handle<StackFrameInfo> CreateStackFrameInfo() const;
398 
399    private:
400     Handle<Object> receiver_;
401     Handle<JSFunction> function_;
402     Handle<AbstractCode> abstract_code_;
403     int code_offset_;
404     bool is_constructor_;
405     Handle<FixedArray> parameters_;
406   };
407 
408 #if V8_ENABLE_WEBASSEMBLY
409   class WasmFrameSummary : public FrameSummaryBase {
410    public:
411     WasmFrameSummary(Isolate*, Handle<WasmInstanceObject>, wasm::WasmCode*,
412                      int code_offset, bool at_to_number_conversion);
413 
414     Handle<Object> receiver() const;
415     uint32_t function_index() const;
code()416     wasm::WasmCode* code() const { return code_; }
code_offset()417     int code_offset() const { return code_offset_; }
418     V8_EXPORT_PRIVATE int byte_offset() const;
is_constructor()419     bool is_constructor() const { return false; }
is_subject_to_debugging()420     bool is_subject_to_debugging() const { return true; }
421     int SourcePosition() const;
SourceStatementPosition()422     int SourceStatementPosition() const { return SourcePosition(); }
423     Handle<Script> script() const;
wasm_instance()424     Handle<WasmInstanceObject> wasm_instance() const { return wasm_instance_; }
425     Handle<Context> native_context() const;
at_to_number_conversion()426     bool at_to_number_conversion() const { return at_to_number_conversion_; }
427     Handle<StackFrameInfo> CreateStackFrameInfo() const;
428 
429    private:
430     Handle<WasmInstanceObject> wasm_instance_;
431     bool at_to_number_conversion_;
432     wasm::WasmCode* const code_;
433     int code_offset_;
434   };
435 #endif  // V8_ENABLE_WEBASSEMBLY
436 
437 #define FRAME_SUMMARY_CONS(kind, type, field, desc) \
438   FrameSummary(type summ) : field(summ) {}  // NOLINT
439   FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CONS)
440 #undef FRAME_SUMMARY_CONS
441 
442   ~FrameSummary();
443 
444   static FrameSummary GetTop(const CommonFrame* frame);
445   static FrameSummary GetBottom(const CommonFrame* frame);
446   static FrameSummary GetSingle(const CommonFrame* frame);
447   static FrameSummary Get(const CommonFrame* frame, int index);
448 
449   void EnsureSourcePositionsAvailable();
450   bool AreSourcePositionsAvailable() const;
451 
452   // Dispatched accessors.
453   Handle<Object> receiver() const;
454   int code_offset() const;
455   bool is_constructor() const;
456   bool is_subject_to_debugging() const;
457   Handle<Object> script() const;
458   int SourcePosition() const;
459   int SourceStatementPosition() const;
460   Handle<Context> native_context() const;
461   Handle<StackFrameInfo> CreateStackFrameInfo() const;
462 
463 #define FRAME_SUMMARY_CAST(kind_, type, field, desc)      \
464   bool Is##desc() const { return base_.kind() == kind_; } \
465   const type& As##desc() const {                          \
466     DCHECK_EQ(base_.kind(), kind_);                       \
467     return field;                                         \
468   }
469   FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CAST)
470 #undef FRAME_SUMMARY_CAST
471 
472  private:
473 #define FRAME_SUMMARY_FIELD(kind, type, field, desc) type field;
474   union {
475     FrameSummaryBase base_;
476     FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_FIELD)
477   };
478 #undef FRAME_SUMMARY_FIELD
479 };
480 
481 class CommonFrame : public StackFrame {
482  public:
483   // Accessors.
484   virtual Object context()
485       const;  // TODO(victorgomes): CommonFrames don't have context.
486   virtual int position() const;
487 
488   // Access the expressions in the stack frame including locals.
489   inline Object GetExpression(int index) const;
490   inline void SetExpression(int index, Object value);
491   int ComputeExpressionsCount() const;
492 
493   Address GetCallerStackPointer() const override;
494 
495   // Build a list with summaries for this frame including all inlined frames.
496   // The functions are ordered bottom-to-top (i.e. summaries.last() is the
497   // top-most activation; caller comes before callee).
498   virtual void Summarize(std::vector<FrameSummary>* frames) const;
499 
cast(StackFrame * frame)500   static CommonFrame* cast(StackFrame* frame) {
501     // It is always safe to cast to common.
502     return static_cast<CommonFrame*>(frame);
503   }
504 
505  protected:
506   inline explicit CommonFrame(StackFrameIteratorBase* iterator);
507 
508   void ComputeCallerState(State* state) const override;
509 
510   // Accessors.
511   inline Address caller_fp() const;
512   inline Address caller_pc() const;
513 
514   // Computes the address of the PC field in the standard frame given
515   // by the provided frame pointer.
516   static inline Address ComputePCAddress(Address fp);
517 
518   // Computes the address of the constant pool  field in the standard
519   // frame given by the provided frame pointer.
520   static inline Address ComputeConstantPoolAddress(Address fp);
521 
522   // Iterate over expression stack including stack handlers, locals,
523   // and parts of the fixed part including context and code fields.
524   void IterateExpressions(RootVisitor* v) const;
525 
526   // Returns the address of the n'th expression stack element.
527   virtual Address GetExpressionAddress(int n) const;
528 
529   // Used by OptimizedFrames and StubFrames.
530   void IterateCompiledFrame(RootVisitor* v) const;
531 
532  private:
533   friend class StackFrame;
534   friend class SafeStackFrameIterator;
535 };
536 
537 class TypedFrame : public CommonFrame {
538  public:
unchecked_code()539   Code unchecked_code() const override { return {}; }
Iterate(RootVisitor * v)540   void Iterate(RootVisitor* v) const override { IterateCompiledFrame(v); }
541 
542  protected:
543   inline explicit TypedFrame(StackFrameIteratorBase* iterator);
544 };
545 
546 class CommonFrameWithJSLinkage : public CommonFrame {
547  public:
548   // Accessors.
549   virtual JSFunction function() const = 0;
550 
551   // Access the parameters.
552   virtual Object receiver() const;
553   virtual Object GetParameter(int index) const;
554   virtual int ComputeParametersCount() const;
555   Handle<FixedArray> GetParameters() const;
556   virtual int GetActualArgumentCount() const;
557 
558   // Determine the code for the frame.
559   Code unchecked_code() const override;
560 
561   // Lookup exception handler for current {pc}, returns -1 if none found. Also
562   // returns data associated with the handler site specific to the frame type:
563   //  - OptimizedFrame  : Data is not used and will not return a value.
564   //  - UnoptimizedFrame: Data is the register index holding the context.
565   virtual int LookupExceptionHandlerInTable(
566       int* data, HandlerTable::CatchPrediction* prediction);
567 
568   // Check if this frame is a constructor frame invoked through 'new'.
569   virtual bool IsConstructor() const;
570 
571   // Summarize Frame
572   void Summarize(std::vector<FrameSummary>* frames) const override;
573 
574  protected:
575   inline explicit CommonFrameWithJSLinkage(StackFrameIteratorBase* iterator);
576 
577   // Determines if the standard frame for the given frame pointer is a
578   // construct frame.
579   static inline bool IsConstructFrame(Address fp);
580   inline Address GetParameterSlot(int index) const;
581 };
582 
583 class TypedFrameWithJSLinkage : public CommonFrameWithJSLinkage {
584  public:
585   void Iterate(RootVisitor* v) const override;
586 
587  protected:
588   inline explicit TypedFrameWithJSLinkage(StackFrameIteratorBase* iterator);
589 };
590 
591 class JavaScriptFrame : public CommonFrameWithJSLinkage {
592  public:
593   Type type() const override = 0;
594 
595   // Accessors.
596   JSFunction function() const override;
597   Object unchecked_function() const;
598   Script script() const;
599   Object context() const override;
600   int GetActualArgumentCount() const override;
601 
602   inline void set_receiver(Object value);
603 
604   // Debugger access.
605   void SetParameterValue(int index, Object value) const;
606 
607   // Check if this frame is a constructor frame invoked through 'new'.
608   bool IsConstructor() const override;
609 
610   // Determines whether this frame includes inlined activations. To get details
611   // about the inlined frames use {GetFunctions} and {Summarize}.
612   bool HasInlinedFrames() const;
613 
614   // Garbage collection support.
615   void Iterate(RootVisitor* v) const override;
616 
617   // Printing support.
618   void Print(StringStream* accumulator, PrintMode mode,
619              int index) const override;
620 
621   // Return a list with {SharedFunctionInfo} objects of this frame.
622   virtual void GetFunctions(std::vector<SharedFunctionInfo>* functions) const;
623 
624   void GetFunctions(std::vector<Handle<SharedFunctionInfo>>* functions) const;
625 
626   // Architecture-specific register description.
627   static Register fp_register();
628   static Register context_register();
629   static Register constant_pool_pointer_register();
630 
cast(StackFrame * frame)631   static JavaScriptFrame* cast(StackFrame* frame) {
632     DCHECK(frame->is_java_script());
633     return static_cast<JavaScriptFrame*>(frame);
634   }
635 
636   static void PrintFunctionAndOffset(JSFunction function, AbstractCode code,
637                                      int code_offset, FILE* file,
638                                      bool print_line_number);
639 
640   static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
641                        bool print_line_number);
642 
643   static void CollectFunctionAndOffsetForICStats(JSFunction function,
644                                                  AbstractCode code,
645                                                  int code_offset);
646 
647  protected:
648   inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator);
649 
650   Address GetCallerStackPointer() const override;
651 
PrintFrameKind(StringStream * accumulator)652   virtual void PrintFrameKind(StringStream* accumulator) const {}
653 
654  private:
655   inline Object function_slot_object() const;
656 
657   friend class StackFrameIteratorBase;
658 };
659 
660 class NativeFrame : public TypedFrame {
661  public:
type()662   Type type() const override { return NATIVE; }
663 
664   // Garbage collection support.
Iterate(RootVisitor * v)665   void Iterate(RootVisitor* v) const override {}
666 
667  protected:
668   inline explicit NativeFrame(StackFrameIteratorBase* iterator);
669 
670  private:
671   void ComputeCallerState(State* state) const override;
672 
673   friend class StackFrameIteratorBase;
674 };
675 
676 // Entry frames are used to enter JavaScript execution from C.
677 class EntryFrame : public TypedFrame {
678  public:
type()679   Type type() const override { return ENTRY; }
680 
681   Code unchecked_code() const override;
682 
683   // Garbage collection support.
684   void Iterate(RootVisitor* v) const override;
685 
cast(StackFrame * frame)686   static EntryFrame* cast(StackFrame* frame) {
687     DCHECK(frame->is_entry());
688     return static_cast<EntryFrame*>(frame);
689   }
690 
691  protected:
692   inline explicit EntryFrame(StackFrameIteratorBase* iterator);
693 
694   // The caller stack pointer for entry frames is always zero. The
695   // real information about the caller frame is available through the
696   // link to the top exit frame.
GetCallerStackPointer()697   Address GetCallerStackPointer() const override { return 0; }
698 
699  private:
700   void ComputeCallerState(State* state) const override;
701   Type GetCallerState(State* state) const override;
702 
703   friend class StackFrameIteratorBase;
704 };
705 
706 class ConstructEntryFrame : public EntryFrame {
707  public:
type()708   Type type() const override { return CONSTRUCT_ENTRY; }
709 
710   Code unchecked_code() const override;
711 
cast(StackFrame * frame)712   static ConstructEntryFrame* cast(StackFrame* frame) {
713     DCHECK(frame->is_construct_entry());
714     return static_cast<ConstructEntryFrame*>(frame);
715   }
716 
717  protected:
718   inline explicit ConstructEntryFrame(StackFrameIteratorBase* iterator);
719 
720  private:
721   friend class StackFrameIteratorBase;
722 };
723 
724 // Exit frames are used to exit JavaScript execution and go to C, or to switch
725 // out of the current stack for wasm stack-switching.
726 class ExitFrame : public TypedFrame {
727  public:
type()728   Type type() const override { return EXIT; }
729 
730   // Garbage collection support.
731   void Iterate(RootVisitor* v) const override;
732 
cast(StackFrame * frame)733   static ExitFrame* cast(StackFrame* frame) {
734     DCHECK(frame->is_exit());
735     return static_cast<ExitFrame*>(frame);
736   }
737 
738   // Compute the state and type of an exit frame given a frame
739   // pointer. Used when constructing the first stack frame seen by an
740   // iterator and the frames following entry frames.
741   static Type GetStateForFramePointer(Address fp, State* state);
742   static Address ComputeStackPointer(Address fp);
743   static StackFrame::Type ComputeFrameType(Address fp);
744   static void FillState(Address fp, Address sp, State* state);
745 
746  protected:
747   inline explicit ExitFrame(StackFrameIteratorBase* iterator);
748 
749  private:
750   void ComputeCallerState(State* state) const override;
751 
752   friend class StackFrameIteratorBase;
753 };
754 
755 // Builtin exit frames are a special case of exit frames, which are used
756 // whenever C++ builtins (e.g., Math.acos) are called. Their main purpose is
757 // to allow such builtins to appear in stack traces.
758 class BuiltinExitFrame : public ExitFrame {
759  public:
type()760   Type type() const override { return BUILTIN_EXIT; }
761 
762   JSFunction function() const;
763 
764   Object receiver() const;
765   Object GetParameter(int i) const;
766   int ComputeParametersCount() const;
767   Handle<FixedArray> GetParameters() const;
768 
769   // Check if this frame is a constructor frame invoked through 'new'.
770   bool IsConstructor() const;
771 
772   void Print(StringStream* accumulator, PrintMode mode,
773              int index) const override;
774 
775   // Summarize Frame
776   void Summarize(std::vector<FrameSummary>* frames) const override;
777 
778  protected:
779   inline explicit BuiltinExitFrame(StackFrameIteratorBase* iterator);
780 
781  private:
782   inline Object receiver_slot_object() const;
783   inline Object argc_slot_object() const;
784   inline Object target_slot_object() const;
785   inline Object new_target_slot_object() const;
786 
787   friend class StackFrameIteratorBase;
788 };
789 
790 class StubFrame : public TypedFrame {
791  public:
type()792   Type type() const override { return STUB; }
793 
794   // Determine the code for the frame.
795   Code unchecked_code() const override;
796 
797   // Lookup exception handler for current {pc}, returns -1 if none found. Only
798   // TurboFan stub frames are supported.
799   int LookupExceptionHandlerInTable();
800 
801  protected:
802   inline explicit StubFrame(StackFrameIteratorBase* iterator);
803 
804  private:
805   friend class StackFrameIteratorBase;
806 };
807 
808 class OptimizedFrame : public JavaScriptFrame {
809  public:
type()810   Type type() const override { return OPTIMIZED; }
811 
812   // GC support.
813   void Iterate(RootVisitor* v) const override;
814 
815   // Return a list with {SharedFunctionInfo} objects of this frame.
816   // The functions are ordered bottom-to-top (i.e. functions.last()
817   // is the top-most activation)
818   void GetFunctions(std::vector<SharedFunctionInfo>* functions) const override;
819 
820   void Summarize(std::vector<FrameSummary>* frames) const override;
821 
822   // Lookup exception handler for current {pc}, returns -1 if none found.
823   int LookupExceptionHandlerInTable(
824       int* data, HandlerTable::CatchPrediction* prediction) override;
825 
826   DeoptimizationData GetDeoptimizationData(int* deopt_index) const;
827 
828   int ComputeParametersCount() const override;
829 
830   static int StackSlotOffsetRelativeToFp(int slot_index);
831 
832  protected:
833   inline explicit OptimizedFrame(StackFrameIteratorBase* iterator);
834 
835  private:
836   friend class StackFrameIteratorBase;
837 
838   Object StackSlotAt(int index) const;
839 };
840 
841 // An unoptimized frame is a JavaScript frame that is executing bytecode. It
842 // may be executing it using the interpreter, or via baseline code compiled from
843 // the bytecode.
844 class UnoptimizedFrame : public JavaScriptFrame {
845  public:
846   // Accessors.
847   int position() const override;
848 
849   // Lookup exception handler for current {pc}, returns -1 if none found.
850   int LookupExceptionHandlerInTable(
851       int* data, HandlerTable::CatchPrediction* prediction) override;
852 
853   // Returns the current offset into the bytecode stream.
854   virtual int GetBytecodeOffset() const = 0;
855 
856   // Returns the frame's current bytecode array.
857   BytecodeArray GetBytecodeArray() const;
858 
859   // Access to the interpreter register file for this frame.
860   Object ReadInterpreterRegister(int register_index) const;
861 
862   // Build a list with summaries for this frame including all inlined frames.
863   void Summarize(std::vector<FrameSummary>* frames) const override;
864 
cast(StackFrame * frame)865   static UnoptimizedFrame* cast(StackFrame* frame) {
866     DCHECK(frame->is_unoptimized());
867     return static_cast<UnoptimizedFrame*>(frame);
868   }
869 
870  protected:
871   inline explicit UnoptimizedFrame(StackFrameIteratorBase* iterator);
872 
873   Address GetExpressionAddress(int n) const override;
874 
875  private:
876   friend class StackFrameIteratorBase;
877 };
878 
879 class InterpretedFrame : public UnoptimizedFrame {
880  public:
type()881   Type type() const override { return INTERPRETED; }
882 
883   // Returns the current offset into the bytecode stream.
884   int GetBytecodeOffset() const override;
885 
886   // Updates the current offset into the bytecode stream, mainly used for stack
887   // unwinding to continue execution at a different bytecode offset.
888   void PatchBytecodeOffset(int new_offset);
889 
890   // Updates the frame's BytecodeArray with |bytecode_array|. Used by the
891   // debugger to swap execution onto a BytecodeArray patched with breakpoints.
892   void PatchBytecodeArray(BytecodeArray bytecode_array);
893 
cast(StackFrame * frame)894   static InterpretedFrame* cast(StackFrame* frame) {
895     DCHECK(frame->is_interpreted());
896     return static_cast<InterpretedFrame*>(frame);
897   }
cast(const StackFrame * frame)898   static const InterpretedFrame* cast(const StackFrame* frame) {
899     DCHECK(frame->is_interpreted());
900     return static_cast<const InterpretedFrame*>(frame);
901   }
902 
903   static int GetBytecodeOffset(Address fp);
904 
905  protected:
906   inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);
907 
908  private:
909   friend class StackFrameIteratorBase;
910 };
911 
912 class BaselineFrame : public UnoptimizedFrame {
913  public:
type()914   Type type() const override { return BASELINE; }
915 
916   // Returns the current offset into the bytecode stream.
917   int GetBytecodeOffset() const override;
918 
919   intptr_t GetPCForBytecodeOffset(int lookup_offset) const;
920 
921   void PatchContext(Context value);
922 
cast(StackFrame * frame)923   static BaselineFrame* cast(StackFrame* frame) {
924     DCHECK(frame->is_baseline());
925     return static_cast<BaselineFrame*>(frame);
926   }
927 
928  protected:
929   inline explicit BaselineFrame(StackFrameIteratorBase* iterator);
930 
931  private:
932   friend class StackFrameIteratorBase;
933 };
934 
935 // Builtin frames are built for builtins with JavaScript linkage, such as
936 // various standard library functions (i.e. Math.asin, Math.floor, etc.).
937 class BuiltinFrame final : public TypedFrameWithJSLinkage {
938  public:
type()939   Type type() const final { return BUILTIN; }
940 
cast(StackFrame * frame)941   static BuiltinFrame* cast(StackFrame* frame) {
942     DCHECK(frame->is_builtin());
943     return static_cast<BuiltinFrame*>(frame);
944   }
945 
946   JSFunction function() const override;
947   int ComputeParametersCount() const override;
948 
949  protected:
950   inline explicit BuiltinFrame(StackFrameIteratorBase* iterator);
951 
952  private:
953   friend class StackFrameIteratorBase;
954 };
955 
956 #if V8_ENABLE_WEBASSEMBLY
957 class WasmFrame : public TypedFrame {
958  public:
type()959   Type type() const override { return WASM; }
960 
961   // Printing support.
962   void Print(StringStream* accumulator, PrintMode mode,
963              int index) const override;
964 
965   // Lookup exception handler for current {pc}, returns -1 if none found.
966   int LookupExceptionHandlerInTable();
967 
968   // Accessors.
969   V8_EXPORT_PRIVATE WasmInstanceObject wasm_instance() const;
970   V8_EXPORT_PRIVATE wasm::NativeModule* native_module() const;
971   wasm::WasmCode* wasm_code() const;
972   int function_index() const;
973   Script script() const;
974   // Byte position in the module, or asm.js source position.
975   int position() const override;
976   Object context() const override;
977   bool at_to_number_conversion() const;
978   // Byte offset in the function.
979   int byte_offset() const;
980   bool is_inspectable() const;
981 
982   void Summarize(std::vector<FrameSummary>* frames) const override;
983 
cast(StackFrame * frame)984   static WasmFrame* cast(StackFrame* frame) {
985     DCHECK(frame->is_wasm());
986     return static_cast<WasmFrame*>(frame);
987   }
988 
989  protected:
990   inline explicit WasmFrame(StackFrameIteratorBase* iterator);
991 
992  private:
993   friend class StackFrameIteratorBase;
994   WasmModuleObject module_object() const;
995 };
996 
997 class WasmExitFrame : public WasmFrame {
998  public:
type()999   Type type() const override { return WASM_EXIT; }
1000   static Address ComputeStackPointer(Address fp);
1001 
1002  protected:
1003   inline explicit WasmExitFrame(StackFrameIteratorBase* iterator);
1004 
1005  private:
1006   friend class StackFrameIteratorBase;
1007 };
1008 
1009 class WasmDebugBreakFrame final : public TypedFrame {
1010  public:
type()1011   Type type() const override { return WASM_DEBUG_BREAK; }
1012 
1013   // GC support.
1014   void Iterate(RootVisitor* v) const override;
1015 
1016   void Print(StringStream* accumulator, PrintMode mode,
1017              int index) const override;
1018 
cast(StackFrame * frame)1019   static WasmDebugBreakFrame* cast(StackFrame* frame) {
1020     DCHECK(frame->is_wasm_debug_break());
1021     return static_cast<WasmDebugBreakFrame*>(frame);
1022   }
1023 
1024  protected:
1025   inline explicit WasmDebugBreakFrame(StackFrameIteratorBase*);
1026 
1027  private:
1028   friend class StackFrameIteratorBase;
1029 };
1030 
1031 class WasmToJsFrame : public StubFrame {
1032  public:
type()1033   Type type() const override { return WASM_TO_JS; }
1034 
1035  protected:
1036   inline explicit WasmToJsFrame(StackFrameIteratorBase* iterator);
1037 
1038  private:
1039   friend class StackFrameIteratorBase;
1040 };
1041 
1042 class JsToWasmFrame : public StubFrame {
1043  public:
type()1044   Type type() const override { return JS_TO_WASM; }
1045 
1046   void Iterate(RootVisitor* v) const override;
1047 
1048  protected:
1049   inline explicit JsToWasmFrame(StackFrameIteratorBase* iterator);
1050 
1051  private:
1052   friend class StackFrameIteratorBase;
1053 };
1054 
1055 class StackSwitchFrame : public ExitFrame {
1056  public:
type()1057   Type type() const override { return STACK_SWITCH; }
1058   void Iterate(RootVisitor* v) const override;
1059   static void GetStateForJumpBuffer(wasm::JumpBuffer* jmpbuf, State* state);
1060 
1061  protected:
1062   inline explicit StackSwitchFrame(StackFrameIteratorBase* iterator);
1063 
1064  private:
1065   friend class StackFrameIteratorBase;
1066 };
1067 
1068 class CWasmEntryFrame : public StubFrame {
1069  public:
type()1070   Type type() const override { return C_WASM_ENTRY; }
1071 
1072  protected:
1073   inline explicit CWasmEntryFrame(StackFrameIteratorBase* iterator);
1074 
1075  private:
1076   friend class StackFrameIteratorBase;
1077   Type GetCallerState(State* state) const override;
1078 };
1079 
1080 class WasmCompileLazyFrame : public TypedFrame {
1081  public:
type()1082   Type type() const override { return WASM_COMPILE_LAZY; }
1083 
1084   WasmInstanceObject wasm_instance() const;
1085   FullObjectSlot wasm_instance_slot() const;
1086 
1087   // Garbage collection support.
1088   void Iterate(RootVisitor* v) const override;
1089 
cast(StackFrame * frame)1090   static WasmCompileLazyFrame* cast(StackFrame* frame) {
1091     DCHECK(frame->is_wasm_compile_lazy());
1092     return static_cast<WasmCompileLazyFrame*>(frame);
1093   }
1094 
1095  protected:
1096   inline explicit WasmCompileLazyFrame(StackFrameIteratorBase* iterator);
1097 
1098  private:
1099   friend class StackFrameIteratorBase;
1100 };
1101 #endif  // V8_ENABLE_WEBASSEMBLY
1102 
1103 class InternalFrame : public TypedFrame {
1104  public:
type()1105   Type type() const override { return INTERNAL; }
1106 
1107   // Garbage collection support.
1108   void Iterate(RootVisitor* v) 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  private:
1119   friend class StackFrameIteratorBase;
1120 };
1121 
1122 // Construct frames are special trampoline frames introduced to handle
1123 // function invocations through 'new'.
1124 class ConstructFrame : public InternalFrame {
1125  public:
type()1126   Type type() const override { return CONSTRUCT; }
1127 
cast(StackFrame * frame)1128   static ConstructFrame* cast(StackFrame* frame) {
1129     DCHECK(frame->is_construct());
1130     return static_cast<ConstructFrame*>(frame);
1131   }
1132 
1133  protected:
1134   inline explicit ConstructFrame(StackFrameIteratorBase* iterator);
1135 
1136  private:
1137   friend class StackFrameIteratorBase;
1138 };
1139 
1140 class BuiltinContinuationFrame : public InternalFrame {
1141  public:
type()1142   Type type() const override { return BUILTIN_CONTINUATION; }
1143 
cast(StackFrame * frame)1144   static BuiltinContinuationFrame* cast(StackFrame* frame) {
1145     DCHECK(frame->is_builtin_continuation());
1146     return static_cast<BuiltinContinuationFrame*>(frame);
1147   }
1148 
1149  protected:
1150   inline explicit BuiltinContinuationFrame(StackFrameIteratorBase* iterator);
1151 
1152  private:
1153   friend class StackFrameIteratorBase;
1154 };
1155 
1156 class JavaScriptBuiltinContinuationFrame : public TypedFrameWithJSLinkage {
1157  public:
type()1158   Type type() const override { return JAVA_SCRIPT_BUILTIN_CONTINUATION; }
1159 
cast(StackFrame * frame)1160   static JavaScriptBuiltinContinuationFrame* cast(StackFrame* frame) {
1161     DCHECK(frame->is_java_script_builtin_continuation());
1162     return static_cast<JavaScriptBuiltinContinuationFrame*>(frame);
1163   }
1164 
1165   JSFunction function() const override;
1166   int ComputeParametersCount() const override;
1167   intptr_t GetSPToFPDelta() const;
1168 
1169   Object context() const override;
1170 
1171  protected:
1172   inline explicit JavaScriptBuiltinContinuationFrame(
1173       StackFrameIteratorBase* iterator);
1174 
1175  private:
1176   friend class StackFrameIteratorBase;
1177 };
1178 
1179 class JavaScriptBuiltinContinuationWithCatchFrame
1180     : public JavaScriptBuiltinContinuationFrame {
1181  public:
type()1182   Type type() const override {
1183     return JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
1184   }
1185 
cast(StackFrame * frame)1186   static JavaScriptBuiltinContinuationWithCatchFrame* cast(StackFrame* frame) {
1187     DCHECK(frame->is_java_script_builtin_with_catch_continuation());
1188     return static_cast<JavaScriptBuiltinContinuationWithCatchFrame*>(frame);
1189   }
1190 
1191   // Patch in the exception object at the appropriate location into the stack
1192   // frame.
1193   void SetException(Object exception);
1194 
1195  protected:
1196   inline explicit JavaScriptBuiltinContinuationWithCatchFrame(
1197       StackFrameIteratorBase* iterator);
1198 
1199  private:
1200   friend class StackFrameIteratorBase;
1201 };
1202 
1203 class StackFrameIteratorBase {
1204  public:
1205   StackFrameIteratorBase(const StackFrameIteratorBase&) = delete;
1206   StackFrameIteratorBase& operator=(const StackFrameIteratorBase&) = delete;
1207 
isolate()1208   Isolate* isolate() const { return isolate_; }
1209 
done()1210   bool done() const { return frame_ == nullptr; }
1211 
1212  protected:
1213   // An iterator that iterates over a given thread's stack.
1214   StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects);
1215 
1216   Isolate* isolate_;
1217 #define DECLARE_SINGLETON(ignore, type) type type##_;
1218   STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
1219 #undef DECLARE_SINGLETON
1220   StackFrame* frame_;
1221   StackHandler* handler_;
1222   const bool can_access_heap_objects_;
1223 
handler()1224   StackHandler* handler() const {
1225     DCHECK(!done());
1226     return handler_;
1227   }
1228 
1229   // Get the type-specific frame singleton in a given state.
1230   StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
1231   // A helper function, can return a nullptr pointer.
1232   StackFrame* SingletonFor(StackFrame::Type type);
1233 
1234  private:
1235   friend class StackFrame;
1236 };
1237 
1238 class StackFrameIterator : public StackFrameIteratorBase {
1239  public:
1240   // An iterator that iterates over the isolate's current thread's stack,
1241   V8_EXPORT_PRIVATE explicit StackFrameIterator(Isolate* isolate);
1242   // An iterator that iterates over a given thread's stack.
1243   V8_EXPORT_PRIVATE StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
1244 #if V8_ENABLE_WEBASSEMBLY
1245   // An iterator that iterates over a given wasm stack segment.
1246   V8_EXPORT_PRIVATE StackFrameIterator(Isolate* isolate,
1247                                        wasm::StackMemory* stack);
1248 #endif
1249 
1250   StackFrameIterator(const StackFrameIterator&) = delete;
1251   StackFrameIterator& operator=(const StackFrameIterator&) = delete;
1252 
frame()1253   StackFrame* frame() const {
1254     DCHECK(!done());
1255     return frame_;
1256   }
1257   V8_EXPORT_PRIVATE void Advance();
1258   StackFrame* Reframe();
1259 
1260  private:
1261   // Go back to the first frame.
1262   void Reset(ThreadLocalTop* top);
1263 #if V8_ENABLE_WEBASSEMBLY
1264   void Reset(ThreadLocalTop* top, wasm::StackMemory* stack);
1265 #endif
1266 };
1267 
1268 // Iterator that supports iterating through all JavaScript frames.
1269 class JavaScriptFrameIterator {
1270  public:
1271   inline explicit JavaScriptFrameIterator(Isolate* isolate);
1272   inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top);
1273 
1274   inline JavaScriptFrame* frame() const;
1275 
done()1276   bool done() const { return iterator_.done(); }
1277   V8_EXPORT_PRIVATE void Advance();
AdvanceOneFrame()1278   void AdvanceOneFrame() { iterator_.Advance(); }
1279   inline JavaScriptFrame* Reframe();
1280 
1281  private:
1282   StackFrameIterator iterator_;
1283 };
1284 
1285 // NOTE: The stack trace frame iterator is an iterator that only traverse proper
1286 // JavaScript frames that have proper JavaScript functions and WebAssembly
1287 // frames.
1288 class V8_EXPORT_PRIVATE StackTraceFrameIterator {
1289  public:
1290   explicit StackTraceFrameIterator(Isolate* isolate);
1291   // Skip frames until the frame with the given id is reached.
1292   StackTraceFrameIterator(Isolate* isolate, StackFrameId id);
done()1293   bool done() const { return iterator_.done(); }
1294   void Advance();
AdvanceOneFrame()1295   void AdvanceOneFrame() { iterator_.Advance(); }
1296   int FrameFunctionCount() const;
1297 
1298   inline CommonFrame* frame() const;
1299   inline CommonFrame* Reframe();
1300 
1301   inline bool is_javascript() const;
1302 #if V8_ENABLE_WEBASSEMBLY
1303   inline bool is_wasm() const;
1304 #endif  // V8_ENABLE_WEBASSEMBLY
1305   inline JavaScriptFrame* javascript_frame() const;
1306 
1307   // Use this instead of FrameSummary::GetTop(javascript_frame) to keep
1308   // filtering behavior consistent with the rest of StackTraceFrameIterator.
1309   FrameSummary GetTopValidFrame() const;
1310 
1311  private:
1312   StackFrameIterator iterator_;
1313   static bool IsValidFrame(StackFrame* frame);
1314   static bool IsValidJSFunction(JSFunction f);
1315 };
1316 
1317 class SafeStackFrameIterator : public StackFrameIteratorBase {
1318  public:
1319   SafeStackFrameIterator(Isolate* isolate, Address pc, Address fp, Address sp,
1320                          Address lr, Address js_entry_sp);
1321 
1322   inline StackFrame* frame() const;
1323   void Advance();
1324 
top_frame_type()1325   StackFrame::Type top_frame_type() const { return top_frame_type_; }
top_context_address()1326   Address top_context_address() const { return top_context_address_; }
1327 
1328  private:
1329   void AdvanceOneFrame();
1330 
IsValidStackAddress(Address addr)1331   bool IsValidStackAddress(Address addr) const {
1332     return low_bound_ <= addr && addr <= high_bound_;
1333   }
1334   bool IsValidFrame(StackFrame* frame) const;
1335   bool IsValidCaller(StackFrame* frame);
1336   bool IsValidExitFrame(Address fp) const;
1337   bool IsValidTop(ThreadLocalTop* top) const;
1338 
1339   // Returns true if the pc points to a bytecode handler and the frame pointer
1340   // doesn't seem to be a bytecode handler's frame, which implies that the
1341   // bytecode handler has an elided frame. This is not precise and might give
1342   // false negatives since it relies on checks to the frame's type marker,
1343   // which might be uninitialized.
1344   bool IsNoFrameBytecodeHandlerPc(Isolate* isolate, Address pc,
1345                                   Address fp) const;
1346 
1347   const Address low_bound_;
1348   const Address high_bound_;
1349   StackFrame::Type top_frame_type_;
1350   Address top_context_address_;
1351   ExternalCallbackScope* external_callback_scope_;
1352   Address top_link_register_;
1353 };
1354 
1355 // Frame layout helper classes. Used by the deoptimizer and instruction
1356 // selector.
1357 // -------------------------------------------------------------------------
1358 
1359 // How to calculate the frame layout information. Precise, when all information
1360 // is available during deoptimization. Conservative, when an overapproximation
1361 // is fine.
1362 // TODO(jgruber): Investigate whether the conservative kind can be removed. It
1363 // seems possible: 1. is_topmost should be known through the outer_state chain
1364 // of FrameStateDescriptor; 2. the deopt_kind may be a property of the bailout
1365 // id; 3. for continuation_mode, we only care whether it is a mode with catch,
1366 // and that is likewise known at compile-time.
1367 // There is nothing specific blocking this, the investigation just requires time
1368 // and it is not that important to get the exact frame height at compile-time.
1369 enum class FrameInfoKind {
1370   kPrecise,
1371   kConservative,
1372 };
1373 
1374 // Used by the deoptimizer. Corresponds to frame kinds:
1375 enum class BuiltinContinuationMode {
1376   STUB,                        // BuiltinContinuationFrame
1377   JAVASCRIPT,                  // JavaScriptBuiltinContinuationFrame
1378   JAVASCRIPT_WITH_CATCH,       // JavaScriptBuiltinContinuationWithCatchFrame
1379   JAVASCRIPT_HANDLE_EXCEPTION  // JavaScriptBuiltinContinuationWithCatchFrame
1380 };
1381 
1382 class UnoptimizedFrameInfo {
1383  public:
Precise(int parameters_count_with_receiver,int translation_height,bool is_topmost,bool pad_arguments)1384   static UnoptimizedFrameInfo Precise(int parameters_count_with_receiver,
1385                                       int translation_height, bool is_topmost,
1386                                       bool pad_arguments) {
1387     return {parameters_count_with_receiver, translation_height, is_topmost,
1388             pad_arguments, FrameInfoKind::kPrecise};
1389   }
1390 
Conservative(int parameters_count_with_receiver,int locals_count)1391   static UnoptimizedFrameInfo Conservative(int parameters_count_with_receiver,
1392                                            int locals_count) {
1393     return {parameters_count_with_receiver, locals_count, false, true,
1394             FrameInfoKind::kConservative};
1395   }
1396 
1397   static uint32_t GetStackSizeForAdditionalArguments(int parameters_count);
1398 
register_stack_slot_count()1399   uint32_t register_stack_slot_count() const {
1400     return register_stack_slot_count_;
1401   }
frame_size_in_bytes_without_fixed()1402   uint32_t frame_size_in_bytes_without_fixed() const {
1403     return frame_size_in_bytes_without_fixed_;
1404   }
frame_size_in_bytes()1405   uint32_t frame_size_in_bytes() const { return frame_size_in_bytes_; }
1406 
1407  private:
1408   UnoptimizedFrameInfo(int parameters_count_with_receiver,
1409                        int translation_height, bool is_topmost,
1410                        bool pad_arguments, FrameInfoKind frame_info_kind);
1411 
1412   uint32_t register_stack_slot_count_;
1413   uint32_t frame_size_in_bytes_without_fixed_;
1414   uint32_t frame_size_in_bytes_;
1415 };
1416 
1417 class ConstructStubFrameInfo {
1418  public:
Precise(int translation_height,bool is_topmost)1419   static ConstructStubFrameInfo Precise(int translation_height,
1420                                         bool is_topmost) {
1421     return {translation_height, is_topmost, FrameInfoKind::kPrecise};
1422   }
1423 
Conservative(int parameters_count)1424   static ConstructStubFrameInfo Conservative(int parameters_count) {
1425     return {parameters_count, false, FrameInfoKind::kConservative};
1426   }
1427 
frame_size_in_bytes_without_fixed()1428   uint32_t frame_size_in_bytes_without_fixed() const {
1429     return frame_size_in_bytes_without_fixed_;
1430   }
frame_size_in_bytes()1431   uint32_t frame_size_in_bytes() const { return frame_size_in_bytes_; }
1432 
1433  private:
1434   ConstructStubFrameInfo(int translation_height, bool is_topmost,
1435                          FrameInfoKind frame_info_kind);
1436 
1437   uint32_t frame_size_in_bytes_without_fixed_;
1438   uint32_t frame_size_in_bytes_;
1439 };
1440 
1441 // Used by BuiltinContinuationFrameInfo.
1442 class CallInterfaceDescriptor;
1443 class RegisterConfiguration;
1444 
1445 class BuiltinContinuationFrameInfo {
1446  public:
Precise(int translation_height,const CallInterfaceDescriptor & continuation_descriptor,const RegisterConfiguration * register_config,bool is_topmost,DeoptimizeKind deopt_kind,BuiltinContinuationMode continuation_mode)1447   static BuiltinContinuationFrameInfo Precise(
1448       int translation_height,
1449       const CallInterfaceDescriptor& continuation_descriptor,
1450       const RegisterConfiguration* register_config, bool is_topmost,
1451       DeoptimizeKind deopt_kind, BuiltinContinuationMode continuation_mode) {
1452     return {translation_height,
1453             continuation_descriptor,
1454             register_config,
1455             is_topmost,
1456             deopt_kind,
1457             continuation_mode,
1458             FrameInfoKind::kPrecise};
1459   }
1460 
Conservative(int parameters_count,const CallInterfaceDescriptor & continuation_descriptor,const RegisterConfiguration * register_config)1461   static BuiltinContinuationFrameInfo Conservative(
1462       int parameters_count,
1463       const CallInterfaceDescriptor& continuation_descriptor,
1464       const RegisterConfiguration* register_config) {
1465     // It doesn't matter what we pass as is_topmost, deopt_kind and
1466     // continuation_mode; these values are ignored in conservative mode.
1467     return {parameters_count,
1468             continuation_descriptor,
1469             register_config,
1470             false,
1471             DeoptimizeKind::kEager,
1472             BuiltinContinuationMode::STUB,
1473             FrameInfoKind::kConservative};
1474   }
1475 
frame_has_result_stack_slot()1476   bool frame_has_result_stack_slot() const {
1477     return frame_has_result_stack_slot_;
1478   }
translated_stack_parameter_count()1479   uint32_t translated_stack_parameter_count() const {
1480     return translated_stack_parameter_count_;
1481   }
stack_parameter_count()1482   uint32_t stack_parameter_count() const { return stack_parameter_count_; }
frame_size_in_bytes()1483   uint32_t frame_size_in_bytes() const { return frame_size_in_bytes_; }
frame_size_in_bytes_above_fp()1484   uint32_t frame_size_in_bytes_above_fp() const {
1485     return frame_size_in_bytes_above_fp_;
1486   }
1487 
1488  private:
1489   BuiltinContinuationFrameInfo(
1490       int translation_height,
1491       const CallInterfaceDescriptor& continuation_descriptor,
1492       const RegisterConfiguration* register_config, bool is_topmost,
1493       DeoptimizeKind deopt_kind, BuiltinContinuationMode continuation_mode,
1494       FrameInfoKind frame_info_kind);
1495 
1496   bool frame_has_result_stack_slot_;
1497   uint32_t translated_stack_parameter_count_;
1498   uint32_t stack_parameter_count_;
1499   uint32_t frame_size_in_bytes_;
1500   uint32_t frame_size_in_bytes_above_fp_;
1501 };
1502 
1503 }  // namespace internal
1504 }  // namespace v8
1505 
1506 #endif  // V8_EXECUTION_FRAMES_H_
1507