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