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 ASSERT(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 ASSERT(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 ASSERT(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 ASSERT(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 ASSERT(frame->is_java_script()); 614 return static_cast<JavaScriptFrame*>(frame); 615 } 616 617 static void PrintTop(Isolate* isolate, 618 FILE* file, 619 bool print_args, 620 bool print_line_number); 621 622 protected: 623 inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator); 624 625 virtual Address GetCallerStackPointer() const; 626 627 virtual int GetNumberOfIncomingArguments() const; 628 629 // Garbage collection support. Iterates over incoming arguments, 630 // receiver, and any callee-saved registers. 631 void IterateArguments(ObjectVisitor* v) const; 632 633 private: 634 inline Object* function_slot_object() const; 635 636 friend class StackFrameIteratorBase; 637 }; 638 639 640 class StubFrame : public StandardFrame { 641 public: type()642 virtual Type type() const { return STUB; } 643 644 // GC support. 645 virtual void Iterate(ObjectVisitor* v) const; 646 647 // Determine the code for the frame. 648 virtual Code* unchecked_code() const; 649 650 protected: 651 inline explicit StubFrame(StackFrameIteratorBase* iterator); 652 653 virtual Address GetCallerStackPointer() const; 654 655 virtual int GetNumberOfIncomingArguments() const; 656 657 friend class StackFrameIteratorBase; 658 }; 659 660 661 class OptimizedFrame : public JavaScriptFrame { 662 public: type()663 virtual Type type() const { return OPTIMIZED; } 664 665 // GC support. 666 virtual void Iterate(ObjectVisitor* v) const; 667 668 virtual int GetInlineCount(); 669 670 // Return a list with JSFunctions of this frame. 671 // The functions are ordered bottom-to-top (i.e. functions.last() 672 // is the top-most activation) 673 virtual void GetFunctions(List<JSFunction*>* functions); 674 675 virtual void Summarize(List<FrameSummary>* frames); 676 677 DeoptimizationInputData* GetDeoptimizationData(int* deopt_index); 678 679 protected: 680 inline explicit OptimizedFrame(StackFrameIteratorBase* iterator); 681 682 private: 683 JSFunction* LiteralAt(FixedArray* literal_array, int literal_id); 684 685 friend class StackFrameIteratorBase; 686 }; 687 688 689 // Arguments adaptor frames are automatically inserted below 690 // JavaScript frames when the actual number of parameters does not 691 // match the formal number of parameters. 692 class ArgumentsAdaptorFrame: public JavaScriptFrame { 693 public: type()694 virtual Type type() const { return ARGUMENTS_ADAPTOR; } 695 696 // Determine the code for the frame. 697 virtual Code* unchecked_code() const; 698 cast(StackFrame * frame)699 static ArgumentsAdaptorFrame* cast(StackFrame* frame) { 700 ASSERT(frame->is_arguments_adaptor()); 701 return static_cast<ArgumentsAdaptorFrame*>(frame); 702 } 703 704 // Printing support. 705 virtual void Print(StringStream* accumulator, 706 PrintMode mode, 707 int index) const; 708 709 protected: 710 inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator); 711 712 virtual int GetNumberOfIncomingArguments() const; 713 714 virtual Address GetCallerStackPointer() const; 715 716 private: 717 friend class StackFrameIteratorBase; 718 }; 719 720 721 class InternalFrame: public StandardFrame { 722 public: type()723 virtual Type type() const { return INTERNAL; } 724 725 // Garbage collection support. 726 virtual void Iterate(ObjectVisitor* v) const; 727 728 // Determine the code for the frame. 729 virtual Code* unchecked_code() const; 730 cast(StackFrame * frame)731 static InternalFrame* cast(StackFrame* frame) { 732 ASSERT(frame->is_internal()); 733 return static_cast<InternalFrame*>(frame); 734 } 735 736 protected: 737 inline explicit InternalFrame(StackFrameIteratorBase* iterator); 738 739 virtual Address GetCallerStackPointer() const; 740 741 private: 742 friend class StackFrameIteratorBase; 743 }; 744 745 746 class StubFailureTrampolineFrame: public StandardFrame { 747 public: 748 // sizeof(Arguments) - sizeof(Arguments*) is 3 * kPointerSize), but the 749 // presubmit script complains about using sizeof() on a type. 750 static const int kFirstRegisterParameterFrameOffset = 751 StandardFrameConstants::kMarkerOffset - 3 * kPointerSize; 752 753 static const int kCallerStackParameterCountFrameOffset = 754 StandardFrameConstants::kMarkerOffset - 2 * kPointerSize; 755 type()756 virtual Type type() const { return STUB_FAILURE_TRAMPOLINE; } 757 758 // Get the code associated with this frame. 759 // This method could be called during marking phase of GC. 760 virtual Code* unchecked_code() const; 761 762 virtual void Iterate(ObjectVisitor* v) const; 763 764 // Architecture-specific register description. 765 static Register fp_register(); 766 static Register context_register(); 767 static Register constant_pool_pointer_register(); 768 769 protected: 770 inline explicit StubFailureTrampolineFrame( 771 StackFrameIteratorBase* iterator); 772 773 virtual Address GetCallerStackPointer() const; 774 775 private: 776 friend class StackFrameIteratorBase; 777 }; 778 779 780 // Construct frames are special trampoline frames introduced to handle 781 // function invocations through 'new'. 782 class ConstructFrame: public InternalFrame { 783 public: type()784 virtual Type type() const { return CONSTRUCT; } 785 cast(StackFrame * frame)786 static ConstructFrame* cast(StackFrame* frame) { 787 ASSERT(frame->is_construct()); 788 return static_cast<ConstructFrame*>(frame); 789 } 790 791 protected: 792 inline explicit ConstructFrame(StackFrameIteratorBase* iterator); 793 794 private: 795 friend class StackFrameIteratorBase; 796 }; 797 798 799 class StackFrameIteratorBase BASE_EMBEDDED { 800 public: isolate()801 Isolate* isolate() const { return isolate_; } 802 done()803 bool done() const { return frame_ == NULL; } 804 805 protected: 806 // An iterator that iterates over a given thread's stack. 807 StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects); 808 809 Isolate* isolate_; 810 #define DECLARE_SINGLETON(ignore, type) type type##_; 811 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON) 812 #undef DECLARE_SINGLETON 813 StackFrame* frame_; 814 StackHandler* handler_; 815 const bool can_access_heap_objects_; 816 handler()817 StackHandler* handler() const { 818 ASSERT(!done()); 819 return handler_; 820 } 821 822 // Get the type-specific frame singleton in a given state. 823 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state); 824 // A helper function, can return a NULL pointer. 825 StackFrame* SingletonFor(StackFrame::Type type); 826 827 private: 828 friend class StackFrame; 829 DISALLOW_COPY_AND_ASSIGN(StackFrameIteratorBase); 830 }; 831 832 833 class StackFrameIterator: public StackFrameIteratorBase { 834 public: 835 // An iterator that iterates over the isolate's current thread's stack, 836 explicit StackFrameIterator(Isolate* isolate); 837 // An iterator that iterates over a given thread's stack. 838 StackFrameIterator(Isolate* isolate, ThreadLocalTop* t); 839 frame()840 StackFrame* frame() const { 841 ASSERT(!done()); 842 return frame_; 843 } 844 void Advance(); 845 846 private: 847 // Go back to the first frame. 848 void Reset(ThreadLocalTop* top); 849 850 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator); 851 }; 852 853 854 // Iterator that supports iterating through all JavaScript frames. 855 class JavaScriptFrameIterator BASE_EMBEDDED { 856 public: 857 inline explicit JavaScriptFrameIterator(Isolate* isolate); 858 inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top); 859 // Skip frames until the frame with the given id is reached. 860 JavaScriptFrameIterator(Isolate* isolate, StackFrame::Id id); 861 862 inline JavaScriptFrame* frame() const; 863 done()864 bool done() const { return iterator_.done(); } 865 void Advance(); 866 867 // Advance to the frame holding the arguments for the current 868 // frame. This only affects the current frame if it has adapted 869 // arguments. 870 void AdvanceToArgumentsFrame(); 871 872 private: 873 StackFrameIterator iterator_; 874 }; 875 876 877 // NOTE: The stack trace frame iterator is an iterator that only 878 // traverse proper JavaScript frames; that is JavaScript frames that 879 // have proper JavaScript functions. This excludes the problematic 880 // functions in runtime.js. 881 class StackTraceFrameIterator: public JavaScriptFrameIterator { 882 public: 883 explicit StackTraceFrameIterator(Isolate* isolate); 884 void Advance(); 885 886 private: 887 bool IsValidFrame(); 888 }; 889 890 891 class SafeStackFrameIterator: public StackFrameIteratorBase { 892 public: 893 SafeStackFrameIterator(Isolate* isolate, 894 Address fp, Address sp, 895 Address js_entry_sp); 896 897 inline StackFrame* frame() const; 898 void Advance(); 899 top_frame_type()900 StackFrame::Type top_frame_type() const { return top_frame_type_; } 901 902 private: 903 void AdvanceOneFrame(); 904 IsValidStackAddress(Address addr)905 bool IsValidStackAddress(Address addr) const { 906 return low_bound_ <= addr && addr <= high_bound_; 907 } 908 bool IsValidFrame(StackFrame* frame) const; 909 bool IsValidCaller(StackFrame* frame); 910 bool IsValidExitFrame(Address fp) const; 911 bool IsValidTop(ThreadLocalTop* top) const; 912 913 const Address low_bound_; 914 const Address high_bound_; 915 StackFrame::Type top_frame_type_; 916 ExternalCallbackScope* external_callback_scope_; 917 }; 918 919 920 class StackFrameLocator BASE_EMBEDDED { 921 public: StackFrameLocator(Isolate * isolate)922 explicit StackFrameLocator(Isolate* isolate) : iterator_(isolate) {} 923 924 // Find the nth JavaScript frame on the stack. The caller must 925 // guarantee that such a frame exists. 926 JavaScriptFrame* FindJavaScriptFrame(int n); 927 928 private: 929 StackFrameIterator iterator_; 930 }; 931 932 933 // Reads all frames on the current stack and copies them into the current 934 // zone memory. 935 Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone); 936 937 } } // namespace v8::internal 938 939 #endif // V8_FRAMES_H_ 940