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 |