| 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 #if defined(OS_POSIX) | 7 #if defined(OS_POSIX) |
| 8 #include <signal.h> | 8 #include <signal.h> |
| 9 #define USE_SIGNALS | 9 #define USE_SIGNALS |
| 10 #endif | 10 #endif |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 static scoped_ptr<Sampler> CreateForCurrentThread(); | 110 static scoped_ptr<Sampler> CreateForCurrentThread(); |
| 111 static Sampler* GetInstance() { return tls_instance_.Pointer()->Get(); } | 111 static Sampler* GetInstance() { return tls_instance_.Pointer()->Get(); } |
| 112 | 112 |
| 113 // These methods are called from the sampling thread. | 113 // These methods are called from the sampling thread. |
| 114 void Start(); | 114 void Start(); |
| 115 void Stop(); | 115 void Stop(); |
| 116 void Sample(); | 116 void Sample(); |
| 117 | 117 |
| 118 void DoSample(const v8::RegisterState& state); | 118 void DoSample(const v8::RegisterState& state); |
| 119 | 119 |
| 120 void SetEventsToCollectForTest(int code_added_events, int sample_events) { |
| 121 code_added_events_to_collect_for_test_ = code_added_events; |
| 122 sample_events_to_collect_for_test_ = sample_events; |
| 123 } |
| 124 |
| 120 bool EventsCollectedForTest() const { | 125 bool EventsCollectedForTest() const { |
| 121 return base::subtle::NoBarrier_Load(&code_added_events_count_) != 0 || | 126 return base::subtle::NoBarrier_Load(&code_added_events_count_) >= |
| 122 base::subtle::NoBarrier_Load(&samples_count_) != 0; | 127 code_added_events_to_collect_for_test_ && |
| 128 base::subtle::NoBarrier_Load(&samples_count_) >= |
| 129 sample_events_to_collect_for_test_; |
| 123 } | 130 } |
| 124 | 131 |
| 125 private: | 132 private: |
| 126 Sampler(); | 133 Sampler(); |
| 127 | 134 |
| 128 static void InstallJitCodeEventHandler(Isolate* isolate, void* data); | 135 static void InstallJitCodeEventHandler(Isolate* isolate, void* data); |
| 129 static void HandleJitCodeEvent(const v8::JitCodeEvent* event); | 136 static void HandleJitCodeEvent(const v8::JitCodeEvent* event); |
| 130 static scoped_refptr<ConvertableToTraceFormat> JitCodeEventToTraceFormat( | 137 static scoped_refptr<ConvertableToTraceFormat> JitCodeEventToTraceFormat( |
| 131 const v8::JitCodeEvent* event); | 138 const v8::JitCodeEvent* event); |
| 132 static base::PlatformThreadHandle GetCurrentThreadHandle(); | 139 static base::PlatformThreadHandle GetCurrentThreadHandle(); |
| 133 | 140 |
| 134 void InjectPendingEvents(); | 141 void InjectPendingEvents(); |
| 135 | 142 |
| 136 static const unsigned kNumberOfSamples = 10; | 143 static const unsigned kNumberOfSamples = 10; |
| 137 typedef LockFreeCircularQueue<SampleRecord, kNumberOfSamples> SamplingQueue; | 144 typedef LockFreeCircularQueue<SampleRecord, kNumberOfSamples> SamplingQueue; |
| 138 | 145 |
| 139 base::PlatformThreadId thread_id_; | 146 base::PlatformThreadId thread_id_; |
| 140 base::PlatformThreadHandle thread_handle_; | 147 base::PlatformThreadHandle thread_handle_; |
| 141 Isolate* isolate_; | 148 Isolate* isolate_; |
| 142 scoped_ptr<SamplingQueue> samples_data_; | 149 scoped_ptr<SamplingQueue> samples_data_; |
| 143 base::subtle::Atomic32 code_added_events_count_; | 150 base::subtle::Atomic32 code_added_events_count_; |
| 144 base::subtle::Atomic32 samples_count_; | 151 base::subtle::Atomic32 samples_count_; |
| 152 int code_added_events_to_collect_for_test_; |
| 153 int sample_events_to_collect_for_test_; |
| 145 | 154 |
| 146 static base::LazyInstance<base::ThreadLocalPointer<Sampler>>::Leaky | 155 static base::LazyInstance<base::ThreadLocalPointer<Sampler>>::Leaky |
| 147 tls_instance_; | 156 tls_instance_; |
| 148 }; | 157 }; |
| 149 | 158 |
| 150 base::LazyInstance<base::ThreadLocalPointer<Sampler>>::Leaky | 159 base::LazyInstance<base::ThreadLocalPointer<Sampler>>::Leaky |
| 151 Sampler::tls_instance_ = LAZY_INSTANCE_INITIALIZER; | 160 Sampler::tls_instance_ = LAZY_INSTANCE_INITIALIZER; |
| 152 | 161 |
| 153 Sampler::Sampler() | 162 Sampler::Sampler() |
| 154 : thread_id_(base::PlatformThread::CurrentId()), | 163 : thread_id_(base::PlatformThread::CurrentId()), |
| 155 thread_handle_(Sampler::GetCurrentThreadHandle()), | 164 thread_handle_(Sampler::GetCurrentThreadHandle()), |
| 156 isolate_(Isolate::GetCurrent()), | 165 isolate_(Isolate::GetCurrent()), |
| 157 code_added_events_count_(0), | 166 code_added_events_count_(0), |
| 158 samples_count_(0) { | 167 samples_count_(0), |
| 168 code_added_events_to_collect_for_test_(0), |
| 169 sample_events_to_collect_for_test_(0) { |
| 159 DCHECK(isolate_); | 170 DCHECK(isolate_); |
| 160 DCHECK(!GetInstance()); | 171 DCHECK(!GetInstance()); |
| 161 tls_instance_.Pointer()->Set(this); | 172 tls_instance_.Pointer()->Set(this); |
| 162 } | 173 } |
| 163 | 174 |
| 164 Sampler::~Sampler() { | 175 Sampler::~Sampler() { |
| 165 DCHECK(GetInstance()); | 176 DCHECK(GetInstance()); |
| 166 tls_instance_.Pointer()->Set(nullptr); | 177 tls_instance_.Pointer()->Set(nullptr); |
| 167 } | 178 } |
| 168 | 179 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 | 217 |
| 207 void Sampler::DoSample(const v8::RegisterState& state) { | 218 void Sampler::DoSample(const v8::RegisterState& state) { |
| 208 // Called in the sampled thread signal handler. | 219 // Called in the sampled thread signal handler. |
| 209 // Because of that it is not allowed to do any memory allocation here. | 220 // Because of that it is not allowed to do any memory allocation here. |
| 210 base::TimeTicks timestamp = base::TimeTicks::NowFromSystemTraceTime(); | 221 base::TimeTicks timestamp = base::TimeTicks::NowFromSystemTraceTime(); |
| 211 SampleRecord* record = samples_data_->StartEnqueue(); | 222 SampleRecord* record = samples_data_->StartEnqueue(); |
| 212 if (!record) | 223 if (!record) |
| 213 return; | 224 return; |
| 214 record->Collect(isolate_, timestamp, state); | 225 record->Collect(isolate_, timestamp, state); |
| 215 samples_data_->FinishEnqueue(); | 226 samples_data_->FinishEnqueue(); |
| 216 base::subtle::NoBarrier_AtomicIncrement(&samples_count_, 1); | |
| 217 } | 227 } |
| 218 | 228 |
| 219 void Sampler::InjectPendingEvents() { | 229 void Sampler::InjectPendingEvents() { |
| 220 SampleRecord* record = samples_data_->Peek(); | 230 SampleRecord* record = samples_data_->Peek(); |
| 221 while (record) { | 231 while (record) { |
| 222 TRACE_EVENT_SAMPLE_WITH_TID_AND_TIMESTAMP1( | 232 TRACE_EVENT_SAMPLE_WITH_TID_AND_TIMESTAMP1( |
| 223 TRACE_DISABLED_BY_DEFAULT("v8.cpu_profile"), "V8Sample", thread_id_, | 233 TRACE_DISABLED_BY_DEFAULT("v8.cpu_profile"), "V8Sample", thread_id_, |
| 224 (record->timestamp() - base::TimeTicks()).InMicroseconds(), "data", | 234 (record->timestamp() - base::TimeTicks()).InMicroseconds(), "data", |
| 225 record->ToTraceFormat()); | 235 record->ToTraceFormat()); |
| 226 samples_data_->Remove(); | 236 samples_data_->Remove(); |
| 227 record = samples_data_->Peek(); | 237 record = samples_data_->Peek(); |
| 238 base::subtle::NoBarrier_AtomicIncrement(&samples_count_, 1); |
| 228 } | 239 } |
| 229 } | 240 } |
| 230 | 241 |
| 231 // static | 242 // static |
| 232 void Sampler::InstallJitCodeEventHandler(Isolate* isolate, void* data) { | 243 void Sampler::InstallJitCodeEventHandler(Isolate* isolate, void* data) { |
| 233 // Called on the sampled V8 thread. | 244 // Called on the sampled V8 thread. |
| 234 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.cpu_profile"), | 245 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.cpu_profile"), |
| 235 "Sampler::InstallJitCodeEventHandler"); | 246 "Sampler::InstallJitCodeEventHandler"); |
| 236 v8::JitCodeEventHandler handler = | 247 v8::JitCodeEventHandler handler = |
| 237 reinterpret_cast<v8::JitCodeEventHandler>(data); | 248 reinterpret_cast<v8::JitCodeEventHandler>(data); |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 base::Unretained(this))); | 552 base::Unretained(this))); |
| 542 } | 553 } |
| 543 | 554 |
| 544 void V8SamplingProfiler::OnTraceLogDisabled() { | 555 void V8SamplingProfiler::OnTraceLogDisabled() { |
| 545 if (!sampling_thread_.get()) | 556 if (!sampling_thread_.get()) |
| 546 return; | 557 return; |
| 547 sampling_thread_->Stop(); | 558 sampling_thread_->Stop(); |
| 548 sampling_thread_.reset(); | 559 sampling_thread_.reset(); |
| 549 } | 560 } |
| 550 | 561 |
| 551 void V8SamplingProfiler::EnableSamplingEventForTesting() { | 562 void V8SamplingProfiler::EnableSamplingEventForTesting(int code_added_events, |
| 563 int sample_events) { |
| 564 render_thread_sampler_->SetEventsToCollectForTest(code_added_events, |
| 565 sample_events); |
| 552 waitable_event_for_testing_.reset(new base::WaitableEvent(false, false)); | 566 waitable_event_for_testing_.reset(new base::WaitableEvent(false, false)); |
| 553 } | 567 } |
| 554 | 568 |
| 555 void V8SamplingProfiler::WaitSamplingEventForTesting() { | 569 void V8SamplingProfiler::WaitSamplingEventForTesting() { |
| 556 waitable_event_for_testing_->Wait(); | 570 waitable_event_for_testing_->Wait(); |
| 557 } | 571 } |
| 558 | 572 |
| 559 } // namespace blink | 573 } // namespace blink |
| OLD | NEW |