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 InnerPointerToCodeCache(Isolate * isolate)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 Flush()51 void Flush() { 52 memset(&cache_[0], 0, sizeof(cache_)); 53 } 54 55 InnerPointerToCodeCacheEntry* GetCacheEntry(Address inner_pointer); 56 57 private: cache(int index)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 class StackHandlerConstants : public AllStatic { 70 public: 71 static const int kNextOffset = 0 * kPointerSize; 72 static const int kCodeOffset = 1 * kPointerSize; 73 static const int kStateOffset = 2 * kPointerSize; 74 static const int kContextOffset = 3 * kPointerSize; 75 static const int kFPOffset = 4 * kPointerSize; 76 77 static const int kSize = kFPOffset + kFPOnStackSize; 78 static const int kSlotCount = kSize >> kPointerSizeLog2; 79 }; 80 81 82 class StackHandler BASE_EMBEDDED { 83 public: 84 enum Kind { 85 JS_ENTRY, 86 CATCH, 87 FINALLY, 88 LAST_KIND = FINALLY 89 }; 90 91 static const int kKindWidth = 2; 92 STATIC_ASSERT(LAST_KIND < (1 << kKindWidth)); 93 static const int kIndexWidth = 32 - kKindWidth; 94 class KindField: public BitField<StackHandler::Kind, 0, kKindWidth> {}; 95 class IndexField: public BitField<unsigned, kKindWidth, kIndexWidth> {}; 96 97 // Get the address of this stack handler. 98 inline Address address() const; 99 100 // Get the next stack handler in the chain. 101 inline StackHandler* next() const; 102 103 // Tells whether the given address is inside this handler. 104 inline bool includes(Address address) const; 105 106 // Garbage collection support. 107 inline void Iterate(ObjectVisitor* v, Code* holder) const; 108 109 // Conversion support. 110 static inline StackHandler* FromAddress(Address address); 111 112 // Testers 113 inline bool is_js_entry() const; 114 inline bool is_catch() const; 115 inline bool is_finally() const; 116 117 // Generator support to preserve stack handlers. 118 void Unwind(Isolate* isolate, FixedArray* array, int offset, 119 int previous_handler_offset) const; 120 int Rewind(Isolate* isolate, FixedArray* array, int offset, Address fp); 121 122 private: 123 // Accessors. 124 inline Kind kind() const; 125 inline unsigned index() const; 126 127 inline Object** constant_pool_address() const; 128 inline Object** context_address() const; 129 inline Object** code_address() const; 130 inline void SetFp(Address slot, Address fp); 131 132 DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler); 133 }; 134 135 136 #define STACK_FRAME_TYPE_LIST(V) \ 137 V(ENTRY, EntryFrame) \ 138 V(ENTRY_CONSTRUCT, EntryConstructFrame) \ 139 V(EXIT, ExitFrame) \ 140 V(JAVA_SCRIPT, JavaScriptFrame) \ 141 V(OPTIMIZED, OptimizedFrame) \ 142 V(STUB, StubFrame) \ 143 V(STUB_FAILURE_TRAMPOLINE, StubFailureTrampolineFrame) \ 144 V(INTERNAL, InternalFrame) \ 145 V(CONSTRUCT, ConstructFrame) \ 146 V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame) 147 148 149 class StandardFrameConstants : public AllStatic { 150 public: 151 // Fixed part of the frame consists of return address, caller fp, 152 // constant pool (if FLAG_enable_ool_constant_pool), context, and function. 153 // StandardFrame::IterateExpressions assumes that kLastObjectOffset is the 154 // last object pointer. 155 static const int kCPSlotSize = 156 FLAG_enable_ool_constant_pool ? kPointerSize : 0; 157 static const int kFixedFrameSizeFromFp = 2 * kPointerSize + kCPSlotSize; 158 static const int kFixedFrameSize = kPCOnStackSize + kFPOnStackSize + 159 kFixedFrameSizeFromFp; 160 static const int kExpressionsOffset = -3 * kPointerSize - kCPSlotSize; 161 static const int kMarkerOffset = -2 * kPointerSize - kCPSlotSize; 162 static const int kContextOffset = -1 * kPointerSize - kCPSlotSize; 163 static const int kConstantPoolOffset = FLAG_enable_ool_constant_pool ? 164 -1 * kPointerSize : 0; 165 static const int kCallerFPOffset = 0 * kPointerSize; 166 static const int kCallerPCOffset = +1 * kFPOnStackSize; 167 static const int kCallerSPOffset = kCallerPCOffset + 1 * kPCOnStackSize; 168 169 static const int kLastObjectOffset = FLAG_enable_ool_constant_pool ? 170 kConstantPoolOffset : kContextOffset; 171 }; 172 173 174 // Abstract base class for all stack frames. 175 class StackFrame BASE_EMBEDDED { 176 public: 177 #define DECLARE_TYPE(type, ignore) type, 178 enum Type { 179 NONE = 0, 180 STACK_FRAME_TYPE_LIST(DECLARE_TYPE) 181 NUMBER_OF_TYPES, 182 // Used by FrameScope to indicate that the stack frame is constructed 183 // manually and the FrameScope does not need to emit code. 184 MANUAL 185 }; 186 #undef DECLARE_TYPE 187 188 // Opaque data type for identifying stack frames. Used extensively 189 // by the debugger. 190 // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type 191 // has correct value range (see Issue 830 for more details). 192 enum Id { 193 ID_MIN_VALUE = kMinInt, 194 ID_MAX_VALUE = kMaxInt, 195 NO_ID = 0 196 }; 197 198 // Used to mark the outermost JS entry frame. 199 enum JsFrameMarker { 200 INNER_JSENTRY_FRAME = 0, 201 OUTERMOST_JSENTRY_FRAME = 1 202 }; 203 204 struct State { StateState205 State() : sp(NULL), fp(NULL), pc_address(NULL), 206 constant_pool_address(NULL) { } 207 Address sp; 208 Address fp; 209 Address* pc_address; 210 Address* constant_pool_address; 211 }; 212 213 // Copy constructor; it breaks the connection to host iterator 214 // (as an iterator usually lives on stack). StackFrame(const StackFrame & original)215 StackFrame(const StackFrame& original) { 216 this->state_ = original.state_; 217 this->iterator_ = NULL; 218 this->isolate_ = original.isolate_; 219 } 220 221 // Type testers. is_entry()222 bool is_entry() const { return type() == ENTRY; } is_entry_construct()223 bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; } is_exit()224 bool is_exit() const { return type() == EXIT; } is_optimized()225 bool is_optimized() const { return type() == OPTIMIZED; } is_arguments_adaptor()226 bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; } is_internal()227 bool is_internal() const { return type() == INTERNAL; } is_stub_failure_trampoline()228 bool is_stub_failure_trampoline() const { 229 return type() == STUB_FAILURE_TRAMPOLINE; 230 } is_construct()231 bool is_construct() const { return type() == CONSTRUCT; } is_standard()232 virtual bool is_standard() const { return false; } 233 is_java_script()234 bool is_java_script() const { 235 Type type = this->type(); 236 return (type == JAVA_SCRIPT) || (type == OPTIMIZED); 237 } 238 239 // Accessors. sp()240 Address sp() const { return state_.sp; } fp()241 Address fp() const { return state_.fp; } caller_sp()242 Address caller_sp() const { return GetCallerStackPointer(); } 243 244 // If this frame is optimized and was dynamically aligned return its old 245 // unaligned frame pointer. When the frame is deoptimized its FP will shift 246 // up one word and become unaligned. 247 Address UnpaddedFP() const; 248 pc()249 Address pc() const { return *pc_address(); } set_pc(Address pc)250 void set_pc(Address pc) { *pc_address() = pc; } 251 constant_pool()252 Address constant_pool() const { return *constant_pool_address(); } set_constant_pool(ConstantPoolArray * constant_pool)253 void set_constant_pool(ConstantPoolArray* constant_pool) { 254 *constant_pool_address() = reinterpret_cast<Address>(constant_pool); 255 } 256 257 virtual void SetCallerFp(Address caller_fp) = 0; 258 259 // Manually changes value of fp in this object. UpdateFp(Address fp)260 void UpdateFp(Address fp) { state_.fp = fp; } 261 pc_address()262 Address* pc_address() const { return state_.pc_address; } 263 constant_pool_address()264 Address* constant_pool_address() const { 265 return state_.constant_pool_address; 266 } 267 268 // Get the id of this stack frame. id()269 Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); } 270 271 // Checks if this frame includes any stack handlers. 272 bool HasHandler() const; 273 274 // Get the type of this frame. 275 virtual Type type() const = 0; 276 277 // Get the code associated with this frame. 278 // This method could be called during marking phase of GC. 279 virtual Code* unchecked_code() const = 0; 280 281 // Get the code associated with this frame. 282 inline Code* LookupCode() const; 283 284 // Get the code object that contains the given pc. 285 static inline Code* GetContainingCode(Isolate* isolate, Address pc); 286 287 // Get the code object containing the given pc and fill in the 288 // safepoint entry and the number of stack slots. The pc must be at 289 // a safepoint. 290 static Code* GetSafepointData(Isolate* isolate, 291 Address pc, 292 SafepointEntry* safepoint_entry, 293 unsigned* stack_slots); 294 295 virtual void Iterate(ObjectVisitor* v) const = 0; 296 static void IteratePc(ObjectVisitor* v, Address* pc_address, Code* holder); 297 298 // Sets a callback function for return-address rewriting profilers 299 // to resolve the location of a return address to the location of the 300 // profiler's stashed return address. 301 static void SetReturnAddressLocationResolver( 302 ReturnAddressLocationResolver resolver); 303 304 // Resolves pc_address through the resolution address function if one is set. 305 static inline Address* ResolveReturnAddressLocation(Address* pc_address); 306 307 308 // Printing support. 309 enum PrintMode { OVERVIEW, DETAILS }; Print(StringStream * accumulator,PrintMode mode,int index)310 virtual void Print(StringStream* accumulator, 311 PrintMode mode, 312 int index) const { } 313 isolate()314 Isolate* isolate() const { return isolate_; } 315 316 protected: 317 inline explicit StackFrame(StackFrameIteratorBase* iterator); ~StackFrame()318 virtual ~StackFrame() { } 319 320 // Compute the stack pointer for the calling frame. 321 virtual Address GetCallerStackPointer() const = 0; 322 323 // Printing support. 324 static void PrintIndex(StringStream* accumulator, 325 PrintMode mode, 326 int index); 327 328 // Get the top handler from the current stack iterator. 329 inline StackHandler* top_handler() const; 330 331 // Compute the stack frame type for the given state. 332 static Type ComputeType(const StackFrameIteratorBase* iterator, State* state); 333 334 #ifdef DEBUG 335 bool can_access_heap_objects() const; 336 #endif 337 338 private: 339 const StackFrameIteratorBase* iterator_; 340 Isolate* isolate_; 341 State state_; 342 343 static ReturnAddressLocationResolver return_address_location_resolver_; 344 345 // Fill in the state of the calling frame. 346 virtual void ComputeCallerState(State* state) const = 0; 347 348 // Get the type and the state of the calling frame. 349 virtual Type GetCallerState(State* state) const; 350 351 static const intptr_t kIsolateTag = 1; 352 353 friend class StackFrameIterator; 354 friend class StackFrameIteratorBase; 355 friend class StackHandlerIterator; 356 friend class SafeStackFrameIterator; 357 358 private: 359 void operator=(const StackFrame& original); 360 }; 361 362 363 // Entry frames are used to enter JavaScript execution from C. 364 class EntryFrame: public StackFrame { 365 public: type()366 virtual Type type() const { return ENTRY; } 367 368 virtual Code* unchecked_code() const; 369 370 // Garbage collection support. 371 virtual void Iterate(ObjectVisitor* v) const; 372 cast(StackFrame * frame)373 static EntryFrame* cast(StackFrame* frame) { 374 DCHECK(frame->is_entry()); 375 return static_cast<EntryFrame*>(frame); 376 } 377 virtual void SetCallerFp(Address caller_fp); 378 379 protected: 380 inline explicit EntryFrame(StackFrameIteratorBase* iterator); 381 382 // The caller stack pointer for entry frames is always zero. The 383 // real information about the caller frame is available through the 384 // link to the top exit frame. GetCallerStackPointer()385 virtual Address GetCallerStackPointer() const { return 0; } 386 387 private: 388 virtual void ComputeCallerState(State* state) const; 389 virtual Type GetCallerState(State* state) const; 390 391 friend class StackFrameIteratorBase; 392 }; 393 394 395 class EntryConstructFrame: public EntryFrame { 396 public: type()397 virtual Type type() const { return ENTRY_CONSTRUCT; } 398 399 virtual Code* unchecked_code() const; 400 cast(StackFrame * frame)401 static EntryConstructFrame* cast(StackFrame* frame) { 402 DCHECK(frame->is_entry_construct()); 403 return static_cast<EntryConstructFrame*>(frame); 404 } 405 406 protected: 407 inline explicit EntryConstructFrame(StackFrameIteratorBase* iterator); 408 409 private: 410 friend class StackFrameIteratorBase; 411 }; 412 413 414 // Exit frames are used to exit JavaScript execution and go to C. 415 class ExitFrame: public StackFrame { 416 public: type()417 virtual Type type() const { return EXIT; } 418 419 virtual Code* unchecked_code() const; 420 421 Object*& code_slot() const; 422 Object*& constant_pool_slot() const; 423 424 // Garbage collection support. 425 virtual void Iterate(ObjectVisitor* v) const; 426 427 virtual void SetCallerFp(Address caller_fp); 428 cast(StackFrame * frame)429 static ExitFrame* cast(StackFrame* frame) { 430 DCHECK(frame->is_exit()); 431 return static_cast<ExitFrame*>(frame); 432 } 433 434 // Compute the state and type of an exit frame given a frame 435 // pointer. Used when constructing the first stack frame seen by an 436 // iterator and the frames following entry frames. 437 static Type GetStateForFramePointer(Address fp, State* state); 438 static Address ComputeStackPointer(Address fp); 439 static void FillState(Address fp, Address sp, State* state); 440 441 protected: 442 inline explicit ExitFrame(StackFrameIteratorBase* iterator); 443 444 virtual Address GetCallerStackPointer() const; 445 446 private: 447 virtual void ComputeCallerState(State* state) const; 448 449 friend class StackFrameIteratorBase; 450 }; 451 452 453 class StandardFrame: public StackFrame { 454 public: 455 // Testers. is_standard()456 virtual bool is_standard() const { return true; } 457 458 // Accessors. 459 inline Object* context() const; 460 461 // Access the expressions in the stack frame including locals. 462 inline Object* GetExpression(int index) const; 463 inline void SetExpression(int index, Object* value); 464 int ComputeExpressionsCount() const; 465 static Object* GetExpression(Address fp, int index); 466 467 virtual void SetCallerFp(Address caller_fp); 468 cast(StackFrame * frame)469 static StandardFrame* cast(StackFrame* frame) { 470 DCHECK(frame->is_standard()); 471 return static_cast<StandardFrame*>(frame); 472 } 473 474 protected: 475 inline explicit StandardFrame(StackFrameIteratorBase* iterator); 476 477 virtual void ComputeCallerState(State* state) const; 478 479 // Accessors. 480 inline Address caller_fp() const; 481 inline Address caller_pc() const; 482 483 // Computes the address of the PC field in the standard frame given 484 // by the provided frame pointer. 485 static inline Address ComputePCAddress(Address fp); 486 487 // Computes the address of the constant pool field in the standard 488 // frame given by the provided frame pointer. 489 static inline Address ComputeConstantPoolAddress(Address fp); 490 491 // Iterate over expression stack including stack handlers, locals, 492 // and parts of the fixed part including context and code fields. 493 void IterateExpressions(ObjectVisitor* v) const; 494 495 // Returns the address of the n'th expression stack element. 496 Address GetExpressionAddress(int n) const; 497 static Address GetExpressionAddress(Address fp, int n); 498 499 // Determines if the n'th expression stack element is in a stack 500 // handler or not. Requires traversing all handlers in this frame. 501 bool IsExpressionInsideHandler(int n) const; 502 503 // Determines if the standard frame for the given frame pointer is 504 // an arguments adaptor frame. 505 static inline bool IsArgumentsAdaptorFrame(Address fp); 506 507 // Determines if the standard frame for the given frame pointer is a 508 // construct frame. 509 static inline bool IsConstructFrame(Address fp); 510 511 // Used by OptimizedFrames and StubFrames. 512 void IterateCompiledFrame(ObjectVisitor* v) const; 513 514 private: 515 friend class StackFrame; 516 friend class SafeStackFrameIterator; 517 }; 518 519 520 class FrameSummary BASE_EMBEDDED { 521 public: FrameSummary(Object * receiver,JSFunction * function,Code * code,int offset,bool is_constructor)522 FrameSummary(Object* receiver, 523 JSFunction* function, 524 Code* code, 525 int offset, 526 bool is_constructor) 527 : receiver_(receiver, function->GetIsolate()), 528 function_(function), 529 code_(code), 530 offset_(offset), 531 is_constructor_(is_constructor) { } receiver()532 Handle<Object> receiver() { return receiver_; } function()533 Handle<JSFunction> function() { return function_; } code()534 Handle<Code> code() { return code_; } pc()535 Address pc() { return code_->address() + offset_; } offset()536 int offset() { return offset_; } is_constructor()537 bool is_constructor() { return is_constructor_; } 538 539 void Print(); 540 541 private: 542 Handle<Object> receiver_; 543 Handle<JSFunction> function_; 544 Handle<Code> code_; 545 int offset_; 546 bool is_constructor_; 547 }; 548 549 550 class JavaScriptFrame: public StandardFrame { 551 public: type()552 virtual Type type() const { return JAVA_SCRIPT; } 553 554 // Accessors. 555 inline JSFunction* function() const; 556 inline Object* receiver() const; 557 inline void set_receiver(Object* value); 558 559 // Access the parameters. 560 inline Address GetParameterSlot(int index) const; 561 inline Object* GetParameter(int index) const; ComputeParametersCount()562 inline int ComputeParametersCount() const { 563 return GetNumberOfIncomingArguments(); 564 } 565 566 // Access the operand stack. 567 inline Address GetOperandSlot(int index) const; 568 inline Object* GetOperand(int index) const; 569 inline int ComputeOperandsCount() const; 570 571 // Generator support to preserve operand stack and stack handlers. 572 void SaveOperandStack(FixedArray* store, int* stack_handler_index) const; 573 void RestoreOperandStack(FixedArray* store, int stack_handler_index); 574 575 // Debugger access. 576 void SetParameterValue(int index, Object* value) const; 577 578 // Check if this frame is a constructor frame invoked through 'new'. 579 bool IsConstructor() const; 580 581 // Check if this frame has "adapted" arguments in the sense that the 582 // actual passed arguments are available in an arguments adaptor 583 // frame below it on the stack. 584 inline bool has_adapted_arguments() const; 585 int GetArgumentsLength() const; 586 587 // Garbage collection support. 588 virtual void Iterate(ObjectVisitor* v) const; 589 590 // Printing support. 591 virtual void Print(StringStream* accumulator, 592 PrintMode mode, 593 int index) const; 594 595 // Determine the code for the frame. 596 virtual Code* unchecked_code() const; 597 598 // Returns the levels of inlining for this frame. GetInlineCount()599 virtual int GetInlineCount() { return 1; } 600 601 // Return a list with JSFunctions of this frame. 602 virtual void GetFunctions(List<JSFunction*>* functions); 603 604 // Build a list with summaries for this frame including all inlined frames. 605 virtual void Summarize(List<FrameSummary>* frames); 606 607 // Architecture-specific register description. 608 static Register fp_register(); 609 static Register context_register(); 610 static Register constant_pool_pointer_register(); 611 cast(StackFrame * frame)612 static JavaScriptFrame* cast(StackFrame* frame) { 613 DCHECK(frame->is_java_script()); 614 return static_cast<JavaScriptFrame*>(frame); 615 } 616 617 static void PrintFunctionAndOffset(JSFunction* function, Code* code, 618 Address pc, FILE* file, 619 bool print_line_number); 620 621 static void PrintTop(Isolate* isolate, FILE* file, bool print_args, 622 bool print_line_number); 623 624 protected: 625 inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator); 626 627 virtual Address GetCallerStackPointer() const; 628 629 virtual int GetNumberOfIncomingArguments() const; 630 631 // Garbage collection support. Iterates over incoming arguments, 632 // receiver, and any callee-saved registers. 633 void IterateArguments(ObjectVisitor* v) const; 634 635 private: 636 inline Object* function_slot_object() const; 637 638 friend class StackFrameIteratorBase; 639 }; 640 641 642 class StubFrame : public StandardFrame { 643 public: type()644 virtual Type type() const { return STUB; } 645 646 // GC support. 647 virtual void Iterate(ObjectVisitor* v) const; 648 649 // Determine the code for the frame. 650 virtual Code* unchecked_code() const; 651 652 protected: 653 inline explicit StubFrame(StackFrameIteratorBase* iterator); 654 655 virtual Address GetCallerStackPointer() const; 656 657 virtual int GetNumberOfIncomingArguments() const; 658 659 friend class StackFrameIteratorBase; 660 }; 661 662 663 class OptimizedFrame : public JavaScriptFrame { 664 public: type()665 virtual Type type() const { return OPTIMIZED; } 666 667 // GC support. 668 virtual void Iterate(ObjectVisitor* v) const; 669 670 virtual int GetInlineCount(); 671 672 // Return a list with JSFunctions of this frame. 673 // The functions are ordered bottom-to-top (i.e. functions.last() 674 // is the top-most activation) 675 virtual void GetFunctions(List<JSFunction*>* functions); 676 677 virtual void Summarize(List<FrameSummary>* frames); 678 679 DeoptimizationInputData* GetDeoptimizationData(int* deopt_index); 680 681 protected: 682 inline explicit OptimizedFrame(StackFrameIteratorBase* iterator); 683 684 private: 685 JSFunction* LiteralAt(FixedArray* literal_array, int literal_id); 686 687 friend class StackFrameIteratorBase; 688 }; 689 690 691 // Arguments adaptor frames are automatically inserted below 692 // JavaScript frames when the actual number of parameters does not 693 // match the formal number of parameters. 694 class ArgumentsAdaptorFrame: public JavaScriptFrame { 695 public: type()696 virtual Type type() const { return ARGUMENTS_ADAPTOR; } 697 698 // Determine the code for the frame. 699 virtual Code* unchecked_code() const; 700 cast(StackFrame * frame)701 static ArgumentsAdaptorFrame* cast(StackFrame* frame) { 702 DCHECK(frame->is_arguments_adaptor()); 703 return static_cast<ArgumentsAdaptorFrame*>(frame); 704 } 705 706 // Printing support. 707 virtual void Print(StringStream* accumulator, 708 PrintMode mode, 709 int index) const; 710 711 protected: 712 inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator); 713 714 virtual int GetNumberOfIncomingArguments() const; 715 716 virtual Address GetCallerStackPointer() const; 717 718 private: 719 friend class StackFrameIteratorBase; 720 }; 721 722 723 class InternalFrame: public StandardFrame { 724 public: type()725 virtual Type type() const { return INTERNAL; } 726 727 // Garbage collection support. 728 virtual void Iterate(ObjectVisitor* v) const; 729 730 // Determine the code for the frame. 731 virtual Code* unchecked_code() const; 732 cast(StackFrame * frame)733 static InternalFrame* cast(StackFrame* frame) { 734 DCHECK(frame->is_internal()); 735 return static_cast<InternalFrame*>(frame); 736 } 737 738 protected: 739 inline explicit InternalFrame(StackFrameIteratorBase* iterator); 740 741 virtual Address GetCallerStackPointer() const; 742 743 private: 744 friend class StackFrameIteratorBase; 745 }; 746 747 748 class StubFailureTrampolineFrame: public StandardFrame { 749 public: 750 // sizeof(Arguments) - sizeof(Arguments*) is 3 * kPointerSize), but the 751 // presubmit script complains about using sizeof() on a type. 752 static const int kFirstRegisterParameterFrameOffset = 753 StandardFrameConstants::kMarkerOffset - 3 * kPointerSize; 754 755 static const int kCallerStackParameterCountFrameOffset = 756 StandardFrameConstants::kMarkerOffset - 2 * kPointerSize; 757 type()758 virtual Type type() const { return STUB_FAILURE_TRAMPOLINE; } 759 760 // Get the code associated with this frame. 761 // This method could be called during marking phase of GC. 762 virtual Code* unchecked_code() const; 763 764 virtual void Iterate(ObjectVisitor* v) const; 765 766 // Architecture-specific register description. 767 static Register fp_register(); 768 static Register context_register(); 769 static Register constant_pool_pointer_register(); 770 771 protected: 772 inline explicit StubFailureTrampolineFrame( 773 StackFrameIteratorBase* iterator); 774 775 virtual Address GetCallerStackPointer() const; 776 777 private: 778 friend class StackFrameIteratorBase; 779 }; 780 781 782 // Construct frames are special trampoline frames introduced to handle 783 // function invocations through 'new'. 784 class ConstructFrame: public InternalFrame { 785 public: type()786 virtual Type type() const { return CONSTRUCT; } 787 cast(StackFrame * frame)788 static ConstructFrame* cast(StackFrame* frame) { 789 DCHECK(frame->is_construct()); 790 return static_cast<ConstructFrame*>(frame); 791 } 792 793 protected: 794 inline explicit ConstructFrame(StackFrameIteratorBase* iterator); 795 796 private: 797 friend class StackFrameIteratorBase; 798 }; 799 800 801 class StackFrameIteratorBase BASE_EMBEDDED { 802 public: isolate()803 Isolate* isolate() const { return isolate_; } 804 done()805 bool done() const { return frame_ == NULL; } 806 807 protected: 808 // An iterator that iterates over a given thread's stack. 809 StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects); 810 811 Isolate* isolate_; 812 #define DECLARE_SINGLETON(ignore, type) type type##_; 813 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON) 814 #undef DECLARE_SINGLETON 815 StackFrame* frame_; 816 StackHandler* handler_; 817 const bool can_access_heap_objects_; 818 handler()819 StackHandler* handler() const { 820 DCHECK(!done()); 821 return handler_; 822 } 823 824 // Get the type-specific frame singleton in a given state. 825 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state); 826 // A helper function, can return a NULL pointer. 827 StackFrame* SingletonFor(StackFrame::Type type); 828 829 private: 830 friend class StackFrame; 831 DISALLOW_COPY_AND_ASSIGN(StackFrameIteratorBase); 832 }; 833 834 835 class StackFrameIterator: public StackFrameIteratorBase { 836 public: 837 // An iterator that iterates over the isolate's current thread's stack, 838 explicit StackFrameIterator(Isolate* isolate); 839 // An iterator that iterates over a given thread's stack. 840 StackFrameIterator(Isolate* isolate, ThreadLocalTop* t); 841 frame()842 StackFrame* frame() const { 843 DCHECK(!done()); 844 return frame_; 845 } 846 void Advance(); 847 848 private: 849 // Go back to the first frame. 850 void Reset(ThreadLocalTop* top); 851 852 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator); 853 }; 854 855 856 // Iterator that supports iterating through all JavaScript frames. 857 class JavaScriptFrameIterator BASE_EMBEDDED { 858 public: 859 inline explicit JavaScriptFrameIterator(Isolate* isolate); 860 inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top); 861 // Skip frames until the frame with the given id is reached. 862 JavaScriptFrameIterator(Isolate* isolate, StackFrame::Id id); 863 864 inline JavaScriptFrame* frame() const; 865 done()866 bool done() const { return iterator_.done(); } 867 void Advance(); 868 869 // Advance to the frame holding the arguments for the current 870 // frame. This only affects the current frame if it has adapted 871 // arguments. 872 void AdvanceToArgumentsFrame(); 873 874 private: 875 StackFrameIterator iterator_; 876 }; 877 878 879 // NOTE: The stack trace frame iterator is an iterator that only 880 // traverse proper JavaScript frames; that is JavaScript frames that 881 // have proper JavaScript functions. This excludes the problematic 882 // functions in runtime.js. 883 class StackTraceFrameIterator: public JavaScriptFrameIterator { 884 public: 885 explicit StackTraceFrameIterator(Isolate* isolate); 886 void Advance(); 887 888 private: 889 bool IsValidFrame(); 890 }; 891 892 893 class SafeStackFrameIterator: public StackFrameIteratorBase { 894 public: 895 SafeStackFrameIterator(Isolate* isolate, 896 Address fp, Address sp, 897 Address js_entry_sp); 898 899 inline StackFrame* frame() const; 900 void Advance(); 901 top_frame_type()902 StackFrame::Type top_frame_type() const { return top_frame_type_; } 903 904 private: 905 void AdvanceOneFrame(); 906 IsValidStackAddress(Address addr)907 bool IsValidStackAddress(Address addr) const { 908 return low_bound_ <= addr && addr <= high_bound_; 909 } 910 bool IsValidFrame(StackFrame* frame) const; 911 bool IsValidCaller(StackFrame* frame); 912 bool IsValidExitFrame(Address fp) const; 913 bool IsValidTop(ThreadLocalTop* top) const; 914 915 const Address low_bound_; 916 const Address high_bound_; 917 StackFrame::Type top_frame_type_; 918 ExternalCallbackScope* external_callback_scope_; 919 }; 920 921 922 class StackFrameLocator BASE_EMBEDDED { 923 public: StackFrameLocator(Isolate * isolate)924 explicit StackFrameLocator(Isolate* isolate) : iterator_(isolate) {} 925 926 // Find the nth JavaScript frame on the stack. The caller must 927 // guarantee that such a frame exists. 928 JavaScriptFrame* FindJavaScriptFrame(int n); 929 930 private: 931 StackFrameIterator iterator_; 932 }; 933 934 935 // Reads all frames on the current stack and copies them into the current 936 // zone memory. 937 Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone); 938 939 } } // namespace v8::internal 940 941 #endif // V8_FRAMES_H_ 942