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