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