| Index: src/v8threads.cc
|
| ===================================================================
|
| --- src/v8threads.cc (revision 3427)
|
| +++ src/v8threads.cc (working copy)
|
| @@ -36,22 +36,13 @@
|
|
|
| namespace v8 {
|
|
|
| -static internal::Thread::LocalStorageKey thread_state_key =
|
| - internal::Thread::CreateThreadLocalKey();
|
| -static internal::Thread::LocalStorageKey thread_id_key =
|
| - internal::Thread::CreateThreadLocalKey();
|
| -
|
| -
|
| -// Track whether this V8 instance has ever called v8::Locker. This allows the
|
| -// API code to verify that the lock is always held when V8 is being entered.
|
| -bool Locker::active_ = false;
|
| -
|
| -
|
| // Constructor for the Locker object. Once the Locker is constructed the
|
| // current thread will be guaranteed to have the big V8 lock.
|
| Locker::Locker() : has_lock_(false), top_level_(true) {
|
| + internal::V8Context* const v8context = v8_context();
|
| +
|
| // Record that the Locker has been used at least once.
|
| - active_ = true;
|
| + v8context->v8_data_.active_ = true;
|
| // Get the big lock if necessary.
|
| if (!internal::ThreadManager::IsLockedByCurrentThread()) {
|
| internal::ThreadManager::Lock();
|
| @@ -78,6 +69,9 @@
|
| internal::ThreadManager::AssignId();
|
| }
|
|
|
| +bool Locker::IsActive() {
|
| + return v8_context()->v8_data_.active_;
|
| +}
|
|
|
| bool Locker::IsLocked() {
|
| return internal::ThreadManager::IsLockedByCurrentThread();
|
| @@ -125,17 +119,21 @@
|
|
|
|
|
| bool ThreadManager::RestoreThread() {
|
| + ThreadManagerData& thread_manager_data = v8_context()->thread_manager_data_;
|
| // First check whether the current thread has been 'lazily archived', ie
|
| // not archived at all. If that is the case we put the state storage we
|
| // had prepared back in the free list, since we didn't need it after all.
|
| - if (lazily_archived_thread_.IsSelf()) {
|
| - lazily_archived_thread_.Initialize(ThreadHandle::INVALID);
|
| - ASSERT(Thread::GetThreadLocal(thread_state_key) ==
|
| - lazily_archived_thread_state_);
|
| - lazily_archived_thread_state_->set_id(kInvalidId);
|
| - lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST);
|
| - lazily_archived_thread_state_ = NULL;
|
| - Thread::SetThreadLocal(thread_state_key, NULL);
|
| + if (thread_manager_data.lazily_archived_thread_.IsSelf()) {
|
| + thread_manager_data.lazily_archived_thread_.Initialize(
|
| + ThreadHandle::INVALID);
|
| + ASSERT(Thread::GetThreadLocal(thread_manager_data.thread_state_key_) ==
|
| + thread_manager_data.lazily_archived_thread_state_);
|
| + thread_manager_data.lazily_archived_thread_state_->set_id(kInvalidId);
|
| + thread_manager_data.lazily_archived_thread_state_->LinkInto(
|
| + ThreadState::FREE_LIST);
|
| +
|
| + thread_manager_data.lazily_archived_thread_state_ = NULL;
|
| + Thread::SetThreadLocal(thread_manager_data.thread_state_key_, NULL);
|
| return true;
|
| }
|
|
|
| @@ -145,11 +143,11 @@
|
|
|
| // If there is another thread that was lazily archived then we have to really
|
| // archive it now.
|
| - if (lazily_archived_thread_.IsValid()) {
|
| + if (thread_manager_data.lazily_archived_thread_.IsValid()) {
|
| EagerlyArchiveThread();
|
| }
|
| - ThreadState* state =
|
| - reinterpret_cast<ThreadState*>(Thread::GetThreadLocal(thread_state_key));
|
| + ThreadState* state = reinterpret_cast<ThreadState*>(
|
| + Thread::GetThreadLocal(thread_manager_data.thread_state_key_));
|
| if (state == NULL) {
|
| // This is a new thread.
|
| StackGuard::InitThread(access);
|
| @@ -165,7 +163,7 @@
|
| from = StackGuard::RestoreStackGuard(from);
|
| from = RegExpStack::RestoreStack(from);
|
| from = Bootstrapper::RestoreState(from);
|
| - Thread::SetThreadLocal(thread_state_key, NULL);
|
| + Thread::SetThreadLocal(thread_manager_data.thread_state_key_, NULL);
|
| if (state->terminate_on_restore()) {
|
| StackGuard::TerminateExecution();
|
| state->set_terminate_on_restore(false);
|
| @@ -178,15 +176,17 @@
|
|
|
|
|
| void ThreadManager::Lock() {
|
| - mutex_->Lock();
|
| - mutex_owner_.Initialize(ThreadHandle::SELF);
|
| + v8_context()->thread_manager_data_.mutex_->Lock();
|
| + v8_context()->thread_manager_data_.mutex_owner_.Initialize(
|
| + ThreadHandle::SELF);
|
| ASSERT(IsLockedByCurrentThread());
|
| }
|
|
|
|
|
| void ThreadManager::Unlock() {
|
| - mutex_owner_.Initialize(ThreadHandle::INVALID);
|
| - mutex_->Unlock();
|
| + v8_context()->thread_manager_data_.mutex_owner_.Initialize(
|
| + ThreadHandle::INVALID);
|
| + v8_context()->thread_manager_data_.mutex_->Unlock();
|
| }
|
|
|
|
|
| @@ -203,8 +203,6 @@
|
| }
|
|
|
|
|
| -ThreadState* ThreadState::free_anchor_ = new ThreadState();
|
| -ThreadState* ThreadState::in_use_anchor_ = new ThreadState();
|
|
|
|
|
| ThreadState::ThreadState() : id_(ThreadManager::kInvalidId),
|
| @@ -225,8 +223,9 @@
|
|
|
|
|
| void ThreadState::LinkInto(List list) {
|
| - ThreadState* flying_anchor =
|
| - list == FREE_LIST ? free_anchor_ : in_use_anchor_;
|
| + ThreadState* flying_anchor = list == FREE_LIST ?
|
| + v8_context()->thread_manager_data_.free_anchor_
|
| + : v8_context()->thread_manager_data_.in_use_anchor_;
|
| next_ = flying_anchor->next_;
|
| previous_ = flying_anchor;
|
| flying_anchor->next_ = this;
|
| @@ -235,8 +234,8 @@
|
|
|
|
|
| ThreadState* ThreadState::GetFree() {
|
| - ThreadState* gotten = free_anchor_->next_;
|
| - if (gotten == free_anchor_) {
|
| + ThreadState* gotten = v8_context()->thread_manager_data_.free_anchor_->next_;
|
| + if (gotten == v8_context()->thread_manager_data_.free_anchor_) {
|
| ThreadState* new_thread_state = new ThreadState();
|
| new_thread_state->AllocateSpace();
|
| return new_thread_state;
|
| @@ -247,34 +246,43 @@
|
|
|
| // Gets the first in the list of archived threads.
|
| ThreadState* ThreadState::FirstInUse() {
|
| - return in_use_anchor_->Next();
|
| + return v8_context()->thread_manager_data_.in_use_anchor_->Next();
|
| }
|
|
|
|
|
| ThreadState* ThreadState::Next() {
|
| - if (next_ == in_use_anchor_) return NULL;
|
| + if (next_ == v8_context()->thread_manager_data_.in_use_anchor_) return NULL;
|
| return next_;
|
| }
|
|
|
|
|
| +ThreadManagerData::ThreadManagerData()
|
| // Thread ids must start with 1, because in TLS having thread id 0 can't
|
| // be distinguished from not having a thread id at all (since NULL is
|
| // defined as 0.)
|
| -int ThreadManager::last_id_ = 0;
|
| -Mutex* ThreadManager::mutex_ = OS::CreateMutex();
|
| -ThreadHandle ThreadManager::mutex_owner_(ThreadHandle::INVALID);
|
| -ThreadHandle ThreadManager::lazily_archived_thread_(ThreadHandle::INVALID);
|
| -ThreadState* ThreadManager::lazily_archived_thread_state_ = NULL;
|
| + :last_id_(0),
|
| + mutex_(OS::CreateMutex()),
|
| + mutex_owner_(ThreadHandle::INVALID),
|
| + lazily_archived_thread_(ThreadHandle::INVALID),
|
| + lazily_archived_thread_state_(NULL),
|
| + free_anchor_(new ThreadState()),
|
| + in_use_anchor_(new ThreadState()),
|
| + singleton_(NULL),
|
| + thread_state_key_(Thread::CreateThreadLocalKey()),
|
| + thread_id_key_(Thread::CreateThreadLocalKey()) {
|
| +}
|
|
|
| -
|
| void ThreadManager::ArchiveThread() {
|
| - ASSERT(!lazily_archived_thread_.IsValid());
|
| + ThreadManagerData& thread_manager_data = v8_context()->thread_manager_data_;
|
| + ASSERT(!thread_manager_data.lazily_archived_thread_.IsValid());
|
| ASSERT(!IsArchived());
|
| ThreadState* state = ThreadState::GetFree();
|
| state->Unlink();
|
| - Thread::SetThreadLocal(thread_state_key, reinterpret_cast<void*>(state));
|
| - lazily_archived_thread_.Initialize(ThreadHandle::SELF);
|
| - lazily_archived_thread_state_ = state;
|
| + Thread::SetThreadLocal(thread_manager_data .thread_state_key_,
|
| + reinterpret_cast<void*>(state));
|
| +
|
| + thread_manager_data.lazily_archived_thread_.Initialize(ThreadHandle::SELF);
|
| + thread_manager_data.lazily_archived_thread_state_ = state;
|
| ASSERT(state->id() == kInvalidId);
|
| state->set_id(CurrentId());
|
| ASSERT(state->id() != kInvalidId);
|
| @@ -282,7 +290,8 @@
|
|
|
|
|
| void ThreadManager::EagerlyArchiveThread() {
|
| - ThreadState* state = lazily_archived_thread_state_;
|
| + ThreadManagerData& thread_manager_data = v8_context()->thread_manager_data_;
|
| + ThreadState* state = thread_manager_data.lazily_archived_thread_state_;
|
| state->LinkInto(ThreadState::IN_USE_LIST);
|
| char* to = state->data();
|
| // Ensure that data containing GC roots are archived first, and handle them
|
| @@ -296,8 +305,8 @@
|
| to = StackGuard::ArchiveStackGuard(to);
|
| to = RegExpStack::ArchiveStack(to);
|
| to = Bootstrapper::ArchiveState(to);
|
| - lazily_archived_thread_.Initialize(ThreadHandle::INVALID);
|
| - lazily_archived_thread_state_ = NULL;
|
| + thread_manager_data.lazily_archived_thread_.Initialize(ThreadHandle::INVALID);
|
| + thread_manager_data.lazily_archived_thread_state_ = NULL;
|
| }
|
|
|
|
|
| @@ -314,7 +323,8 @@
|
|
|
|
|
| bool ThreadManager::IsArchived() {
|
| - return Thread::HasThreadLocal(thread_state_key);
|
| + return Thread::HasThreadLocal(
|
| + v8_context()->thread_manager_data_.thread_state_key_);
|
| }
|
|
|
|
|
| @@ -354,23 +364,26 @@
|
|
|
|
|
| int ThreadManager::CurrentId() {
|
| - return Thread::GetThreadLocalInt(thread_id_key);
|
| + return Thread::GetThreadLocalInt(
|
| + v8_context()->thread_manager_data_.thread_id_key_);
|
| }
|
|
|
|
|
| void ThreadManager::AssignId() {
|
| if (!HasId()) {
|
| ASSERT(Locker::IsLocked());
|
| - int thread_id = ++last_id_;
|
| + ThreadManagerData& thread_manager_data = v8_context()->thread_manager_data_;
|
| + int thread_id = ++thread_manager_data.last_id_;
|
| ASSERT(thread_id > 0); // see the comment near last_id_ definition.
|
| - Thread::SetThreadLocalInt(thread_id_key, thread_id);
|
| + Thread::SetThreadLocalInt(thread_manager_data.thread_id_key_, thread_id);
|
| Top::set_thread_id(thread_id);
|
| }
|
| }
|
|
|
|
|
| bool ThreadManager::HasId() {
|
| - return Thread::HasThreadLocal(thread_id_key);
|
| + return Thread::HasThreadLocal(
|
| + v8_context()->thread_manager_data_.thread_id_key_);
|
| }
|
|
|
|
|
| @@ -384,12 +397,6 @@
|
| }
|
| }
|
|
|
| -
|
| -// This is the ContextSwitcher singleton. There is at most a single thread
|
| -// running which delivers preemption events to V8 threads.
|
| -ContextSwitcher* ContextSwitcher::singleton_ = NULL;
|
| -
|
| -
|
| ContextSwitcher::ContextSwitcher(int every_n_ms)
|
| : keep_going_(true),
|
| sleep_ms_(every_n_ms) {
|
| @@ -400,14 +407,15 @@
|
| // ContextSwitcher thread if needed.
|
| void ContextSwitcher::StartPreemption(int every_n_ms) {
|
| ASSERT(Locker::IsLocked());
|
| - if (singleton_ == NULL) {
|
| + ContextSwitcher* & singleton = v8_context()->thread_manager_data_.singleton_;
|
| + if (singleton == NULL) {
|
| // If the ContextSwitcher thread is not running at the moment start it now.
|
| - singleton_ = new ContextSwitcher(every_n_ms);
|
| - singleton_->Start();
|
| + singleton = new ContextSwitcher(every_n_ms);
|
| + singleton->Start();
|
| } else {
|
| // ContextSwitcher thread is already running, so we just change the
|
| // scheduling interval.
|
| - singleton_->sleep_ms_ = every_n_ms;
|
| + singleton->sleep_ms_ = every_n_ms;
|
| }
|
| }
|
|
|
| @@ -416,14 +424,15 @@
|
| // must cooperatively schedule amongst them from this point on.
|
| void ContextSwitcher::StopPreemption() {
|
| ASSERT(Locker::IsLocked());
|
| - if (singleton_ != NULL) {
|
| + ContextSwitcher* & singleton = v8_context()->thread_manager_data_.singleton_;
|
| + if (singleton != NULL) {
|
| // The ContextSwitcher thread is running. We need to stop it and release
|
| // its resources.
|
| - singleton_->keep_going_ = false;
|
| - singleton_->Join(); // Wait for the ContextSwitcher thread to exit.
|
| + singleton->keep_going_ = false;
|
| + singleton->Join(); // Wait for the ContextSwitcher thread to exit.
|
| // Thread has exited, now we can delete it.
|
| - delete(singleton_);
|
| - singleton_ = NULL;
|
| + delete(singleton);
|
| + singleton = NULL;
|
| }
|
| }
|
|
|
|
|