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