Index: content/renderer/devtools/v8_sampling_profiler.cc |
diff --git a/content/renderer/devtools/v8_sampling_profiler.cc b/content/renderer/devtools/v8_sampling_profiler.cc |
index 9b3249745e27c070582e3c0858029e6222c04549..8f3821b063b4511553f99ad8eaca0e643a57aca5 100644 |
--- a/content/renderer/devtools/v8_sampling_profiler.cc |
+++ b/content/renderer/devtools/v8_sampling_profiler.cc |
@@ -15,6 +15,9 @@ |
#include "base/threading/platform_thread.h" |
#include "base/trace_event/trace_event.h" |
#include "base/trace_event/trace_event_argument.h" |
+#if defined(OS_WIN) |
+#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.
|
+#endif |
#include "content/renderer/devtools/lock_free_circular_queue.h" |
#include "content/renderer/render_thread_impl.h" |
#include "v8/include/v8.h" |
@@ -28,6 +31,12 @@ namespace content { |
namespace { |
+#if defined(OS_WIN) |
+typedef base::win::ScopedHandle UniversalThreadHandle; |
+#else |
+typedef base::PlatformThreadHandle UniversalThreadHandle; |
+#endif |
+ |
std::string PtrToString(const void* value) { |
return base::StringPrintf( |
"0x%" PRIx64, static_cast<uint64>(reinterpret_cast<intptr_t>(value))); |
@@ -136,7 +145,7 @@ class Sampler { |
static void HandleJitCodeEvent(const v8::JitCodeEvent* event); |
static scoped_refptr<ConvertableToTraceFormat> JitCodeEventToTraceFormat( |
const v8::JitCodeEvent* event); |
- static base::PlatformThreadHandle GetCurrentThreadHandle(); |
+ static UniversalThreadHandle GetCurrentThreadHandle(); |
void InjectPendingEvents(); |
@@ -144,7 +153,7 @@ class Sampler { |
typedef LockFreeCircularQueue<SampleRecord, kNumberOfSamples> SamplingQueue; |
base::PlatformThreadId thread_id_; |
- base::PlatformThreadHandle thread_handle_; |
+ UniversalThreadHandle thread_handle_; |
Isolate* isolate_; |
scoped_ptr<SamplingQueue> samples_data_; |
base::subtle::Atomic32 code_added_events_count_; |
@@ -183,10 +192,11 @@ scoped_ptr<Sampler> Sampler::CreateForCurrentThread() { |
} |
// static |
-base::PlatformThreadHandle Sampler::GetCurrentThreadHandle() { |
+UniversalThreadHandle Sampler::GetCurrentThreadHandle() { |
#ifdef OS_WIN |
- // TODO(alph): Add Windows support. |
- return base::PlatformThreadHandle(); |
+ return base::win::ScopedHandle(::OpenThread( |
+ THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION, |
+ false, base::PlatformThread::CurrentId())); |
#else |
return base::PlatformThread::CurrentHandle(); |
#endif |
@@ -204,15 +214,38 @@ void Sampler::Stop() { |
samples_data_.reset(); |
} |
+#if ARCH_CPU_64_BITS |
+#define REG_64_32(reg64, reg32) reg64 |
+#else |
+#define REG_64_32(reg64, reg32) reg32 |
+#endif // ARCH_CPU_64_BITS |
+ |
void Sampler::Sample() { |
-#if defined(USE_SIGNALS) |
+#if defined(OS_WIN) |
+ const DWORD kSuspendFailed = static_cast<DWORD>(-1); |
+ if (::SuspendThread(thread_handle_.Get()) == kSuspendFailed) |
+ return; |
+ CONTEXT context; |
+ memset(&context, 0, sizeof(context)); |
+ context.ContextFlags = CONTEXT_FULL; |
+ if (::GetThreadContext(thread_handle_.Get(), &context) != 0) { |
+ v8::RegisterState state; |
+ state.pc = reinterpret_cast<void*>(context.REG_64_32(Rip, Eip)); |
+ state.sp = reinterpret_cast<void*>(context.REG_64_32(Rsp, Esp)); |
+ state.fp = reinterpret_cast<void*>(context.REG_64_32(Rbp, Ebp)); |
+ // TODO(alph): It is not needed to buffer the events on Windows. |
+ // We can just collect and fire trace event right away. |
+ DoSample(state); |
+ } |
+ ::ResumeThread(thread_handle_.Get()); |
+#elif defined(USE_SIGNALS) |
int error = pthread_kill(thread_handle_.platform_handle(), SIGPROF); |
if (error) { |
LOG(ERROR) << "pthread_kill failed with error " << error << " " |
<< strerror(error); |
} |
- InjectPendingEvents(); |
#endif |
+ InjectPendingEvents(); |
} |
void Sampler::DoSample(const v8::RegisterState& state) { |
@@ -457,40 +490,22 @@ void V8SamplingThread::HandleProfilerSignal(int signal, |
v8::RegisterState state; |
#if defined(ARCH_CPU_ARM_FAMILY) |
- |
-#if ARCH_CPU_64_BITS |
- state.pc = reinterpret_cast<void*>(mcontext.pc); |
- state.sp = reinterpret_cast<void*>(mcontext.sp); |
- state.fp = reinterpret_cast<void*>(mcontext.regs[29]); |
-#elif ARCH_CPU_32_BITS |
- state.pc = reinterpret_cast<void*>(mcontext.arm_pc); |
- state.sp = reinterpret_cast<void*>(mcontext.arm_sp); |
- state.fp = reinterpret_cast<void*>(mcontext.arm_fp); |
-#endif // ARCH_CPU_32_BITS |
+ state.pc = reinterpret_cast<void*>(mcontext.REG_64_32(pc, arm_pc)); |
+ state.sp = reinterpret_cast<void*>(mcontext.REG_64_32(sp, arm_sp)); |
+ state.fp = reinterpret_cast<void*>(mcontext.REG_64_32(regs[29], arm_fp)); |
#elif defined(ARCH_CPU_X86_FAMILY) |
- |
#if defined(OS_MACOSX) |
-#if ARCH_CPU_64_BITS |
- state.pc = reinterpret_cast<void*>(mcontext->__ss.__rip); |
- state.sp = reinterpret_cast<void*>(mcontext->__ss.__rsp); |
- state.fp = reinterpret_cast<void*>(mcontext->__ss.__rbp); |
-#elif ARCH_CPU_32_BITS |
- state.pc = reinterpret_cast<void*>(mcontext->__ss.__eip); |
- state.sp = reinterpret_cast<void*>(mcontext->__ss.__esp); |
- state.fp = reinterpret_cast<void*>(mcontext->__ss.__ebp); |
-#endif // ARCH_CPU_32_BITS |
- |
+ state.pc = reinterpret_cast<void*>(mcontext->__ss.REG_64_32(__rip, __eip)); |
+ state.sp = reinterpret_cast<void*>(mcontext->__ss.REG_64_32(__rsp, __esp)); |
+ state.fp = reinterpret_cast<void*>(mcontext->__ss.REG_64_32(__rbp, __ebp)); |
#else |
-#if ARCH_CPU_64_BITS |
- state.pc = reinterpret_cast<void*>(mcontext.gregs[REG_RIP]); |
- state.sp = reinterpret_cast<void*>(mcontext.gregs[REG_RSP]); |
- state.fp = reinterpret_cast<void*>(mcontext.gregs[REG_RBP]); |
-#elif ARCH_CPU_32_BITS |
- state.pc = reinterpret_cast<void*>(mcontext.gregs[REG_EIP]); |
- state.sp = reinterpret_cast<void*>(mcontext.gregs[REG_ESP]); |
- state.fp = reinterpret_cast<void*>(mcontext.gregs[REG_EBP]); |
-#endif // ARCH_CPU_32_BITS |
+ state.pc = |
+ reinterpret_cast<void*>(mcontext.gregs[REG_64_32(REG_RIP, REG_EIP)]); |
+ state.sp = |
+ reinterpret_cast<void*>(mcontext.gregs[REG_64_32(REG_RSP, REG_ESP)]); |
+ state.fp = |
+ reinterpret_cast<void*>(mcontext.gregs[REG_64_32(REG_RBP, REG_EBP)]); |
#endif // OS_MACOS |
#endif // ARCH_CPU_X86_FAMILY |