char* Isolate::ArchiveThread(char* to) {
- if (RuntimeProfiler::IsEnabled() && current_vm_state() == JS) {
- RuntimeProfiler::IsolateExitedJS(this);
- }
memcpy(to, reinterpret_cast<char*>(thread_local_top()),
sizeof(ThreadLocalTop));
InitializeThreadLocal();
thread_local_top()->simulator_ = Simulator::current(this);
#endif
#endif
- if (RuntimeProfiler::IsEnabled() && current_vm_state() == JS) {
- RuntimeProfiler::IsolateEnteredJS(this);
- }
ASSERT(context() == NULL || context()->IsContext());
return from + sizeof(ThreadLocalTop);
}
}
void SetCurrentVMState(StateTag state) {
- if (RuntimeProfiler::IsEnabled()) {
- // Make sure thread local top is initialized.
- ASSERT(thread_local_top_.isolate_ == this);
- StateTag current_state = thread_local_top_.current_vm_state_;
- if (current_state != JS && state == JS) {
- // Non-JS -> JS transition.
- RuntimeProfiler::IsolateEnteredJS(this);
- } else if (current_state == JS && state != JS) {
- // JS -> non-JS transition.
- RuntimeProfiler::IsolateExitedJS(this);
- } else {
- // Other types of state transitions are not interesting to the
- // runtime profiler, because they don't affect whether we're
- // in JS or not.
- ASSERT((current_state == JS) == (state == JS));
- }
- }
thread_local_top_.current_vm_state_ = state;
}
ScopedLock lock(mutex_);
SamplerRegistry::RemoveActiveSampler(sampler);
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
- RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
+ instance_->Join();
delete instance_;
instance_ = NULL;
}
// profiled. We must not suspend.
if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) {
SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this);
- } else {
- if (RuntimeProfiler::WaitForSomeIsolateToEnterJS()) continue;
}
OS::Sleep(interval_);
}
ScopedLock lock(mutex_);
SamplerRegistry::RemoveActiveSampler(sampler);
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
- RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
+ instance_->Join();
delete instance_;
instance_ = NULL;
// profiled. We must not suspend.
if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) {
SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this);
- } else {
- if (RuntimeProfiler::WaitForSomeIsolateToEnterJS()) continue;
}
Sleep(); // TODO(svenpanne) Figure out if OS:Sleep(interval_) is enough.
}
ScopedLock lock(mutex_);
SamplerRegistry::RemoveActiveSampler(sampler);
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
- RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
+ instance_->Join();
delete instance_;
instance_ = NULL;
RestoreSignalHandler();
SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this);
} else {
if (signal_handler_installed_) RestoreSignalHandler();
- if (RuntimeProfiler::WaitForSomeIsolateToEnterJS()) continue;
}
Sleep(); // TODO(svenpanne) Figure out if OS:Sleep(interval_) is enough.
}
ScopedLock lock(mutex_);
SamplerRegistry::RemoveActiveSampler(sampler);
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
- RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
+ instance_->Join();
delete instance_;
instance_ = NULL;
}
// profiled. We must not suspend.
if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) {
SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this);
- } else {
- if (RuntimeProfiler::WaitForSomeIsolateToEnterJS()) continue;
}
OS::Sleep(interval_);
}
ScopedLock lock(mutex_);
SamplerRegistry::RemoveActiveSampler(sampler);
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
- RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
+ instance_->Join();
delete instance_;
instance_ = NULL;
RestoreSignalHandler();
if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) {
if (!signal_handler_installed_) InstallSignalHandler();
SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this);
- } else {
- if (signal_handler_installed_) RestoreSignalHandler();
- if (RuntimeProfiler::WaitForSomeIsolateToEnterJS()) continue;
+ } else if (signal_handler_installed_) {
+ RestoreSignalHandler();
}
Sleep(); // TODO(svenpanne) Figure out if OS:Sleep(interval_) is enough.
}
ScopedLock lock(mutex_);
SamplerRegistry::RemoveActiveSampler(sampler);
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
- RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
+ instance_->Join();
delete instance_;
instance_ = NULL;
RestoreSignalHandler();
if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) {
if (!signal_handler_installed_) InstallSignalHandler();
SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this);
- } else {
- if (signal_handler_installed_) RestoreSignalHandler();
- if (RuntimeProfiler::WaitForSomeIsolateToEnterJS()) continue;
+ } else if (signal_handler_installed_) {
+ RestoreSignalHandler();
}
Sleep(); // TODO(svenpanne) Figure out if OS:Sleep(interval_) is enough.
}
ScopedLock lock(mutex_);
SamplerRegistry::RemoveActiveSampler(sampler);
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
- RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
+ instance_->Join();
delete instance_;
instance_ = NULL;
}
// profiled. We must not suspend.
if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) {
SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this);
- } else {
- if (RuntimeProfiler::WaitForSomeIsolateToEnterJS()) continue;
}
OS::Sleep(interval_);
}
5 * FullCodeGenerator::kBackEdgeDistanceUnit;
-Atomic32 RuntimeProfiler::state_ = 0;
-
-// TODO(isolates): Clean up the semaphore when it is no longer required.
-static LazySemaphore<0>::type semaphore = LAZY_SEMAPHORE_INITIALIZER;
-
-#ifdef DEBUG
-bool RuntimeProfiler::has_been_globally_set_up_ = false;
-#endif
-bool RuntimeProfiler::enabled_ = false;
-
-
RuntimeProfiler::RuntimeProfiler(Isolate* isolate)
: isolate_(isolate),
sampler_threshold_(kSamplerThresholdInit),
}
-void RuntimeProfiler::GlobalSetUp() {
- ASSERT(!has_been_globally_set_up_);
- enabled_ = V8::UseCrankshaft() && FLAG_opt;
-#ifdef DEBUG
- has_been_globally_set_up_ = true;
-#endif
-}
-
-
static void GetICCounts(JSFunction* function,
int* ic_with_type_info_count,
int* ic_total_count,
void RuntimeProfiler::SetUp() {
- ASSERT(has_been_globally_set_up_);
if (!FLAG_watch_ic_patching) {
ClearSampleBuffer();
}
}
-void RuntimeProfiler::HandleWakeUp(Isolate* isolate) {
- // The profiler thread must still be waiting.
- ASSERT(NoBarrier_Load(&state_) >= 0);
- // In IsolateEnteredJS we have already incremented the counter and
- // undid the decrement done by the profiler thread. Increment again
- // to get the right count of active isolates.
- NoBarrier_AtomicIncrement(&state_, 1);
- semaphore.Pointer()->Signal();
-}
-
-
-bool RuntimeProfiler::WaitForSomeIsolateToEnterJS() {
- Atomic32 old_state = NoBarrier_CompareAndSwap(&state_, 0, -1);
- ASSERT(old_state >= -1);
- if (old_state != 0) return false;
- semaphore.Pointer()->Wait();
- return true;
-}
-
-
-void RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(Thread* thread) {
- // Do a fake increment. If the profiler is waiting on the semaphore,
- // the returned state is 0, which can be left as an initial state in
- // case profiling is restarted later. If the profiler is not
- // waiting, the increment will prevent it from waiting, but has to
- // be undone after the profiler is stopped.
- Atomic32 new_state = NoBarrier_AtomicIncrement(&state_, 1);
- ASSERT(new_state >= 0);
- if (new_state == 0) {
- // The profiler thread is waiting. Wake it up. It must check for
- // stop conditions before attempting to wait again.
- semaphore.Pointer()->Signal();
- }
- thread->Join();
- // The profiler thread is now stopped. Undo the increment in case it
- // was not waiting.
- if (new_state != 0) {
- NoBarrier_AtomicIncrement(&state_, -1);
- }
-}
-
-
void RuntimeProfiler::RemoveDeadSamples() {
for (int i = 0; i < kSamplerWindowSize; i++) {
Object* function = sampler_window_[i];
public:
explicit RuntimeProfiler(Isolate* isolate);
- static void GlobalSetUp();
-
- static inline bool IsEnabled() {
- ASSERT(has_been_globally_set_up_);
- return enabled_;
- }
-
void OptimizeNow();
void SetUp();
// Rate limiting support.
- // VM thread interface.
- //
- // Called by isolates when their states change.
- static inline void IsolateEnteredJS(Isolate* isolate);
- static inline void IsolateExitedJS(Isolate* isolate);
-
- // Profiler thread interface.
- //
- // WaitForSomeIsolateToEnterJS():
- // When no isolates are running JavaScript code for some time the
- // profiler thread suspends itself by calling the wait function. The
- // wait function returns true after it waited or false immediately.
- // While the function was waiting the profiler may have been
- // disabled so it *must check* whether it is allowed to continue.
- static bool WaitForSomeIsolateToEnterJS();
-
- // Stops the runtime profiler thread when profiling support is being
- // turned off.
- static void StopRuntimeProfilerThreadBeforeShutdown(Thread* thread);
-
void UpdateSamplesAfterScavenge();
void RemoveDeadSamples();
void UpdateSamplesAfterCompact(ObjectVisitor* visitor);
private:
static const int kSamplerWindowSize = 16;
- static void HandleWakeUp(Isolate* isolate);
-
void Optimize(JSFunction* function, const char* reason);
void ClearSampleBuffer();
bool any_ic_changed_;
bool code_generated_;
-
- // Possible state values:
- // -1 => the profiler thread is waiting on the semaphore
- // 0 or positive => the number of isolates running JavaScript code.
- static Atomic32 state_;
-
-#ifdef DEBUG
- static bool has_been_globally_set_up_;
-#endif
- static bool enabled_;
};
-
-// Implementation of RuntimeProfiler inline functions.
-
-void RuntimeProfiler::IsolateEnteredJS(Isolate* isolate) {
- Atomic32 new_state = NoBarrier_AtomicIncrement(&state_, 1);
- if (new_state == 0) {
- // Just incremented from -1 to 0. -1 can only be set by the
- // profiler thread before it suspends itself and starts waiting on
- // the semaphore.
- HandleWakeUp(isolate);
- }
- ASSERT(new_state >= 0);
-}
-
-
-void RuntimeProfiler::IsolateExitedJS(Isolate* isolate) {
- Atomic32 new_state = NoBarrier_AtomicIncrement(&state_, -1);
- ASSERT(new_state >= 0);
- USE(new_state);
-}
-
} } // namespace v8::internal
#endif // V8_RUNTIME_PROFILER_H_
&& !Serializer::enabled()
&& CPU::SupportsCrankshaft();
OS::PostSetUp();
- RuntimeProfiler::GlobalSetUp();
ElementsAccessor::InitializeOncePerProcess();
LOperand::SetUpCaches();
SetUpJSCallerSavedCodeData();