1c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org// Copyright 2012 the V8 project authors. All rights reserved. 23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be 33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file. 443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h" 643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 7196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/api.h" 8196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/bootstrapper.h" 9196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/debug.h" 10196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/execution.h" 11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/regexp-stack.h" 124b0feeef5d01dbc2948080b4f69daa37e1083461machenbach@chromium.org#include "src/v8threads.h" 1343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 1443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansennamespace v8 { 1543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 16ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org 17ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org// Track whether this V8 instance has ever called v8::Locker. This allows the 18ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org// API code to verify that the lock is always held when V8 is being entered. 19ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.orgbool Locker::active_ = false; 20ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org 21ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org 2246a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org// Once the Locker is initialized, the current thread will be guaranteed to have 2346a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org// the lock for a given isolate. 2446a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.orgvoid Locker::Initialize(v8::Isolate* isolate) { 25e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(isolate != NULL); 2646a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org has_lock_= false; 2746a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org top_level_ = true; 2846a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org isolate_ = reinterpret_cast<i::Isolate*>(isolate); 29ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org // Record that the Locker has been used at least once. 30ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org active_ = true; 3143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Get the big lock if necessary. 321c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org if (!isolate_->thread_manager()->IsLockedByCurrentThread()) { 331c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org isolate_->thread_manager()->Lock(); 3443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen has_lock_ = true; 35ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 36c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org // Make sure that V8 is initialized. Archiving of threads interferes 37c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org // with deserialization by adding additional root pointers, so we must 38c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org // initialize here, before anyone can call ~Locker() or Unlocker(). 391c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org if (!isolate_->IsInitialized()) { 401c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org isolate_->Enter(); 41c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org V8::Initialize(); 421c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org isolate_->Exit(); 43c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org } 441c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org 4543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // This may be a locker within an unlocker in which case we have to 4643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // get the saved state for this thread and restore it. 471c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org if (isolate_->thread_manager()->RestoreThread()) { 4843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen top_level_ = false; 49c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org } else { 501c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org internal::ExecutionAccess access(isolate_); 511c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org isolate_->stack_guard()->ClearThread(access); 521c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org isolate_->stack_guard()->InitThread(access); 531c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org } 5443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 55e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread()); 5643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 5743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 5843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 591c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.orgbool Locker::IsLocked(v8::Isolate* isolate) { 60e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(isolate != NULL); 611c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); 621c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org return internal_isolate->thread_manager()->IsLockedByCurrentThread(); 6343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 6443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 6543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 667c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.orgbool Locker::IsActive() { 677c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org return active_; 687c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org} 697c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org 707c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org 7143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenLocker::~Locker() { 72e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread()); 7343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (has_lock_) { 74c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org if (top_level_) { 751c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org isolate_->thread_manager()->FreeThreadResources(); 76c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org } else { 771c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org isolate_->thread_manager()->ArchiveThread(); 7843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 791c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org isolate_->thread_manager()->Unlock(); 8043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 8143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 8243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 8343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 8446a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.orgvoid Unlocker::Initialize(v8::Isolate* isolate) { 85e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(isolate != NULL); 8646a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org isolate_ = reinterpret_cast<i::Isolate*>(isolate); 87e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread()); 881c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org isolate_->thread_manager()->ArchiveThread(); 891c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org isolate_->thread_manager()->Unlock(); 9043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 9143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 9243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 9343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenUnlocker::~Unlocker() { 94e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!isolate_->thread_manager()->IsLockedByCurrentThread()); 951c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org isolate_->thread_manager()->Lock(); 961c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org isolate_->thread_manager()->RestoreThread(); 9743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 9843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 9943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 10043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansennamespace internal { 10143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 10243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 10343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenbool ThreadManager::RestoreThread() { 104e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(IsLockedByCurrentThread()); 1052efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org // First check whether the current thread has been 'lazily archived', i.e. 10643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // not archived at all. If that is the case we put the state storage we 10743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // had prepared back in the free list, since we didn't need it after all. 108a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org if (lazily_archived_thread_.Equals(ThreadId::Current())) { 109a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org lazily_archived_thread_ = ThreadId::Invalid(); 1101c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Isolate::PerIsolateThreadData* per_thread = 1111c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org isolate_->FindPerThreadDataForThisThread(); 112e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(per_thread != NULL); 113e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(per_thread->thread_state() == lazily_archived_thread_state_); 114a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org lazily_archived_thread_state_->set_id(ThreadId::Invalid()); 11543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST); 11643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen lazily_archived_thread_state_ = NULL; 1171c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org per_thread->set_thread_state(NULL); 11843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return true; 11943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 120ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org 121ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org // Make sure that the preemption thread cannot modify the thread state while 122ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org // it is being archived or restored. 123ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org ExecutionAccess access(isolate_); 124ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org 12543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // If there is another thread that was lazily archived then we have to really 12643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // archive it now. 12743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (lazily_archived_thread_.IsValid()) { 12843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen EagerlyArchiveThread(); 12943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 130ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org Isolate::PerIsolateThreadData* per_thread = 1311c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org isolate_->FindPerThreadDataForThisThread(); 132ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org if (per_thread == NULL || per_thread->thread_state() == NULL) { 133c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org // This is a new thread. 134ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org isolate_->stack_guard()->InitThread(access); 13543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return false; 13643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 137ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org ThreadState* state = per_thread->thread_state(); 13843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen char* from = state->data(); 139ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org from = isolate_->handle_scope_implementer()->RestoreThread(from); 140ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org from = isolate_->RestoreThread(from); 1411c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org from = Relocatable::RestoreState(isolate_, from); 142ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org from = isolate_->debug()->RestoreDebug(from); 143ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org from = isolate_->stack_guard()->RestoreStackGuard(from); 144ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org from = isolate_->regexp_stack()->RestoreStack(from); 145ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org from = isolate_->bootstrapper()->RestoreState(from); 146ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org per_thread->set_thread_state(NULL); 147c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org if (state->terminate_on_restore()) { 1483c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org isolate_->stack_guard()->RequestTerminateExecution(); 149c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org state->set_terminate_on_restore(false); 150c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org } 151a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org state->set_id(ThreadId::Invalid()); 15243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen state->Unlink(); 15343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen state->LinkInto(ThreadState::FREE_LIST); 15443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return true; 15543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 15643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 15743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 15843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ThreadManager::Lock() { 159dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org mutex_.Lock(); 160a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org mutex_owner_ = ThreadId::Current(); 161e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(IsLockedByCurrentThread()); 16243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 16343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 16443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 16543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ThreadManager::Unlock() { 166a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org mutex_owner_ = ThreadId::Invalid(); 167dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org mutex_.Unlock(); 16843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 16943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 17043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 17143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstatic int ArchiveSpacePerThread() { 17243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return HandleScopeImplementer::ArchiveSpacePerThread() + 173ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org Isolate::ArchiveSpacePerThread() + 17443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen Debug::ArchiveSpacePerThread() + 1753291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org StackGuard::ArchiveSpacePerThread() + 176ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org RegExpStack::ArchiveSpacePerThread() + 177c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org Bootstrapper::ArchiveSpacePerThread() + 178c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org Relocatable::ArchiveSpacePerThread(); 17943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 18043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 18143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 182ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgThreadState::ThreadState(ThreadManager* thread_manager) 183a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org : id_(ThreadId::Invalid()), 184ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org terminate_on_restore_(false), 185c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org data_(NULL), 186ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org next_(this), 187ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org previous_(this), 188ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org thread_manager_(thread_manager) { 18943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 19043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 19143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 192c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.orgThreadState::~ThreadState() { 193c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org DeleteArray<char>(data_); 194c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org} 195c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org 196c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org 19743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ThreadState::AllocateSpace() { 19843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen data_ = NewArray<char>(ArchiveSpacePerThread()); 19943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 20043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 20143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 20243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ThreadState::Unlink() { 20343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen next_->previous_ = previous_; 20443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen previous_->next_ = next_; 20543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 20643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 20743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 20843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ThreadState::LinkInto(List list) { 20943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen ThreadState* flying_anchor = 210ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org list == FREE_LIST ? thread_manager_->free_anchor_ 211ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org : thread_manager_->in_use_anchor_; 21243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen next_ = flying_anchor->next_; 21343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen previous_ = flying_anchor; 21443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen flying_anchor->next_ = this; 21543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen next_->previous_ = this; 21643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 21743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 21843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 219ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgThreadState* ThreadManager::GetFreeThreadState() { 22043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen ThreadState* gotten = free_anchor_->next_; 22143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen if (gotten == free_anchor_) { 222ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org ThreadState* new_thread_state = new ThreadState(this); 22343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen new_thread_state->AllocateSpace(); 22443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return new_thread_state; 22543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 22643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return gotten; 22743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 22843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 22943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 23043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Gets the first in the list of archived threads. 231ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgThreadState* ThreadManager::FirstThreadStateInUse() { 23243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return in_use_anchor_->Next(); 23343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 23443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 23543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 23643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenThreadState* ThreadState::Next() { 237ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org if (next_ == thread_manager_->in_use_anchor_) return NULL; 23843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen return next_; 23943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 24043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 24143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 242a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org// Thread ids must start with 1, because in TLS having thread id 0 can't 243a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org// be distinguished from not having a thread id at all (since NULL is 244a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org// defined as 0.) 245ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgThreadManager::ThreadManager() 246dc94e19484d1700cb0ec22365444223e49a3ac1ejkummerow@chromium.org : mutex_owner_(ThreadId::Invalid()), 247a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org lazily_archived_thread_(ThreadId::Invalid()), 248ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org lazily_archived_thread_state_(NULL), 249ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org free_anchor_(NULL), 250ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org in_use_anchor_(NULL) { 251ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org free_anchor_ = new ThreadState(this); 252ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org in_use_anchor_ = new ThreadState(this); 253ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org} 254ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 255ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org 256ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgThreadManager::~ThreadManager() { 257c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org DeleteThreadStateList(free_anchor_); 258c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org DeleteThreadStateList(in_use_anchor_); 259c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org} 260c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org 261c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org 262c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.orgvoid ThreadManager::DeleteThreadStateList(ThreadState* anchor) { 263c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org // The list starts and ends with the anchor. 264c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org for (ThreadState* current = anchor->next_; current != anchor;) { 265c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org ThreadState* next = current->next_; 266c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org delete current; 267c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org current = next; 268c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org } 269c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org delete anchor; 270ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org} 27143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 27243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 27343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ThreadManager::ArchiveThread() { 274e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(lazily_archived_thread_.Equals(ThreadId::Invalid())); 275e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!IsArchived()); 276e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(IsLockedByCurrentThread()); 277ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org ThreadState* state = GetFreeThreadState(); 27843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen state->Unlink(); 2791c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Isolate::PerIsolateThreadData* per_thread = 2801c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org isolate_->FindOrAllocatePerThreadDataForThisThread(); 2811c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org per_thread->set_thread_state(state); 282a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org lazily_archived_thread_ = ThreadId::Current(); 28343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen lazily_archived_thread_state_ = state; 284e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(state->id().Equals(ThreadId::Invalid())); 285bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org state->set_id(CurrentId()); 286e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(!state->id().Equals(ThreadId::Invalid())); 28743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 28843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 28943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 29043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ThreadManager::EagerlyArchiveThread() { 291e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org DCHECK(IsLockedByCurrentThread()); 29243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen ThreadState* state = lazily_archived_thread_state_; 29343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen state->LinkInto(ThreadState::IN_USE_LIST); 29443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen char* to = state->data(); 29571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org // Ensure that data containing GC roots are archived first, and handle them 29671affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org // in ThreadManager::Iterate(ObjectVisitor*). 297ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org to = isolate_->handle_scope_implementer()->ArchiveThread(to); 298ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org to = isolate_->ArchiveThread(to); 2991c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org to = Relocatable::ArchiveState(isolate_, to); 300ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org to = isolate_->debug()->ArchiveDebug(to); 301ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org to = isolate_->stack_guard()->ArchiveStackGuard(to); 302ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org to = isolate_->regexp_stack()->ArchiveStack(to); 303ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org to = isolate_->bootstrapper()->ArchiveState(to); 304a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org lazily_archived_thread_ = ThreadId::Invalid(); 30543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen lazily_archived_thread_state_ = NULL; 30643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 30743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 30843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 309c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.orgvoid ThreadManager::FreeThreadResources() { 3105e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org DCHECK(!isolate_->has_pending_exception()); 3115e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org DCHECK(!isolate_->external_caught_exception()); 3125e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org DCHECK(isolate_->try_catch_handler() == NULL); 313ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org isolate_->handle_scope_implementer()->FreeThreadResources(); 314ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org isolate_->FreeThreadResources(); 315ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org isolate_->debug()->FreeThreadResources(); 316ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org isolate_->stack_guard()->FreeThreadResources(); 317ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org isolate_->regexp_stack()->FreeThreadResources(); 318ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org isolate_->bootstrapper()->FreeThreadResources(); 319c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org} 320c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org 321c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org 322a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.orgbool ThreadManager::IsArchived() { 3231c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org Isolate::PerIsolateThreadData* data = 3241c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org isolate_->FindPerThreadDataForThisThread(); 325ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org return data != NULL && data->thread_state() != NULL; 326a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org} 327a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org 328e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org 32943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ThreadManager::Iterate(ObjectVisitor* v) { 33043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen // Expecting no threads during serialization/deserialization 331ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org for (ThreadState* state = FirstThreadStateInUse(); 33243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen state != NULL; 33343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen state = state->Next()) { 33443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen char* data = state->data(); 33543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen data = HandleScopeImplementer::Iterate(v, data); 336ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org data = isolate_->Iterate(v, data); 337c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org data = Relocatable::Iterate(v, data); 33843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen } 33943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} 34043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 34143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen 3421af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.orgvoid ThreadManager::IterateArchivedThreads(ThreadVisitor* v) { 343ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org for (ThreadState* state = FirstThreadStateInUse(); 344cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org state != NULL; 345cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org state = state->Next()) { 346cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org char* data = state->data(); 347cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org data += HandleScopeImplementer::ArchiveSpacePerThread(); 348ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org isolate_->IterateThread(v, data); 349cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org } 350cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org} 351cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org 352cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org 353a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.orgThreadId ThreadManager::CurrentId() { 354a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org return ThreadId::Current(); 355a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org} 356a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org 357a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org 358a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.orgvoid ThreadManager::TerminateExecution(ThreadId thread_id) { 359ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org for (ThreadState* state = FirstThreadStateInUse(); 360c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org state != NULL; 361c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org state = state->Next()) { 362a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org if (thread_id.Equals(state->id())) { 363c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org state->set_terminate_on_restore(true); 364c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org } 365bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org } 366bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org} 367bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org 368bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org 36943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} // namespace internal 37043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen} // namespace v8 371