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