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 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 52 void Flush() { 53 memset(&cache_[0], 0, sizeof(cache_)); 54 } 55 56 InnerPointerToCodeCacheEntry* GetCacheEntry(Address inner_pointer); 57 58 private: 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 405 inline static int FPOffsetToFrameSlot(int frame_offset) { 406 return StandardFrameConstants::kFixedSlotCountAboveFp - 1 - 407 frame_offset / kPointerSize; 408 } 409 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. 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. 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. 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). 495 StackFrame(const StackFrame& original) { 496 this->state_ = original.state_; 497 this->iterator_ = NULL; 498 this->isolate_ = original.isolate_; 499 } 500 501 // Type testers. 502 bool is_entry() const { return type() == ENTRY; } 503 bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; } 504 bool is_exit() const { return type() == EXIT; } 505 bool is_optimized() const { return type() == OPTIMIZED; } 506 bool is_interpreted() const { return type() == INTERPRETED; } 507 bool is_wasm_compiled() const { return type() == WASM_COMPILED; } 508 bool is_wasm_to_js() const { return type() == WASM_TO_JS; } 509 bool is_js_to_wasm() const { return type() == JS_TO_WASM; } 510 bool is_wasm_interpreter_entry() const { 511 return type() == WASM_INTERPRETER_ENTRY; 512 } 513 bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; } 514 bool is_builtin() const { return type() == BUILTIN; } 515 bool is_internal() const { return type() == INTERNAL; } 516 bool is_stub_failure_trampoline() const { 517 return type() == STUB_FAILURE_TRAMPOLINE; 518 } 519 bool is_construct() const { return type() == CONSTRUCT; } 520 bool is_builtin_exit() const { return type() == BUILTIN_EXIT; } 521 virtual bool is_standard() const { return false; } 522 523 bool is_java_script() const { 524 Type type = this->type(); 525 return (type == JAVA_SCRIPT) || (type == OPTIMIZED) || 526 (type == INTERPRETED) || (type == BUILTIN); 527 } 528 bool is_wasm() const { 529 Type type = this->type(); 530 return type == WASM_COMPILED || type == WASM_INTERPRETER_ENTRY; 531 } 532 533 // Accessors. 534 Address sp() const { return state_.sp; } 535 Address fp() const { return state_.fp; } 536 Address callee_pc() const { 537 return state_.callee_pc_address ? *state_.callee_pc_address : nullptr; 538 } 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 546 Address pc() const { return *pc_address(); } 547 void set_pc(Address pc) { *pc_address() = pc; } 548 549 Address constant_pool() const { return *constant_pool_address(); } 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. 557 void UpdateFp(Address fp) { state_.fp = fp; } 558 559 Address* pc_address() const { return state_.pc_address; } 560 561 Address* constant_pool_address() const { 562 return state_.constant_pool_address; 563 } 564 565 // Get the id of this stack frame. 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 }; 607 virtual void Print(StringStream* accumulator, 608 PrintMode mode, 609 int index) const { } 610 611 Isolate* isolate() const { return isolate_; } 612 613 void operator=(const StackFrame& original) = delete; 614 615 protected: 616 inline explicit StackFrame(StackFrameIteratorBase* iterator); 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: 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 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. 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: 690 Type type() const override { return ENTRY_CONSTRUCT; } 691 692 Code* unchecked_code() const override; 693 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: 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 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: 750 Type type() const override { return BUILTIN_EXIT; } 751 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: 805 FrameSummaryBase(Isolate* isolate, Kind kind) 806 : isolate_(isolate), kind_(kind) {} 807 Isolate* isolate() const { return isolate_; } 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 822 Handle<Object> receiver() const { return receiver_; } 823 Handle<JSFunction> function() const { return function_; } 824 Handle<AbstractCode> abstract_code() const { return abstract_code_; } 825 int code_offset() const { return code_offset_; } 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; 851 bool is_constructor() const { return false; } 852 bool is_subject_to_debugging() const { return true; } 853 int SourcePosition() const; 854 int SourceStatementPosition() const { return SourcePosition(); } 855 Handle<Script> script() const; 856 Handle<WasmInstanceObject> wasm_instance() const { return wasm_instance_; } 857 Handle<String> FunctionName() const; 858 Handle<Context> native_context() const; 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; 871 Handle<Code> code() const { return code_; } 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); 884 uint32_t function_index() const { return function_index_; } 885 int code_offset() const { return 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 } 923 FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CAST) 924 #undef FRAME_SUMMARY_CAST 925 926 bool IsWasm() const { return IsWasmCompiled() || IsWasmInterpreted(); } 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. 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 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: 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 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 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: 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: 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: 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: 1231 Type type() const override { return ARGUMENTS_ADAPTOR; } 1232 1233 // Determine the code for the frame. 1234 Code* unchecked_code() const override; 1235 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: 1260 Type type() const final { return BUILTIN; } 1261 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: 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 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: 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 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: 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: 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: 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 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: 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: 1433 Type type() const override { return CONSTRUCT; } 1434 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: 1450 Isolate* isolate() const { return isolate_; } 1451 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 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 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 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); 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 1559 StackFrame::Type top_frame_type() const { return top_frame_type_; } 1560 1561 private: 1562 void AdvanceOneFrame(); 1563 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: 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