Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(268)

Side by Side Diff: content/renderer/devtools/v8_sampling_profiler.cc

Issue 1029823002: V8 Sampling Profiler: Support sampling on Windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | content/renderer/devtools/v8_sampling_profiler_browsertest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 11
12 #include "base/format_macros.h" 12 #include "base/format_macros.h"
13 #include "base/strings/stringprintf.h" 13 #include "base/strings/stringprintf.h"
14 #include "base/synchronization/cancellation_flag.h" 14 #include "base/synchronization/cancellation_flag.h"
15 #include "base/threading/platform_thread.h" 15 #include "base/threading/platform_thread.h"
16 #include "base/trace_event/trace_event.h" 16 #include "base/trace_event/trace_event.h"
17 #include "base/trace_event/trace_event_argument.h" 17 #include "base/trace_event/trace_event_argument.h"
18 #if defined(OS_WIN)
19 #include "base/win/scoped_handle.h"
yurys 2015/03/24 14:15:25 Please minimize number of dependencies on base/ an
alph 2015/03/24 14:17:08 Acknowledged.
20 #endif
18 #include "content/renderer/devtools/lock_free_circular_queue.h" 21 #include "content/renderer/devtools/lock_free_circular_queue.h"
19 #include "content/renderer/render_thread_impl.h" 22 #include "content/renderer/render_thread_impl.h"
20 #include "v8/include/v8.h" 23 #include "v8/include/v8.h"
21 24
22 using base::trace_event::ConvertableToTraceFormat; 25 using base::trace_event::ConvertableToTraceFormat;
23 using base::trace_event::TraceLog; 26 using base::trace_event::TraceLog;
24 using base::trace_event::TracedValue; 27 using base::trace_event::TracedValue;
25 using v8::Isolate; 28 using v8::Isolate;
26 29
27 namespace content { 30 namespace content {
28 31
29 namespace { 32 namespace {
30 33
34 #if defined(OS_WIN)
35 typedef base::win::ScopedHandle UniversalThreadHandle;
36 #else
37 typedef base::PlatformThreadHandle UniversalThreadHandle;
38 #endif
39
31 std::string PtrToString(const void* value) { 40 std::string PtrToString(const void* value) {
32 return base::StringPrintf( 41 return base::StringPrintf(
33 "0x%" PRIx64, static_cast<uint64>(reinterpret_cast<intptr_t>(value))); 42 "0x%" PRIx64, static_cast<uint64>(reinterpret_cast<intptr_t>(value)));
34 } 43 }
35 44
36 class SampleRecord { 45 class SampleRecord {
37 public: 46 public:
38 static const int kMaxFramesCountLog2 = 8; 47 static const int kMaxFramesCountLog2 = 8;
39 static const unsigned kMaxFramesCount = (1u << kMaxFramesCountLog2) - 1; 48 static const unsigned kMaxFramesCount = (1u << kMaxFramesCountLog2) - 1;
40 49
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 sample_events_to_collect_for_test_; 138 sample_events_to_collect_for_test_;
130 } 139 }
131 140
132 private: 141 private:
133 Sampler(); 142 Sampler();
134 143
135 static void InstallJitCodeEventHandler(Isolate* isolate, void* data); 144 static void InstallJitCodeEventHandler(Isolate* isolate, void* data);
136 static void HandleJitCodeEvent(const v8::JitCodeEvent* event); 145 static void HandleJitCodeEvent(const v8::JitCodeEvent* event);
137 static scoped_refptr<ConvertableToTraceFormat> JitCodeEventToTraceFormat( 146 static scoped_refptr<ConvertableToTraceFormat> JitCodeEventToTraceFormat(
138 const v8::JitCodeEvent* event); 147 const v8::JitCodeEvent* event);
139 static base::PlatformThreadHandle GetCurrentThreadHandle(); 148 static UniversalThreadHandle GetCurrentThreadHandle();
140 149
141 void InjectPendingEvents(); 150 void InjectPendingEvents();
142 151
143 static const unsigned kNumberOfSamples = 10; 152 static const unsigned kNumberOfSamples = 10;
144 typedef LockFreeCircularQueue<SampleRecord, kNumberOfSamples> SamplingQueue; 153 typedef LockFreeCircularQueue<SampleRecord, kNumberOfSamples> SamplingQueue;
145 154
146 base::PlatformThreadId thread_id_; 155 base::PlatformThreadId thread_id_;
147 base::PlatformThreadHandle thread_handle_; 156 UniversalThreadHandle thread_handle_;
148 Isolate* isolate_; 157 Isolate* isolate_;
149 scoped_ptr<SamplingQueue> samples_data_; 158 scoped_ptr<SamplingQueue> samples_data_;
150 base::subtle::Atomic32 code_added_events_count_; 159 base::subtle::Atomic32 code_added_events_count_;
151 base::subtle::Atomic32 samples_count_; 160 base::subtle::Atomic32 samples_count_;
152 int code_added_events_to_collect_for_test_; 161 int code_added_events_to_collect_for_test_;
153 int sample_events_to_collect_for_test_; 162 int sample_events_to_collect_for_test_;
154 163
155 static base::LazyInstance<base::ThreadLocalPointer<Sampler>>::Leaky 164 static base::LazyInstance<base::ThreadLocalPointer<Sampler>>::Leaky
156 tls_instance_; 165 tls_instance_;
157 }; 166 };
(...skipping 18 matching lines...) Expand all
176 DCHECK(GetInstance()); 185 DCHECK(GetInstance());
177 tls_instance_.Pointer()->Set(nullptr); 186 tls_instance_.Pointer()->Set(nullptr);
178 } 187 }
179 188
180 // static 189 // static
181 scoped_ptr<Sampler> Sampler::CreateForCurrentThread() { 190 scoped_ptr<Sampler> Sampler::CreateForCurrentThread() {
182 return scoped_ptr<Sampler>(new Sampler()); 191 return scoped_ptr<Sampler>(new Sampler());
183 } 192 }
184 193
185 // static 194 // static
186 base::PlatformThreadHandle Sampler::GetCurrentThreadHandle() { 195 UniversalThreadHandle Sampler::GetCurrentThreadHandle() {
187 #ifdef OS_WIN 196 #ifdef OS_WIN
188 // TODO(alph): Add Windows support. 197 return base::win::ScopedHandle(::OpenThread(
189 return base::PlatformThreadHandle(); 198 THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION,
199 false, base::PlatformThread::CurrentId()));
190 #else 200 #else
191 return base::PlatformThread::CurrentHandle(); 201 return base::PlatformThread::CurrentHandle();
192 #endif 202 #endif
193 } 203 }
194 204
195 void Sampler::Start() { 205 void Sampler::Start() {
196 samples_data_.reset(new SamplingQueue()); 206 samples_data_.reset(new SamplingQueue());
197 v8::JitCodeEventHandler handler = &HandleJitCodeEvent; 207 v8::JitCodeEventHandler handler = &HandleJitCodeEvent;
198 isolate_->RequestInterrupt(&InstallJitCodeEventHandler, 208 isolate_->RequestInterrupt(&InstallJitCodeEventHandler,
199 reinterpret_cast<void*>(handler)); 209 reinterpret_cast<void*>(handler));
200 } 210 }
201 211
202 void Sampler::Stop() { 212 void Sampler::Stop() {
203 isolate_->RequestInterrupt(&InstallJitCodeEventHandler, nullptr); 213 isolate_->RequestInterrupt(&InstallJitCodeEventHandler, nullptr);
204 samples_data_.reset(); 214 samples_data_.reset();
205 } 215 }
206 216
217 #if ARCH_CPU_64_BITS
218 #define REG_64_32(reg64, reg32) reg64
219 #else
220 #define REG_64_32(reg64, reg32) reg32
221 #endif // ARCH_CPU_64_BITS
222
207 void Sampler::Sample() { 223 void Sampler::Sample() {
208 #if defined(USE_SIGNALS) 224 #if defined(OS_WIN)
225 const DWORD kSuspendFailed = static_cast<DWORD>(-1);
226 if (::SuspendThread(thread_handle_.Get()) == kSuspendFailed)
227 return;
228 CONTEXT context;
229 memset(&context, 0, sizeof(context));
230 context.ContextFlags = CONTEXT_FULL;
231 if (::GetThreadContext(thread_handle_.Get(), &context) != 0) {
232 v8::RegisterState state;
233 state.pc = reinterpret_cast<void*>(context.REG_64_32(Rip, Eip));
234 state.sp = reinterpret_cast<void*>(context.REG_64_32(Rsp, Esp));
235 state.fp = reinterpret_cast<void*>(context.REG_64_32(Rbp, Ebp));
236 // TODO(alph): It is not needed to buffer the events on Windows.
237 // We can just collect and fire trace event right away.
238 DoSample(state);
239 }
240 ::ResumeThread(thread_handle_.Get());
241 #elif defined(USE_SIGNALS)
209 int error = pthread_kill(thread_handle_.platform_handle(), SIGPROF); 242 int error = pthread_kill(thread_handle_.platform_handle(), SIGPROF);
210 if (error) { 243 if (error) {
211 LOG(ERROR) << "pthread_kill failed with error " << error << " " 244 LOG(ERROR) << "pthread_kill failed with error " << error << " "
212 << strerror(error); 245 << strerror(error);
213 } 246 }
247 #endif
214 InjectPendingEvents(); 248 InjectPendingEvents();
215 #endif
216 } 249 }
217 250
218 void Sampler::DoSample(const v8::RegisterState& state) { 251 void Sampler::DoSample(const v8::RegisterState& state) {
219 // Called in the sampled thread signal handler. 252 // Called in the sampled thread signal handler.
220 // Because of that it is not allowed to do any memory allocation here. 253 // Because of that it is not allowed to do any memory allocation here.
221 base::TimeTicks timestamp = base::TimeTicks::NowFromSystemTraceTime(); 254 base::TimeTicks timestamp = base::TimeTicks::NowFromSystemTraceTime();
222 SampleRecord* record = samples_data_->StartEnqueue(); 255 SampleRecord* record = samples_data_->StartEnqueue();
223 if (!record) 256 if (!record)
224 return; 257 return;
225 record->Collect(isolate_, timestamp, state); 258 record->Collect(isolate_, timestamp, state);
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 void V8SamplingThread::HandleProfilerSignal(int signal, 483 void V8SamplingThread::HandleProfilerSignal(int signal,
451 siginfo_t* info, 484 siginfo_t* info,
452 void* context) { 485 void* context) {
453 if (signal != SIGPROF) 486 if (signal != SIGPROF)
454 return; 487 return;
455 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context); 488 ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
456 mcontext_t& mcontext = ucontext->uc_mcontext; 489 mcontext_t& mcontext = ucontext->uc_mcontext;
457 v8::RegisterState state; 490 v8::RegisterState state;
458 491
459 #if defined(ARCH_CPU_ARM_FAMILY) 492 #if defined(ARCH_CPU_ARM_FAMILY)
460 493 state.pc = reinterpret_cast<void*>(mcontext.REG_64_32(pc, arm_pc));
461 #if ARCH_CPU_64_BITS 494 state.sp = reinterpret_cast<void*>(mcontext.REG_64_32(sp, arm_sp));
462 state.pc = reinterpret_cast<void*>(mcontext.pc); 495 state.fp = reinterpret_cast<void*>(mcontext.REG_64_32(regs[29], arm_fp));
463 state.sp = reinterpret_cast<void*>(mcontext.sp);
464 state.fp = reinterpret_cast<void*>(mcontext.regs[29]);
465 #elif ARCH_CPU_32_BITS
466 state.pc = reinterpret_cast<void*>(mcontext.arm_pc);
467 state.sp = reinterpret_cast<void*>(mcontext.arm_sp);
468 state.fp = reinterpret_cast<void*>(mcontext.arm_fp);
469 #endif // ARCH_CPU_32_BITS
470 496
471 #elif defined(ARCH_CPU_X86_FAMILY) 497 #elif defined(ARCH_CPU_X86_FAMILY)
472
473 #if defined(OS_MACOSX) 498 #if defined(OS_MACOSX)
474 #if ARCH_CPU_64_BITS 499 state.pc = reinterpret_cast<void*>(mcontext->__ss.REG_64_32(__rip, __eip));
475 state.pc = reinterpret_cast<void*>(mcontext->__ss.__rip); 500 state.sp = reinterpret_cast<void*>(mcontext->__ss.REG_64_32(__rsp, __esp));
476 state.sp = reinterpret_cast<void*>(mcontext->__ss.__rsp); 501 state.fp = reinterpret_cast<void*>(mcontext->__ss.REG_64_32(__rbp, __ebp));
477 state.fp = reinterpret_cast<void*>(mcontext->__ss.__rbp);
478 #elif ARCH_CPU_32_BITS
479 state.pc = reinterpret_cast<void*>(mcontext->__ss.__eip);
480 state.sp = reinterpret_cast<void*>(mcontext->__ss.__esp);
481 state.fp = reinterpret_cast<void*>(mcontext->__ss.__ebp);
482 #endif // ARCH_CPU_32_BITS
483
484 #else 502 #else
485 #if ARCH_CPU_64_BITS 503 state.pc =
486 state.pc = reinterpret_cast<void*>(mcontext.gregs[REG_RIP]); 504 reinterpret_cast<void*>(mcontext.gregs[REG_64_32(REG_RIP, REG_EIP)]);
487 state.sp = reinterpret_cast<void*>(mcontext.gregs[REG_RSP]); 505 state.sp =
488 state.fp = reinterpret_cast<void*>(mcontext.gregs[REG_RBP]); 506 reinterpret_cast<void*>(mcontext.gregs[REG_64_32(REG_RSP, REG_ESP)]);
489 #elif ARCH_CPU_32_BITS 507 state.fp =
490 state.pc = reinterpret_cast<void*>(mcontext.gregs[REG_EIP]); 508 reinterpret_cast<void*>(mcontext.gregs[REG_64_32(REG_RBP, REG_EBP)]);
491 state.sp = reinterpret_cast<void*>(mcontext.gregs[REG_ESP]);
492 state.fp = reinterpret_cast<void*>(mcontext.gregs[REG_EBP]);
493 #endif // ARCH_CPU_32_BITS
494 #endif // OS_MACOS 509 #endif // OS_MACOS
495 #endif // ARCH_CPU_X86_FAMILY 510 #endif // ARCH_CPU_X86_FAMILY
496 511
497 Sampler::GetInstance()->DoSample(state); 512 Sampler::GetInstance()->DoSample(state);
498 } 513 }
499 #endif 514 #endif
500 515
501 void V8SamplingThread::Start() { 516 void V8SamplingThread::Start() {
502 if (!base::PlatformThread::Create(0, this, &sampling_thread_handle_)) { 517 if (!base::PlatformThread::Create(0, this, &sampling_thread_handle_)) {
503 DCHECK(false) << "failed to create sampling thread"; 518 DCHECK(false) << "failed to create sampling thread";
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 render_thread_sampler_->SetEventsToCollectForTest(code_added_events, 579 render_thread_sampler_->SetEventsToCollectForTest(code_added_events,
565 sample_events); 580 sample_events);
566 waitable_event_for_testing_.reset(new base::WaitableEvent(false, false)); 581 waitable_event_for_testing_.reset(new base::WaitableEvent(false, false));
567 } 582 }
568 583
569 void V8SamplingProfiler::WaitSamplingEventForTesting() { 584 void V8SamplingProfiler::WaitSamplingEventForTesting() {
570 waitable_event_for_testing_->Wait(); 585 waitable_event_for_testing_->Wait();
571 } 586 }
572 587
573 } // namespace blink 588 } // namespace blink
OLDNEW
« no previous file with comments | « no previous file | content/renderer/devtools/v8_sampling_profiler_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698