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