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