| 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 |