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 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 | 132 |
133 bool Profiler::paused_ = false; | 133 bool Profiler::paused_ = false; |
134 | 134 |
135 | 135 |
136 // | 136 // |
137 // Ticker used to provide ticks to the profiler and the sliding state | 137 // Ticker used to provide ticks to the profiler and the sliding state |
138 // window. | 138 // window. |
139 // | 139 // |
140 class Ticker: public Sampler { | 140 class Ticker: public Sampler { |
141 public: | 141 public: |
142 explicit Ticker(int interval): | 142 explicit Ticker(int interval, unsigned int low_stack_bound): |
143 Sampler(interval, FLAG_prof), window_(NULL), profiler_(NULL) {} | 143 Sampler(interval, FLAG_prof), window_(NULL), profiler_(NULL), |
| 144 low_stack_bound_(low_stack_bound) {} |
144 | 145 |
145 ~Ticker() { if (IsActive()) Stop(); } | 146 ~Ticker() { if (IsActive()) Stop(); } |
146 | 147 |
147 void Tick(TickSample* sample) { | 148 void Tick(TickSample* sample) { |
| 149 if (IsProfiling()) SampleStack(sample); |
148 if (profiler_) profiler_->Insert(sample); | 150 if (profiler_) profiler_->Insert(sample); |
149 if (window_) window_->AddState(sample->state); | 151 if (window_) window_->AddState(sample->state); |
150 } | 152 } |
151 | 153 |
152 void SetWindow(SlidingStateWindow* window) { | 154 void SetWindow(SlidingStateWindow* window) { |
153 window_ = window; | 155 window_ = window; |
154 if (!IsActive()) Start(); | 156 if (!IsActive()) Start(); |
155 } | 157 } |
156 | 158 |
157 void ClearWindow() { | 159 void ClearWindow() { |
158 window_ = NULL; | 160 window_ = NULL; |
159 if (!profiler_ && IsActive()) Stop(); | 161 if (!profiler_ && IsActive()) Stop(); |
160 } | 162 } |
161 | 163 |
162 void SetProfiler(Profiler* profiler) { | 164 void SetProfiler(Profiler* profiler) { |
163 profiler_ = profiler; | 165 profiler_ = profiler; |
164 if (!IsActive()) Start(); | 166 if (!IsActive()) Start(); |
165 } | 167 } |
166 | 168 |
167 void ClearProfiler() { | 169 void ClearProfiler() { |
168 profiler_ = NULL; | 170 profiler_ = NULL; |
169 if (!window_ && IsActive()) Stop(); | 171 if (!window_ && IsActive()) Stop(); |
170 } | 172 } |
171 | 173 |
172 private: | 174 private: |
| 175 void SampleStack(TickSample* sample) { |
| 176 // Assuming that stack grows from lower addresses |
| 177 if (sample->sp < sample->fp && sample->fp < low_stack_bound_) { |
| 178 sample->InitStack(1); |
| 179 sample->stack[0] = Memory::Address_at( |
| 180 (Address)(sample->fp + StandardFrameConstants::kCallerPCOffset)); |
| 181 } else { |
| 182 // FP seems to be in some intermediate state, better discard this sample |
| 183 sample->InitStack(0); |
| 184 } |
| 185 } |
| 186 |
173 SlidingStateWindow* window_; | 187 SlidingStateWindow* window_; |
174 Profiler* profiler_; | 188 Profiler* profiler_; |
| 189 unsigned int low_stack_bound_; |
175 }; | 190 }; |
176 | 191 |
177 | 192 |
178 // | 193 // |
179 // SlidingStateWindow implementation. | 194 // SlidingStateWindow implementation. |
180 // | 195 // |
181 SlidingStateWindow::SlidingStateWindow(): current_index_(0), is_full_(false) { | 196 SlidingStateWindow::SlidingStateWindow(): current_index_(0), is_full_(false) { |
182 for (int i = 0; i < kBufferSize; i++) { | 197 for (int i = 0; i < kBufferSize; i++) { |
183 buffer_[i] = static_cast<byte>(OTHER); | 198 buffer_[i] = static_cast<byte>(OTHER); |
184 } | 199 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 | 247 |
233 void Profiler::Disengage() { | 248 void Profiler::Disengage() { |
234 // Stop receiving ticks. | 249 // Stop receiving ticks. |
235 Logger::ticker_->ClearProfiler(); | 250 Logger::ticker_->ClearProfiler(); |
236 | 251 |
237 // Terminate the worker thread by setting running_ to false, | 252 // Terminate the worker thread by setting running_ to false, |
238 // inserting a fake element in the queue and then wait for | 253 // inserting a fake element in the queue and then wait for |
239 // the thread to terminate. | 254 // the thread to terminate. |
240 running_ = false; | 255 running_ = false; |
241 TickSample sample; | 256 TickSample sample; |
242 sample.pc = 0; | |
243 sample.sp = 0; | |
244 sample.state = OTHER; | |
245 Insert(&sample); | 257 Insert(&sample); |
246 Join(); | 258 Join(); |
247 | 259 |
248 LOG(UncheckedStringEvent("profiler", "end")); | 260 LOG(UncheckedStringEvent("profiler", "end")); |
249 } | 261 } |
250 | 262 |
251 | 263 |
252 void Profiler::Run() { | 264 void Profiler::Run() { |
253 TickSample sample; | 265 TickSample sample; |
254 bool overflow = Logger::profiler_->Remove(&sample); | 266 bool overflow = Logger::profiler_->Remove(&sample); |
(...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
893 | 905 |
894 #ifdef ENABLE_LOGGING_AND_PROFILING | 906 #ifdef ENABLE_LOGGING_AND_PROFILING |
895 void Logger::TickEvent(TickSample* sample, bool overflow) { | 907 void Logger::TickEvent(TickSample* sample, bool overflow) { |
896 if (logfile_ == NULL || !FLAG_prof) return; | 908 if (logfile_ == NULL || !FLAG_prof) return; |
897 LogMessageBuilder msg; | 909 LogMessageBuilder msg; |
898 msg.Append("tick,0x%x,0x%x,%d", sample->pc, sample->sp, | 910 msg.Append("tick,0x%x,0x%x,%d", sample->pc, sample->sp, |
899 static_cast<int>(sample->state)); | 911 static_cast<int>(sample->state)); |
900 if (overflow) { | 912 if (overflow) { |
901 msg.Append(",overflow"); | 913 msg.Append(",overflow"); |
902 } | 914 } |
| 915 if (*(sample->stack)) { |
| 916 for (size_t i = 0; sample->stack[i]; ++i) { |
| 917 msg.Append(",0x%x", reinterpret_cast<unsigned int>(sample->stack[i])); |
| 918 } |
| 919 } |
903 msg.Append('\n'); | 920 msg.Append('\n'); |
904 msg.WriteToLogFile(); | 921 msg.WriteToLogFile(); |
905 } | 922 } |
906 | 923 |
907 | 924 |
908 bool Logger::IsProfilerPaused() { | 925 bool Logger::IsProfilerPaused() { |
909 return profiler_->paused(); | 926 return profiler_->paused(); |
910 } | 927 } |
911 | 928 |
912 | 929 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
983 logfile_ = OS::FOpen(*expanded, "w"); | 1000 logfile_ = OS::FOpen(*expanded, "w"); |
984 } else { | 1001 } else { |
985 logfile_ = OS::FOpen(FLAG_logfile, "w"); | 1002 logfile_ = OS::FOpen(FLAG_logfile, "w"); |
986 } | 1003 } |
987 message_buffer_ = NewArray<char>(kMessageBufferSize); | 1004 message_buffer_ = NewArray<char>(kMessageBufferSize); |
988 mutex_ = OS::CreateMutex(); | 1005 mutex_ = OS::CreateMutex(); |
989 } | 1006 } |
990 | 1007 |
991 current_state_ = new VMState(OTHER); | 1008 current_state_ = new VMState(OTHER); |
992 | 1009 |
993 ticker_ = new Ticker(10); | 1010 // as log is initialized early with V8, we can assume that JS execution |
| 1011 // frames can never reach this point on stack |
| 1012 int stack_var; |
| 1013 ticker_ = new Ticker(10, reinterpret_cast<unsigned int>(&stack_var)); |
994 | 1014 |
995 if (FLAG_sliding_state_window && sliding_state_window_ == NULL) { | 1015 if (FLAG_sliding_state_window && sliding_state_window_ == NULL) { |
996 sliding_state_window_ = new SlidingStateWindow(); | 1016 sliding_state_window_ = new SlidingStateWindow(); |
997 } | 1017 } |
998 | 1018 |
999 if (FLAG_prof) { | 1019 if (FLAG_prof) { |
1000 profiler_ = new Profiler(); | 1020 profiler_ = new Profiler(); |
1001 if (!FLAG_prof_auto) | 1021 if (!FLAG_prof_auto) |
1002 profiler_->pause(); | 1022 profiler_->pause(); |
1003 profiler_->Engage(); | 1023 profiler_->Engage(); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1098 if (FLAG_log_state_changes) { | 1118 if (FLAG_log_state_changes) { |
1099 LOG(UncheckedStringEvent("Leaving", StateToString(state_))); | 1119 LOG(UncheckedStringEvent("Leaving", StateToString(state_))); |
1100 if (previous_) { | 1120 if (previous_) { |
1101 LOG(UncheckedStringEvent("To", StateToString(previous_->state_))); | 1121 LOG(UncheckedStringEvent("To", StateToString(previous_->state_))); |
1102 } | 1122 } |
1103 } | 1123 } |
1104 } | 1124 } |
1105 #endif | 1125 #endif |
1106 | 1126 |
1107 } } // namespace v8::internal | 1127 } } // namespace v8::internal |
OLD | NEW |