o The thread local state in an isolate has to be initialized before
it's used.
o v8::Locker was incorrectly tracking whether it's the topmost one.
o Waking the profiler thread on shutdown should not leave the
semaphore counter in an inconsitent state.
R=fschneider@chromium.org
BUG=v8:1522
TEST=cctest/test-lockers/Regress1433
Review URL: http://codereview.chromium.org/7309013
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8537
ce2b1a6d-e550-0410-aec6-
3dcde31c8c00
void StackGuard::FreeThreadResources() {
- Isolate::CurrentPerIsolateThreadData()->set_stack_limit(
- thread_local_.real_climit_);
+ Isolate::PerIsolateThreadData* per_thread =
+ isolate_->FindOrAllocatePerThreadDataForThisThread();
+ per_thread->set_stack_limit(thread_local_.real_climit_);
}
uintptr_t stored_limit = per_thread->stack_limit();
// You should hold the ExecutionAccess lock when you call this.
if (stored_limit != 0) {
- StackGuard::SetStackLimit(stored_limit);
+ SetStackLimit(stored_limit);
}
}
return false;
}
+ InitializeThreadLocal();
+
bootstrapper_->Initialize(create_heap_objects);
builtins_.Setup(create_heap_objects);
- InitializeThreadLocal();
-
// Only preallocate on the first initialization.
if (FLAG_preallocate_message_memory && preallocated_message_space_ == NULL) {
// Start the thread which will set aside some memory.
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.
ScopedLock lock(mutex_);
SamplerRegistry::RemoveActiveSampler(sampler);
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
- RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
- instance_->Join();
+ RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
delete instance_;
instance_ = NULL;
}
ScopedLock lock(mutex_);
SamplerRegistry::RemoveActiveSampler(sampler);
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
- RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
- instance_->Join();
+ RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
delete instance_;
instance_ = NULL;
ScopedLock lock(mutex_);
SamplerRegistry::RemoveActiveSampler(sampler);
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
- RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
- instance_->Join();
+ RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
delete instance_;
instance_ = NULL;
RestoreSignalHandler();
ScopedLock lock(mutex_);
SamplerRegistry::RemoveActiveSampler(sampler);
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
- RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
- instance_->Join();
+ RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
delete instance_;
instance_ = NULL;
}
ScopedLock lock(mutex_);
SamplerRegistry::RemoveActiveSampler(sampler);
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
- RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
- instance_->Join();
+ RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
delete instance_;
instance_ = NULL;
ScopedLock lock(mutex_);
SamplerRegistry::RemoveActiveSampler(sampler);
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
- RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
- instance_->Join();
+ RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
delete instance_;
instance_ = NULL;
RestoreSignalHandler();
ScopedLock lock(mutex_);
SamplerRegistry::RemoveActiveSampler(sampler);
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
- RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
- instance_->Join();
+ RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
delete instance_;
instance_ = NULL;
}
}
-void RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown() {
+void RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(Thread* thread) {
#ifdef ENABLE_LOGGING_AND_PROFILING
- semaphore_->Signal();
+ // 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_->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);
+ }
#endif
}
static bool IsSomeIsolateInJS();
static bool WaitForSomeIsolateToEnterJS();
- // When shutting down we join the profiler thread. Doing so while
- // it's waiting on a semaphore will cause a deadlock, so we have to
- // wake it up first.
- static void WakeUpRuntimeProfilerThreadBeforeShutdown();
+ // Stops the runtime profiler thread when profiling support is being
+ // turned off.
+ static void StopRuntimeProfilerThreadBeforeShutdown(Thread* thread);
void UpdateSamplesAfterScavenge();
void RemoveDeadSamples();
// current thread will be guaranteed to have the lock for a given isolate.
Locker::Locker(v8::Isolate* isolate)
: has_lock_(false),
- top_level_(false),
+ top_level_(true),
isolate_(reinterpret_cast<i::Isolate*>(isolate)) {
if (isolate_ == NULL) {
isolate_ = i::Isolate::GetDefaultIsolateForLocking();