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