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/allocation.h"
9#include "src/handles.h"
10#include "src/safepoint-table.h"
11
12namespace v8 {
13namespace internal {
14
15#if V8_TARGET_ARCH_ARM64
16typedef uint64_t RegList;
17#else
18typedef uint32_t RegList;
19#endif
20
21// Get the number of registers in a given register list.
22int NumRegs(RegList list);
23
24void SetUpJSCallerSavedCodeData();
25
26// Return the code of the n-th saved register available to JavaScript.
27int JSCallerSavedCode(int n);
28
29
30// Forward declarations.
31class ExternalCallbackScope;
32class StackFrameIteratorBase;
33class ThreadLocalTop;
34class Isolate;
35
36class InnerPointerToCodeCache {
37 public:
38  struct InnerPointerToCodeCacheEntry {
39    Address inner_pointer;
40    Code* code;
41    SafepointEntry safepoint_entry;
42  };
43
44  explicit InnerPointerToCodeCache(Isolate* isolate) : isolate_(isolate) {
45    Flush();
46  }
47
48  Code* GcSafeFindCodeForInnerPointer(Address inner_pointer);
49  Code* GcSafeCastToCode(HeapObject* object, Address inner_pointer);
50
51  void Flush() {
52    memset(&cache_[0], 0, sizeof(cache_));
53  }
54
55  InnerPointerToCodeCacheEntry* GetCacheEntry(Address inner_pointer);
56
57 private:
58  InnerPointerToCodeCacheEntry* cache(int index) { return &cache_[index]; }
59
60  Isolate* isolate_;
61
62  static const int kInnerPointerToCodeCacheSize = 1024;
63  InnerPointerToCodeCacheEntry cache_[kInnerPointerToCodeCacheSize];
64
65  DISALLOW_COPY_AND_ASSIGN(InnerPointerToCodeCache);
66};
67
68
69// Every try-block pushes the context register.
70class TryBlockConstant : public AllStatic {
71 public:
72  static const int kElementCount = 1;
73};
74
75
76class StackHandlerConstants : public AllStatic {
77 public:
78  static const int kNextOffset = 0 * kPointerSize;
79
80  static const int kSize = kNextOffset + kPointerSize;
81  static const int kSlotCount = kSize >> kPointerSizeLog2;
82};
83
84
85class StackHandler BASE_EMBEDDED {
86 public:
87  // Get the address of this stack handler.
88  inline Address address() const;
89
90  // Get the next stack handler in the chain.
91  inline StackHandler* next() const;
92
93  // Conversion support.
94  static inline StackHandler* FromAddress(Address address);
95
96 private:
97  DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
98};
99
100#define STACK_FRAME_TYPE_LIST(V)                         \
101  V(ENTRY, EntryFrame)                                   \
102  V(ENTRY_CONSTRUCT, EntryConstructFrame)                \
103  V(EXIT, ExitFrame)                                     \
104  V(JAVA_SCRIPT, JavaScriptFrame)                        \
105  V(OPTIMIZED, OptimizedFrame)                           \
106  V(WASM, WasmFrame)                                     \
107  V(WASM_TO_JS, WasmToJsFrame)                           \
108  V(JS_TO_WASM, JsToWasmFrame)                           \
109  V(INTERPRETED, InterpretedFrame)                       \
110  V(STUB, StubFrame)                                     \
111  V(STUB_FAILURE_TRAMPOLINE, StubFailureTrampolineFrame) \
112  V(INTERNAL, InternalFrame)                             \
113  V(CONSTRUCT, ConstructFrame)                           \
114  V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)            \
115  V(BUILTIN, BuiltinFrame)
116
117// Every pointer in a frame has a slot id. On 32-bit platforms, doubles consume
118// two slots.
119//
120// Stack slot indices >= 0 access the callee stack with slot 0 corresponding to
121// the callee's saved return address and 1 corresponding to the saved frame
122// pointer. Some frames have additional information stored in the fixed header,
123// for example JSFunctions store the function context and marker in the fixed
124// header, with slot index 2 corresponding to the current function context and 3
125// corresponding to the frame marker/JSFunction.
126//
127//  slot      JS frame
128//       +-----------------+--------------------------------
129//  -n-1 |   parameter 0   |                            ^
130//       |- - - - - - - - -|                            |
131//  -n   |                 |                          Caller
132//  ...  |       ...       |                       frame slots
133//  -2   |  parameter n-1  |                       (slot < 0)
134//       |- - - - - - - - -|                            |
135//  -1   |   parameter n   |                            v
136//  -----+-----------------+--------------------------------
137//   0   |   return addr   |   ^                        ^
138//       |- - - - - - - - -|   |                        |
139//   1   | saved frame ptr | Fixed                      |
140//       |- - - - - - - - -| Header <-- frame ptr       |
141//   2   | [Constant Pool] |   |                        |
142//       |- - - - - - - - -|   |                        |
143// 2+cp  |Context/Frm. Type|   v   if a constant pool   |
144//       |-----------------+----    is used, cp = 1,    |
145// 3+cp  |                 |   ^   otherwise, cp = 0    |
146//       |- - - - - - - - -|   |                        |
147// 4+cp  |                 |   |                      Callee
148//       |- - - - - - - - -|   |                   frame slots
149//  ...  |                 | Frame slots           (slot >= 0)
150//       |- - - - - - - - -|   |                        |
151//       |                 |   v                        |
152//  -----+-----------------+----- <-- stack ptr -------------
153//
154class CommonFrameConstants : public AllStatic {
155 public:
156  static const int kCallerFPOffset = 0 * kPointerSize;
157  static const int kCallerPCOffset = kCallerFPOffset + 1 * kFPOnStackSize;
158  static const int kCallerSPOffset = kCallerPCOffset + 1 * kPCOnStackSize;
159
160  // Fixed part of the frame consists of return address, caller fp,
161  // constant pool (if FLAG_enable_embedded_constant_pool), context, and
162  // function. StandardFrame::IterateExpressions assumes that kLastObjectOffset
163  // is the last object pointer.
164  static const int kFixedFrameSizeAboveFp = kPCOnStackSize + kFPOnStackSize;
165  static const int kFixedSlotCountAboveFp =
166      kFixedFrameSizeAboveFp / kPointerSize;
167  static const int kCPSlotSize =
168      FLAG_enable_embedded_constant_pool ? kPointerSize : 0;
169  static const int kCPSlotCount = kCPSlotSize / kPointerSize;
170  static const int kConstantPoolOffset = kCPSlotSize ? -1 * kPointerSize : 0;
171  static const int kContextOrFrameTypeSize = kPointerSize;
172  static const int kContextOrFrameTypeOffset =
173      -(kCPSlotSize + kContextOrFrameTypeSize);
174};
175
176// StandardFrames are used for interpreted, full-codegen and optimized
177// JavaScript frames. They always have a context below the saved fp/constant
178// pool and below that the JSFunction of the executing function.
179//
180//  slot      JS frame
181//       +-----------------+--------------------------------
182//  -n-1 |   parameter 0   |                            ^
183//       |- - - - - - - - -|                            |
184//  -n   |                 |                          Caller
185//  ...  |       ...       |                       frame slots
186//  -2   |  parameter n-1  |                       (slot < 0)
187//       |- - - - - - - - -|                            |
188//  -1   |   parameter n   |                            v
189//  -----+-----------------+--------------------------------
190//   0   |   return addr   |   ^                        ^
191//       |- - - - - - - - -|   |                        |
192//   1   | saved frame ptr | Fixed                      |
193//       |- - - - - - - - -| Header <-- frame ptr       |
194//   2   | [Constant Pool] |   |                        |
195//       |- - - - - - - - -|   |                        |
196// 2+cp  |     Context     |   |   if a constant pool   |
197//       |- - - - - - - - -|   |    is used, cp = 1,    |
198// 3+cp  |    JSFunction   |   v   otherwise, cp = 0    |
199//       +-----------------+----                        |
200// 4+cp  |                 |   ^                      Callee
201//       |- - - - - - - - -|   |                   frame slots
202//  ...  |                 | Frame slots           (slot >= 0)
203//       |- - - - - - - - -|   |                        |
204//       |                 |   v                        |
205//  -----+-----------------+----- <-- stack ptr -------------
206//
207class StandardFrameConstants : public CommonFrameConstants {
208 public:
209  static const int kFixedFrameSizeFromFp = 2 * kPointerSize + kCPSlotSize;
210  static const int kFixedFrameSize =
211      kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp;
212  static const int kFixedSlotCountFromFp = kFixedFrameSizeFromFp / kPointerSize;
213  static const int kFixedSlotCount = kFixedFrameSize / kPointerSize;
214  static const int kContextOffset = kContextOrFrameTypeOffset;
215  static const int kFunctionOffset = -2 * kPointerSize - kCPSlotSize;
216  static const int kExpressionsOffset = -3 * kPointerSize - kCPSlotSize;
217  static const int kLastObjectOffset = kContextOffset;
218};
219
220// TypedFrames have a SMI type maker value below the saved FP/constant pool to
221// distinguish them from StandardFrames, which have a context in that position
222// instead.
223//
224//  slot      JS frame
225//       +-----------------+--------------------------------
226//  -n-1 |   parameter 0   |                            ^
227//       |- - - - - - - - -|                            |
228//  -n   |                 |                          Caller
229//  ...  |       ...       |                       frame slots
230//  -2   |  parameter n-1  |                       (slot < 0)
231//       |- - - - - - - - -|                            |
232//  -1   |   parameter n   |                            v
233//  -----+-----------------+--------------------------------
234//   0   |   return addr   |   ^                        ^
235//       |- - - - - - - - -|   |                        |
236//   1   | saved frame ptr | Fixed                      |
237//       |- - - - - - - - -| Header <-- frame ptr       |
238//   2   | [Constant Pool] |   |                        |
239//       |- - - - - - - - -|   |                        |
240// 2+cp  |Frame Type Marker|   v   if a constant pool   |
241//       |-----------------+----    is used, cp = 1,    |
242// 3+cp  |                 |   ^   otherwise, cp = 0    |
243//       |- - - - - - - - -|   |                        |
244// 4+cp  |                 |   |                      Callee
245//       |- - - - - - - - -|   |                   frame slots
246//  ...  |                 | Frame slots           (slot >= 0)
247//       |- - - - - - - - -|   |                        |
248//       |                 |   v                        |
249//  -----+-----------------+----- <-- stack ptr -------------
250//
251class TypedFrameConstants : public CommonFrameConstants {
252 public:
253  static const int kFrameTypeSize = kContextOrFrameTypeSize;
254  static const int kFrameTypeOffset = kContextOrFrameTypeOffset;
255  static const int kFixedFrameSizeFromFp = kCPSlotSize + kFrameTypeSize;
256  static const int kFixedSlotCountFromFp = kFixedFrameSizeFromFp / kPointerSize;
257  static const int kFixedFrameSize =
258      StandardFrameConstants::kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp;
259  static const int kFixedSlotCount = kFixedFrameSize / kPointerSize;
260  static const int kFirstPushedFrameValueOffset =
261      -StandardFrameConstants::kCPSlotSize - kFrameTypeSize - kPointerSize;
262};
263
264#define TYPED_FRAME_PUSHED_VALUE_OFFSET(x) \
265  (TypedFrameConstants::kFirstPushedFrameValueOffset - (x)*kPointerSize)
266#define TYPED_FRAME_SIZE(count) \
267  (TypedFrameConstants::kFixedFrameSize + (count)*kPointerSize)
268#define TYPED_FRAME_SIZE_FROM_SP(count) \
269  (TypedFrameConstants::kFixedFrameSizeFromFp + (count)*kPointerSize)
270#define DEFINE_TYPED_FRAME_SIZES(count)                                     \
271  static const int kFixedFrameSize = TYPED_FRAME_SIZE(count);               \
272  static const int kFixedSlotCount = kFixedFrameSize / kPointerSize;        \
273  static const int kFixedFrameSizeFromFp = TYPED_FRAME_SIZE_FROM_SP(count); \
274  static const int kFixedSlotCountFromFp = kFixedFrameSizeFromFp / kPointerSize
275
276class ArgumentsAdaptorFrameConstants : public TypedFrameConstants {
277 public:
278  // FP-relative.
279  static const int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
280  static const int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
281  DEFINE_TYPED_FRAME_SIZES(2);
282};
283
284class BuiltinFrameConstants : public TypedFrameConstants {
285 public:
286  // FP-relative.
287  static const int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
288  static const int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
289  DEFINE_TYPED_FRAME_SIZES(2);
290};
291
292class InternalFrameConstants : public TypedFrameConstants {
293 public:
294  // FP-relative.
295  static const int kCodeOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
296  DEFINE_TYPED_FRAME_SIZES(1);
297};
298
299class FrameDropperFrameConstants : public InternalFrameConstants {
300 public:
301  // FP-relative.
302  static const int kFunctionOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
303  DEFINE_TYPED_FRAME_SIZES(2);
304};
305
306class ConstructFrameConstants : public TypedFrameConstants {
307 public:
308  // FP-relative.
309  static const int kContextOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
310  static const int kAllocationSiteOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
311  static const int kLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2);
312  static const int kImplicitReceiverOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(3);
313  DEFINE_TYPED_FRAME_SIZES(4);
314};
315
316class StubFailureTrampolineFrameConstants : public InternalFrameConstants {
317 public:
318  static const int kArgumentsArgumentsOffset =
319      TYPED_FRAME_PUSHED_VALUE_OFFSET(0);
320  static const int kArgumentsLengthOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(1);
321  static const int kArgumentsPointerOffset = TYPED_FRAME_PUSHED_VALUE_OFFSET(2);
322  static const int kFixedHeaderBottomOffset = kArgumentsPointerOffset;
323  DEFINE_TYPED_FRAME_SIZES(3);
324};
325
326
327class InterpreterFrameConstants : public AllStatic {
328 public:
329  // Fixed frame includes new.target and bytecode offset.
330  static const int kFixedFrameSize =
331      StandardFrameConstants::kFixedFrameSize + 3 * kPointerSize;
332  static const int kFixedFrameSizeFromFp =
333      StandardFrameConstants::kFixedFrameSizeFromFp + 3 * kPointerSize;
334
335  // FP-relative.
336  static const int kLastParamFromFp = StandardFrameConstants::kCallerSPOffset;
337  static const int kCallerPCOffsetFromFp =
338      StandardFrameConstants::kCallerPCOffset;
339  static const int kNewTargetFromFp =
340      -StandardFrameConstants::kFixedFrameSizeFromFp - 1 * kPointerSize;
341  static const int kBytecodeArrayFromFp =
342      -StandardFrameConstants::kFixedFrameSizeFromFp - 2 * kPointerSize;
343  static const int kBytecodeOffsetFromFp =
344      -StandardFrameConstants::kFixedFrameSizeFromFp - 3 * kPointerSize;
345  static const int kRegisterFileFromFp =
346      -StandardFrameConstants::kFixedFrameSizeFromFp - 4 * kPointerSize;
347
348  static const int kExpressionsOffset = kRegisterFileFromFp;
349
350  // Expression index for {StandardFrame::GetExpressionAddress}.
351  static const int kBytecodeArrayExpressionIndex = -2;
352  static const int kBytecodeOffsetExpressionIndex = -1;
353  static const int kRegisterFileExpressionIndex = 0;
354};
355
356inline static int FPOffsetToFrameSlot(int frame_offset) {
357  return StandardFrameConstants::kFixedSlotCountAboveFp - 1 -
358         frame_offset / kPointerSize;
359}
360
361inline static int FrameSlotToFPOffset(int slot) {
362  return (StandardFrameConstants::kFixedSlotCountAboveFp - 1 - slot) *
363         kPointerSize;
364}
365
366// Abstract base class for all stack frames.
367class StackFrame BASE_EMBEDDED {
368 public:
369#define DECLARE_TYPE(type, ignore) type,
370  enum Type {
371    NONE = 0,
372    STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
373    NUMBER_OF_TYPES,
374    // Used by FrameScope to indicate that the stack frame is constructed
375    // manually and the FrameScope does not need to emit code.
376    MANUAL
377  };
378#undef DECLARE_TYPE
379
380  // Opaque data type for identifying stack frames. Used extensively
381  // by the debugger.
382  // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
383  // has correct value range (see Issue 830 for more details).
384  enum Id {
385    ID_MIN_VALUE = kMinInt,
386    ID_MAX_VALUE = kMaxInt,
387    NO_ID = 0
388  };
389
390  // Used to mark the outermost JS entry frame.
391  enum JsFrameMarker {
392    INNER_JSENTRY_FRAME = 0,
393    OUTERMOST_JSENTRY_FRAME = 1
394  };
395
396  struct State {
397    State() : sp(NULL), fp(NULL), pc_address(NULL),
398              constant_pool_address(NULL) { }
399    Address sp;
400    Address fp;
401    Address* pc_address;
402    Address* constant_pool_address;
403  };
404
405  // Copy constructor; it breaks the connection to host iterator
406  // (as an iterator usually lives on stack).
407  StackFrame(const StackFrame& original) {
408    this->state_ = original.state_;
409    this->iterator_ = NULL;
410    this->isolate_ = original.isolate_;
411  }
412
413  // Type testers.
414  bool is_entry() const { return type() == ENTRY; }
415  bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
416  bool is_exit() const { return type() == EXIT; }
417  bool is_optimized() const { return type() == OPTIMIZED; }
418  bool is_interpreted() const { return type() == INTERPRETED; }
419  bool is_wasm() const { return type() == WASM; }
420  bool is_wasm_to_js() const { return type() == WASM_TO_JS; }
421  bool is_js_to_wasm() const { return type() == JS_TO_WASM; }
422  bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
423  bool is_builtin() const { return type() == BUILTIN; }
424  bool is_internal() const { return type() == INTERNAL; }
425  bool is_stub_failure_trampoline() const {
426    return type() == STUB_FAILURE_TRAMPOLINE;
427  }
428  bool is_construct() const { return type() == CONSTRUCT; }
429  virtual bool is_standard() const { return false; }
430
431  bool is_java_script() const {
432    Type type = this->type();
433    return (type == JAVA_SCRIPT) || (type == OPTIMIZED) ||
434           (type == INTERPRETED) || (type == BUILTIN);
435  }
436
437  // Accessors.
438  Address sp() const { return state_.sp; }
439  Address fp() const { return state_.fp; }
440  Address caller_sp() const { return GetCallerStackPointer(); }
441
442  // If this frame is optimized and was dynamically aligned return its old
443  // unaligned frame pointer.  When the frame is deoptimized its FP will shift
444  // up one word and become unaligned.
445  Address UnpaddedFP() const;
446
447  Address pc() const { return *pc_address(); }
448  void set_pc(Address pc) { *pc_address() = pc; }
449
450  Address constant_pool() const { return *constant_pool_address(); }
451  void set_constant_pool(Address constant_pool) {
452    *constant_pool_address() = constant_pool;
453  }
454
455  virtual void SetCallerFp(Address caller_fp) = 0;
456
457  // Manually changes value of fp in this object.
458  void UpdateFp(Address fp) { state_.fp = fp; }
459
460  Address* pc_address() const { return state_.pc_address; }
461
462  Address* constant_pool_address() const {
463    return state_.constant_pool_address;
464  }
465
466  // Get the id of this stack frame.
467  Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
468
469  // Get the top handler from the current stack iterator.
470  inline StackHandler* top_handler() const;
471
472  // Get the type of this frame.
473  virtual Type type() const = 0;
474
475  // Get the code associated with this frame.
476  // This method could be called during marking phase of GC.
477  virtual Code* unchecked_code() const = 0;
478
479  // Get the code associated with this frame.
480  inline Code* LookupCode() const;
481
482  // Get the code object that contains the given pc.
483  static inline Code* GetContainingCode(Isolate* isolate, Address pc);
484
485  // Get the code object containing the given pc and fill in the
486  // safepoint entry and the number of stack slots. The pc must be at
487  // a safepoint.
488  static Code* GetSafepointData(Isolate* isolate,
489                                Address pc,
490                                SafepointEntry* safepoint_entry,
491                                unsigned* stack_slots);
492
493  virtual void Iterate(ObjectVisitor* v) const = 0;
494  static void IteratePc(ObjectVisitor* v, Address* pc_address,
495                        Address* constant_pool_address, Code* holder);
496
497  // Sets a callback function for return-address rewriting profilers
498  // to resolve the location of a return address to the location of the
499  // profiler's stashed return address.
500  static void SetReturnAddressLocationResolver(
501      ReturnAddressLocationResolver resolver);
502
503  // Resolves pc_address through the resolution address function if one is set.
504  static inline Address* ResolveReturnAddressLocation(Address* pc_address);
505
506  // Printing support.
507  enum PrintMode { OVERVIEW, DETAILS };
508  virtual void Print(StringStream* accumulator,
509                     PrintMode mode,
510                     int index) const { }
511
512  Isolate* isolate() const { return isolate_; }
513
514 protected:
515  inline explicit StackFrame(StackFrameIteratorBase* iterator);
516  virtual ~StackFrame() { }
517
518  // Compute the stack pointer for the calling frame.
519  virtual Address GetCallerStackPointer() const = 0;
520
521  // Printing support.
522  static void PrintIndex(StringStream* accumulator,
523                         PrintMode mode,
524                         int index);
525
526  // Compute the stack frame type for the given state.
527  static Type ComputeType(const StackFrameIteratorBase* iterator, State* state);
528
529#ifdef DEBUG
530  bool can_access_heap_objects() const;
531#endif
532
533 private:
534  const StackFrameIteratorBase* iterator_;
535  Isolate* isolate_;
536  State state_;
537
538  static ReturnAddressLocationResolver return_address_location_resolver_;
539
540  // Fill in the state of the calling frame.
541  virtual void ComputeCallerState(State* state) const = 0;
542
543  // Get the type and the state of the calling frame.
544  virtual Type GetCallerState(State* state) const;
545
546  static const intptr_t kIsolateTag = 1;
547
548  friend class StackFrameIterator;
549  friend class StackFrameIteratorBase;
550  friend class StackHandlerIterator;
551  friend class SafeStackFrameIterator;
552
553 private:
554  void operator=(const StackFrame& original);
555};
556
557
558// Entry frames are used to enter JavaScript execution from C.
559class EntryFrame: public StackFrame {
560 public:
561  Type type() const override { return ENTRY; }
562
563  Code* unchecked_code() const override;
564
565  // Garbage collection support.
566  void Iterate(ObjectVisitor* v) const override;
567
568  static EntryFrame* cast(StackFrame* frame) {
569    DCHECK(frame->is_entry());
570    return static_cast<EntryFrame*>(frame);
571  }
572  void SetCallerFp(Address caller_fp) override;
573
574 protected:
575  inline explicit EntryFrame(StackFrameIteratorBase* iterator);
576
577  // The caller stack pointer for entry frames is always zero. The
578  // real information about the caller frame is available through the
579  // link to the top exit frame.
580  Address GetCallerStackPointer() const override { return 0; }
581
582 private:
583  void ComputeCallerState(State* state) const override;
584  Type GetCallerState(State* state) const override;
585
586  friend class StackFrameIteratorBase;
587};
588
589
590class EntryConstructFrame: public EntryFrame {
591 public:
592  Type type() const override { return ENTRY_CONSTRUCT; }
593
594  Code* unchecked_code() const override;
595
596  static EntryConstructFrame* cast(StackFrame* frame) {
597    DCHECK(frame->is_entry_construct());
598    return static_cast<EntryConstructFrame*>(frame);
599  }
600
601 protected:
602  inline explicit EntryConstructFrame(StackFrameIteratorBase* iterator);
603
604 private:
605  friend class StackFrameIteratorBase;
606};
607
608
609// Exit frames are used to exit JavaScript execution and go to C.
610class ExitFrame: public StackFrame {
611 public:
612  Type type() const override { return EXIT; }
613
614  Code* unchecked_code() const override;
615
616  Object*& code_slot() const;
617
618  // Garbage collection support.
619  void Iterate(ObjectVisitor* v) const override;
620
621  void SetCallerFp(Address caller_fp) override;
622
623  static ExitFrame* cast(StackFrame* frame) {
624    DCHECK(frame->is_exit());
625    return static_cast<ExitFrame*>(frame);
626  }
627
628  // Compute the state and type of an exit frame given a frame
629  // pointer. Used when constructing the first stack frame seen by an
630  // iterator and the frames following entry frames.
631  static Type GetStateForFramePointer(Address fp, State* state);
632  static Address ComputeStackPointer(Address fp);
633  static void FillState(Address fp, Address sp, State* state);
634
635 protected:
636  inline explicit ExitFrame(StackFrameIteratorBase* iterator);
637
638  Address GetCallerStackPointer() const override;
639
640 private:
641  void ComputeCallerState(State* state) const override;
642
643  friend class StackFrameIteratorBase;
644};
645
646class JavaScriptFrame;
647
648class FrameSummary BASE_EMBEDDED {
649 public:
650  // Mode for JavaScriptFrame::Summarize. Exact summary is required to produce
651  // an exact stack trace. It will trigger an assertion failure if that is not
652  // possible, e.g., because of missing deoptimization information. The
653  // approximate mode should produce a summary even without deoptimization
654  // information, but it might miss frames.
655  enum Mode { kExactSummary, kApproximateSummary };
656
657  FrameSummary(Object* receiver, JSFunction* function,
658               AbstractCode* abstract_code, int code_offset,
659               bool is_constructor, Mode mode = kExactSummary);
660
661  static FrameSummary GetFirst(JavaScriptFrame* frame);
662
663  Handle<Object> receiver() { return receiver_; }
664  Handle<JSFunction> function() { return function_; }
665  Handle<AbstractCode> abstract_code() { return abstract_code_; }
666  int code_offset() { return code_offset_; }
667  bool is_constructor() { return is_constructor_; }
668
669  void Print();
670
671 private:
672  Handle<Object> receiver_;
673  Handle<JSFunction> function_;
674  Handle<AbstractCode> abstract_code_;
675  int code_offset_;
676  bool is_constructor_;
677};
678
679class StandardFrame : public StackFrame {
680 public:
681  // Testers.
682  bool is_standard() const override { return true; }
683
684  // Accessors.
685  inline Object* context() const;
686
687  // Access the expressions in the stack frame including locals.
688  inline Object* GetExpression(int index) const;
689  inline void SetExpression(int index, Object* value);
690  int ComputeExpressionsCount() const;
691
692  void SetCallerFp(Address caller_fp) override;
693
694  static StandardFrame* cast(StackFrame* frame) {
695    DCHECK(frame->is_standard());
696    return static_cast<StandardFrame*>(frame);
697  }
698
699 protected:
700  inline explicit StandardFrame(StackFrameIteratorBase* iterator);
701
702  void ComputeCallerState(State* state) const override;
703
704  // Accessors.
705  inline Address caller_fp() const;
706  inline Address caller_pc() const;
707
708  // Computes the address of the PC field in the standard frame given
709  // by the provided frame pointer.
710  static inline Address ComputePCAddress(Address fp);
711
712  // Computes the address of the constant pool  field in the standard
713  // frame given by the provided frame pointer.
714  static inline Address ComputeConstantPoolAddress(Address fp);
715
716  // Iterate over expression stack including stack handlers, locals,
717  // and parts of the fixed part including context and code fields.
718  void IterateExpressions(ObjectVisitor* v) const;
719
720  // Returns the address of the n'th expression stack element.
721  virtual Address GetExpressionAddress(int n) const;
722
723  // Determines if the standard frame for the given frame pointer is
724  // an arguments adaptor frame.
725  static inline bool IsArgumentsAdaptorFrame(Address fp);
726
727  // Determines if the standard frame for the given frame pointer is a
728  // construct frame.
729  static inline bool IsConstructFrame(Address fp);
730
731  // Used by OptimizedFrames and StubFrames.
732  void IterateCompiledFrame(ObjectVisitor* v) const;
733
734 private:
735  friend class StackFrame;
736  friend class SafeStackFrameIterator;
737};
738
739class JavaScriptFrame : public StandardFrame {
740 public:
741  Type type() const override { return JAVA_SCRIPT; }
742
743  // Build a list with summaries for this frame including all inlined frames.
744  virtual void Summarize(
745      List<FrameSummary>* frames,
746      FrameSummary::Mode mode = FrameSummary::kExactSummary) const;
747
748  // Accessors.
749  virtual JSFunction* function() const;
750  virtual Object* receiver() const;
751
752  inline void set_receiver(Object* value);
753
754  // Access the parameters.
755  inline Address GetParameterSlot(int index) const;
756  inline Object* GetParameter(int index) const;
757  inline int ComputeParametersCount() const {
758    return GetNumberOfIncomingArguments();
759  }
760
761  // Access the operand stack.
762  inline Address GetOperandSlot(int index) const;
763  inline Object* GetOperand(int index) const;
764  inline int ComputeOperandsCount() const;
765
766  // Generator support to preserve operand stack.
767  void SaveOperandStack(FixedArray* store) const;
768
769  // Debugger access.
770  void SetParameterValue(int index, Object* value) const;
771
772  // Check if this frame is a constructor frame invoked through 'new'.
773  bool IsConstructor() const;
774
775  // Determines whether this frame includes inlined activations. To get details
776  // about the inlined frames use {GetFunctions} and {Summarize}.
777  bool HasInlinedFrames() const;
778
779  // Check if this frame has "adapted" arguments in the sense that the
780  // actual passed arguments are available in an arguments adaptor
781  // frame below it on the stack.
782  inline bool has_adapted_arguments() const;
783  int GetArgumentsLength() const;
784
785  // Garbage collection support.
786  void Iterate(ObjectVisitor* v) const override;
787
788  // Printing support.
789  void Print(StringStream* accumulator, PrintMode mode,
790             int index) const override;
791
792  // Determine the code for the frame.
793  Code* unchecked_code() const override;
794
795  // Return a list with JSFunctions of this frame.
796  virtual void GetFunctions(List<JSFunction*>* functions) const;
797
798  // Lookup exception handler for current {pc}, returns -1 if none found. Also
799  // returns data associated with the handler site specific to the frame type:
800  //  - JavaScriptFrame : Data is the stack depth at entry of the try-block.
801  //  - OptimizedFrame  : Data is the stack slot count of the entire frame.
802  //  - InterpretedFrame: Data is the register index holding the context.
803  virtual int LookupExceptionHandlerInTable(
804      int* data, HandlerTable::CatchPrediction* prediction);
805
806  // Architecture-specific register description.
807  static Register fp_register();
808  static Register context_register();
809  static Register constant_pool_pointer_register();
810
811  static JavaScriptFrame* cast(StackFrame* frame) {
812    DCHECK(frame->is_java_script());
813    return static_cast<JavaScriptFrame*>(frame);
814  }
815
816  static void PrintFunctionAndOffset(JSFunction* function, Code* code,
817                                     Address pc, FILE* file,
818                                     bool print_line_number);
819
820  static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
821                       bool print_line_number);
822
823 protected:
824  inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator);
825
826  Address GetCallerStackPointer() const override;
827
828  virtual int GetNumberOfIncomingArguments() const;
829
830  // Garbage collection support. Iterates over incoming arguments,
831  // receiver, and any callee-saved registers.
832  void IterateArguments(ObjectVisitor* v) const;
833
834 private:
835  inline Object* function_slot_object() const;
836
837  friend class StackFrameIteratorBase;
838};
839
840
841class StubFrame : public StandardFrame {
842 public:
843  Type type() const override { return STUB; }
844
845  // GC support.
846  void Iterate(ObjectVisitor* v) const override;
847
848  // Determine the code for the frame.
849  Code* unchecked_code() const override;
850
851 protected:
852  inline explicit StubFrame(StackFrameIteratorBase* iterator);
853
854  Address GetCallerStackPointer() const override;
855
856  virtual int GetNumberOfIncomingArguments() const;
857
858  friend class StackFrameIteratorBase;
859};
860
861
862class OptimizedFrame : public JavaScriptFrame {
863 public:
864  Type type() const override { return OPTIMIZED; }
865
866  // GC support.
867  void Iterate(ObjectVisitor* v) const override;
868
869  // Return a list with JSFunctions of this frame.
870  // The functions are ordered bottom-to-top (i.e. functions.last()
871  // is the top-most activation)
872  void GetFunctions(List<JSFunction*>* functions) const override;
873
874  void Summarize(
875      List<FrameSummary>* frames,
876      FrameSummary::Mode mode = FrameSummary::kExactSummary) const override;
877
878  // Lookup exception handler for current {pc}, returns -1 if none found.
879  int LookupExceptionHandlerInTable(
880      int* data, HandlerTable::CatchPrediction* prediction) override;
881
882  DeoptimizationInputData* GetDeoptimizationData(int* deopt_index) const;
883
884  static int StackSlotOffsetRelativeToFp(int slot_index);
885
886 protected:
887  inline explicit OptimizedFrame(StackFrameIteratorBase* iterator);
888
889 private:
890  friend class StackFrameIteratorBase;
891
892  Object* StackSlotAt(int index) const;
893};
894
895
896class InterpretedFrame : public JavaScriptFrame {
897 public:
898  Type type() const override { return INTERPRETED; }
899
900  // Lookup exception handler for current {pc}, returns -1 if none found.
901  int LookupExceptionHandlerInTable(
902      int* data, HandlerTable::CatchPrediction* prediction) override;
903
904  // Returns the current offset into the bytecode stream.
905  int GetBytecodeOffset() const;
906
907  // Updates the current offset into the bytecode stream, mainly used for stack
908  // unwinding to continue execution at a different bytecode offset.
909  void PatchBytecodeOffset(int new_offset);
910
911  // Returns the frame's current bytecode array.
912  BytecodeArray* GetBytecodeArray() const;
913
914  // Updates the frame's BytecodeArray with |bytecode_array|. Used by the
915  // debugger to swap execution onto a BytecodeArray patched with breakpoints.
916  void PatchBytecodeArray(BytecodeArray* bytecode_array);
917
918  // Access to the interpreter register file for this frame.
919  Object* ReadInterpreterRegister(int register_index) const;
920  void WriteInterpreterRegister(int register_index, Object* value);
921
922  // Build a list with summaries for this frame including all inlined frames.
923  void Summarize(
924      List<FrameSummary>* frames,
925      FrameSummary::Mode mode = FrameSummary::kExactSummary) const override;
926
927 protected:
928  inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);
929
930  Address GetExpressionAddress(int n) const override;
931
932 private:
933  friend class StackFrameIteratorBase;
934};
935
936
937// Arguments adaptor frames are automatically inserted below
938// JavaScript frames when the actual number of parameters does not
939// match the formal number of parameters.
940class ArgumentsAdaptorFrame: public JavaScriptFrame {
941 public:
942  Type type() const override { return ARGUMENTS_ADAPTOR; }
943
944  // Determine the code for the frame.
945  Code* unchecked_code() const override;
946
947  static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
948    DCHECK(frame->is_arguments_adaptor());
949    return static_cast<ArgumentsAdaptorFrame*>(frame);
950  }
951
952  // Printing support.
953  void Print(StringStream* accumulator, PrintMode mode,
954             int index) const override;
955
956  static int GetLength(Address fp);
957
958 protected:
959  inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator);
960
961  int GetNumberOfIncomingArguments() const override;
962
963 private:
964  friend class StackFrameIteratorBase;
965};
966
967// Builtin frames are built for builtins with JavaScript linkage, such as
968// various standard library functions (i.e. Math.asin, Math.floor, etc.).
969class BuiltinFrame final : public JavaScriptFrame {
970 public:
971  Type type() const final { return BUILTIN; }
972
973  static BuiltinFrame* cast(StackFrame* frame) {
974    DCHECK(frame->is_builtin());
975    return static_cast<BuiltinFrame*>(frame);
976  }
977
978  // Printing support.
979  void Print(StringStream* accumulator, PrintMode mode, int index) const final;
980
981 protected:
982  inline explicit BuiltinFrame(StackFrameIteratorBase* iterator);
983
984  int GetNumberOfIncomingArguments() const final;
985
986 private:
987  friend class StackFrameIteratorBase;
988};
989
990class WasmFrame : public StandardFrame {
991 public:
992  Type type() const override { return WASM; }
993
994  // GC support.
995  void Iterate(ObjectVisitor* v) const override;
996
997  // Printing support.
998  void Print(StringStream* accumulator, PrintMode mode,
999             int index) const override;
1000
1001  // Determine the code for the frame.
1002  Code* unchecked_code() const override;
1003
1004  Object* wasm_obj();
1005  uint32_t function_index();
1006
1007  static WasmFrame* cast(StackFrame* frame) {
1008    DCHECK(frame->is_wasm());
1009    return static_cast<WasmFrame*>(frame);
1010  }
1011
1012 protected:
1013  inline explicit WasmFrame(StackFrameIteratorBase* iterator);
1014
1015  Address GetCallerStackPointer() const override;
1016
1017 private:
1018  friend class StackFrameIteratorBase;
1019};
1020
1021class WasmToJsFrame : public StubFrame {
1022 public:
1023  Type type() const override { return WASM_TO_JS; }
1024
1025 protected:
1026  inline explicit WasmToJsFrame(StackFrameIteratorBase* iterator);
1027
1028 private:
1029  friend class StackFrameIteratorBase;
1030};
1031
1032class JsToWasmFrame : public StubFrame {
1033 public:
1034  Type type() const override { return JS_TO_WASM; }
1035
1036 protected:
1037  inline explicit JsToWasmFrame(StackFrameIteratorBase* iterator);
1038
1039 private:
1040  friend class StackFrameIteratorBase;
1041};
1042
1043class InternalFrame: public StandardFrame {
1044 public:
1045  Type type() const override { return INTERNAL; }
1046
1047  // Garbage collection support.
1048  void Iterate(ObjectVisitor* v) const override;
1049
1050  // Determine the code for the frame.
1051  Code* unchecked_code() const override;
1052
1053  static InternalFrame* cast(StackFrame* frame) {
1054    DCHECK(frame->is_internal());
1055    return static_cast<InternalFrame*>(frame);
1056  }
1057
1058 protected:
1059  inline explicit InternalFrame(StackFrameIteratorBase* iterator);
1060
1061  Address GetCallerStackPointer() const override;
1062
1063 private:
1064  friend class StackFrameIteratorBase;
1065};
1066
1067
1068class StubFailureTrampolineFrame: public StandardFrame {
1069 public:
1070  Type type() const override { return STUB_FAILURE_TRAMPOLINE; }
1071
1072  // Get the code associated with this frame.
1073  // This method could be called during marking phase of GC.
1074  Code* unchecked_code() const override;
1075
1076  void Iterate(ObjectVisitor* v) const override;
1077
1078  // Architecture-specific register description.
1079  static Register fp_register();
1080  static Register context_register();
1081  static Register constant_pool_pointer_register();
1082
1083 protected:
1084  inline explicit StubFailureTrampolineFrame(
1085      StackFrameIteratorBase* iterator);
1086
1087  Address GetCallerStackPointer() const override;
1088
1089 private:
1090  friend class StackFrameIteratorBase;
1091};
1092
1093
1094// Construct frames are special trampoline frames introduced to handle
1095// function invocations through 'new'.
1096class ConstructFrame: public InternalFrame {
1097 public:
1098  Type type() const override { return CONSTRUCT; }
1099
1100  static ConstructFrame* cast(StackFrame* frame) {
1101    DCHECK(frame->is_construct());
1102    return static_cast<ConstructFrame*>(frame);
1103  }
1104
1105 protected:
1106  inline explicit ConstructFrame(StackFrameIteratorBase* iterator);
1107
1108 private:
1109  friend class StackFrameIteratorBase;
1110};
1111
1112
1113class StackFrameIteratorBase BASE_EMBEDDED {
1114 public:
1115  Isolate* isolate() const { return isolate_; }
1116
1117  bool done() const { return frame_ == NULL; }
1118
1119 protected:
1120  // An iterator that iterates over a given thread's stack.
1121  StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects);
1122
1123  Isolate* isolate_;
1124#define DECLARE_SINGLETON(ignore, type) type type##_;
1125  STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
1126#undef DECLARE_SINGLETON
1127  StackFrame* frame_;
1128  StackHandler* handler_;
1129  const bool can_access_heap_objects_;
1130
1131  StackHandler* handler() const {
1132    DCHECK(!done());
1133    return handler_;
1134  }
1135
1136  // Get the type-specific frame singleton in a given state.
1137  StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
1138  // A helper function, can return a NULL pointer.
1139  StackFrame* SingletonFor(StackFrame::Type type);
1140
1141 private:
1142  friend class StackFrame;
1143  DISALLOW_COPY_AND_ASSIGN(StackFrameIteratorBase);
1144};
1145
1146
1147class StackFrameIterator: public StackFrameIteratorBase {
1148 public:
1149  // An iterator that iterates over the isolate's current thread's stack,
1150  explicit StackFrameIterator(Isolate* isolate);
1151  // An iterator that iterates over a given thread's stack.
1152  StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
1153
1154  StackFrame* frame() const {
1155    DCHECK(!done());
1156    return frame_;
1157  }
1158  void Advance();
1159
1160 private:
1161  // Go back to the first frame.
1162  void Reset(ThreadLocalTop* top);
1163
1164  DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
1165};
1166
1167// Iterator that supports iterating through all JavaScript frames.
1168class JavaScriptFrameIterator BASE_EMBEDDED {
1169 public:
1170  inline explicit JavaScriptFrameIterator(Isolate* isolate);
1171  inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top);
1172  // Skip frames until the frame with the given id is reached.
1173  JavaScriptFrameIterator(Isolate* isolate, StackFrame::Id id);
1174
1175  inline JavaScriptFrame* frame() const;
1176
1177  bool done() const { return iterator_.done(); }
1178  void Advance();
1179
1180  // Advance to the frame holding the arguments for the current
1181  // frame. This only affects the current frame if it has adapted
1182  // arguments.
1183  void AdvanceToArgumentsFrame();
1184
1185 private:
1186  StackFrameIterator iterator_;
1187};
1188
1189// NOTE: The stack trace frame iterator is an iterator that only traverse proper
1190// JavaScript frames that have proper JavaScript functions and WASM frames.
1191// This excludes the problematic functions in runtime.js.
1192class StackTraceFrameIterator BASE_EMBEDDED {
1193 public:
1194  explicit StackTraceFrameIterator(Isolate* isolate);
1195  bool done() const { return iterator_.done(); }
1196  void Advance();
1197
1198  inline StandardFrame* frame() const;
1199
1200  inline bool is_javascript() const;
1201  inline bool is_wasm() const;
1202  inline JavaScriptFrame* javascript_frame() const;
1203  inline WasmFrame* wasm_frame() const;
1204
1205 private:
1206  StackFrameIterator iterator_;
1207  bool IsValidFrame(StackFrame* frame) const;
1208};
1209
1210
1211class SafeStackFrameIterator: public StackFrameIteratorBase {
1212 public:
1213  SafeStackFrameIterator(Isolate* isolate,
1214                         Address fp, Address sp,
1215                         Address js_entry_sp);
1216
1217  inline StackFrame* frame() const;
1218  void Advance();
1219
1220  StackFrame::Type top_frame_type() const { return top_frame_type_; }
1221
1222 private:
1223  void AdvanceOneFrame();
1224
1225  bool IsValidStackAddress(Address addr) const {
1226    return low_bound_ <= addr && addr <= high_bound_;
1227  }
1228  bool IsValidFrame(StackFrame* frame) const;
1229  bool IsValidCaller(StackFrame* frame);
1230  bool IsValidExitFrame(Address fp) const;
1231  bool IsValidTop(ThreadLocalTop* top) const;
1232
1233  const Address low_bound_;
1234  const Address high_bound_;
1235  StackFrame::Type top_frame_type_;
1236  ExternalCallbackScope* external_callback_scope_;
1237};
1238
1239
1240class StackFrameLocator BASE_EMBEDDED {
1241 public:
1242  explicit StackFrameLocator(Isolate* isolate) : iterator_(isolate) {}
1243
1244  // Find the nth JavaScript frame on the stack. The caller must
1245  // guarantee that such a frame exists.
1246  JavaScriptFrame* FindJavaScriptFrame(int n);
1247
1248 private:
1249  StackFrameIterator iterator_;
1250};
1251
1252
1253// Reads all frames on the current stack and copies them into the current
1254// zone memory.
1255Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone);
1256
1257}  // namespace internal
1258}  // namespace v8
1259
1260#endif  // V8_FRAMES_H_
1261