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