Revision: 5641
Author: [email protected]
Date: Mon Oct 18 05:37:07 2010
Log: Try to simplify the semantics of the profiling code by making
sure to suspend the thread (if necessary) on mac/win32 before
reading the VM state.
Avoid dealing with signals delivered to non-VM threads on
linux no matter if we're profiling or not.
Review URL: http://codereview.chromium.org/3845006
http://code.google.com/p/v8/source/detail?r=5641
Modified:
/branches/bleeding_edge/src/log.cc
/branches/bleeding_edge/src/platform-linux.cc
/branches/bleeding_edge/src/platform-macos.cc
/branches/bleeding_edge/src/platform-win32.cc
/branches/bleeding_edge/src/platform.h
/branches/bleeding_edge/test/cctest/test-log.cc
=======================================
--- /branches/bleeding_edge/src/log.cc Thu Sep 30 00:22:53 2010
+++ /branches/bleeding_edge/src/log.cc Mon Oct 18 05:37:07 2010
@@ -191,11 +191,12 @@
~Ticker() { if (IsActive()) Stop(); }
- void SampleStack(TickSample* sample) {
+ virtual void SampleStack(TickSample* sample) {
+ ASSERT(IsSynchronous());
StackTracer::Trace(sample);
}
- void Tick(TickSample* sample) {
+ virtual void Tick(TickSample* sample) {
if (profiler_) profiler_->Insert(sample);
if (window_) window_->AddState(sample->state);
}
=======================================
--- /branches/bleeding_edge/src/platform-linux.cc Fri Aug 13 03:19:45 2010
+++ /branches/bleeding_edge/src/platform-linux.cc Mon Oct 18 05:37:07 2010
@@ -748,6 +748,7 @@
USE(info);
if (signal != SIGPROF) return;
if (active_sampler_ == NULL) return;
+ if (!IsVmThread()) return;
TickSample sample_obj;
TickSample* sample = CpuProfiler::TickSampleEvent();
@@ -755,6 +756,7 @@
// We always sample the VM state.
sample->state = VMState::current_state();
+
// If profiling, we extract the current pc and sp.
if (active_sampler_->IsProfiling()) {
// Extracting the sample from the context is extremely machine
dependent.
@@ -783,9 +785,7 @@
// Implement this on MIPS.
UNIMPLEMENTED();
#endif
- if (IsVmThread()) {
- active_sampler_->SampleStack(sample);
- }
+ active_sampler_->SampleStack(sample);
}
active_sampler_->Tick(sample);
@@ -806,7 +806,10 @@
Sampler::Sampler(int interval, bool profiling)
- : interval_(interval), profiling_(profiling), active_(false) {
+ : interval_(interval),
+ profiling_(profiling),
+ synchronous_(profiling),
+ active_(false) {
data_ = new PlatformData();
}
=======================================
--- /branches/bleeding_edge/src/platform-macos.cc Fri May 21 22:27:19 2010
+++ /branches/bleeding_edge/src/platform-macos.cc Mon Oct 18 05:37:07 2010
@@ -549,17 +549,24 @@
// Sampler thread handler.
void Runner() {
- // Loop until the sampler is disengaged, keeping the specified samling
freq.
+ // Loop until the sampler is disengaged, keeping the specified
+ // sampling frequency.
for ( ; sampler_->IsActive(); OS::Sleep(sampler_->interval_)) {
TickSample sample_obj;
TickSample* sample = CpuProfiler::TickSampleEvent();
if (sample == NULL) sample = &sample_obj;
+
+ // If the sampler runs in sync with the JS thread, we try to
+ // suspend it. If we fail, we skip the current sample.
+ if (sampler_->IsSynchronous()) {
+ if (KERN_SUCCESS != thread_suspend(profiled_thread_)) continue;
+ }
// We always sample the VM state.
sample->state = VMState::current_state();
+
// If profiling, we record the pc and sp of the profiled thread.
- if (sampler_->IsProfiling()
- && KERN_SUCCESS == thread_suspend(profiled_thread_)) {
+ if (sampler_->IsProfiling()) {
#if V8_HOST_ARCH_X64
thread_state_flavor_t flavor = x86_THREAD_STATE64;
x86_thread_state64_t state;
@@ -591,11 +598,14 @@
sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
sampler_->SampleStack(sample);
}
- thread_resume(profiled_thread_);
}
// Invoke tick handler with program counter and stack pointer.
sampler_->Tick(sample);
+
+ // If the sampler runs in sync with the JS thread, we have to
+ // remember to resume it.
+ if (sampler_->IsSynchronous()) thread_resume(profiled_thread_);
}
}
};
@@ -613,7 +623,10 @@
Sampler::Sampler(int interval, bool profiling)
- : interval_(interval), profiling_(profiling), active_(false) {
+ : interval_(interval),
+ profiling_(profiling),
+ synchronous_(profiling),
+ active_(false) {
data_ = new PlatformData(this);
}
@@ -624,9 +637,9 @@
void Sampler::Start() {
- // If we are profiling, we need to be able to access the calling
- // thread.
- if (IsProfiling()) {
+ // If we are starting a synchronous sampler, we need to be able to
+ // access the calling thread.
+ if (IsSynchronous()) {
data_->profiled_thread_ = mach_thread_self();
}
@@ -655,7 +668,7 @@
pthread_join(data_->sampler_thread_, NULL);
// Deallocate Mach port for thread.
- if (IsProfiling()) {
+ if (IsSynchronous()) {
mach_port_deallocate(data_->task_self_, data_->profiled_thread_);
}
}
=======================================
--- /branches/bleeding_edge/src/platform-win32.cc Fri Aug 13 04:11:36 2010
+++ /branches/bleeding_edge/src/platform-win32.cc Mon Oct 18 05:37:07 2010
@@ -1838,17 +1838,25 @@
// Context used for sampling the register state of the profiled thread.
CONTEXT context;
memset(&context, 0, sizeof(context));
- // Loop until the sampler is disengaged, keeping the specified samling
freq.
+ // Loop until the sampler is disengaged, keeping the specified
+ // sampling frequency.
for ( ; sampler_->IsActive(); Sleep(sampler_->interval_)) {
TickSample sample_obj;
TickSample* sample = CpuProfiler::TickSampleEvent();
if (sample == NULL) sample = &sample_obj;
+
+ // If the sampler runs in sync with the JS thread, we try to
+ // suspend it. If we fail, we skip the current sample.
+ if (sampler_->IsSynchronous()) {
+ static const DWORD kSuspendFailed = static_cast<DWORD>(-1);
+ if (SuspendThread(profiled_thread_) == kSuspendFailed) continue;
+ }
// We always sample the VM state.
sample->state = VMState::current_state();
+
// If profiling, we record the pc and sp of the profiled thread.
- if (sampler_->IsProfiling()
- && SuspendThread(profiled_thread_) != (DWORD)-1) {
+ if (sampler_->IsProfiling()) {
context.ContextFlags = CONTEXT_FULL;
if (GetThreadContext(profiled_thread_, &context) != 0) {
#if V8_HOST_ARCH_X64
@@ -1862,11 +1870,14 @@
#endif
sampler_->SampleStack(sample);
}
- ResumeThread(profiled_thread_);
}
// Invoke tick handler with program counter and stack pointer.
sampler_->Tick(sample);
+
+ // If the sampler runs in sync with the JS thread, we have to
+ // remember to resume it.
+ if (sampler_->IsSynchronous()) ResumeThread(profiled_thread_);
}
}
};
@@ -1883,7 +1894,10 @@
// Initialize a profile sampler.
Sampler::Sampler(int interval, bool profiling)
- : interval_(interval), profiling_(profiling), active_(false) {
+ : interval_(interval),
+ profiling_(profiling),
+ synchronous_(profiling),
+ active_(false) {
data_ = new PlatformData(this);
}
@@ -1895,9 +1909,9 @@
// Start profiling.
void Sampler::Start() {
- // If we are profiling, we need to be able to access the calling
- // thread.
- if (IsProfiling()) {
+ // If we are starting a synchronous sampler, we need to be able to
+ // access the calling thread.
+ if (IsSynchronous()) {
// Get a handle to the calling thread. This is the thread that we are
// going to profile. We need to make a copy of the handle because we
are
// going to use it in the sampler thread. Using GetThreadHandle() will
=======================================
--- /branches/bleeding_edge/src/platform.h Thu Sep 2 03:18:44 2010
+++ /branches/bleeding_edge/src/platform.h Mon Oct 18 05:37:07 2010
@@ -563,17 +563,24 @@
void Start();
void Stop();
- // Is the sampler used for profiling.
- inline bool IsProfiling() { return profiling_; }
+ // Is the sampler used for profiling?
+ bool IsProfiling() const { return profiling_; }
+
+ // Is the sampler running in sync with the JS thread? On platforms
+ // where the sampler is implemented with a thread that wakes up
+ // every now and then, having a synchronous sampler implies
+ // suspending/resuming the JS thread.
+ bool IsSynchronous() const { return synchronous_; }
// Whether the sampler is running (that is, consumes resources).
- inline bool IsActive() { return active_; }
+ bool IsActive() const { return active_; }
class PlatformData;
private:
const int interval_;
const bool profiling_;
+ const bool synchronous_;
bool active_;
PlatformData* data_; // Platform specific data.
DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
=======================================
--- /branches/bleeding_edge/test/cctest/test-log.cc Tue Apr 6 03:36:38 2010
+++ /branches/bleeding_edge/test/cctest/test-log.cc Mon Oct 18 05:37:07 2010
@@ -469,7 +469,7 @@
CHECK(!sampler.WasSampleStackCalled());
nonJsThread.WaitForRunning();
nonJsThread.SendSigProf();
- CHECK(sampler.WaitForTick());
+ CHECK(!sampler.WaitForTick());
CHECK(!sampler.WasSampleStackCalled());
sampler.Stop();
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev