V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
frames.h
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_FRAMES_H_
6 #define V8_FRAMES_H_
7 
8 #include "src/handles.h"
9 #include "src/objects.h"
10 #include "src/objects/code.h"
11 #include "src/safepoint-table.h"
12 
13 namespace v8 {
14 namespace internal {
15 namespace wasm {
16 class WasmCode;
17 }
18 
19 // Forward declarations.
20 class AbstractCode;
21 class Debug;
22 class ExternalCallbackScope;
23 class InnerPointerToCodeCache;
24 class Isolate;
25 class ObjectVisitor;
26 class RootVisitor;
27 class StackFrameIteratorBase;
28 class StringStream;
29 class ThreadLocalTop;
30 class WasmDebugInfo;
31 class WasmInstanceObject;
32 class WasmModuleObject;
33 
35  public:
36  static const int kNextOffset = 0 * kPointerSize;
37  static const int kPaddingOffset = 1 * kPointerSize;
38 
39  static const int kSize = kPaddingOffset + kPointerSize;
40  static const int kSlotCount = kSize >> kPointerSizeLog2;
41 };
42 
43 class StackHandler {
44  public:
45  // Get the address of this stack handler.
46  inline Address address() const;
47 
48  // Get the next stack handler in the chain.
49  inline StackHandler* next() const;
50 
51  // Conversion support.
52  static inline StackHandler* FromAddress(Address address);
53 
54  private:
55  DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
56 };
57 
58 #define STACK_FRAME_TYPE_LIST(V) \
59  V(ENTRY, EntryFrame) \
60  V(CONSTRUCT_ENTRY, ConstructEntryFrame) \
61  V(EXIT, ExitFrame) \
62  V(OPTIMIZED, OptimizedFrame) \
63  V(WASM_COMPILED, WasmCompiledFrame) \
64  V(WASM_TO_JS, WasmToJsFrame) \
65  V(JS_TO_WASM, JsToWasmFrame) \
66  V(WASM_INTERPRETER_ENTRY, WasmInterpreterEntryFrame) \
67  V(C_WASM_ENTRY, CWasmEntryFrame) \
68  V(WASM_COMPILE_LAZY, WasmCompileLazyFrame) \
69  V(INTERPRETED, InterpretedFrame) \
70  V(STUB, StubFrame) \
71  V(BUILTIN_CONTINUATION, BuiltinContinuationFrame) \
72  V(JAVA_SCRIPT_BUILTIN_CONTINUATION, JavaScriptBuiltinContinuationFrame) \
73  V(JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH, \
74  JavaScriptBuiltinContinuationWithCatchFrame) \
75  V(INTERNAL, InternalFrame) \
76  V(CONSTRUCT, ConstructFrame) \
77  V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame) \
78  V(BUILTIN, BuiltinFrame) \
79  V(BUILTIN_EXIT, BuiltinExitFrame) \
80  V(NATIVE, NativeFrame)
81 
82 // Abstract base class for all stack frames.
83 class StackFrame {
84  public:
85 #define DECLARE_TYPE(type, ignore) type,
86  enum Type {
87  NONE = 0,
88  STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
89  NUMBER_OF_TYPES,
90  // Used by FrameScope to indicate that the stack frame is constructed
91  // manually and the FrameScope does not need to emit code.
92  MANUAL
93  };
94 #undef DECLARE_TYPE
95 
96  // Opaque data type for identifying stack frames. Used extensively
97  // by the debugger.
98  // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
99  // has correct value range (see Issue 830 for more details).
100  enum Id {
101  ID_MIN_VALUE = kMinInt,
102  ID_MAX_VALUE = kMaxInt,
103  NO_ID = 0
104  };
105 
106  // Used to mark the outermost JS entry frame.
107  //
108  // The mark is an opaque value that should be pushed onto the stack directly,
109  // carefully crafted to not be interpreted as a tagged pointer.
110  enum JsFrameMarker {
111  INNER_JSENTRY_FRAME = (0 << kSmiTagSize) | kSmiTag,
112  OUTERMOST_JSENTRY_FRAME = (1 << kSmiTagSize) | kSmiTag
113  };
114  STATIC_ASSERT((INNER_JSENTRY_FRAME & kHeapObjectTagMask) != kHeapObjectTag);
115  STATIC_ASSERT((OUTERMOST_JSENTRY_FRAME & kHeapObjectTagMask) !=
116  kHeapObjectTag);
117 
118  struct State {
119  Address sp = kNullAddress;
120  Address fp = kNullAddress;
121  Address* pc_address = nullptr;
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.
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.
145  static Type MarkerToType(intptr_t marker) {
146  DCHECK(IsTypeMarker(marker));
147  return static_cast<Type>(marker >> kSmiTagSize);
148  }
149 
150  // Check if a marker is a stack frame type marker or a tagged pointer.
151  //
152  // Returns true if the given marker is tagged as a stack frame type marker,
153  // and should be converted back to a stack frame type using MarkerToType.
154  // Otherwise, the value is a tagged function pointer.
155  static bool IsTypeMarker(intptr_t function_or_marker) {
156  return (function_or_marker & kSmiTagMask) == kSmiTag;
157  }
158 
159  // Copy constructor; it breaks the connection to host iterator
160  // (as an iterator usually lives on stack).
161  StackFrame(const StackFrame& original) {
162  this->state_ = original.state_;
163  this->iterator_ = nullptr;
164  this->isolate_ = original.isolate_;
165  }
166 
167  // Type testers.
168  bool is_entry() const { return type() == ENTRY; }
169  bool is_construct_entry() const { return type() == CONSTRUCT_ENTRY; }
170  bool is_exit() const { return type() == EXIT; }
171  bool is_optimized() const { return type() == OPTIMIZED; }
172  bool is_interpreted() const { return type() == INTERPRETED; }
173  bool is_wasm_compiled() const { return type() == WASM_COMPILED; }
174  bool is_wasm_compile_lazy() const { return type() == WASM_COMPILE_LAZY; }
175  bool is_wasm_to_js() const { return type() == WASM_TO_JS; }
176  bool is_js_to_wasm() const { return type() == JS_TO_WASM; }
177  bool is_wasm_interpreter_entry() const {
178  return type() == WASM_INTERPRETER_ENTRY;
179  }
180  bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
181  bool is_builtin() const { return type() == BUILTIN; }
182  bool is_internal() const { return type() == INTERNAL; }
183  bool is_builtin_continuation() const {
184  return type() == BUILTIN_CONTINUATION;
185  }
186  bool is_java_script_builtin_continuation() const {
187  return type() == JAVA_SCRIPT_BUILTIN_CONTINUATION;
188  }
189  bool is_java_script_builtin_with_catch_continuation() const {
190  return type() == JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
191  }
192  bool is_construct() const { return type() == CONSTRUCT; }
193  bool is_builtin_exit() const { return type() == BUILTIN_EXIT; }
194  virtual bool is_standard() const { return false; }
195 
196  bool is_java_script() const {
197  Type type = this->type();
198  return (type == OPTIMIZED) || (type == INTERPRETED) || (type == BUILTIN) ||
199  (type == JAVA_SCRIPT_BUILTIN_CONTINUATION) ||
200  (type == JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH);
201  }
202  bool is_wasm() const {
203  Type type = this->type();
204  return type == WASM_COMPILED || type == WASM_INTERPRETER_ENTRY;
205  }
206 
207  // Accessors.
208  Address sp() const { return state_.sp; }
209  Address fp() const { return state_.fp; }
210  Address callee_pc() const {
211  return state_.callee_pc_address ? *state_.callee_pc_address : kNullAddress;
212  }
213  Address caller_sp() const { return GetCallerStackPointer(); }
214 
215  // If this frame is optimized and was dynamically aligned return its old
216  // unaligned frame pointer. When the frame is deoptimized its FP will shift
217  // up one word and become unaligned.
218  Address UnpaddedFP() const;
219 
220  Address pc() const { return *pc_address(); }
221  void set_pc(Address pc) { *pc_address() = pc; }
222 
223  Address constant_pool() const { return *constant_pool_address(); }
224  void set_constant_pool(Address constant_pool) {
225  *constant_pool_address() = constant_pool;
226  }
227 
228  Address* pc_address() const { return state_.pc_address; }
229 
230  Address* constant_pool_address() const {
231  return state_.constant_pool_address;
232  }
233 
234  // Get the id of this stack frame.
235  Id id() const { return static_cast<Id>(caller_sp()); }
236 
237  // Get the top handler from the current stack iterator.
238  inline StackHandler* top_handler() const;
239 
240  // Get the type of this frame.
241  virtual Type type() const = 0;
242 
243  // Get the code associated with this frame.
244  // This method could be called during marking phase of GC.
245  virtual Code unchecked_code() const = 0;
246 
247  // Search for the code associated with this frame.
248  Code LookupCode() const;
249 
250  virtual void Iterate(RootVisitor* v) const = 0;
251  static void IteratePc(RootVisitor* v, Address* pc_address,
252  Address* constant_pool_address, Code holder);
253 
254  // Sets a callback function for return-address rewriting profilers
255  // to resolve the location of a return address to the location of the
256  // profiler's stashed return address.
257  static void SetReturnAddressLocationResolver(
258  ReturnAddressLocationResolver resolver);
259 
260  // Resolves pc_address through the resolution address function if one is set.
261  static inline Address* ResolveReturnAddressLocation(Address* pc_address);
262 
263  // Printing support.
264  enum PrintMode { OVERVIEW, DETAILS };
265  virtual void Print(StringStream* accumulator, PrintMode mode,
266  int index) const;
267 
268  Isolate* isolate() const { return isolate_; }
269 
270  void operator=(const StackFrame& original) = delete;
271 
272  protected:
273  inline explicit StackFrame(StackFrameIteratorBase* iterator);
274  virtual ~StackFrame() = default;
275 
276  // Compute the stack pointer for the calling frame.
277  virtual Address GetCallerStackPointer() const = 0;
278 
279  // Compute the stack frame type for the given state.
280  static Type ComputeType(const StackFrameIteratorBase* iterator, State* state);
281 
282 #ifdef DEBUG
283  bool can_access_heap_objects() const;
284 #endif
285 
286  private:
287  const StackFrameIteratorBase* iterator_;
288  Isolate* isolate_;
289  State state_;
290 
291  static ReturnAddressLocationResolver return_address_location_resolver_;
292 
293  // Fill in the state of the calling frame.
294  virtual void ComputeCallerState(State* state) const = 0;
295 
296  // Get the type and the state of the calling frame.
297  virtual Type GetCallerState(State* state) const;
298 
299  static const intptr_t kIsolateTag = 1;
300 
301  friend class StackFrameIterator;
302  friend class StackFrameIteratorBase;
303  friend class StackHandlerIterator;
304  friend class SafeStackFrameIterator;
305 };
306 
307 class NativeFrame : public StackFrame {
308  public:
309  Type type() const override { return NATIVE; }
310 
311  Code unchecked_code() const override;
312 
313  // Garbage collection support.
314  void Iterate(RootVisitor* v) const override {}
315 
316  protected:
317  inline explicit NativeFrame(StackFrameIteratorBase* iterator);
318 
319  Address GetCallerStackPointer() const override;
320 
321  private:
322  void ComputeCallerState(State* state) const override;
323 
324  friend class StackFrameIteratorBase;
325 };
326 
327 // Entry frames are used to enter JavaScript execution from C.
328 class EntryFrame: public StackFrame {
329  public:
330  Type type() const override { return ENTRY; }
331 
332  Code unchecked_code() const override;
333 
334  // Garbage collection support.
335  void Iterate(RootVisitor* v) const override;
336 
337  static EntryFrame* cast(StackFrame* frame) {
338  DCHECK(frame->is_entry());
339  return static_cast<EntryFrame*>(frame);
340  }
341 
342  protected:
343  inline explicit EntryFrame(StackFrameIteratorBase* iterator);
344 
345  // The caller stack pointer for entry frames is always zero. The
346  // real information about the caller frame is available through the
347  // link to the top exit frame.
348  Address GetCallerStackPointer() const override { return 0; }
349 
350  private:
351  void ComputeCallerState(State* state) const override;
352  Type GetCallerState(State* state) const override;
353 
354  friend class StackFrameIteratorBase;
355 };
356 
358  public:
359  Type type() const override { return CONSTRUCT_ENTRY; }
360 
361  Code unchecked_code() const override;
362 
363  static ConstructEntryFrame* cast(StackFrame* frame) {
364  DCHECK(frame->is_construct_entry());
365  return static_cast<ConstructEntryFrame*>(frame);
366  }
367 
368  protected:
369  inline explicit ConstructEntryFrame(StackFrameIteratorBase* iterator);
370 
371  private:
372  friend class StackFrameIteratorBase;
373 };
374 
375 
376 // Exit frames are used to exit JavaScript execution and go to C.
377 class ExitFrame: public StackFrame {
378  public:
379  Type type() const override { return EXIT; }
380 
381  Code unchecked_code() const override;
382 
383  Object*& code_slot() const;
384 
385  // Garbage collection support.
386  void Iterate(RootVisitor* v) const override;
387 
388  static ExitFrame* cast(StackFrame* frame) {
389  DCHECK(frame->is_exit());
390  return static_cast<ExitFrame*>(frame);
391  }
392 
393  // Compute the state and type of an exit frame given a frame
394  // pointer. Used when constructing the first stack frame seen by an
395  // iterator and the frames following entry frames.
396  static Type GetStateForFramePointer(Address fp, State* state);
397  static Address ComputeStackPointer(Address fp);
398  static StackFrame::Type ComputeFrameType(Address fp);
399  static void FillState(Address fp, Address sp, State* state);
400 
401  protected:
402  inline explicit ExitFrame(StackFrameIteratorBase* iterator);
403 
404  Address GetCallerStackPointer() const override;
405 
406  private:
407  void ComputeCallerState(State* state) const override;
408 
409  friend class StackFrameIteratorBase;
410 };
411 
412 // Builtin exit frames are a special case of exit frames, which are used
413 // whenever C++ builtins (e.g., Math.acos) are called. Their main purpose is
414 // to allow such builtins to appear in stack traces.
415 class BuiltinExitFrame : public ExitFrame {
416  public:
417  Type type() const override { return BUILTIN_EXIT; }
418 
419  static BuiltinExitFrame* cast(StackFrame* frame) {
420  DCHECK(frame->is_builtin_exit());
421  return static_cast<BuiltinExitFrame*>(frame);
422  }
423 
424  JSFunction* function() const;
425  Object* receiver() const;
426 
427  bool IsConstructor() const;
428 
429  void Print(StringStream* accumulator, PrintMode mode,
430  int index) const override;
431 
432  protected:
433  inline explicit BuiltinExitFrame(StackFrameIteratorBase* iterator);
434 
435  private:
436  Object* GetParameter(int i) const;
437  int ComputeParametersCount() const;
438 
439  inline Object* receiver_slot_object() const;
440  inline Object* argc_slot_object() const;
441  inline Object* target_slot_object() const;
442  inline Object* new_target_slot_object() const;
443 
444  friend class StackFrameIteratorBase;
445 };
446 
447 class StandardFrame;
448 
450  public:
451 // Subclasses for the different summary kinds:
452 #define FRAME_SUMMARY_VARIANTS(F) \
453  F(JAVA_SCRIPT, JavaScriptFrameSummary, java_script_summary_, JavaScript) \
454  F(WASM_COMPILED, WasmCompiledFrameSummary, wasm_compiled_summary_, \
455  WasmCompiled) \
456  F(WASM_INTERPRETED, WasmInterpretedFrameSummary, wasm_interpreted_summary_, \
457  WasmInterpreted)
458 
459 #define FRAME_SUMMARY_KIND(kind, type, field, desc) kind,
460  enum Kind { FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_KIND) };
461 #undef FRAME_SUMMARY_KIND
462 
464  public:
465  FrameSummaryBase(Isolate* isolate, Kind kind)
466  : isolate_(isolate), kind_(kind) {}
467  Isolate* isolate() const { return isolate_; }
468  Kind kind() const { return kind_; }
469 
470  private:
471  Isolate* isolate_;
472  Kind kind_;
473  };
474 
476  public:
477  JavaScriptFrameSummary(Isolate* isolate, Object* receiver,
478  JSFunction* function, AbstractCode abstract_code,
479  int code_offset, bool is_constructor);
480 
481  Handle<Object> receiver() const { return receiver_; }
482  Handle<JSFunction> function() const { return function_; }
483  Handle<AbstractCode> abstract_code() const { return abstract_code_; }
484  int code_offset() const { return code_offset_; }
485  bool is_constructor() const { return is_constructor_; }
486  bool is_subject_to_debugging() const;
487  int SourcePosition() const;
488  int SourceStatementPosition() const;
489  Handle<Object> script() const;
490  Handle<String> FunctionName() const;
491  Handle<Context> native_context() const;
492 
493  private:
494  Handle<Object> receiver_;
495  Handle<JSFunction> function_;
496  Handle<AbstractCode> abstract_code_;
497  int code_offset_;
498  bool is_constructor_;
499  };
500 
502  protected:
504  bool at_to_number_conversion);
505 
506  public:
507  Handle<Object> receiver() const;
508  uint32_t function_index() const;
509  int byte_offset() const;
510  bool is_constructor() const { return false; }
511  bool is_subject_to_debugging() const { return true; }
512  int SourcePosition() const;
513  int SourceStatementPosition() const { return SourcePosition(); }
514  Handle<Script> script() const;
515  Handle<WasmInstanceObject> wasm_instance() const { return wasm_instance_; }
516  Handle<String> FunctionName() const;
517  Handle<Context> native_context() const;
518  bool at_to_number_conversion() const { return at_to_number_conversion_; }
519 
520  private:
521  Handle<WasmInstanceObject> wasm_instance_;
522  bool at_to_number_conversion_;
523  };
524 
526  public:
528  wasm::WasmCode*, int code_offset,
529  bool at_to_number_conversion);
530  uint32_t function_index() const;
531  wasm::WasmCode* code() const { return code_; }
532  int code_offset() const { return code_offset_; }
533  int byte_offset() const;
534  static int GetWasmSourcePosition(const wasm::WasmCode* code, int offset);
535 
536  private:
537  wasm::WasmCode* const code_;
538  int code_offset_;
539  };
540 
542  public:
544  uint32_t function_index, int byte_offset);
545  uint32_t function_index() const { return function_index_; }
546  int code_offset() const { return byte_offset_; }
547  int byte_offset() const { return byte_offset_; }
548 
549  private:
550  uint32_t function_index_;
551  int byte_offset_;
552  };
553 
554 #undef FRAME_SUMMARY_FIELD
555 #define FRAME_SUMMARY_CONS(kind, type, field, desc) \
556  FrameSummary(type summ) : field(summ) {} // NOLINT
557  FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CONS)
558 #undef FRAME_SUMMARY_CONS
559 
560  ~FrameSummary();
561 
562  static FrameSummary GetTop(const StandardFrame* frame);
563  static FrameSummary GetBottom(const StandardFrame* frame);
564  static FrameSummary GetSingle(const StandardFrame* frame);
565  static FrameSummary Get(const StandardFrame* frame, int index);
566 
567  // Dispatched accessors.
568  Handle<Object> receiver() const;
569  int code_offset() const;
570  bool is_constructor() const;
571  bool is_subject_to_debugging() const;
572  Handle<Object> script() const;
573  int SourcePosition() const;
574  int SourceStatementPosition() const;
575  Handle<String> FunctionName() const;
576  Handle<Context> native_context() const;
577 
578 #define FRAME_SUMMARY_CAST(kind_, type, field, desc) \
579  bool Is##desc() const { return base_.kind() == kind_; } \
580  const type& As##desc() const { \
581  DCHECK_EQ(base_.kind(), kind_); \
582  return field; \
583  }
584  FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CAST)
585 #undef FRAME_SUMMARY_CAST
586 
587  bool IsWasm() const { return IsWasmCompiled() || IsWasmInterpreted(); }
588  const WasmFrameSummary& AsWasm() const {
589  if (IsWasmCompiled()) return AsWasmCompiled();
590  return AsWasmInterpreted();
591  }
592 
593  private:
594 #define FRAME_SUMMARY_FIELD(kind, type, field, desc) type field;
595  union {
596  FrameSummaryBase base_;
597  FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_FIELD)
598  };
599 };
600 
601 class StandardFrame : public StackFrame {
602  public:
603  // Testers.
604  bool is_standard() const override { return true; }
605 
606  // Accessors.
607  virtual Object* receiver() const;
608  virtual Script* script() const;
609  virtual Object* context() const;
610  virtual int position() const;
611 
612  // Access the expressions in the stack frame including locals.
613  inline Object* GetExpression(int index) const;
614  inline void SetExpression(int index, Object* value);
615  int ComputeExpressionsCount() const;
616 
617  // Access the parameters.
618  virtual Object* GetParameter(int index) const;
619  virtual int ComputeParametersCount() const;
620 
621  // Check if this frame is a constructor frame invoked through 'new'.
622  virtual bool IsConstructor() const;
623 
624  // Build a list with summaries for this frame including all inlined frames.
625  // The functions are ordered bottom-to-top (i.e. summaries.last() is the
626  // top-most activation; caller comes before callee).
627  virtual void Summarize(std::vector<FrameSummary>* frames) const;
628 
629  static StandardFrame* cast(StackFrame* frame) {
630  DCHECK(frame->is_standard());
631  return static_cast<StandardFrame*>(frame);
632  }
633 
634  protected:
635  inline explicit StandardFrame(StackFrameIteratorBase* iterator);
636 
637  void ComputeCallerState(State* state) const override;
638 
639  // Accessors.
640  inline Address caller_fp() const;
641  inline Address caller_pc() const;
642 
643  // Computes the address of the PC field in the standard frame given
644  // by the provided frame pointer.
645  static inline Address ComputePCAddress(Address fp);
646 
647  // Computes the address of the constant pool field in the standard
648  // frame given by the provided frame pointer.
649  static inline Address ComputeConstantPoolAddress(Address fp);
650 
651  // Iterate over expression stack including stack handlers, locals,
652  // and parts of the fixed part including context and code fields.
653  void IterateExpressions(RootVisitor* v) const;
654 
655  // Returns the address of the n'th expression stack element.
656  virtual Address GetExpressionAddress(int n) const;
657 
658  // Determines if the standard frame for the given frame pointer is
659  // an arguments adaptor frame.
660  static inline bool IsArgumentsAdaptorFrame(Address fp);
661 
662  // Determines if the standard frame for the given frame pointer is a
663  // construct frame.
664  static inline bool IsConstructFrame(Address fp);
665 
666  // Used by OptimizedFrames and StubFrames.
667  void IterateCompiledFrame(RootVisitor* v) const;
668 
669  private:
670  friend class StackFrame;
671  friend class SafeStackFrameIterator;
672 };
673 
675  public:
676  Type type() const override = 0;
677 
678  void Summarize(std::vector<FrameSummary>* frames) const override;
679 
680  // Accessors.
681  virtual JSFunction* function() const;
682  Object* unchecked_function() const;
683  Object* receiver() const override;
684  Object* context() const override;
685  Script* script() const override;
686 
687  inline void set_receiver(Object* value);
688 
689  // Access the parameters.
690  inline Address GetParameterSlot(int index) const;
691  Object* GetParameter(int index) const override;
692  int ComputeParametersCount() const override;
693 
694  // Debugger access.
695  void SetParameterValue(int index, Object* value) const;
696 
697  // Check if this frame is a constructor frame invoked through 'new'.
698  bool IsConstructor() const override;
699 
700  // Determines whether this frame includes inlined activations. To get details
701  // about the inlined frames use {GetFunctions} and {Summarize}.
702  bool HasInlinedFrames() const;
703 
704  // Check if this frame has "adapted" arguments in the sense that the
705  // actual passed arguments are available in an arguments adaptor
706  // frame below it on the stack.
707  inline bool has_adapted_arguments() const;
708 
709  // Garbage collection support.
710  void Iterate(RootVisitor* v) const override;
711 
712  // Printing support.
713  void Print(StringStream* accumulator, PrintMode mode,
714  int index) const override;
715 
716  // Determine the code for the frame.
717  Code unchecked_code() const override;
718 
719  // Return a list with {SharedFunctionInfo} objects of this frame.
720  virtual void GetFunctions(std::vector<SharedFunctionInfo*>* functions) const;
721 
722  void GetFunctions(std::vector<Handle<SharedFunctionInfo>>* functions) const;
723 
724  // Lookup exception handler for current {pc}, returns -1 if none found. Also
725  // returns data associated with the handler site specific to the frame type:
726  // - OptimizedFrame : Data is the stack slot count of the entire frame.
727  // - InterpretedFrame: Data is the register index holding the context.
728  virtual int LookupExceptionHandlerInTable(
729  int* data, HandlerTable::CatchPrediction* prediction);
730 
731  // Architecture-specific register description.
732  static Register fp_register();
733  static Register context_register();
734  static Register constant_pool_pointer_register();
735 
736  static JavaScriptFrame* cast(StackFrame* frame) {
737  DCHECK(frame->is_java_script());
738  return static_cast<JavaScriptFrame*>(frame);
739  }
740 
741  static void PrintFunctionAndOffset(JSFunction* function, AbstractCode code,
742  int code_offset, FILE* file,
743  bool print_line_number);
744 
745  static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
746  bool print_line_number);
747 
748  static void CollectFunctionAndOffsetForICStats(JSFunction* function,
749  AbstractCode code,
750  int code_offset);
751  static void CollectTopFrameForICStats(Isolate* isolate);
752 
753  protected:
754  inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator);
755 
756  Address GetCallerStackPointer() const override;
757 
758  virtual int GetNumberOfIncomingArguments() const;
759 
760  virtual void PrintFrameKind(StringStream* accumulator) const {}
761 
762  private:
763  inline Object* function_slot_object() const;
764 
765  friend class StackFrameIteratorBase;
766 };
767 
768 
769 class StubFrame : public StandardFrame {
770  public:
771  Type type() const override { return STUB; }
772 
773  // GC support.
774  void Iterate(RootVisitor* v) const override;
775 
776  // Determine the code for the frame.
777  Code unchecked_code() const override;
778 
779  // Lookup exception handler for current {pc}, returns -1 if none found. Only
780  // TurboFan stub frames are supported. Also returns data associated with the
781  // handler site:
782  // - TurboFan stub: Data is the stack slot count of the entire frame.
783  int LookupExceptionHandlerInTable(int* data);
784 
785  protected:
786  inline explicit StubFrame(StackFrameIteratorBase* iterator);
787 
788  Address GetCallerStackPointer() const override;
789 
790  virtual int GetNumberOfIncomingArguments() const;
791 
792  friend class StackFrameIteratorBase;
793 };
794 
795 
797  public:
798  Type type() const override { return OPTIMIZED; }
799 
800  // GC support.
801  void Iterate(RootVisitor* v) const override;
802 
803  // Return a list with {SharedFunctionInfo} objects of this frame.
804  // The functions are ordered bottom-to-top (i.e. functions.last()
805  // is the top-most activation)
806  void GetFunctions(std::vector<SharedFunctionInfo*>* functions) const override;
807 
808  void Summarize(std::vector<FrameSummary>* frames) const override;
809 
810  // Lookup exception handler for current {pc}, returns -1 if none found.
811  int LookupExceptionHandlerInTable(
812  int* data, HandlerTable::CatchPrediction* prediction) override;
813 
814  DeoptimizationData GetDeoptimizationData(int* deopt_index) const;
815 
816  Object* receiver() const override;
817 
818  static int StackSlotOffsetRelativeToFp(int slot_index);
819 
820  protected:
821  inline explicit OptimizedFrame(StackFrameIteratorBase* iterator);
822 
823  int GetNumberOfIncomingArguments() const override;
824 
825  private:
826  friend class StackFrameIteratorBase;
827 
828  Object* StackSlotAt(int index) const;
829 };
830 
831 
833  public:
834  Type type() const override { return INTERPRETED; }
835 
836  // Accessors.
837  int position() const override;
838 
839  // Lookup exception handler for current {pc}, returns -1 if none found.
840  int LookupExceptionHandlerInTable(
841  int* data, HandlerTable::CatchPrediction* prediction) override;
842 
843  // Returns the current offset into the bytecode stream.
844  int GetBytecodeOffset() const;
845 
846  // Updates the current offset into the bytecode stream, mainly used for stack
847  // unwinding to continue execution at a different bytecode offset.
848  void PatchBytecodeOffset(int new_offset);
849 
850  // Returns the frame's current bytecode array.
851  BytecodeArray GetBytecodeArray() const;
852 
853  // Updates the frame's BytecodeArray with |bytecode_array|. Used by the
854  // debugger to swap execution onto a BytecodeArray patched with breakpoints.
855  void PatchBytecodeArray(BytecodeArray bytecode_array);
856 
857  // Access to the interpreter register file for this frame.
858  Object* ReadInterpreterRegister(int register_index) const;
859  void WriteInterpreterRegister(int register_index, Object* value);
860 
861  // Build a list with summaries for this frame including all inlined frames.
862  void Summarize(std::vector<FrameSummary>* frames) const override;
863 
864  static int GetBytecodeOffset(Address fp);
865 
866  static InterpretedFrame* cast(StackFrame* frame) {
867  DCHECK(frame->is_interpreted());
868  return static_cast<InterpretedFrame*>(frame);
869  }
870 
871  protected:
872  inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);
873 
874  Address GetExpressionAddress(int n) const override;
875 
876  private:
877  friend class StackFrameIteratorBase;
878 };
879 
880 
881 // Arguments adaptor frames are automatically inserted below
882 // JavaScript frames when the actual number of parameters does not
883 // match the formal number of parameters.
885  public:
886  Type type() const override { return ARGUMENTS_ADAPTOR; }
887 
888  // Determine the code for the frame.
889  Code unchecked_code() const override;
890 
891  static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
892  DCHECK(frame->is_arguments_adaptor());
893  return static_cast<ArgumentsAdaptorFrame*>(frame);
894  }
895 
896  // Printing support.
897  void Print(StringStream* accumulator, PrintMode mode,
898  int index) const override;
899 
900  protected:
901  inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator);
902 
903  int GetNumberOfIncomingArguments() const override;
904 
905  private:
906  friend class StackFrameIteratorBase;
907 };
908 
909 // Builtin frames are built for builtins with JavaScript linkage, such as
910 // various standard library functions (i.e. Math.asin, Math.floor, etc.).
911 class BuiltinFrame final : public JavaScriptFrame {
912  public:
913  Type type() const final { return BUILTIN; }
914 
915  static BuiltinFrame* cast(StackFrame* frame) {
916  DCHECK(frame->is_builtin());
917  return static_cast<BuiltinFrame*>(frame);
918  }
919 
920  protected:
921  inline explicit BuiltinFrame(StackFrameIteratorBase* iterator);
922 
923  int GetNumberOfIncomingArguments() const final;
924  void PrintFrameKind(StringStream* accumulator) const override;
925 
926  private:
927  friend class StackFrameIteratorBase;
928 };
929 
930 class WasmCompiledFrame final : public StandardFrame {
931  public:
932  Type type() const override { return WASM_COMPILED; }
933 
934  // GC support.
935  void Iterate(RootVisitor* v) const override;
936 
937  // Printing support.
938  void Print(StringStream* accumulator, PrintMode mode,
939  int index) const override;
940 
941  // Lookup exception handler for current {pc}, returns -1 if none found. Also
942  // returns the stack slot count of the entire frame.
943  int LookupExceptionHandlerInTable(int* data);
944 
945  // Determine the code for the frame.
946  Code unchecked_code() const override;
947 
948  // Accessors.
949  WasmInstanceObject* wasm_instance() const;
950  wasm::WasmCode* wasm_code() const;
951  uint32_t function_index() const;
952  Script* script() const override;
953  int position() const override;
954  bool at_to_number_conversion() const;
955 
956  void Summarize(std::vector<FrameSummary>* frames) const override;
957 
958  static WasmCompiledFrame* cast(StackFrame* frame) {
959  DCHECK(frame->is_wasm_compiled());
960  return static_cast<WasmCompiledFrame*>(frame);
961  }
962 
963  protected:
964  inline explicit WasmCompiledFrame(StackFrameIteratorBase* iterator);
965 
966  Address GetCallerStackPointer() const override;
967 
968  private:
969  friend class StackFrameIteratorBase;
970  WasmModuleObject* module_object() const;
971 };
972 
974  public:
975  Type type() const override { return WASM_INTERPRETER_ENTRY; }
976 
977  // GC support.
978  void Iterate(RootVisitor* v) const override;
979 
980  // Printing support.
981  void Print(StringStream* accumulator, PrintMode mode,
982  int index) const override;
983 
984  void Summarize(std::vector<FrameSummary>* frames) const override;
985 
986  // Determine the code for the frame.
987  Code unchecked_code() const override;
988 
989  // Accessors.
990  WasmDebugInfo* debug_info() const;
991  WasmInstanceObject* wasm_instance() const;
992 
993  Script* script() const override;
994  int position() const override;
995  Object* context() const override;
996 
997  static WasmInterpreterEntryFrame* cast(StackFrame* frame) {
998  DCHECK(frame->is_wasm_interpreter_entry());
999  return static_cast<WasmInterpreterEntryFrame*>(frame);
1000  }
1001 
1002  protected:
1003  inline explicit WasmInterpreterEntryFrame(StackFrameIteratorBase* iterator);
1004 
1005  Address GetCallerStackPointer() const override;
1006 
1007  private:
1008  friend class StackFrameIteratorBase;
1009  WasmModuleObject* module_object() const;
1010 };
1011 
1012 class WasmToJsFrame : public StubFrame {
1013  public:
1014  Type type() const override { return WASM_TO_JS; }
1015 
1016  protected:
1017  inline explicit WasmToJsFrame(StackFrameIteratorBase* iterator);
1018 
1019  private:
1020  friend class StackFrameIteratorBase;
1021 };
1022 
1023 class JsToWasmFrame : public StubFrame {
1024  public:
1025  Type type() const override { return JS_TO_WASM; }
1026 
1027  protected:
1028  inline explicit JsToWasmFrame(StackFrameIteratorBase* iterator);
1029 
1030  private:
1031  friend class StackFrameIteratorBase;
1032 };
1033 
1034 class CWasmEntryFrame : public StubFrame {
1035  public:
1036  Type type() const override { return C_WASM_ENTRY; }
1037 
1038  protected:
1039  inline explicit CWasmEntryFrame(StackFrameIteratorBase* iterator);
1040 
1041  private:
1042  friend class StackFrameIteratorBase;
1043 };
1044 
1046  public:
1047  Type type() const override { return WASM_COMPILE_LAZY; }
1048 
1049  Code unchecked_code() const override;
1050  WasmInstanceObject* wasm_instance() const;
1051  ObjectSlot wasm_instance_slot() const;
1052 
1053  // Garbage collection support.
1054  void Iterate(RootVisitor* v) const override;
1055 
1056  static WasmCompileLazyFrame* cast(StackFrame* frame) {
1057  DCHECK(frame->is_wasm_compile_lazy());
1058  return static_cast<WasmCompileLazyFrame*>(frame);
1059  }
1060 
1061  protected:
1062  inline explicit WasmCompileLazyFrame(StackFrameIteratorBase* iterator);
1063 
1064  Address GetCallerStackPointer() const override;
1065 
1066  private:
1067  friend class StackFrameIteratorBase;
1068 };
1069 
1071  public:
1072  Type type() const override { return INTERNAL; }
1073 
1074  // Garbage collection support.
1075  void Iterate(RootVisitor* v) const override;
1076 
1077  // Determine the code for the frame.
1078  Code unchecked_code() const override;
1079 
1080  static InternalFrame* cast(StackFrame* frame) {
1081  DCHECK(frame->is_internal());
1082  return static_cast<InternalFrame*>(frame);
1083  }
1084 
1085  protected:
1086  inline explicit InternalFrame(StackFrameIteratorBase* iterator);
1087 
1088  Address GetCallerStackPointer() const override;
1089 
1090  private:
1091  friend class StackFrameIteratorBase;
1092 };
1093 
1094 
1095 // Construct frames are special trampoline frames introduced to handle
1096 // function invocations through 'new'.
1098  public:
1099  Type type() const override { return CONSTRUCT; }
1100 
1101  static ConstructFrame* cast(StackFrame* frame) {
1102  DCHECK(frame->is_construct());
1103  return static_cast<ConstructFrame*>(frame);
1104  }
1105 
1106  protected:
1107  inline explicit ConstructFrame(StackFrameIteratorBase* iterator);
1108 
1109  private:
1110  friend class StackFrameIteratorBase;
1111 };
1112 
1114  public:
1115  Type type() const override { return BUILTIN_CONTINUATION; }
1116 
1117  static BuiltinContinuationFrame* cast(StackFrame* frame) {
1118  DCHECK(frame->is_builtin_continuation());
1119  return static_cast<BuiltinContinuationFrame*>(frame);
1120  }
1121 
1122  protected:
1123  inline explicit BuiltinContinuationFrame(StackFrameIteratorBase* iterator);
1124 
1125  private:
1126  friend class StackFrameIteratorBase;
1127 };
1128 
1130  public:
1131  Type type() const override { return JAVA_SCRIPT_BUILTIN_CONTINUATION; }
1132 
1133  static JavaScriptBuiltinContinuationFrame* cast(StackFrame* frame) {
1134  DCHECK(frame->is_java_script_builtin_continuation());
1135  return static_cast<JavaScriptBuiltinContinuationFrame*>(frame);
1136  }
1137 
1138  int ComputeParametersCount() const override;
1139  intptr_t GetSPToFPDelta() const;
1140 
1141  Object* context() const override;
1142 
1143  protected:
1144  inline explicit JavaScriptBuiltinContinuationFrame(
1145  StackFrameIteratorBase* iterator);
1146 
1147  private:
1148  friend class StackFrameIteratorBase;
1149 };
1150 
1153  public:
1154  Type type() const override {
1155  return JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
1156  }
1157 
1159  DCHECK(frame->is_java_script_builtin_with_catch_continuation());
1160  return static_cast<JavaScriptBuiltinContinuationWithCatchFrame*>(frame);
1161  }
1162 
1163  // Patch in the exception object at the appropriate location into the stack
1164  // frame.
1165  void SetException(Object* exception);
1166 
1167  protected:
1169  StackFrameIteratorBase* iterator);
1170 
1171  private:
1172  friend class StackFrameIteratorBase;
1173 };
1174 
1176  public:
1177  Isolate* isolate() const { return isolate_; }
1178 
1179  bool done() const { return frame_ == nullptr; }
1180 
1181  protected:
1182  // An iterator that iterates over a given thread's stack.
1183  StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects);
1184 
1185  Isolate* isolate_;
1186 #define DECLARE_SINGLETON(ignore, type) type type##_;
1187  STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
1188 #undef DECLARE_SINGLETON
1189  StackFrame* frame_;
1190  StackHandler* handler_;
1191  const bool can_access_heap_objects_;
1192 
1193  StackHandler* handler() const {
1194  DCHECK(!done());
1195  return handler_;
1196  }
1197 
1198  // Get the type-specific frame singleton in a given state.
1199  StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
1200  // A helper function, can return a nullptr pointer.
1201  StackFrame* SingletonFor(StackFrame::Type type);
1202 
1203  private:
1204  friend class StackFrame;
1205  DISALLOW_COPY_AND_ASSIGN(StackFrameIteratorBase);
1206 };
1207 
1208 
1210  public:
1211  // An iterator that iterates over the isolate's current thread's stack,
1212  explicit StackFrameIterator(Isolate* isolate);
1213  // An iterator that iterates over a given thread's stack.
1215 
1216  StackFrame* frame() const {
1217  DCHECK(!done());
1218  return frame_;
1219  }
1220  void Advance();
1221 
1222  private:
1223  // Go back to the first frame.
1224  void Reset(ThreadLocalTop* top);
1225 
1226  DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
1227 };
1228 
1229 // Iterator that supports iterating through all JavaScript frames.
1231  public:
1232  inline explicit JavaScriptFrameIterator(Isolate* isolate);
1233  inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top);
1234 
1235  inline JavaScriptFrame* frame() const;
1236 
1237  bool done() const { return iterator_.done(); }
1238  void Advance();
1239  void AdvanceOneFrame() { iterator_.Advance(); }
1240 
1241  private:
1242  StackFrameIterator iterator_;
1243 };
1244 
1245 // NOTE: The stack trace frame iterator is an iterator that only traverse proper
1246 // JavaScript frames that have proper JavaScript functions and WebAssembly
1247 // frames.
1249  public:
1250  explicit StackTraceFrameIterator(Isolate* isolate);
1251  // Skip frames until the frame with the given id is reached.
1252  StackTraceFrameIterator(Isolate* isolate, StackFrame::Id id);
1253  bool done() const { return iterator_.done(); }
1254  void Advance();
1255  void AdvanceOneFrame() { iterator_.Advance(); }
1256 
1257  inline StandardFrame* frame() const;
1258 
1259  inline bool is_javascript() const;
1260  inline bool is_wasm() const;
1261  inline JavaScriptFrame* javascript_frame() const;
1262 
1263  private:
1264  StackFrameIterator iterator_;
1265  bool IsValidFrame(StackFrame* frame) const;
1266 };
1267 
1268 
1270  public:
1272  Address fp, Address sp,
1273  Address js_entry_sp);
1274 
1275  inline StackFrame* frame() const;
1276  void Advance();
1277 
1278  StackFrame::Type top_frame_type() const { return top_frame_type_; }
1279 
1280  private:
1281  void AdvanceOneFrame();
1282 
1283  bool IsValidStackAddress(Address addr) const {
1284  return low_bound_ <= addr && addr <= high_bound_;
1285  }
1286  bool IsValidFrame(StackFrame* frame) const;
1287  bool IsValidCaller(StackFrame* frame);
1288  bool IsValidExitFrame(Address fp) const;
1289  bool IsValidTop(ThreadLocalTop* top) const;
1290 
1291  const Address low_bound_;
1292  const Address high_bound_;
1293  StackFrame::Type top_frame_type_;
1294  ExternalCallbackScope* external_callback_scope_;
1295 };
1296 } // namespace internal
1297 } // namespace v8
1298 
1299 #endif // V8_FRAMES_H_
Definition: libplatform.h:13