1c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Redistribution and use in source and binary forms, with or without
343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// modification, are permitted provided that the following conditions are
443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// met:
543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//
643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//     * Redistributions of source code must retain the above copyright
743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       notice, this list of conditions and the following disclaimer.
843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//     * Redistributions in binary form must reproduce the above
943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       copyright notice, this list of conditions and the following
1043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       disclaimer in the documentation and/or other materials provided
1143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       with the distribution.
1243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//     * Neither the name of Google Inc. nor the names of its
1343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       contributors may be used to endorse or promote products derived
1443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//       from this software without specific prior written permission.
1543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//
1643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "v8.h"
2943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "api.h"
31ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org#include "bootstrapper.h"
3243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "debug.h"
3343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "execution.h"
3443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen#include "v8threads.h"
353291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org#include "regexp-stack.h"
3643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
3743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansennamespace v8 {
3843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
39ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org
40ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org// Track whether this V8 instance has ever called v8::Locker. This allows the
41ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org// API code to verify that the lock is always held when V8 is being entered.
42ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.orgbool Locker::active_ = false;
43ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org
44ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org
4546a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.orgLocker::Locker() {
4646a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  Initialize(i::Isolate::GetDefaultIsolateForLocking());
4746a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org}
4846a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org
4946a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org
5046a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org// Once the Locker is initialized, the current thread will be guaranteed to have
5146a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org// the lock for a given isolate.
5246a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.orgvoid Locker::Initialize(v8::Isolate* isolate) {
5346a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  ASSERT(isolate != NULL);
5446a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  has_lock_= false;
5546a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  top_level_ = true;
5646a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  isolate_ = reinterpret_cast<i::Isolate*>(isolate);
57ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org  // Record that the Locker has been used at least once.
58ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org  active_ = true;
5943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Get the big lock if necessary.
601c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  if (!isolate_->thread_manager()->IsLockedByCurrentThread()) {
611c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    isolate_->thread_manager()->Lock();
6243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    has_lock_ = true;
63ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
64c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    // Make sure that V8 is initialized.  Archiving of threads interferes
65c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    // with deserialization by adding additional root pointers, so we must
66c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    // initialize here, before anyone can call ~Locker() or Unlocker().
671c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    if (!isolate_->IsInitialized()) {
681c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      isolate_->Enter();
69c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org      V8::Initialize();
701c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      isolate_->Exit();
71c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    }
721c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org
7343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // This may be a locker within an unlocker in which case we have to
7443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    // get the saved state for this thread and restore it.
751c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    if (isolate_->thread_manager()->RestoreThread()) {
7643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen      top_level_ = false;
77c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    } else {
781c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      internal::ExecutionAccess access(isolate_);
791c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      isolate_->stack_guard()->ClearThread(access);
801c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      isolate_->stack_guard()->InitThread(access);
811c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    }
821c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    if (isolate_->IsDefaultIsolate()) {
831c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      // This only enters if not yet entered.
841c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      internal::Isolate::EnterDefaultIsolate();
8543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
8643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
871c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
8843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
8943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
9043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
911c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.orgbool Locker::IsLocked(v8::Isolate* isolate) {
9246a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  ASSERT(isolate != NULL);
931c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
941c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  return internal_isolate->thread_manager()->IsLockedByCurrentThread();
9543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
9643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
9743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
987c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.orgbool Locker::IsActive() {
997c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org  return active_;
1007c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org}
1017c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org
1027c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.org
10343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenLocker::~Locker() {
1041c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
10543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (has_lock_) {
1061c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    if (isolate_->IsDefaultIsolate()) {
1071c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      isolate_->Exit();
1081c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    }
109c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    if (top_level_) {
1101c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      isolate_->thread_manager()->FreeThreadResources();
111c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    } else {
1121c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      isolate_->thread_manager()->ArchiveThread();
11343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    }
1141c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    isolate_->thread_manager()->Unlock();
11543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
11643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
11743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
11843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
11946a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.orgUnlocker::Unlocker() {
12046a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  Initialize(i::Isolate::GetDefaultIsolateForLocking());
12146a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org}
12246a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org
12346a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org
12446a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.orgvoid Unlocker::Initialize(v8::Isolate* isolate) {
12546a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  ASSERT(isolate != NULL);
12646a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  isolate_ = reinterpret_cast<i::Isolate*>(isolate);
1271c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
1281c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  if (isolate_->IsDefaultIsolate()) {
1291c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    isolate_->Exit();
1301c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  }
1311c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  isolate_->thread_manager()->ArchiveThread();
1321c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  isolate_->thread_manager()->Unlock();
13343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
13443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
13543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
13643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenUnlocker::~Unlocker() {
1371c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  ASSERT(!isolate_->thread_manager()->IsLockedByCurrentThread());
1381c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  isolate_->thread_manager()->Lock();
1391c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  isolate_->thread_manager()->RestoreThread();
1401c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  if (isolate_->IsDefaultIsolate()) {
1411c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    isolate_->Enter();
1421c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  }
14343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
14443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
14543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
14643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid Locker::StartPreemption(int every_n_ms) {
14743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  v8::internal::ContextSwitcher::StartPreemption(every_n_ms);
14843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
14943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
15043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
15143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid Locker::StopPreemption() {
15243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  v8::internal::ContextSwitcher::StopPreemption();
15343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
15443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
15543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
15643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansennamespace internal {
15743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
15843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
15943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenbool ThreadManager::RestoreThread() {
1601c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  ASSERT(IsLockedByCurrentThread());
1612efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  // First check whether the current thread has been 'lazily archived', i.e.
16243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // not archived at all.  If that is the case we put the state storage we
16343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // had prepared back in the free list, since we didn't need it after all.
164a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org  if (lazily_archived_thread_.Equals(ThreadId::Current())) {
165a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org    lazily_archived_thread_ = ThreadId::Invalid();
1661c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    Isolate::PerIsolateThreadData* per_thread =
1671c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org        isolate_->FindPerThreadDataForThisThread();
1681c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    ASSERT(per_thread != NULL);
1691c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    ASSERT(per_thread->thread_state() == lazily_archived_thread_state_);
170a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org    lazily_archived_thread_state_->set_id(ThreadId::Invalid());
17143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST);
17243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    lazily_archived_thread_state_ = NULL;
1731c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org    per_thread->set_thread_state(NULL);
17443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return true;
17543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
176ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org
177ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org  // Make sure that the preemption thread cannot modify the thread state while
178ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org  // it is being archived or restored.
179ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  ExecutionAccess access(isolate_);
180ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org
18143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // If there is another thread that was lazily archived then we have to really
18243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // archive it now.
18343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (lazily_archived_thread_.IsValid()) {
18443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    EagerlyArchiveThread();
18543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
186ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Isolate::PerIsolateThreadData* per_thread =
1871c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      isolate_->FindPerThreadDataForThisThread();
188ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  if (per_thread == NULL || per_thread->thread_state() == NULL) {
189c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    // This is a new thread.
190ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    isolate_->stack_guard()->InitThread(access);
19143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return false;
19243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
193ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  ThreadState* state = per_thread->thread_state();
19443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  char* from = state->data();
195ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  from = isolate_->handle_scope_implementer()->RestoreThread(from);
196ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  from = isolate_->RestoreThread(from);
1971c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  from = Relocatable::RestoreState(isolate_, from);
19865dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org#ifdef ENABLE_DEBUGGER_SUPPORT
199ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  from = isolate_->debug()->RestoreDebug(from);
20065dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org#endif
201ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  from = isolate_->stack_guard()->RestoreStackGuard(from);
202ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  from = isolate_->regexp_stack()->RestoreStack(from);
203ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  from = isolate_->bootstrapper()->RestoreState(from);
204ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  per_thread->set_thread_state(NULL);
205c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  if (state->terminate_on_restore()) {
206ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    isolate_->stack_guard()->TerminateExecution();
207c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org    state->set_terminate_on_restore(false);
208c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org  }
209a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org  state->set_id(ThreadId::Invalid());
21043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  state->Unlink();
21143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  state->LinkInto(ThreadState::FREE_LIST);
21243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return true;
21343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
21443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
21543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
21643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ThreadManager::Lock() {
21743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  mutex_->Lock();
218a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org  mutex_owner_ = ThreadId::Current();
21943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ASSERT(IsLockedByCurrentThread());
22043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
22143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
22243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
22343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ThreadManager::Unlock() {
224a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org  mutex_owner_ = ThreadId::Invalid();
22543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  mutex_->Unlock();
22643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
22743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
22843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
22943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenstatic int ArchiveSpacePerThread() {
23043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return HandleScopeImplementer::ArchiveSpacePerThread() +
231ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                        Isolate::ArchiveSpacePerThread() +
23265dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org#ifdef ENABLE_DEBUGGER_SUPPORT
23343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                          Debug::ArchiveSpacePerThread() +
23465dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org#endif
2353291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                     StackGuard::ArchiveSpacePerThread() +
236ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org                    RegExpStack::ArchiveSpacePerThread() +
237c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org                   Bootstrapper::ArchiveSpacePerThread() +
238c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org                    Relocatable::ArchiveSpacePerThread();
23943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
24043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
24143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
242ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgThreadState::ThreadState(ThreadManager* thread_manager)
243a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org    : id_(ThreadId::Invalid()),
244ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      terminate_on_restore_(false),
245c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org      data_(NULL),
246ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      next_(this),
247ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      previous_(this),
248ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      thread_manager_(thread_manager) {
24943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
25043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
25143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
252c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.orgThreadState::~ThreadState() {
253c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org  DeleteArray<char>(data_);
254c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org}
255c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org
256c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org
25743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ThreadState::AllocateSpace() {
25843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  data_ = NewArray<char>(ArchiveSpacePerThread());
25943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
26043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
26143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
26243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ThreadState::Unlink() {
26343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  next_->previous_ = previous_;
26443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  previous_->next_ = next_;
26543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
26643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
26743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
26843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ThreadState::LinkInto(List list) {
26943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ThreadState* flying_anchor =
270ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      list == FREE_LIST ? thread_manager_->free_anchor_
271ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org                        : thread_manager_->in_use_anchor_;
27243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  next_ = flying_anchor->next_;
27343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  previous_ = flying_anchor;
27443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  flying_anchor->next_ = this;
27543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  next_->previous_ = this;
27643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
27743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
27843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
279ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgThreadState* ThreadManager::GetFreeThreadState() {
28043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ThreadState* gotten = free_anchor_->next_;
28143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  if (gotten == free_anchor_) {
282ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    ThreadState* new_thread_state = new ThreadState(this);
28343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    new_thread_state->AllocateSpace();
28443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return new_thread_state;
28543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
28643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return gotten;
28743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
28843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
28943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
29043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Gets the first in the list of archived threads.
291ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgThreadState* ThreadManager::FirstThreadStateInUse() {
29243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return in_use_anchor_->Next();
29343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
29443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
29543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
29643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenThreadState* ThreadState::Next() {
297ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  if (next_ == thread_manager_->in_use_anchor_) return NULL;
29843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  return next_;
29943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
30043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
30143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
302a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org// Thread ids must start with 1, because in TLS having thread id 0 can't
303a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org// be distinguished from not having a thread id at all (since NULL is
304a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org// defined as 0.)
305ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgThreadManager::ThreadManager()
306ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    : mutex_(OS::CreateMutex()),
307a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      mutex_owner_(ThreadId::Invalid()),
308a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org      lazily_archived_thread_(ThreadId::Invalid()),
309ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      lazily_archived_thread_state_(NULL),
310ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      free_anchor_(NULL),
311ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org      in_use_anchor_(NULL) {
312ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  free_anchor_ = new ThreadState(this);
313ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  in_use_anchor_ = new ThreadState(this);
314ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org}
315ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
316ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
317ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgThreadManager::~ThreadManager() {
31828a37086dc5bb171203246e0d9701882d56d6e81rossberg@chromium.org  delete mutex_;
319c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org  DeleteThreadStateList(free_anchor_);
320c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org  DeleteThreadStateList(in_use_anchor_);
321c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org}
322c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org
323c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org
324c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.orgvoid ThreadManager::DeleteThreadStateList(ThreadState* anchor) {
325c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org  // The list starts and ends with the anchor.
326c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org  for (ThreadState* current = anchor->next_; current != anchor;) {
327c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org    ThreadState* next = current->next_;
328c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org    delete current;
329c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org    current = next;
330c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org  }
331c6d9cee74ef337517b541fbd58e5438920699a77mstarzinger@chromium.org  delete anchor;
332ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org}
33343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
33443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
33543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ThreadManager::ArchiveThread() {
336a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org  ASSERT(lazily_archived_thread_.Equals(ThreadId::Invalid()));
337a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org  ASSERT(!IsArchived());
3381c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  ASSERT(IsLockedByCurrentThread());
339ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  ThreadState* state = GetFreeThreadState();
34043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  state->Unlink();
3411c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Isolate::PerIsolateThreadData* per_thread =
3421c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      isolate_->FindOrAllocatePerThreadDataForThisThread();
3431c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  per_thread->set_thread_state(state);
344a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org  lazily_archived_thread_ = ThreadId::Current();
34543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  lazily_archived_thread_state_ = state;
346a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org  ASSERT(state->id().Equals(ThreadId::Invalid()));
347bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  state->set_id(CurrentId());
348a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org  ASSERT(!state->id().Equals(ThreadId::Invalid()));
34943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
35043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
35143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
35243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ThreadManager::EagerlyArchiveThread() {
3531c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  ASSERT(IsLockedByCurrentThread());
35443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ThreadState* state = lazily_archived_thread_state_;
35543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  state->LinkInto(ThreadState::IN_USE_LIST);
35643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  char* to = state->data();
35771affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // Ensure that data containing GC roots are archived first, and handle them
35871affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org  // in ThreadManager::Iterate(ObjectVisitor*).
359ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  to = isolate_->handle_scope_implementer()->ArchiveThread(to);
360ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  to = isolate_->ArchiveThread(to);
3611c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  to = Relocatable::ArchiveState(isolate_, to);
36265dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org#ifdef ENABLE_DEBUGGER_SUPPORT
363ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  to = isolate_->debug()->ArchiveDebug(to);
36465dad4b091d2925543c6326db635d0f7cf9e1edcager@chromium.org#endif
365ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  to = isolate_->stack_guard()->ArchiveStackGuard(to);
366ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  to = isolate_->regexp_stack()->ArchiveStack(to);
367ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  to = isolate_->bootstrapper()->ArchiveState(to);
368a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org  lazily_archived_thread_ = ThreadId::Invalid();
36943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  lazily_archived_thread_state_ = NULL;
37043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
37143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
37243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
373c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.orgvoid ThreadManager::FreeThreadResources() {
374ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  isolate_->handle_scope_implementer()->FreeThreadResources();
375ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  isolate_->FreeThreadResources();
376c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org#ifdef ENABLE_DEBUGGER_SUPPORT
377ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  isolate_->debug()->FreeThreadResources();
378c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org#endif
379ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  isolate_->stack_guard()->FreeThreadResources();
380ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  isolate_->regexp_stack()->FreeThreadResources();
381ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  isolate_->bootstrapper()->FreeThreadResources();
382c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org}
383c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
384c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org
385a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.orgbool ThreadManager::IsArchived() {
3861c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org  Isolate::PerIsolateThreadData* data =
3871c09276ce2ac5214e81ca554360b9f101187893blrn@chromium.org      isolate_->FindPerThreadDataForThisThread();
388ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  return data != NULL && data->thread_state() != NULL;
389a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org}
390a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org
391e0e1b0d3e70c933d36ed381d511e9fda39f2a751mstarzinger@chromium.org
39243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ThreadManager::Iterate(ObjectVisitor* v) {
39343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Expecting no threads during serialization/deserialization
394ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  for (ThreadState* state = FirstThreadStateInUse();
39543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen       state != NULL;
39643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen       state = state->Next()) {
39743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    char* data = state->data();
39843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    data = HandleScopeImplementer::Iterate(v, data);
399ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    data = isolate_->Iterate(v, data);
400c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org    data = Relocatable::Iterate(v, data);
40143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
40243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
40343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
40443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4051af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.orgvoid ThreadManager::IterateArchivedThreads(ThreadVisitor* v) {
406ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  for (ThreadState* state = FirstThreadStateInUse();
407cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org       state != NULL;
408cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org       state = state->Next()) {
409cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    char* data = state->data();
410cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org    data += HandleScopeImplementer::ArchiveSpacePerThread();
411ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    isolate_->IterateThread(v, data);
412cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org  }
413cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org}
414cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
415cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org
416a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.orgThreadId ThreadManager::CurrentId() {
417a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org  return ThreadId::Current();
418a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org}
419a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org
420a1645e29968e70a41226edda2c49788fcea48b74ager@chromium.org
421a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.orgvoid ThreadManager::TerminateExecution(ThreadId thread_id) {
422ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  for (ThreadState* state = FirstThreadStateInUse();
423c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org       state != NULL;
424c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org       state = state->Next()) {
425a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org    if (thread_id.Equals(state->id())) {
426c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org      state->set_terminate_on_restore(true);
427c81c894dabeceb472d668027ca59e73096f5cfafsgjesse@chromium.org    }
428bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  }
429bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org}
430bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
431bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org
432ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.orgContextSwitcher::ContextSwitcher(Isolate* isolate, int every_n_ms)
4336d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  : Thread("v8:CtxtSwitcher"),
4345d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    keep_going_(true),
4356d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org    sleep_ms_(every_n_ms),
4366d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org    isolate_(isolate) {
43743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
43843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
43943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
44037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com// Set the scheduling interval of V8 threads. This function starts the
44137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com// ContextSwitcher thread if needed.
44243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ContextSwitcher::StartPreemption(int every_n_ms) {
443ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Isolate* isolate = Isolate::Current();
444d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com  ASSERT(Locker::IsLocked(reinterpret_cast<v8::Isolate*>(isolate)));
445ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  if (isolate->context_switcher() == NULL) {
44637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    // If the ContextSwitcher thread is not running at the moment start it now.
447ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    isolate->set_context_switcher(new ContextSwitcher(isolate, every_n_ms));
448ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    isolate->context_switcher()->Start();
44943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  } else {
45037abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    // ContextSwitcher thread is already running, so we just change the
45137abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    // scheduling interval.
452ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    isolate->context_switcher()->sleep_ms_ = every_n_ms;
45343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
45443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
45543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
45643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
45737abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com// Disable preemption of V8 threads. If multiple threads want to use V8 they
45837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com// must cooperatively schedule amongst them from this point on.
45943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ContextSwitcher::StopPreemption() {
460ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  Isolate* isolate = Isolate::Current();
461d6076d96a1411932548838e5960b594564264010erik.corry@gmail.com  ASSERT(Locker::IsLocked(reinterpret_cast<v8::Isolate*>(isolate)));
462ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  if (isolate->context_switcher() != NULL) {
46337abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    // The ContextSwitcher thread is running. We need to stop it and release
46437abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    // its resources.
465ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    isolate->context_switcher()->keep_going_ = false;
466ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    // Wait for the ContextSwitcher thread to exit.
467ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    isolate->context_switcher()->Join();
46837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com    // Thread has exited, now we can delete it.
469ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    delete(isolate->context_switcher());
470ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    isolate->set_context_switcher(NULL);
47143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
47243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
47343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
47443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
47537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com// Main loop of the ContextSwitcher thread: Preempt the currently running V8
47637abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com// thread at regular intervals.
47743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ContextSwitcher::Run() {
47843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  while (keep_going_) {
47943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    OS::Sleep(sleep_ms_);
480ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org    isolate()->stack_guard()->Preempt();
48143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  }
48243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
48343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
48443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
48537abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com// Acknowledge the preemption by the receiving thread.
48643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenvoid ContextSwitcher::PreemptionReceived() {
48746a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  ASSERT(Locker::IsLocked(i::Isolate::GetDefaultIsolateForLocking()));
48837abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // There is currently no accounting being done for this. But could be in the
48937abdec9cad6edeba05b5c7a9ff73c25f5df2b70christian.plesner.hansen@gmail.com  // future, which is why we leave this in.
49043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}
49143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
49243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
49343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}  // namespace internal
49443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen}  // namespace v8
495