| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 // Return the code of the n-th saved register available to JavaScript. | 39 // Return the code of the n-th saved register available to JavaScript. |
| 40 int JSCallerSavedCode(int n); | 40 int JSCallerSavedCode(int n); |
| 41 | 41 |
| 42 | 42 |
| 43 // Forward declarations. | 43 // Forward declarations. |
| 44 class StackFrameIterator; | 44 class StackFrameIterator; |
| 45 class Top; | 45 class Top; |
| 46 class ThreadLocalTop; | 46 class ThreadLocalTop; |
| 47 | 47 |
| 48 | 48 |
| 49 class PcToCodeCache : AllStatic { |
| 50 public: |
| 51 struct PcToCodeCacheEntry { |
| 52 Address pc; |
| 53 Code* code; |
| 54 }; |
| 55 |
| 56 static PcToCodeCacheEntry* cache(int index) { |
| 57 return &cache_[index]; |
| 58 } |
| 59 |
| 60 static Code* GcSafeFindCodeForPc(Address pc); |
| 61 static Code* GcSafeCastToCode(HeapObject* object, Address pc); |
| 62 |
| 63 static void FlushPcToCodeCache() { |
| 64 memset(&cache_[0], 0, sizeof(cache_)); |
| 65 } |
| 66 |
| 67 static PcToCodeCacheEntry* GetCacheEntry(Address pc); |
| 68 |
| 69 private: |
| 70 static const int kPcToCodeCacheSize = 256; |
| 71 static PcToCodeCacheEntry cache_[kPcToCodeCacheSize]; |
| 72 }; |
| 73 |
| 74 |
| 49 class StackHandler BASE_EMBEDDED { | 75 class StackHandler BASE_EMBEDDED { |
| 50 public: | 76 public: |
| 51 enum State { | 77 enum State { |
| 52 ENTRY, | 78 ENTRY, |
| 53 TRY_CATCH, | 79 TRY_CATCH, |
| 54 TRY_FINALLY | 80 TRY_FINALLY |
| 55 }; | 81 }; |
| 56 | 82 |
| 57 // Get the address of this stack handler. | 83 // Get the address of this stack handler. |
| 58 inline Address address() const; | 84 inline Address address() const; |
| 59 | 85 |
| 60 // Get the next stack handler in the chain. | 86 // Get the next stack handler in the chain. |
| 61 inline StackHandler* next() const; | 87 inline StackHandler* next() const; |
| 62 | 88 |
| 63 // Tells whether the given address is inside this handler. | 89 // Tells whether the given address is inside this handler. |
| 64 inline bool includes(Address address) const; | 90 inline bool includes(Address address) const; |
| 65 | 91 |
| 66 // Garbage collection support. | 92 // Garbage collection support. |
| 67 inline void Iterate(ObjectVisitor* v) const; | 93 inline void Iterate(ObjectVisitor* v, Code* holder) const; |
| 68 | 94 |
| 69 // Conversion support. | 95 // Conversion support. |
| 70 static inline StackHandler* FromAddress(Address address); | 96 static inline StackHandler* FromAddress(Address address); |
| 71 | 97 |
| 72 // Testers | 98 // Testers |
| 73 bool is_entry() { return state() == ENTRY; } | 99 bool is_entry() { return state() == ENTRY; } |
| 74 bool is_try_catch() { return state() == TRY_CATCH; } | 100 bool is_try_catch() { return state() == TRY_CATCH; } |
| 75 bool is_try_finally() { return state() == TRY_FINALLY; } | 101 bool is_try_finally() { return state() == TRY_FINALLY; } |
| 76 | 102 |
| 77 // Garbage collection support. | |
| 78 void Cook(Code* code); | |
| 79 void Uncook(Code* code); | |
| 80 | |
| 81 private: | 103 private: |
| 82 // Accessors. | 104 // Accessors. |
| 83 inline State state() const; | 105 inline State state() const; |
| 84 | 106 |
| 85 inline Address pc() const; | 107 inline Address* pc_address() const; |
| 86 inline void set_pc(Address value); | |
| 87 | 108 |
| 88 DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler); | 109 DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler); |
| 89 }; | 110 }; |
| 90 | 111 |
| 91 | 112 |
| 92 #define STACK_FRAME_TYPE_LIST(V) \ | 113 #define STACK_FRAME_TYPE_LIST(V) \ |
| 93 V(ENTRY, EntryFrame) \ | 114 V(ENTRY, EntryFrame) \ |
| 94 V(ENTRY_CONSTRUCT, EntryConstructFrame) \ | 115 V(ENTRY_CONSTRUCT, EntryConstructFrame) \ |
| 95 V(EXIT, ExitFrame) \ | 116 V(EXIT, ExitFrame) \ |
| 96 V(JAVA_SCRIPT, JavaScriptFrame) \ | 117 V(JAVA_SCRIPT, JavaScriptFrame) \ |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 bool HasHandler() const; | 176 bool HasHandler() const; |
| 156 | 177 |
| 157 // Get the type of this frame. | 178 // Get the type of this frame. |
| 158 virtual Type type() const = 0; | 179 virtual Type type() const = 0; |
| 159 | 180 |
| 160 // Get the code associated with this frame. | 181 // Get the code associated with this frame. |
| 161 // This method could be called during marking phase of GC. | 182 // This method could be called during marking phase of GC. |
| 162 virtual Code* unchecked_code() const = 0; | 183 virtual Code* unchecked_code() const = 0; |
| 163 | 184 |
| 164 // Get the code associated with this frame. | 185 // Get the code associated with this frame. |
| 165 inline Code* code() const { | 186 Code* code() const { return GetContainingCode(pc()); } |
| 166 return Code::cast(unchecked_code()); | 187 |
| 188 // Get the code object that contains the given pc. |
| 189 Code* GetContainingCode(Address pc) const { |
| 190 return PcToCodeCache::GetCacheEntry(pc)->code; |
| 167 } | 191 } |
| 168 | 192 |
| 169 // Garbage collection support. | 193 virtual void Iterate(ObjectVisitor* v) const = 0; |
| 170 static void CookFramesForThread(ThreadLocalTop* thread); | 194 static void IteratePc(ObjectVisitor* v, Address* pc_address, Code* holder); |
| 171 static void UncookFramesForThread(ThreadLocalTop* thread); | |
| 172 | 195 |
| 173 virtual void Iterate(ObjectVisitor* v) const { } | |
| 174 | 196 |
| 175 // Printing support. | 197 // Printing support. |
| 176 enum PrintMode { OVERVIEW, DETAILS }; | 198 enum PrintMode { OVERVIEW, DETAILS }; |
| 177 virtual void Print(StringStream* accumulator, | 199 virtual void Print(StringStream* accumulator, |
| 178 PrintMode mode, | 200 PrintMode mode, |
| 179 int index) const { } | 201 int index) const { } |
| 180 | 202 |
| 181 protected: | 203 protected: |
| 182 struct State { | 204 struct State { |
| 183 Address sp; | 205 Address sp; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 205 private: | 227 private: |
| 206 const StackFrameIterator* iterator_; | 228 const StackFrameIterator* iterator_; |
| 207 State state_; | 229 State state_; |
| 208 | 230 |
| 209 // Fill in the state of the calling frame. | 231 // Fill in the state of the calling frame. |
| 210 virtual void ComputeCallerState(State* state) const = 0; | 232 virtual void ComputeCallerState(State* state) const = 0; |
| 211 | 233 |
| 212 // Get the type and the state of the calling frame. | 234 // Get the type and the state of the calling frame. |
| 213 virtual Type GetCallerState(State* state) const; | 235 virtual Type GetCallerState(State* state) const; |
| 214 | 236 |
| 215 // Cooking/uncooking support. | |
| 216 void Cook(); | |
| 217 void Uncook(); | |
| 218 | |
| 219 friend class StackFrameIterator; | 237 friend class StackFrameIterator; |
| 220 friend class StackHandlerIterator; | 238 friend class StackHandlerIterator; |
| 221 friend class SafeStackFrameIterator; | 239 friend class SafeStackFrameIterator; |
| 222 | 240 |
| 223 private: | 241 private: |
| 224 void operator=(const StackFrame& original); | 242 void operator=(const StackFrame& original); |
| 225 }; | 243 }; |
| 226 | 244 |
| 227 | 245 |
| 228 // Entry frames are used to enter JavaScript execution from C. | 246 // Entry frames are used to enter JavaScript execution from C. |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 410 // Determine the code for the frame. | 428 // Determine the code for the frame. |
| 411 virtual Code* unchecked_code() const; | 429 virtual Code* unchecked_code() const; |
| 412 | 430 |
| 413 static JavaScriptFrame* cast(StackFrame* frame) { | 431 static JavaScriptFrame* cast(StackFrame* frame) { |
| 414 ASSERT(frame->is_java_script()); | 432 ASSERT(frame->is_java_script()); |
| 415 return static_cast<JavaScriptFrame*>(frame); | 433 return static_cast<JavaScriptFrame*>(frame); |
| 416 } | 434 } |
| 417 | 435 |
| 418 protected: | 436 protected: |
| 419 explicit JavaScriptFrame(StackFrameIterator* iterator) | 437 explicit JavaScriptFrame(StackFrameIterator* iterator) |
| 420 : StandardFrame(iterator), disable_heap_access_(false) { } | 438 : StandardFrame(iterator) { } |
| 421 | 439 |
| 422 virtual Address GetCallerStackPointer() const; | 440 virtual Address GetCallerStackPointer() const; |
| 423 | 441 |
| 424 // When this mode is enabled it is not allowed to access heap objects. | |
| 425 // This is a special mode used when gathering stack samples in profiler. | |
| 426 // A shortcoming is that caller's SP value will be calculated incorrectly | |
| 427 // (see GetCallerStackPointer implementation), but it is not used for stack | |
| 428 // sampling. | |
| 429 void DisableHeapAccess() { disable_heap_access_ = true; } | |
| 430 | |
| 431 private: | 442 private: |
| 432 bool disable_heap_access_; | |
| 433 inline Object* function_slot_object() const; | 443 inline Object* function_slot_object() const; |
| 434 | 444 |
| 435 friend class StackFrameIterator; | 445 friend class StackFrameIterator; |
| 436 }; | 446 }; |
| 437 | 447 |
| 438 | 448 |
| 439 // Arguments adaptor frames are automatically inserted below | 449 // Arguments adaptor frames are automatically inserted below |
| 440 // JavaScript frames when the actual number of parameters does not | 450 // JavaScript frames when the actual number of parameters does not |
| 441 // match the formal number of parameters. | 451 // match the formal number of parameters. |
| 442 class ArgumentsAdaptorFrame: public JavaScriptFrame { | 452 class ArgumentsAdaptorFrame: public JavaScriptFrame { |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 629 StackFrame* frame() const { | 639 StackFrame* frame() const { |
| 630 ASSERT(is_working_iterator_); | 640 ASSERT(is_working_iterator_); |
| 631 return iterator_.frame(); | 641 return iterator_.frame(); |
| 632 } | 642 } |
| 633 | 643 |
| 634 bool done() const { return iteration_done_ ? true : iterator_.done(); } | 644 bool done() const { return iteration_done_ ? true : iterator_.done(); } |
| 635 | 645 |
| 636 void Advance(); | 646 void Advance(); |
| 637 void Reset(); | 647 void Reset(); |
| 638 | 648 |
| 649 static bool is_active() { return active_count_ > 0; } |
| 650 |
| 639 static bool IsWithinBounds( | 651 static bool IsWithinBounds( |
| 640 Address low_bound, Address high_bound, Address addr) { | 652 Address low_bound, Address high_bound, Address addr) { |
| 641 return low_bound <= addr && addr <= high_bound; | 653 return low_bound <= addr && addr <= high_bound; |
| 642 } | 654 } |
| 643 | 655 |
| 644 private: | 656 private: |
| 645 bool IsValidStackAddress(Address addr) const { | 657 bool IsValidStackAddress(Address addr) const { |
| 646 return IsWithinBounds(low_bound_, high_bound_, addr); | 658 return IsWithinBounds(low_bound_, high_bound_, addr); |
| 647 } | 659 } |
| 648 bool CanIterateHandles(StackFrame* frame, StackHandler* handler); | 660 bool CanIterateHandles(StackFrame* frame, StackHandler* handler); |
| 649 bool IsValidFrame(StackFrame* frame) const; | 661 bool IsValidFrame(StackFrame* frame) const; |
| 650 bool IsValidCaller(StackFrame* frame); | 662 bool IsValidCaller(StackFrame* frame); |
| 651 | 663 |
| 664 // This is a nasty hack to make sure the active count is incremented |
| 665 // before the constructor for the embedded iterator is invoked. This |
| 666 // is needed because the constructor will start looking at frames |
| 667 // right away and we need to make sure it doesn't start inspecting |
| 668 // heap objects. |
| 669 class ActiveCountMaintainer BASE_EMBEDDED { |
| 670 public: |
| 671 ActiveCountMaintainer() { active_count_++; } |
| 672 ~ActiveCountMaintainer() { active_count_--; } |
| 673 }; |
| 674 |
| 675 ActiveCountMaintainer maintainer_; |
| 676 static int active_count_; |
| 652 Address low_bound_; | 677 Address low_bound_; |
| 653 Address high_bound_; | 678 Address high_bound_; |
| 654 const bool is_valid_top_; | 679 const bool is_valid_top_; |
| 655 const bool is_valid_fp_; | 680 const bool is_valid_fp_; |
| 656 const bool is_working_iterator_; | 681 const bool is_working_iterator_; |
| 657 bool iteration_done_; | 682 bool iteration_done_; |
| 658 StackFrameIterator iterator_; | 683 StackFrameIterator iterator_; |
| 659 }; | 684 }; |
| 660 | 685 |
| 661 | 686 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 684 }; | 709 }; |
| 685 | 710 |
| 686 | 711 |
| 687 // Reads all frames on the current stack and copies them into the current | 712 // Reads all frames on the current stack and copies them into the current |
| 688 // zone memory. | 713 // zone memory. |
| 689 Vector<StackFrame*> CreateStackMap(); | 714 Vector<StackFrame*> CreateStackMap(); |
| 690 | 715 |
| 691 } } // namespace v8::internal | 716 } } // namespace v8::internal |
| 692 | 717 |
| 693 #endif // V8_FRAMES_H_ | 718 #endif // V8_FRAMES_H_ |
| OLD | NEW |