xref: /third_party/node/deps/v8/src/execution/frames.h (revision 1cb0ef41)
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
47namespace v8 {
48namespace internal {
49namespace wasm {
50class WasmCode;
51struct JumpBuffer;
52class StackMemory;
53}  // namespace wasm
54
55class AbstractCode;
56class Debug;
57class ExternalCallbackScope;
58class InnerPointerToCodeCache;
59class Isolate;
60class ObjectVisitor;
61class Register;
62class RootVisitor;
63class StackFrameInfo;
64class StackFrameIteratorBase;
65class StringStream;
66class ThreadLocalTop;
67class WasmInstanceObject;
68class WasmModuleObject;
69
70class 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
79class 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.
125class 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.
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.
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.
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).
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.
213  bool is_entry() const { return type() == ENTRY; }
214  bool is_construct_entry() const { return type() == CONSTRUCT_ENTRY; }
215  bool is_exit() const { return type() == EXIT; }
216  bool is_optimized() const { return type() == OPTIMIZED; }
217  bool is_unoptimized() const {
218    STATIC_ASSERT(BASELINE == INTERPRETED + 1);
219    return base::IsInRange(type(), INTERPRETED, BASELINE);
220  }
221  bool is_interpreted() const { return type() == INTERPRETED; }
222  bool is_baseline() const { return type() == BASELINE; }
223#if V8_ENABLE_WEBASSEMBLY
224  bool is_wasm() const { return this->type() == WASM; }
225  bool is_c_wasm_entry() const { return type() == C_WASM_ENTRY; }
226  bool is_wasm_compile_lazy() const { return type() == WASM_COMPILE_LAZY; }
227  bool is_wasm_debug_break() const { return type() == WASM_DEBUG_BREAK; }
228  bool is_wasm_to_js() const { return type() == WASM_TO_JS; }
229  bool is_js_to_wasm() const { return type() == JS_TO_WASM; }
230#endif  // V8_ENABLE_WEBASSEMBLY
231  bool is_builtin() const { return type() == BUILTIN; }
232  bool is_internal() const { return type() == INTERNAL; }
233  bool is_builtin_continuation() const {
234    return type() == BUILTIN_CONTINUATION;
235  }
236  bool is_java_script_builtin_continuation() const {
237    return type() == JAVA_SCRIPT_BUILTIN_CONTINUATION;
238  }
239  bool is_java_script_builtin_with_catch_continuation() const {
240    return type() == JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
241  }
242  bool is_construct() const { return type() == CONSTRUCT; }
243  bool is_builtin_exit() const { return type() == BUILTIN_EXIT; }
244
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  }
250  bool is_java_script() const { return IsJavaScript(type()); }
251
252  // Accessors.
253  Address sp() const { return state_.sp; }
254  Address fp() const { return state_.fp; }
255  Address callee_fp() const { return state_.callee_fp; }
256  inline Address callee_pc() const;
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
265  Address constant_pool() const { return *constant_pool_address(); }
266  void set_constant_pool(Address constant_pool) {
267    *constant_pool_address() = constant_pool;
268  }
269
270  Address* pc_address() const { return state_.pc_address; }
271
272  Address* constant_pool_address() const {
273    return state_.constant_pool_address;
274  }
275
276  // Get the id of this stack frame.
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
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
351class CommonFrame;
352
353class 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:
366    FrameSummaryBase(Isolate* isolate, Kind kind)
367        : isolate_(isolate), kind_(kind) {}
368    Isolate* isolate() const { return isolate_; }
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
386    Handle<Object> receiver() const { return receiver_; }
387    Handle<JSFunction> function() const { return function_; }
388    Handle<AbstractCode> abstract_code() const { return abstract_code_; }
389    int code_offset() const { return code_offset_; }
390    bool is_constructor() const { return is_constructor_; }
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;
416    wasm::WasmCode* code() const { return code_; }
417    int code_offset() const { return code_offset_; }
418    V8_EXPORT_PRIVATE int byte_offset() const;
419    bool is_constructor() const { return false; }
420    bool is_subject_to_debugging() const { return true; }
421    int SourcePosition() const;
422    int SourceStatementPosition() const { return SourcePosition(); }
423    Handle<Script> script() const;
424    Handle<WasmInstanceObject> wasm_instance() const { return wasm_instance_; }
425    Handle<Context> native_context() const;
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
481class 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
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
537class TypedFrame : public CommonFrame {
538 public:
539  Code unchecked_code() const override { return {}; }
540  void Iterate(RootVisitor* v) const override { IterateCompiledFrame(v); }
541
542 protected:
543  inline explicit TypedFrame(StackFrameIteratorBase* iterator);
544};
545
546class 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
583class TypedFrameWithJSLinkage : public CommonFrameWithJSLinkage {
584 public:
585  void Iterate(RootVisitor* v) const override;
586
587 protected:
588  inline explicit TypedFrameWithJSLinkage(StackFrameIteratorBase* iterator);
589};
590
591class 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
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
652  virtual void PrintFrameKind(StringStream* accumulator) const {}
653
654 private:
655  inline Object function_slot_object() const;
656
657  friend class StackFrameIteratorBase;
658};
659
660class NativeFrame : public TypedFrame {
661 public:
662  Type type() const override { return NATIVE; }
663
664  // Garbage collection support.
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.
677class EntryFrame : public TypedFrame {
678 public:
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
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.
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
706class ConstructEntryFrame : public EntryFrame {
707 public:
708  Type type() const override { return CONSTRUCT_ENTRY; }
709
710  Code unchecked_code() const override;
711
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.
726class ExitFrame : public TypedFrame {
727 public:
728  Type type() const override { return EXIT; }
729
730  // Garbage collection support.
731  void Iterate(RootVisitor* v) const override;
732
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.
758class BuiltinExitFrame : public ExitFrame {
759 public:
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
790class StubFrame : public TypedFrame {
791 public:
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
808class OptimizedFrame : public JavaScriptFrame {
809 public:
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.
844class 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
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
879class InterpretedFrame : public UnoptimizedFrame {
880 public:
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
894  static InterpretedFrame* cast(StackFrame* frame) {
895    DCHECK(frame->is_interpreted());
896    return static_cast<InterpretedFrame*>(frame);
897  }
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
912class BaselineFrame : public UnoptimizedFrame {
913 public:
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
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.).
937class BuiltinFrame final : public TypedFrameWithJSLinkage {
938 public:
939  Type type() const final { return BUILTIN; }
940
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
957class WasmFrame : public TypedFrame {
958 public:
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
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
997class WasmExitFrame : public WasmFrame {
998 public:
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
1009class WasmDebugBreakFrame final : public TypedFrame {
1010 public:
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
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
1031class WasmToJsFrame : public StubFrame {
1032 public:
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
1042class JsToWasmFrame : public StubFrame {
1043 public:
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
1055class StackSwitchFrame : public ExitFrame {
1056 public:
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
1068class CWasmEntryFrame : public StubFrame {
1069 public:
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
1080class WasmCompileLazyFrame : public TypedFrame {
1081 public:
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
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
1103class InternalFrame : public TypedFrame {
1104 public:
1105  Type type() const override { return INTERNAL; }
1106
1107  // Garbage collection support.
1108  void Iterate(RootVisitor* v) const override;
1109
1110  static InternalFrame* cast(StackFrame* frame) {
1111    DCHECK(frame->is_internal());
1112    return static_cast<InternalFrame*>(frame);
1113  }
1114
1115 protected:
1116  inline explicit InternalFrame(StackFrameIteratorBase* iterator);
1117
1118 private:
1119  friend class StackFrameIteratorBase;
1120};
1121
1122// Construct frames are special trampoline frames introduced to handle
1123// function invocations through 'new'.
1124class ConstructFrame : public InternalFrame {
1125 public:
1126  Type type() const override { return CONSTRUCT; }
1127
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
1140class BuiltinContinuationFrame : public InternalFrame {
1141 public:
1142  Type type() const override { return BUILTIN_CONTINUATION; }
1143
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
1156class JavaScriptBuiltinContinuationFrame : public TypedFrameWithJSLinkage {
1157 public:
1158  Type type() const override { return JAVA_SCRIPT_BUILTIN_CONTINUATION; }
1159
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
1179class JavaScriptBuiltinContinuationWithCatchFrame
1180    : public JavaScriptBuiltinContinuationFrame {
1181 public:
1182  Type type() const override {
1183    return JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
1184  }
1185
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
1203class StackFrameIteratorBase {
1204 public:
1205  StackFrameIteratorBase(const StackFrameIteratorBase&) = delete;
1206  StackFrameIteratorBase& operator=(const StackFrameIteratorBase&) = delete;
1207
1208  Isolate* isolate() const { return isolate_; }
1209
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
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
1238class 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
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.
1269class JavaScriptFrameIterator {
1270 public:
1271  inline explicit JavaScriptFrameIterator(Isolate* isolate);
1272  inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top);
1273
1274  inline JavaScriptFrame* frame() const;
1275
1276  bool done() const { return iterator_.done(); }
1277  V8_EXPORT_PRIVATE void Advance();
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.
1288class 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);
1293  bool done() const { return iterator_.done(); }
1294  void Advance();
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
1317class 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
1325  StackFrame::Type top_frame_type() const { return top_frame_type_; }
1326  Address top_context_address() const { return top_context_address_; }
1327
1328 private:
1329  void AdvanceOneFrame();
1330
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.
1369enum class FrameInfoKind {
1370  kPrecise,
1371  kConservative,
1372};
1373
1374// Used by the deoptimizer. Corresponds to frame kinds:
1375enum class BuiltinContinuationMode {
1376  STUB,                        // BuiltinContinuationFrame
1377  JAVASCRIPT,                  // JavaScriptBuiltinContinuationFrame
1378  JAVASCRIPT_WITH_CATCH,       // JavaScriptBuiltinContinuationWithCatchFrame
1379  JAVASCRIPT_HANDLE_EXCEPTION  // JavaScriptBuiltinContinuationWithCatchFrame
1380};
1381
1382class UnoptimizedFrameInfo {
1383 public:
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
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
1399  uint32_t register_stack_slot_count() const {
1400    return register_stack_slot_count_;
1401  }
1402  uint32_t frame_size_in_bytes_without_fixed() const {
1403    return frame_size_in_bytes_without_fixed_;
1404  }
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
1417class ConstructStubFrameInfo {
1418 public:
1419  static ConstructStubFrameInfo Precise(int translation_height,
1420                                        bool is_topmost) {
1421    return {translation_height, is_topmost, FrameInfoKind::kPrecise};
1422  }
1423
1424  static ConstructStubFrameInfo Conservative(int parameters_count) {
1425    return {parameters_count, false, FrameInfoKind::kConservative};
1426  }
1427
1428  uint32_t frame_size_in_bytes_without_fixed() const {
1429    return frame_size_in_bytes_without_fixed_;
1430  }
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.
1442class CallInterfaceDescriptor;
1443class RegisterConfiguration;
1444
1445class BuiltinContinuationFrameInfo {
1446 public:
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
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
1476  bool frame_has_result_stack_slot() const {
1477    return frame_has_result_stack_slot_;
1478  }
1479  uint32_t translated_stack_parameter_count() const {
1480    return translated_stack_parameter_count_;
1481  }
1482  uint32_t stack_parameter_count() const { return stack_parameter_count_; }
1483  uint32_t frame_size_in_bytes() const { return frame_size_in_bytes_; }
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