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