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