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