1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/v8threads.h" 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/api.h" 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/bootstrapper.h" 9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/debug/debug.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/execution.h" 11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/isolate-inl.h" 12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/regexp/regexp-stack.h" 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace { 18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Track whether this V8 instance has ever called v8::Locker. This allows the 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// API code to verify that the lock is always held when V8 is being entered. 21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierbase::Atomic32 g_locker_was_ever_used_ = 0; 22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} // namespace 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Once the Locker is initialized, the current thread will be guaranteed to have 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// the lock for a given isolate. 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Locker::Initialize(v8::Isolate* isolate) { 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(isolate != NULL); 30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier has_lock_ = false; 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch top_level_ = true; 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate_ = reinterpret_cast<i::Isolate*>(isolate); 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Record that the Locker has been used at least once. 34958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier base::NoBarrier_Store(&g_locker_was_ever_used_, 1); 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the big lock if necessary. 36257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!isolate_->thread_manager()->IsLockedByCurrentThread()) { 37257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate_->thread_manager()->Lock(); 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block has_lock_ = true; 3944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This may be a locker within an unlocker in which case we have to 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // get the saved state for this thread and restore it. 42257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (isolate_->thread_manager()->RestoreThread()) { 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block top_level_ = false; 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 45257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch internal::ExecutionAccess access(isolate_); 46257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate_->stack_guard()->ClearThread(access); 47257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate_->stack_guard()->InitThread(access); 48257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread()); 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 54257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochbool Locker::IsLocked(v8::Isolate* isolate) { 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(isolate != NULL); 56257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 57257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return internal_isolate->thread_manager()->IsLockedByCurrentThread(); 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochbool Locker::IsActive() { 62958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return !!base::NoBarrier_Load(&g_locker_was_ever_used_); 6369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} 6469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 6569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockLocker::~Locker() { 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread()); 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (has_lock_) { 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (top_level_) { 70257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate_->thread_manager()->FreeThreadResources(); 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 72257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate_->thread_manager()->ArchiveThread(); 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 74257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate_->thread_manager()->Unlock(); 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Unlocker::Initialize(v8::Isolate* isolate) { 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(isolate != NULL); 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate_ = reinterpret_cast<i::Isolate*>(isolate); 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread()); 83257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate_->thread_manager()->ArchiveThread(); 84257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate_->thread_manager()->Unlock(); 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockUnlocker::~Unlocker() { 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!isolate_->thread_manager()->IsLockedByCurrentThread()); 90257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate_->thread_manager()->Lock(); 91257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate_->thread_manager()->RestoreThread(); 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool ThreadManager::RestoreThread() { 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsLockedByCurrentThread()); 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // First check whether the current thread has been 'lazily archived', i.e. 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // not archived at all. If that is the case we put the state storage we 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // had prepared back in the free list, since we didn't need it after all. 1038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (lazily_archived_thread_.Equals(ThreadId::Current())) { 1048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch lazily_archived_thread_ = ThreadId::Invalid(); 105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Isolate::PerIsolateThreadData* per_thread = 106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate_->FindPerThreadDataForThisThread(); 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(per_thread != NULL); 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(per_thread->thread_state() == lazily_archived_thread_state_); 1098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch lazily_archived_thread_state_->set_id(ThreadId::Invalid()); 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST); 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lazily_archived_thread_state_ = NULL; 112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch per_thread->set_thread_state(NULL); 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that the preemption thread cannot modify the thread state while 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // it is being archived or restored. 11844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExecutionAccess access(isolate_); 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If there is another thread that was lazily archived then we have to really 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // archive it now. 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (lazily_archived_thread_.IsValid()) { 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block EagerlyArchiveThread(); 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 12544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate::PerIsolateThreadData* per_thread = 126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate_->FindPerThreadDataForThisThread(); 12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (per_thread == NULL || per_thread->thread_state() == NULL) { 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This is a new thread. 12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_->stack_guard()->InitThread(access); 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ThreadState* state = per_thread->thread_state(); 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* from = state->data(); 13444f0eee88ff00398ff7f715fab053374d808c90dSteve Block from = isolate_->handle_scope_implementer()->RestoreThread(from); 13544f0eee88ff00398ff7f715fab053374d808c90dSteve Block from = isolate_->RestoreThread(from); 136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch from = Relocatable::RestoreState(isolate_, from); 13744f0eee88ff00398ff7f715fab053374d808c90dSteve Block from = isolate_->debug()->RestoreDebug(from); 13844f0eee88ff00398ff7f715fab053374d808c90dSteve Block from = isolate_->stack_guard()->RestoreStackGuard(from); 13944f0eee88ff00398ff7f715fab053374d808c90dSteve Block from = isolate_->regexp_stack()->RestoreStack(from); 14044f0eee88ff00398ff7f715fab053374d808c90dSteve Block from = isolate_->bootstrapper()->RestoreState(from); 14144f0eee88ff00398ff7f715fab053374d808c90dSteve Block per_thread->set_thread_state(NULL); 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (state->terminate_on_restore()) { 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch isolate_->stack_guard()->RequestTerminateExecution(); 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state->set_terminate_on_restore(false); 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch state->set_id(ThreadId::Invalid()); 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state->Unlink(); 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state->LinkInto(ThreadState::FREE_LIST); 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ThreadManager::Lock() { 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mutex_.Lock(); 1558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch mutex_owner_ = ThreadId::Current(); 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsLockedByCurrentThread()); 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ThreadManager::Unlock() { 1618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch mutex_owner_ = ThreadId::Invalid(); 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mutex_.Unlock(); 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic int ArchiveSpacePerThread() { 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return HandleScopeImplementer::ArchiveSpacePerThread() + 16844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate::ArchiveSpacePerThread() + 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Debug::ArchiveSpacePerThread() + 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackGuard::ArchiveSpacePerThread() + 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegExpStack::ArchiveSpacePerThread() + 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Bootstrapper::ArchiveSpacePerThread() + 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Relocatable::ArchiveSpacePerThread(); 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17744f0eee88ff00398ff7f715fab053374d808c90dSteve BlockThreadState::ThreadState(ThreadManager* thread_manager) 1788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : id_(ThreadId::Invalid()), 17944f0eee88ff00398ff7f715fab053374d808c90dSteve Block terminate_on_restore_(false), 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch data_(NULL), 18144f0eee88ff00398ff7f715fab053374d808c90dSteve Block next_(this), 18244f0eee88ff00398ff7f715fab053374d808c90dSteve Block previous_(this), 18344f0eee88ff00398ff7f715fab053374d808c90dSteve Block thread_manager_(thread_manager) { 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochThreadState::~ThreadState() { 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeleteArray<char>(data_); 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ThreadState::AllocateSpace() { 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data_ = NewArray<char>(ArchiveSpacePerThread()); 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ThreadState::Unlink() { 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block next_->previous_ = previous_; 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block previous_->next_ = next_; 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ThreadState::LinkInto(List list) { 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ThreadState* flying_anchor = 20544f0eee88ff00398ff7f715fab053374d808c90dSteve Block list == FREE_LIST ? thread_manager_->free_anchor_ 20644f0eee88ff00398ff7f715fab053374d808c90dSteve Block : thread_manager_->in_use_anchor_; 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block next_ = flying_anchor->next_; 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block previous_ = flying_anchor; 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block flying_anchor->next_ = this; 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block next_->previous_ = this; 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21444f0eee88ff00398ff7f715fab053374d808c90dSteve BlockThreadState* ThreadManager::GetFreeThreadState() { 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ThreadState* gotten = free_anchor_->next_; 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (gotten == free_anchor_) { 21744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ThreadState* new_thread_state = new ThreadState(this); 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new_thread_state->AllocateSpace(); 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new_thread_state; 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return gotten; 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Gets the first in the list of archived threads. 22644f0eee88ff00398ff7f715fab053374d808c90dSteve BlockThreadState* ThreadManager::FirstThreadStateInUse() { 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return in_use_anchor_->Next(); 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockThreadState* ThreadState::Next() { 23244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (next_ == thread_manager_->in_use_anchor_) return NULL; 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return next_; 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Thread ids must start with 1, because in TLS having thread id 0 can't 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// be distinguished from not having a thread id at all (since NULL is 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// defined as 0.) 24044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockThreadManager::ThreadManager() 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : mutex_owner_(ThreadId::Invalid()), 2428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch lazily_archived_thread_(ThreadId::Invalid()), 24344f0eee88ff00398ff7f715fab053374d808c90dSteve Block lazily_archived_thread_state_(NULL), 24444f0eee88ff00398ff7f715fab053374d808c90dSteve Block free_anchor_(NULL), 24544f0eee88ff00398ff7f715fab053374d808c90dSteve Block in_use_anchor_(NULL) { 24644f0eee88ff00398ff7f715fab053374d808c90dSteve Block free_anchor_ = new ThreadState(this); 24744f0eee88ff00398ff7f715fab053374d808c90dSteve Block in_use_anchor_ = new ThreadState(this); 24844f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 24944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 25044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 25144f0eee88ff00398ff7f715fab053374d808c90dSteve BlockThreadManager::~ThreadManager() { 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeleteThreadStateList(free_anchor_); 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeleteThreadStateList(in_use_anchor_); 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid ThreadManager::DeleteThreadStateList(ThreadState* anchor) { 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The list starts and ends with the anchor. 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (ThreadState* current = anchor->next_; current != anchor;) { 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ThreadState* next = current->next_; 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch delete current; 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current = next; 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch delete anchor; 26544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ThreadManager::ArchiveThread() { 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(lazily_archived_thread_.Equals(ThreadId::Invalid())); 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!IsArchived()); 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsLockedByCurrentThread()); 27244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ThreadState* state = GetFreeThreadState(); 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state->Unlink(); 274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Isolate::PerIsolateThreadData* per_thread = 275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate_->FindOrAllocatePerThreadDataForThisThread(); 276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch per_thread->set_thread_state(state); 2778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch lazily_archived_thread_ = ThreadId::Current(); 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lazily_archived_thread_state_ = state; 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(state->id().Equals(ThreadId::Invalid())); 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state->set_id(CurrentId()); 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!state->id().Equals(ThreadId::Invalid())); 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ThreadManager::EagerlyArchiveThread() { 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsLockedByCurrentThread()); 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ThreadState* state = lazily_archived_thread_state_; 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state->LinkInto(ThreadState::IN_USE_LIST); 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* to = state->data(); 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Ensure that data containing GC roots are archived first, and handle them 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // in ThreadManager::Iterate(ObjectVisitor*). 29244f0eee88ff00398ff7f715fab053374d808c90dSteve Block to = isolate_->handle_scope_implementer()->ArchiveThread(to); 29344f0eee88ff00398ff7f715fab053374d808c90dSteve Block to = isolate_->ArchiveThread(to); 294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch to = Relocatable::ArchiveState(isolate_, to); 29544f0eee88ff00398ff7f715fab053374d808c90dSteve Block to = isolate_->debug()->ArchiveDebug(to); 29644f0eee88ff00398ff7f715fab053374d808c90dSteve Block to = isolate_->stack_guard()->ArchiveStackGuard(to); 29744f0eee88ff00398ff7f715fab053374d808c90dSteve Block to = isolate_->regexp_stack()->ArchiveStack(to); 29844f0eee88ff00398ff7f715fab053374d808c90dSteve Block to = isolate_->bootstrapper()->ArchiveState(to); 2998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch lazily_archived_thread_ = ThreadId::Invalid(); 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lazily_archived_thread_state_ = NULL; 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ThreadManager::FreeThreadResources() { 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!isolate_->has_pending_exception()); 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!isolate_->external_caught_exception()); 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(isolate_->try_catch_handler() == NULL); 30844f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_->handle_scope_implementer()->FreeThreadResources(); 30944f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_->FreeThreadResources(); 31044f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_->debug()->FreeThreadResources(); 31144f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_->stack_guard()->FreeThreadResources(); 31244f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_->regexp_stack()->FreeThreadResources(); 31344f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_->bootstrapper()->FreeThreadResources(); 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool ThreadManager::IsArchived() { 318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Isolate::PerIsolateThreadData* data = 319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate_->FindPerThreadDataForThisThread(); 32044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return data != NULL && data->thread_state() != NULL; 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ThreadManager::Iterate(ObjectVisitor* v) { 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Expecting no threads during serialization/deserialization 32644f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (ThreadState* state = FirstThreadStateInUse(); 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state != NULL; 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state = state->Next()) { 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block char* data = state->data(); 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data = HandleScopeImplementer::Iterate(v, data); 33144f0eee88ff00398ff7f715fab053374d808c90dSteve Block data = isolate_->Iterate(v, data); 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block data = Relocatable::Iterate(v, data); 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3377f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid ThreadManager::IterateArchivedThreads(ThreadVisitor* v) { 33844f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (ThreadState* state = FirstThreadStateInUse(); 3396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block state != NULL; 3406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block state = state->Next()) { 3416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block char* data = state->data(); 3426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block data += HandleScopeImplementer::ArchiveSpacePerThread(); 34344f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_->IterateThread(v, data); 3446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 3456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 3466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 3488b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochThreadId ThreadManager::CurrentId() { 3498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return ThreadId::Current(); 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid ThreadManager::TerminateExecution(ThreadId thread_id) { 35444f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (ThreadState* state = FirstThreadStateInUse(); 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state != NULL; 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state = state->Next()) { 3578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (thread_id.Equals(state->id())) { 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block state->set_terminate_on_restore(true); 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} // namespace internal 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} // namespace v8 366