summaryrefslogtreecommitdiffstats
path: root/src/platform-macos.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform-macos.cc')
-rw-r--r--src/platform-macos.cc102
1 files changed, 51 insertions, 51 deletions
diff --git a/src/platform-macos.cc b/src/platform-macos.cc
index c3f21dc5..85c70882 100644
--- a/src/platform-macos.cc
+++ b/src/platform-macos.cc
@@ -57,6 +57,7 @@
#include "v8.h"
#include "platform.h"
+#include "vm-state-inl.h"
// Manually define these here as weak imports, rather than including execinfo.h.
// This lets us launch on 10.4 which does not have these calls.
@@ -483,11 +484,20 @@ class MacOSMutex : public Mutex {
pthread_mutex_init(&mutex_, &attr);
}
- ~MacOSMutex() { pthread_mutex_destroy(&mutex_); }
+ virtual ~MacOSMutex() { pthread_mutex_destroy(&mutex_); }
- int Lock() { return pthread_mutex_lock(&mutex_); }
+ virtual int Lock() { return pthread_mutex_lock(&mutex_); }
+ virtual int Unlock() { return pthread_mutex_unlock(&mutex_); }
- int Unlock() { return pthread_mutex_unlock(&mutex_); }
+ virtual bool TryLock() {
+ int result = pthread_mutex_trylock(&mutex_);
+ // Return false if the lock is busy and locking failed.
+ if (result == EBUSY) {
+ return false;
+ }
+ ASSERT(result == 0); // Verify no other errors.
+ return true;
+ }
private:
pthread_mutex_t mutex_;
@@ -554,40 +564,38 @@ class Sampler::PlatformData : public Malloced {
mach_port_t task_self_;
thread_act_t profiled_thread_;
pthread_t sampler_thread_;
+ RuntimeProfilerRateLimiter rate_limiter_;
// Sampler thread handler.
void Runner() {
- // Loop until the sampler is disengaged, keeping the specified
- // sampling frequency.
- for ( ; sampler_->IsActive(); OS::Sleep(sampler_->interval_)) {
+ while (sampler_->IsActive()) {
+ if (rate_limiter_.SuspendIfNecessary()) continue;
+ Sample();
+ OS::Sleep(sampler_->interval_);
+ }
+ }
+
+ void Sample() {
+ if (sampler_->IsProfiling()) {
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;
- }
+ if (KERN_SUCCESS != thread_suspend(profiled_thread_)) return;
- // 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()) {
#if V8_HOST_ARCH_X64
- thread_state_flavor_t flavor = x86_THREAD_STATE64;
- x86_thread_state64_t state;
- mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
+ thread_state_flavor_t flavor = x86_THREAD_STATE64;
+ x86_thread_state64_t state;
+ mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
#if __DARWIN_UNIX03
#define REGISTER_FIELD(name) __r ## name
#else
#define REGISTER_FIELD(name) r ## name
#endif // __DARWIN_UNIX03
#elif V8_HOST_ARCH_IA32
- thread_state_flavor_t flavor = i386_THREAD_STATE;
- i386_thread_state_t state;
- mach_msg_type_number_t count = i386_THREAD_STATE_COUNT;
+ thread_state_flavor_t flavor = i386_THREAD_STATE;
+ i386_thread_state_t state;
+ mach_msg_type_number_t count = i386_THREAD_STATE_COUNT;
#if __DARWIN_UNIX03
#define REGISTER_FIELD(name) __e ## name
#else
@@ -597,24 +605,20 @@ class Sampler::PlatformData : public Malloced {
#error Unsupported Mac OS X host architecture.
#endif // V8_HOST_ARCH
- if (thread_get_state(profiled_thread_,
- flavor,
- reinterpret_cast<natural_t*>(&state),
- &count) == KERN_SUCCESS) {
- sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
- sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
- sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
- sampler_->SampleStack(sample);
- }
+ if (thread_get_state(profiled_thread_,
+ flavor,
+ reinterpret_cast<natural_t*>(&state),
+ &count) == KERN_SUCCESS) {
+ sample->state = Top::current_vm_state();
+ sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
+ sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
+ sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
+ sampler_->SampleStack(sample);
+ sampler_->Tick(sample);
}
-
- // 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_);
+ thread_resume(profiled_thread_);
}
+ if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick();
}
};
@@ -630,10 +634,9 @@ static void* SamplerEntry(void* arg) {
}
-Sampler::Sampler(int interval, bool profiling)
+Sampler::Sampler(int interval)
: interval_(interval),
- profiling_(profiling),
- synchronous_(profiling),
+ profiling_(false),
active_(false),
samples_taken_(0) {
data_ = new PlatformData(this);
@@ -646,11 +649,9 @@ Sampler::~Sampler() {
void Sampler::Start() {
- // 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();
- }
+ // Do not start multiple threads for the same sampler.
+ ASSERT(!IsActive());
+ data_->profiled_thread_ = mach_thread_self();
// Create sampler thread with high priority.
// According to POSIX spec, when SCHED_FIFO policy is used, a thread
@@ -663,7 +664,7 @@ void Sampler::Start() {
fifo_param.sched_priority = sched_get_priority_max(SCHED_FIFO);
pthread_attr_setschedparam(&sched_attr, &fifo_param);
- active_ = true;
+ SetActive(true);
pthread_create(&data_->sampler_thread_, &sched_attr, SamplerEntry, data_);
}
@@ -671,15 +672,14 @@ void Sampler::Start() {
void Sampler::Stop() {
// Seting active to false triggers termination of the sampler
// thread.
- active_ = false;
+ SetActive(false);
// Wait for sampler thread to terminate.
+ Top::WakeUpRuntimeProfilerThreadBeforeShutdown();
pthread_join(data_->sampler_thread_, NULL);
// Deallocate Mach port for thread.
- if (IsSynchronous()) {
- mach_port_deallocate(data_->task_self_, data_->profiled_thread_);
- }
+ mach_port_deallocate(data_->task_self_, data_->profiled_thread_);
}
#endif // ENABLE_LOGGING_AND_PROFILING