1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #ifndef V8_FRAMES_H_ 29 #define V8_FRAMES_H_ 30 31 #include "allocation.h" 32 #include "handles.h" 33 #include "safepoint-table.h" 34 35 namespace v8 { 36 namespace internal { 37 38 typedef uint32_t RegList; 39 40 // Get the number of registers in a given register list. 41 int NumRegs(RegList list); 42 43 // Return the code of the n-th saved register available to JavaScript. 44 int JSCallerSavedCode(int n); 45 46 47 // Forward declarations. 48 class StackFrameIterator; 49 class ThreadLocalTop; 50 class Isolate; 51 52 class InnerPointerToCodeCache { 53 public: 54 struct InnerPointerToCodeCacheEntry { 55 Address inner_pointer; 56 Code* code; 57 SafepointEntry safepoint_entry; 58 }; 59 InnerPointerToCodeCache(Isolate * isolate)60 explicit InnerPointerToCodeCache(Isolate* isolate) : isolate_(isolate) { 61 Flush(); 62 } 63 64 Code* GcSafeFindCodeForInnerPointer(Address inner_pointer); 65 Code* GcSafeCastToCode(HeapObject* object, Address inner_pointer); 66 Flush()67 void Flush() { 68 memset(&cache_[0], 0, sizeof(cache_)); 69 } 70 71 InnerPointerToCodeCacheEntry* GetCacheEntry(Address inner_pointer); 72 73 private: cache(int index)74 InnerPointerToCodeCacheEntry* cache(int index) { return &cache_[index]; } 75 76 Isolate* isolate_; 77 78 static const int kInnerPointerToCodeCacheSize = 1024; 79 InnerPointerToCodeCacheEntry cache_[kInnerPointerToCodeCacheSize]; 80 81 DISALLOW_COPY_AND_ASSIGN(InnerPointerToCodeCache); 82 }; 83 84 85 class StackHandler BASE_EMBEDDED { 86 public: 87 enum Kind { 88 JS_ENTRY, 89 CATCH, 90 FINALLY, 91 LAST_KIND = FINALLY 92 }; 93 94 static const int kKindWidth = 2; 95 STATIC_ASSERT(LAST_KIND < (1 << kKindWidth)); 96 static const int kIndexWidth = 32 - kKindWidth; 97 class KindField: public BitField<StackHandler::Kind, 0, kKindWidth> {}; 98 class IndexField: public BitField<unsigned, kKindWidth, kIndexWidth> {}; 99 100 // Get the address of this stack handler. 101 inline Address address() const; 102 103 // Get the next stack handler in the chain. 104 inline StackHandler* next() const; 105 106 // Tells whether the given address is inside this handler. 107 inline bool includes(Address address) const; 108 109 // Garbage collection support. 110 inline void Iterate(ObjectVisitor* v, Code* holder) const; 111 112 // Conversion support. 113 static inline StackHandler* FromAddress(Address address); 114 115 // Testers 116 inline bool is_js_entry() const; 117 inline bool is_catch() const; 118 inline bool is_finally() const; 119 120 private: 121 // Accessors. 122 inline Kind kind() const; 123 124 inline Object** context_address() const; 125 inline Object** code_address() const; 126 127 DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler); 128 }; 129 130 131 #define STACK_FRAME_TYPE_LIST(V) \ 132 V(ENTRY, EntryFrame) \ 133 V(ENTRY_CONSTRUCT, EntryConstructFrame) \ 134 V(EXIT, ExitFrame) \ 135 V(JAVA_SCRIPT, JavaScriptFrame) \ 136 V(OPTIMIZED, OptimizedFrame) \ 137 V(INTERNAL, InternalFrame) \ 138 V(CONSTRUCT, ConstructFrame) \ 139 V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame) 140 141 142 // Abstract base class for all stack frames. 143 class StackFrame BASE_EMBEDDED { 144 public: 145 #define DECLARE_TYPE(type, ignore) type, 146 enum Type { 147 NONE = 0, 148 STACK_FRAME_TYPE_LIST(DECLARE_TYPE) 149 NUMBER_OF_TYPES, 150 // Used by FrameScope to indicate that the stack frame is constructed 151 // manually and the FrameScope does not need to emit code. 152 MANUAL 153 }; 154 #undef DECLARE_TYPE 155 156 // Opaque data type for identifying stack frames. Used extensively 157 // by the debugger. 158 // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type 159 // has correct value range (see Issue 830 for more details). 160 enum Id { 161 ID_MIN_VALUE = kMinInt, 162 ID_MAX_VALUE = kMaxInt, 163 NO_ID = 0 164 }; 165 166 // Used to mark the outermost JS entry frame. 167 enum JsFrameMarker { 168 INNER_JSENTRY_FRAME = 0, 169 OUTERMOST_JSENTRY_FRAME = 1 170 }; 171 172 struct State { StateState173 State() : sp(NULL), fp(NULL), pc_address(NULL) { } 174 Address sp; 175 Address fp; 176 Address* pc_address; 177 }; 178 179 // Copy constructor; it breaks the connection to host iterator 180 // (as an iterator usually lives on stack). StackFrame(const StackFrame & original)181 StackFrame(const StackFrame& original) { 182 this->state_ = original.state_; 183 this->iterator_ = NULL; 184 this->isolate_ = original.isolate_; 185 } 186 187 // Type testers. is_entry()188 bool is_entry() const { return type() == ENTRY; } is_entry_construct()189 bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; } is_exit()190 bool is_exit() const { return type() == EXIT; } is_optimized()191 bool is_optimized() const { return type() == OPTIMIZED; } is_arguments_adaptor()192 bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; } is_internal()193 bool is_internal() const { return type() == INTERNAL; } is_construct()194 bool is_construct() const { return type() == CONSTRUCT; } is_standard()195 virtual bool is_standard() const { return false; } 196 is_java_script()197 bool is_java_script() const { 198 Type type = this->type(); 199 return (type == JAVA_SCRIPT) || (type == OPTIMIZED); 200 } 201 202 // Accessors. sp()203 Address sp() const { return state_.sp; } fp()204 Address fp() const { return state_.fp; } caller_sp()205 Address caller_sp() const { return GetCallerStackPointer(); } 206 pc()207 Address pc() const { return *pc_address(); } set_pc(Address pc)208 void set_pc(Address pc) { *pc_address() = pc; } 209 210 virtual void SetCallerFp(Address caller_fp) = 0; 211 pc_address()212 Address* pc_address() const { return state_.pc_address; } 213 214 // Get the id of this stack frame. id()215 Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); } 216 217 // Checks if this frame includes any stack handlers. 218 bool HasHandler() const; 219 220 // Get the type of this frame. 221 virtual Type type() const = 0; 222 223 // Get the code associated with this frame. 224 // This method could be called during marking phase of GC. 225 virtual Code* unchecked_code() const = 0; 226 227 // Get the code associated with this frame. 228 inline Code* LookupCode() const; 229 230 // Get the code object that contains the given pc. 231 static inline Code* GetContainingCode(Isolate* isolate, Address pc); 232 233 // Get the code object containing the given pc and fill in the 234 // safepoint entry and the number of stack slots. The pc must be at 235 // a safepoint. 236 static Code* GetSafepointData(Isolate* isolate, 237 Address pc, 238 SafepointEntry* safepoint_entry, 239 unsigned* stack_slots); 240 241 virtual void Iterate(ObjectVisitor* v) const = 0; 242 static void IteratePc(ObjectVisitor* v, Address* pc_address, Code* holder); 243 244 // Sets a callback function for return-address rewriting profilers 245 // to resolve the location of a return address to the location of the 246 // profiler's stashed return address. 247 static void SetReturnAddressLocationResolver( 248 ReturnAddressLocationResolver resolver); 249 250 // Printing support. 251 enum PrintMode { OVERVIEW, DETAILS }; Print(StringStream * accumulator,PrintMode mode,int index)252 virtual void Print(StringStream* accumulator, 253 PrintMode mode, 254 int index) const { } 255 256 protected: 257 inline explicit StackFrame(StackFrameIterator* iterator); ~StackFrame()258 virtual ~StackFrame() { } 259 isolate()260 Isolate* isolate() const { return isolate_; } 261 262 // Compute the stack pointer for the calling frame. 263 virtual Address GetCallerStackPointer() const = 0; 264 265 // Printing support. 266 static void PrintIndex(StringStream* accumulator, 267 PrintMode mode, 268 int index); 269 270 // Get the top handler from the current stack iterator. 271 inline StackHandler* top_handler() const; 272 273 // Compute the stack frame type for the given state. 274 static Type ComputeType(Isolate* isolate, State* state); 275 276 private: 277 const StackFrameIterator* iterator_; 278 Isolate* isolate_; 279 State state_; 280 281 // Fill in the state of the calling frame. 282 virtual void ComputeCallerState(State* state) const = 0; 283 284 // Get the type and the state of the calling frame. 285 virtual Type GetCallerState(State* state) const; 286 287 static const intptr_t kIsolateTag = 1; 288 289 friend class StackFrameIterator; 290 friend class StackHandlerIterator; 291 friend class SafeStackFrameIterator; 292 293 private: 294 void operator=(const StackFrame& original); 295 }; 296 297 298 // Entry frames are used to enter JavaScript execution from C. 299 class EntryFrame: public StackFrame { 300 public: type()301 virtual Type type() const { return ENTRY; } 302 303 virtual Code* unchecked_code() const; 304 305 // Garbage collection support. 306 virtual void Iterate(ObjectVisitor* v) const; 307 cast(StackFrame * frame)308 static EntryFrame* cast(StackFrame* frame) { 309 ASSERT(frame->is_entry()); 310 return static_cast<EntryFrame*>(frame); 311 } 312 virtual void SetCallerFp(Address caller_fp); 313 314 protected: 315 inline explicit EntryFrame(StackFrameIterator* iterator); 316 317 // The caller stack pointer for entry frames is always zero. The 318 // real information about the caller frame is available through the 319 // link to the top exit frame. GetCallerStackPointer()320 virtual Address GetCallerStackPointer() const { return 0; } 321 322 private: 323 virtual void ComputeCallerState(State* state) const; 324 virtual Type GetCallerState(State* state) const; 325 326 friend class StackFrameIterator; 327 }; 328 329 330 class EntryConstructFrame: public EntryFrame { 331 public: type()332 virtual Type type() const { return ENTRY_CONSTRUCT; } 333 334 virtual Code* unchecked_code() const; 335 cast(StackFrame * frame)336 static EntryConstructFrame* cast(StackFrame* frame) { 337 ASSERT(frame->is_entry_construct()); 338 return static_cast<EntryConstructFrame*>(frame); 339 } 340 341 protected: 342 inline explicit EntryConstructFrame(StackFrameIterator* iterator); 343 344 private: 345 friend class StackFrameIterator; 346 }; 347 348 349 // Exit frames are used to exit JavaScript execution and go to C. 350 class ExitFrame: public StackFrame { 351 public: type()352 virtual Type type() const { return EXIT; } 353 354 virtual Code* unchecked_code() const; 355 356 Object*& code_slot() const; 357 358 // Garbage collection support. 359 virtual void Iterate(ObjectVisitor* v) const; 360 361 virtual void SetCallerFp(Address caller_fp); 362 cast(StackFrame * frame)363 static ExitFrame* cast(StackFrame* frame) { 364 ASSERT(frame->is_exit()); 365 return static_cast<ExitFrame*>(frame); 366 } 367 368 // Compute the state and type of an exit frame given a frame 369 // pointer. Used when constructing the first stack frame seen by an 370 // iterator and the frames following entry frames. 371 static Type GetStateForFramePointer(Address fp, State* state); 372 static Address ComputeStackPointer(Address fp); 373 static void FillState(Address fp, Address sp, State* state); 374 375 protected: 376 inline explicit ExitFrame(StackFrameIterator* iterator); 377 378 virtual Address GetCallerStackPointer() const; 379 380 private: 381 virtual void ComputeCallerState(State* state) const; 382 383 friend class StackFrameIterator; 384 }; 385 386 387 class StandardFrame: public StackFrame { 388 public: 389 // Testers. is_standard()390 virtual bool is_standard() const { return true; } 391 392 // Accessors. 393 inline Object* context() const; 394 395 // Access the expressions in the stack frame including locals. 396 inline Object* GetExpression(int index) const; 397 inline void SetExpression(int index, Object* value); 398 int ComputeExpressionsCount() const; 399 static Object* GetExpression(Address fp, int index); 400 401 virtual void SetCallerFp(Address caller_fp); 402 cast(StackFrame * frame)403 static StandardFrame* cast(StackFrame* frame) { 404 ASSERT(frame->is_standard()); 405 return static_cast<StandardFrame*>(frame); 406 } 407 408 protected: 409 inline explicit StandardFrame(StackFrameIterator* iterator); 410 411 virtual void ComputeCallerState(State* state) const; 412 413 // Accessors. 414 inline Address caller_fp() const; 415 inline Address caller_pc() const; 416 417 // Computes the address of the PC field in the standard frame given 418 // by the provided frame pointer. 419 static inline Address ComputePCAddress(Address fp); 420 421 // Iterate over expression stack including stack handlers, locals, 422 // and parts of the fixed part including context and code fields. 423 void IterateExpressions(ObjectVisitor* v) const; 424 425 // Returns the address of the n'th expression stack element. 426 Address GetExpressionAddress(int n) const; 427 static Address GetExpressionAddress(Address fp, int n); 428 429 // Determines if the n'th expression stack element is in a stack 430 // handler or not. Requires traversing all handlers in this frame. 431 bool IsExpressionInsideHandler(int n) const; 432 433 // Determines if the standard frame for the given frame pointer is 434 // an arguments adaptor frame. 435 static inline bool IsArgumentsAdaptorFrame(Address fp); 436 437 // Determines if the standard frame for the given frame pointer is a 438 // construct frame. 439 static inline bool IsConstructFrame(Address fp); 440 441 private: 442 friend class StackFrame; 443 friend class StackFrameIterator; 444 }; 445 446 447 class FrameSummary BASE_EMBEDDED { 448 public: FrameSummary(Object * receiver,JSFunction * function,Code * code,int offset,bool is_constructor)449 FrameSummary(Object* receiver, 450 JSFunction* function, 451 Code* code, 452 int offset, 453 bool is_constructor) 454 : receiver_(receiver), 455 function_(function), 456 code_(code), 457 offset_(offset), 458 is_constructor_(is_constructor) { } receiver()459 Handle<Object> receiver() { return receiver_; } function()460 Handle<JSFunction> function() { return function_; } code()461 Handle<Code> code() { return code_; } pc()462 Address pc() { return code_->address() + offset_; } offset()463 int offset() { return offset_; } is_constructor()464 bool is_constructor() { return is_constructor_; } 465 466 void Print(); 467 468 private: 469 Handle<Object> receiver_; 470 Handle<JSFunction> function_; 471 Handle<Code> code_; 472 int offset_; 473 bool is_constructor_; 474 }; 475 476 477 class JavaScriptFrame: public StandardFrame { 478 public: type()479 virtual Type type() const { return JAVA_SCRIPT; } 480 481 // Accessors. 482 inline Object* function() const; 483 inline Object* receiver() const; 484 inline void set_receiver(Object* value); 485 486 // Access the parameters. 487 inline Address GetParameterSlot(int index) const; 488 inline Object* GetParameter(int index) const; ComputeParametersCount()489 inline int ComputeParametersCount() const { 490 return GetNumberOfIncomingArguments(); 491 } 492 493 // Check if this frame is a constructor frame invoked through 'new'. 494 bool IsConstructor() const; 495 496 // Check if this frame has "adapted" arguments in the sense that the 497 // actual passed arguments are available in an arguments adaptor 498 // frame below it on the stack. 499 inline bool has_adapted_arguments() const; 500 int GetArgumentsLength() const; 501 502 // Garbage collection support. 503 virtual void Iterate(ObjectVisitor* v) const; 504 505 // Printing support. 506 virtual void Print(StringStream* accumulator, 507 PrintMode mode, 508 int index) const; 509 510 // Determine the code for the frame. 511 virtual Code* unchecked_code() const; 512 513 // Returns the levels of inlining for this frame. GetInlineCount()514 virtual int GetInlineCount() { return 1; } 515 516 // Return a list with JSFunctions of this frame. 517 virtual void GetFunctions(List<JSFunction*>* functions); 518 519 // Build a list with summaries for this frame including all inlined frames. 520 virtual void Summarize(List<FrameSummary>* frames); 521 cast(StackFrame * frame)522 static JavaScriptFrame* cast(StackFrame* frame) { 523 ASSERT(frame->is_java_script()); 524 return static_cast<JavaScriptFrame*>(frame); 525 } 526 527 static void PrintTop(FILE* file, bool print_args, bool print_line_number); 528 529 protected: 530 inline explicit JavaScriptFrame(StackFrameIterator* iterator); 531 532 virtual Address GetCallerStackPointer() const; 533 534 virtual int GetNumberOfIncomingArguments() const; 535 536 // Garbage collection support. Iterates over incoming arguments, 537 // receiver, and any callee-saved registers. 538 void IterateArguments(ObjectVisitor* v) const; 539 540 private: 541 inline Object* function_slot_object() const; 542 543 friend class StackFrameIterator; 544 friend class StackTracer; 545 }; 546 547 548 class OptimizedFrame : public JavaScriptFrame { 549 public: type()550 virtual Type type() const { return OPTIMIZED; } 551 552 // GC support. 553 virtual void Iterate(ObjectVisitor* v) const; 554 555 virtual int GetInlineCount(); 556 557 // Return a list with JSFunctions of this frame. 558 // The functions are ordered bottom-to-top (i.e. functions.last() 559 // is the top-most activation) 560 virtual void GetFunctions(List<JSFunction*>* functions); 561 562 virtual void Summarize(List<FrameSummary>* frames); 563 564 DeoptimizationInputData* GetDeoptimizationData(int* deopt_index); 565 566 protected: 567 inline explicit OptimizedFrame(StackFrameIterator* iterator); 568 569 private: 570 friend class StackFrameIterator; 571 }; 572 573 574 // Arguments adaptor frames are automatically inserted below 575 // JavaScript frames when the actual number of parameters does not 576 // match the formal number of parameters. 577 class ArgumentsAdaptorFrame: public JavaScriptFrame { 578 public: type()579 virtual Type type() const { return ARGUMENTS_ADAPTOR; } 580 581 // Determine the code for the frame. 582 virtual Code* unchecked_code() const; 583 cast(StackFrame * frame)584 static ArgumentsAdaptorFrame* cast(StackFrame* frame) { 585 ASSERT(frame->is_arguments_adaptor()); 586 return static_cast<ArgumentsAdaptorFrame*>(frame); 587 } 588 589 // Printing support. 590 virtual void Print(StringStream* accumulator, 591 PrintMode mode, 592 int index) const; 593 594 protected: 595 inline explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator); 596 597 virtual int GetNumberOfIncomingArguments() const; 598 599 virtual Address GetCallerStackPointer() const; 600 601 private: 602 friend class StackFrameIterator; 603 }; 604 605 606 class InternalFrame: public StandardFrame { 607 public: type()608 virtual Type type() const { return INTERNAL; } 609 610 // Garbage collection support. 611 virtual void Iterate(ObjectVisitor* v) const; 612 613 // Determine the code for the frame. 614 virtual Code* unchecked_code() const; 615 cast(StackFrame * frame)616 static InternalFrame* cast(StackFrame* frame) { 617 ASSERT(frame->is_internal()); 618 return static_cast<InternalFrame*>(frame); 619 } 620 621 protected: 622 inline explicit InternalFrame(StackFrameIterator* iterator); 623 624 virtual Address GetCallerStackPointer() const; 625 626 private: 627 friend class StackFrameIterator; 628 }; 629 630 631 // Construct frames are special trampoline frames introduced to handle 632 // function invocations through 'new'. 633 class ConstructFrame: public InternalFrame { 634 public: type()635 virtual Type type() const { return CONSTRUCT; } 636 cast(StackFrame * frame)637 static ConstructFrame* cast(StackFrame* frame) { 638 ASSERT(frame->is_construct()); 639 return static_cast<ConstructFrame*>(frame); 640 } 641 642 protected: 643 inline explicit ConstructFrame(StackFrameIterator* iterator); 644 645 private: 646 friend class StackFrameIterator; 647 }; 648 649 650 class StackFrameIterator BASE_EMBEDDED { 651 public: 652 // An iterator that iterates over the current thread's stack, 653 // and uses current isolate. 654 StackFrameIterator(); 655 656 // An iterator that iterates over the isolate's current thread's stack, 657 explicit StackFrameIterator(Isolate* isolate); 658 659 // An iterator that iterates over a given thread's stack. 660 StackFrameIterator(Isolate* isolate, ThreadLocalTop* t); 661 662 // An iterator that can start from a given FP address. 663 // If use_top, then work as usual, if fp isn't NULL, use it, 664 // otherwise, do nothing. 665 StackFrameIterator(Isolate* isolate, bool use_top, Address fp, Address sp); 666 frame()667 StackFrame* frame() const { 668 ASSERT(!done()); 669 return frame_; 670 } 671 isolate()672 Isolate* isolate() const { return isolate_; } 673 done()674 bool done() const { return frame_ == NULL; } Advance()675 void Advance() { (this->*advance_)(); } 676 677 // Go back to the first frame. 678 void Reset(); 679 680 private: 681 Isolate* isolate_; 682 #define DECLARE_SINGLETON(ignore, type) type type##_; 683 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON) 684 #undef DECLARE_SINGLETON 685 StackFrame* frame_; 686 StackHandler* handler_; 687 ThreadLocalTop* thread_; 688 Address fp_; 689 Address sp_; 690 void (StackFrameIterator::*advance_)(); 691 handler()692 StackHandler* handler() const { 693 ASSERT(!done()); 694 return handler_; 695 } 696 697 // Get the type-specific frame singleton in a given state. 698 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state); 699 // A helper function, can return a NULL pointer. 700 StackFrame* SingletonFor(StackFrame::Type type); 701 702 void AdvanceWithHandler(); 703 void AdvanceWithoutHandler(); 704 705 friend class StackFrame; 706 friend class SafeStackFrameIterator; 707 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator); 708 }; 709 710 711 // Iterator that supports iterating through all JavaScript frames. 712 template<typename Iterator> 713 class JavaScriptFrameIteratorTemp BASE_EMBEDDED { 714 public: JavaScriptFrameIteratorTemp()715 JavaScriptFrameIteratorTemp() { if (!done()) Advance(); } 716 717 inline explicit JavaScriptFrameIteratorTemp(Isolate* isolate); 718 719 inline JavaScriptFrameIteratorTemp(Isolate* isolate, ThreadLocalTop* top); 720 721 // Skip frames until the frame with the given id is reached. JavaScriptFrameIteratorTemp(StackFrame::Id id)722 explicit JavaScriptFrameIteratorTemp(StackFrame::Id id) { AdvanceToId(id); } 723 724 inline JavaScriptFrameIteratorTemp(Isolate* isolate, StackFrame::Id id); 725 JavaScriptFrameIteratorTemp(Address fp,Address sp,Address low_bound,Address high_bound)726 JavaScriptFrameIteratorTemp(Address fp, 727 Address sp, 728 Address low_bound, 729 Address high_bound) : 730 iterator_(fp, sp, low_bound, high_bound) { 731 if (!done()) Advance(); 732 } 733 JavaScriptFrameIteratorTemp(Isolate * isolate,Address fp,Address sp,Address low_bound,Address high_bound)734 JavaScriptFrameIteratorTemp(Isolate* isolate, 735 Address fp, 736 Address sp, 737 Address low_bound, 738 Address high_bound) : 739 iterator_(isolate, fp, sp, low_bound, high_bound) { 740 if (!done()) Advance(); 741 } 742 743 inline JavaScriptFrame* frame() const; 744 done()745 bool done() const { return iterator_.done(); } 746 void Advance(); 747 748 // Advance to the frame holding the arguments for the current 749 // frame. This only affects the current frame if it has adapted 750 // arguments. 751 void AdvanceToArgumentsFrame(); 752 753 // Go back to the first frame. 754 void Reset(); 755 756 private: 757 inline void AdvanceToId(StackFrame::Id id); 758 759 Iterator iterator_; 760 }; 761 762 763 typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator; 764 765 766 // NOTE: The stack trace frame iterator is an iterator that only 767 // traverse proper JavaScript frames; that is JavaScript frames that 768 // have proper JavaScript functions. This excludes the problematic 769 // functions in runtime.js. 770 class StackTraceFrameIterator: public JavaScriptFrameIterator { 771 public: 772 StackTraceFrameIterator(); 773 explicit StackTraceFrameIterator(Isolate* isolate); 774 void Advance(); 775 776 private: 777 bool IsValidFrame(); 778 }; 779 780 781 class SafeStackFrameIterator BASE_EMBEDDED { 782 public: 783 SafeStackFrameIterator(Isolate* isolate, 784 Address fp, Address sp, 785 Address low_bound, Address high_bound); 786 frame()787 StackFrame* frame() const { 788 ASSERT(is_working_iterator_); 789 return iterator_.frame(); 790 } 791 done()792 bool done() const { return iteration_done_ ? true : iterator_.done(); } 793 794 void Advance(); 795 void Reset(); 796 797 static bool is_active(Isolate* isolate); 798 IsWithinBounds(Address low_bound,Address high_bound,Address addr)799 static bool IsWithinBounds( 800 Address low_bound, Address high_bound, Address addr) { 801 return low_bound <= addr && addr <= high_bound; 802 } 803 804 private: 805 class StackAddressValidator { 806 public: StackAddressValidator(Address low_bound,Address high_bound)807 StackAddressValidator(Address low_bound, Address high_bound) 808 : low_bound_(low_bound), high_bound_(high_bound) { } IsValid(Address addr)809 bool IsValid(Address addr) const { 810 return IsWithinBounds(low_bound_, high_bound_, addr); 811 } 812 private: 813 Address low_bound_; 814 Address high_bound_; 815 }; 816 817 class ExitFrameValidator { 818 public: ExitFrameValidator(const StackAddressValidator & validator)819 explicit ExitFrameValidator(const StackAddressValidator& validator) 820 : validator_(validator) { } ExitFrameValidator(Address low_bound,Address high_bound)821 ExitFrameValidator(Address low_bound, Address high_bound) 822 : validator_(low_bound, high_bound) { } 823 bool IsValidFP(Address fp); 824 private: 825 StackAddressValidator validator_; 826 }; 827 IsValidStackAddress(Address addr)828 bool IsValidStackAddress(Address addr) const { 829 return stack_validator_.IsValid(addr); 830 } 831 bool CanIterateHandles(StackFrame* frame, StackHandler* handler); 832 bool IsValidFrame(StackFrame* frame) const; 833 bool IsValidCaller(StackFrame* frame); 834 static bool IsValidTop(Isolate* isolate, 835 Address low_bound, Address high_bound); 836 837 // This is a nasty hack to make sure the active count is incremented 838 // before the constructor for the embedded iterator is invoked. This 839 // is needed because the constructor will start looking at frames 840 // right away and we need to make sure it doesn't start inspecting 841 // heap objects. 842 class ActiveCountMaintainer BASE_EMBEDDED { 843 public: 844 explicit ActiveCountMaintainer(Isolate* isolate); 845 ~ActiveCountMaintainer(); 846 private: 847 Isolate* isolate_; 848 }; 849 850 ActiveCountMaintainer maintainer_; 851 StackAddressValidator stack_validator_; 852 const bool is_valid_top_; 853 const bool is_valid_fp_; 854 const bool is_working_iterator_; 855 bool iteration_done_; 856 StackFrameIterator iterator_; 857 }; 858 859 860 typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator> 861 SafeJavaScriptFrameIterator; 862 863 864 class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator { 865 public: 866 explicit SafeStackTraceFrameIterator(Isolate* isolate, 867 Address fp, Address sp, 868 Address low_bound, Address high_bound); 869 void Advance(); 870 }; 871 872 873 class StackFrameLocator BASE_EMBEDDED { 874 public: 875 // Find the nth JavaScript frame on the stack. The caller must 876 // guarantee that such a frame exists. 877 JavaScriptFrame* FindJavaScriptFrame(int n); 878 879 private: 880 StackFrameIterator iterator_; 881 }; 882 883 884 // Reads all frames on the current stack and copies them into the current 885 // zone memory. 886 Vector<StackFrame*> CreateStackMap(); 887 888 } } // namespace v8::internal 889 890 #endif // V8_FRAMES_H_ 891