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

Unified Diff: src/platform-macos.cc

Issue 6529055: [Isolates] Merge crankshaft (r5922 from bleeding_edge). (Closed)
Patch Set: Win32 port Created 9 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/platform-linux.cc ('k') | src/platform-nullos.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/platform-macos.cc
diff --git a/src/platform-macos.cc b/src/platform-macos.cc
index d4768c8974074f0ec8da1432b821105899da7917..d5c1f897f7cc81445cce75d033404ca762f09d23 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.
@@ -493,11 +494,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_;
@@ -550,54 +560,107 @@ Semaphore* OS::CreateSemaphore(int count) {
class Sampler::PlatformData : public Malloced {
public:
- explicit PlatformData(Sampler* sampler)
- : sampler_(sampler),
- task_self_(mach_task_self()),
- profiled_thread_(0),
- sampler_thread_(0) {
+ PlatformData() : profiled_thread_(mach_thread_self()) {}
+
+ ~PlatformData() {
+ // Deallocate Mach port for thread.
+ mach_port_deallocate(mach_task_self(), profiled_thread_);
}
- Sampler* sampler_;
+ thread_act_t profiled_thread() { return profiled_thread_; }
+
+ private:
// Note: for profiled_thread_ Mach primitives are used instead of PThread's
// because the latter doesn't provide thread manipulation primitives required.
// For details, consult "Mac OS X Internals" book, Section 7.3.
- mach_port_t task_self_;
thread_act_t profiled_thread_;
- pthread_t sampler_thread_;
-
- // Sampler thread handler.
- void Runner() {
- // 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;
+};
+
+class SamplerThread : public Thread {
+ public:
+ explicit SamplerThread(int interval) : Thread(NULL), interval_(interval) {}
+
+ static void AddActiveSampler(Sampler* sampler) {
+ ScopedLock lock(mutex_);
+ SamplerRegistry::AddActiveSampler(sampler);
+ if (instance_ == NULL) {
+ instance_ = new SamplerThread(sampler->interval());
+ instance_->Start();
+ } else {
+ ASSERT(instance_->interval_ == sampler->interval());
+ }
+ }
+
+ static void RemoveActiveSampler(Sampler* sampler) {
+ ScopedLock lock(mutex_);
+ SamplerRegistry::RemoveActiveSampler(sampler);
+ if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
+ RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
+ instance_->Join();
+ delete instance_;
+ instance_ = NULL;
+ }
+ }
+
+ // Implement Thread::Run().
+ virtual void Run() {
+ SamplerRegistry::State state = SamplerRegistry::GetState();
+ while (state != SamplerRegistry::HAS_NO_SAMPLERS) {
+ bool cpu_profiling_enabled =
+ (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS);
+ bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled();
+ // When CPU profiling is enabled both JavaScript and C++ code is
+ // profiled. We must not suspend.
+ if (!cpu_profiling_enabled) {
+ if (rate_limiter_.SuspendIfNecessary()) continue;
+ }
+ if (cpu_profiling_enabled) {
+ if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
+ return;
+ }
+ }
+ if (runtime_profiler_enabled) {
+ if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
+ return;
+ }
}
+ OS::Sleep(interval_);
+ }
+ }
- // We always sample the VM state.
- sample->state = VMState::current_state();
+ static void DoCpuProfile(Sampler* sampler, void* raw_sampler_thread) {
+ if (!sampler->IsProfiling()) return;
+ SamplerThread* sampler_thread =
+ reinterpret_cast<SamplerThread*>(raw_sampler_thread);
+ sampler_thread->SampleContext(sampler);
+ }
+
+ static void DoRuntimeProfile(Sampler* sampler, void* ignored) {
+ if (!sampler->isolate()->IsInitialized()) return;
+ sampler->isolate()->runtime_profiler()->NotifyTick();
+ }
+
+ void SampleContext(Sampler* sampler) {
+ thread_act_t profiled_thread = sampler->platform_data()->profiled_thread();
+ TickSample sample_obj;
+ TickSample* sample = CpuProfiler::TickSampleEvent(sampler->isolate());
+ if (sample == NULL) sample = &sample_obj;
+
+ if (KERN_SUCCESS != thread_suspend(profiled_thread)) return;
- // 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
@@ -607,91 +670,64 @@ 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);
- }
- }
-
- // 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_);
+ if (thread_get_state(profiled_thread,
+ flavor,
+ reinterpret_cast<natural_t*>(&state),
+ &count) == KERN_SUCCESS) {
+ sample->state = sampler->isolate()->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);
}
+ thread_resume(profiled_thread);
}
+
+ const int interval_;
+ RuntimeProfilerRateLimiter rate_limiter_;
+
+ // Protects the process wide state below.
+ static Mutex* mutex_;
+ static SamplerThread* instance_;
+
+ DISALLOW_COPY_AND_ASSIGN(SamplerThread);
};
#undef REGISTER_FIELD
-// Entry point for sampler thread.
-static void* SamplerEntry(void* arg) {
- Sampler::PlatformData* data =
- reinterpret_cast<Sampler::PlatformData*>(arg);
- Thread::SetThreadLocal(Isolate::isolate_key(), data->sampler_->isolate());
- data->Runner();
- return 0;
-}
+Mutex* SamplerThread::mutex_ = OS::CreateMutex();
+SamplerThread* SamplerThread::instance_ = NULL;
-Sampler::Sampler(Isolate* isolate, int interval, bool profiling)
+Sampler::Sampler(Isolate* isolate, int interval)
: isolate_(isolate),
interval_(interval),
- synchronous_(profiling),
- profiling_(profiling),
+ profiling_(false),
active_(false),
samples_taken_(0) {
- data_ = new PlatformData(this);
+ data_ = new PlatformData;
}
Sampler::~Sampler() {
+ ASSERT(!IsActive());
delete data_;
}
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();
- }
-
- // Create sampler thread with high priority.
- // According to POSIX spec, when SCHED_FIFO policy is used, a thread
- // runs until it exits or blocks.
- pthread_attr_t sched_attr;
- sched_param fifo_param;
- pthread_attr_init(&sched_attr);
- pthread_attr_setinheritsched(&sched_attr, PTHREAD_EXPLICIT_SCHED);
- pthread_attr_setschedpolicy(&sched_attr, SCHED_FIFO);
- fifo_param.sched_priority = sched_get_priority_max(SCHED_FIFO);
- pthread_attr_setschedparam(&sched_attr, &fifo_param);
-
- active_ = true;
- pthread_create(&data_->sampler_thread_, &sched_attr, SamplerEntry, data_);
+ ASSERT(!IsActive());
+ SetActive(true);
+ SamplerThread::AddActiveSampler(this);
}
void Sampler::Stop() {
- // Seting active to false triggers termination of the sampler
- // thread.
- active_ = false;
-
- // Wait for sampler thread to terminate.
- pthread_join(data_->sampler_thread_, NULL);
-
- // Deallocate Mach port for thread.
- if (IsSynchronous()) {
- mach_port_deallocate(data_->task_self_, data_->profiled_thread_);
- }
+ ASSERT(IsActive());
+ SamplerThread::RemoveActiveSampler(this);
+ SetActive(false);
}
#endif // ENABLE_LOGGING_AND_PROFILING
« no previous file with comments | « src/platform-linux.cc ('k') | src/platform-nullos.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698