OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/devtools/v8_sampling_profiler.h" | 5 #include "content/renderer/devtools/v8_sampling_profiler.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 #include <string.h> | 8 #include <string.h> |
9 | 9 |
10 #include "base/format_macros.h" | 10 #include "base/format_macros.h" |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 public: | 99 public: |
100 static const int kMaxFramesCountLog2 = 8; | 100 static const int kMaxFramesCountLog2 = 8; |
101 static const unsigned kMaxFramesCount = (1u << kMaxFramesCountLog2) - 1; | 101 static const unsigned kMaxFramesCount = (1u << kMaxFramesCountLog2) - 1; |
102 | 102 |
103 SampleRecord() {} | 103 SampleRecord() {} |
104 | 104 |
105 base::TimeTicks timestamp() const { return timestamp_; } | 105 base::TimeTicks timestamp() const { return timestamp_; } |
106 void Collect(v8::Isolate* isolate, | 106 void Collect(v8::Isolate* isolate, |
107 base::TimeTicks timestamp, | 107 base::TimeTicks timestamp, |
108 const v8::RegisterState& state); | 108 const v8::RegisterState& state); |
109 scoped_ptr<ConvertableToTraceFormat> ToTraceFormat() const; | 109 std::unique_ptr<ConvertableToTraceFormat> ToTraceFormat() const; |
110 | 110 |
111 private: | 111 private: |
112 base::TimeTicks timestamp_; | 112 base::TimeTicks timestamp_; |
113 unsigned vm_state_ : 4; | 113 unsigned vm_state_ : 4; |
114 unsigned frames_count_ : kMaxFramesCountLog2; | 114 unsigned frames_count_ : kMaxFramesCountLog2; |
115 const void* frames_[kMaxFramesCount]; | 115 const void* frames_[kMaxFramesCount]; |
116 | 116 |
117 DISALLOW_COPY_AND_ASSIGN(SampleRecord); | 117 DISALLOW_COPY_AND_ASSIGN(SampleRecord); |
118 }; | 118 }; |
119 | 119 |
120 void SampleRecord::Collect(v8::Isolate* isolate, | 120 void SampleRecord::Collect(v8::Isolate* isolate, |
121 base::TimeTicks timestamp, | 121 base::TimeTicks timestamp, |
122 const v8::RegisterState& state) { | 122 const v8::RegisterState& state) { |
123 v8::SampleInfo sample_info; | 123 v8::SampleInfo sample_info; |
124 isolate->GetStackSample(state, (void**)frames_, kMaxFramesCount, | 124 isolate->GetStackSample(state, (void**)frames_, kMaxFramesCount, |
125 &sample_info); | 125 &sample_info); |
126 timestamp_ = timestamp; | 126 timestamp_ = timestamp; |
127 frames_count_ = sample_info.frames_count; | 127 frames_count_ = sample_info.frames_count; |
128 vm_state_ = sample_info.vm_state; | 128 vm_state_ = sample_info.vm_state; |
129 } | 129 } |
130 | 130 |
131 scoped_ptr<ConvertableToTraceFormat> SampleRecord::ToTraceFormat() const { | 131 std::unique_ptr<ConvertableToTraceFormat> SampleRecord::ToTraceFormat() const { |
132 scoped_ptr<base::trace_event::TracedValue> data( | 132 std::unique_ptr<base::trace_event::TracedValue> data( |
133 new base::trace_event::TracedValue()); | 133 new base::trace_event::TracedValue()); |
134 const char* vm_state = nullptr; | 134 const char* vm_state = nullptr; |
135 switch (vm_state_) { | 135 switch (vm_state_) { |
136 case v8::StateTag::JS: | 136 case v8::StateTag::JS: |
137 vm_state = "js"; | 137 vm_state = "js"; |
138 break; | 138 break; |
139 case v8::StateTag::GC: | 139 case v8::StateTag::GC: |
140 vm_state = "gc"; | 140 vm_state = "gc"; |
141 break; | 141 break; |
142 case v8::StateTag::COMPILER: | 142 case v8::StateTag::COMPILER: |
(...skipping 20 matching lines...) Expand all Loading... |
163 return std::move(data); | 163 return std::move(data); |
164 } | 164 } |
165 | 165 |
166 } // namespace | 166 } // namespace |
167 | 167 |
168 // The class implements a sampler responsible for sampling a single thread. | 168 // The class implements a sampler responsible for sampling a single thread. |
169 class Sampler { | 169 class Sampler { |
170 public: | 170 public: |
171 ~Sampler(); | 171 ~Sampler(); |
172 | 172 |
173 static scoped_ptr<Sampler> CreateForCurrentThread(); | 173 static std::unique_ptr<Sampler> CreateForCurrentThread(); |
174 static Sampler* GetInstance() { return tls_instance_.Pointer()->Get(); } | 174 static Sampler* GetInstance() { return tls_instance_.Pointer()->Get(); } |
175 | 175 |
176 // These methods are called from the sampling thread. | 176 // These methods are called from the sampling thread. |
177 void Start(); | 177 void Start(); |
178 void Stop(); | 178 void Stop(); |
179 void Sample(); | 179 void Sample(); |
180 | 180 |
181 void DoSample(const v8::RegisterState& state); | 181 void DoSample(const v8::RegisterState& state); |
182 | 182 |
183 void SetEventsToCollectForTest(int code_added_events, int sample_events) { | 183 void SetEventsToCollectForTest(int code_added_events, int sample_events) { |
184 code_added_events_to_collect_for_test_ = code_added_events; | 184 code_added_events_to_collect_for_test_ = code_added_events; |
185 sample_events_to_collect_for_test_ = sample_events; | 185 sample_events_to_collect_for_test_ = sample_events; |
186 } | 186 } |
187 | 187 |
188 bool EventsCollectedForTest() const { | 188 bool EventsCollectedForTest() const { |
189 return base::subtle::NoBarrier_Load(&code_added_events_count_) >= | 189 return base::subtle::NoBarrier_Load(&code_added_events_count_) >= |
190 code_added_events_to_collect_for_test_ && | 190 code_added_events_to_collect_for_test_ && |
191 base::subtle::NoBarrier_Load(&samples_count_) >= | 191 base::subtle::NoBarrier_Load(&samples_count_) >= |
192 sample_events_to_collect_for_test_; | 192 sample_events_to_collect_for_test_; |
193 } | 193 } |
194 | 194 |
195 private: | 195 private: |
196 Sampler(); | 196 Sampler(); |
197 | 197 |
198 static void InstallJitCodeEventHandler(Isolate* isolate, void* data); | 198 static void InstallJitCodeEventHandler(Isolate* isolate, void* data); |
199 static void HandleJitCodeEvent(const v8::JitCodeEvent* event); | 199 static void HandleJitCodeEvent(const v8::JitCodeEvent* event); |
200 static scoped_ptr<ConvertableToTraceFormat> JitCodeEventToTraceFormat( | 200 static std::unique_ptr<ConvertableToTraceFormat> JitCodeEventToTraceFormat( |
201 const v8::JitCodeEvent* event); | 201 const v8::JitCodeEvent* event); |
202 | 202 |
203 void InjectPendingEvents(); | 203 void InjectPendingEvents(); |
204 | 204 |
205 static const unsigned kNumberOfSamples = 10; | 205 static const unsigned kNumberOfSamples = 10; |
206 typedef LockFreeCircularQueue<SampleRecord, kNumberOfSamples> SamplingQueue; | 206 typedef LockFreeCircularQueue<SampleRecord, kNumberOfSamples> SamplingQueue; |
207 | 207 |
208 PlatformData platform_data_; | 208 PlatformData platform_data_; |
209 Isolate* isolate_; | 209 Isolate* isolate_; |
210 scoped_ptr<SamplingQueue> samples_data_; | 210 std::unique_ptr<SamplingQueue> samples_data_; |
211 base::subtle::Atomic32 code_added_events_count_; | 211 base::subtle::Atomic32 code_added_events_count_; |
212 base::subtle::Atomic32 samples_count_; | 212 base::subtle::Atomic32 samples_count_; |
213 int code_added_events_to_collect_for_test_; | 213 int code_added_events_to_collect_for_test_; |
214 int sample_events_to_collect_for_test_; | 214 int sample_events_to_collect_for_test_; |
215 | 215 |
216 static base::LazyInstance<base::ThreadLocalPointer<Sampler>>::Leaky | 216 static base::LazyInstance<base::ThreadLocalPointer<Sampler>>::Leaky |
217 tls_instance_; | 217 tls_instance_; |
218 }; | 218 }; |
219 | 219 |
220 base::LazyInstance<base::ThreadLocalPointer<Sampler>>::Leaky | 220 base::LazyInstance<base::ThreadLocalPointer<Sampler>>::Leaky |
221 Sampler::tls_instance_ = LAZY_INSTANCE_INITIALIZER; | 221 Sampler::tls_instance_ = LAZY_INSTANCE_INITIALIZER; |
222 | 222 |
223 Sampler::Sampler() | 223 Sampler::Sampler() |
224 : isolate_(Isolate::GetCurrent()), | 224 : isolate_(Isolate::GetCurrent()), |
225 code_added_events_count_(0), | 225 code_added_events_count_(0), |
226 samples_count_(0), | 226 samples_count_(0), |
227 code_added_events_to_collect_for_test_(0), | 227 code_added_events_to_collect_for_test_(0), |
228 sample_events_to_collect_for_test_(0) { | 228 sample_events_to_collect_for_test_(0) { |
229 DCHECK(isolate_); | 229 DCHECK(isolate_); |
230 DCHECK(!GetInstance()); | 230 DCHECK(!GetInstance()); |
231 tls_instance_.Pointer()->Set(this); | 231 tls_instance_.Pointer()->Set(this); |
232 } | 232 } |
233 | 233 |
234 Sampler::~Sampler() { | 234 Sampler::~Sampler() { |
235 DCHECK(GetInstance()); | 235 DCHECK(GetInstance()); |
236 tls_instance_.Pointer()->Set(nullptr); | 236 tls_instance_.Pointer()->Set(nullptr); |
237 } | 237 } |
238 | 238 |
239 // static | 239 // static |
240 scoped_ptr<Sampler> Sampler::CreateForCurrentThread() { | 240 std::unique_ptr<Sampler> Sampler::CreateForCurrentThread() { |
241 return scoped_ptr<Sampler>(new Sampler()); | 241 return std::unique_ptr<Sampler>(new Sampler()); |
242 } | 242 } |
243 | 243 |
244 void Sampler::Start() { | 244 void Sampler::Start() { |
245 samples_data_.reset(new SamplingQueue()); | 245 samples_data_.reset(new SamplingQueue()); |
246 v8::JitCodeEventHandler handler = &HandleJitCodeEvent; | 246 v8::JitCodeEventHandler handler = &HandleJitCodeEvent; |
247 isolate_->RequestInterrupt(&InstallJitCodeEventHandler, | 247 isolate_->RequestInterrupt(&InstallJitCodeEventHandler, |
248 reinterpret_cast<void*>(handler)); | 248 reinterpret_cast<void*>(handler)); |
249 } | 249 } |
250 | 250 |
251 void Sampler::Stop() { | 251 void Sampler::Stop() { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 break; | 353 break; |
354 | 354 |
355 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: | 355 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: |
356 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: | 356 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: |
357 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: | 357 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: |
358 break; | 358 break; |
359 } | 359 } |
360 } | 360 } |
361 | 361 |
362 // static | 362 // static |
363 scoped_ptr<ConvertableToTraceFormat> Sampler::JitCodeEventToTraceFormat( | 363 std::unique_ptr<ConvertableToTraceFormat> Sampler::JitCodeEventToTraceFormat( |
364 const v8::JitCodeEvent* event) { | 364 const v8::JitCodeEvent* event) { |
365 switch (event->type) { | 365 switch (event->type) { |
366 case v8::JitCodeEvent::CODE_ADDED: { | 366 case v8::JitCodeEvent::CODE_ADDED: { |
367 scoped_ptr<base::trace_event::TracedValue> data( | 367 std::unique_ptr<base::trace_event::TracedValue> data( |
368 new base::trace_event::TracedValue()); | 368 new base::trace_event::TracedValue()); |
369 data->SetString("code_start", PtrToString(event->code_start)); | 369 data->SetString("code_start", PtrToString(event->code_start)); |
370 data->SetInteger("code_len", static_cast<unsigned>(event->code_len)); | 370 data->SetInteger("code_len", static_cast<unsigned>(event->code_len)); |
371 data->SetString("name", std::string(event->name.str, event->name.len)); | 371 data->SetString("name", std::string(event->name.str, event->name.len)); |
372 if (!event->script.IsEmpty()) { | 372 if (!event->script.IsEmpty()) { |
373 data->SetInteger("script_id", event->script->GetId()); | 373 data->SetInteger("script_id", event->script->GetId()); |
374 } | 374 } |
375 return std::move(data); | 375 return std::move(data); |
376 } | 376 } |
377 | 377 |
378 case v8::JitCodeEvent::CODE_MOVED: { | 378 case v8::JitCodeEvent::CODE_MOVED: { |
379 scoped_ptr<base::trace_event::TracedValue> data( | 379 std::unique_ptr<base::trace_event::TracedValue> data( |
380 new base::trace_event::TracedValue()); | 380 new base::trace_event::TracedValue()); |
381 data->SetString("code_start", PtrToString(event->code_start)); | 381 data->SetString("code_start", PtrToString(event->code_start)); |
382 data->SetInteger("code_len", static_cast<unsigned>(event->code_len)); | 382 data->SetInteger("code_len", static_cast<unsigned>(event->code_len)); |
383 data->SetString("new_code_start", PtrToString(event->new_code_start)); | 383 data->SetString("new_code_start", PtrToString(event->new_code_start)); |
384 return std::move(data); | 384 return std::move(data); |
385 } | 385 } |
386 | 386 |
387 case v8::JitCodeEvent::CODE_REMOVED: { | 387 case v8::JitCodeEvent::CODE_REMOVED: { |
388 scoped_ptr<base::trace_event::TracedValue> data( | 388 std::unique_ptr<base::trace_event::TracedValue> data( |
389 new base::trace_event::TracedValue()); | 389 new base::trace_event::TracedValue()); |
390 data->SetString("code_start", PtrToString(event->code_start)); | 390 data->SetString("code_start", PtrToString(event->code_start)); |
391 data->SetInteger("code_len", static_cast<unsigned>(event->code_len)); | 391 data->SetInteger("code_len", static_cast<unsigned>(event->code_len)); |
392 return std::move(data); | 392 return std::move(data); |
393 } | 393 } |
394 | 394 |
395 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: | 395 case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO: |
396 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: | 396 case v8::JitCodeEvent::CODE_START_LINE_INFO_RECORDING: |
397 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: | 397 case v8::JitCodeEvent::CODE_END_LINE_INFO_RECORDING: |
398 return nullptr; | 398 return nullptr; |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 render_thread_sampler_->SetEventsToCollectForTest(code_added_events, | 640 render_thread_sampler_->SetEventsToCollectForTest(code_added_events, |
641 sample_events); | 641 sample_events); |
642 waitable_event_for_testing_.reset(new base::WaitableEvent(false, false)); | 642 waitable_event_for_testing_.reset(new base::WaitableEvent(false, false)); |
643 } | 643 } |
644 | 644 |
645 void V8SamplingProfiler::WaitSamplingEventForTesting() { | 645 void V8SamplingProfiler::WaitSamplingEventForTesting() { |
646 waitable_event_for_testing_->Wait(); | 646 waitable_event_for_testing_->Wait(); |
647 } | 647 } |
648 | 648 |
649 } // namespace content | 649 } // namespace content |
OLD | NEW |