Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / v8 / src / v8threads.cc
index cc4f439..b799126 100644 (file)
@@ -1,70 +1,42 @@
 // Copyright 2012 the V8 project authors. All rights reserved.
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-//       notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-//       copyright notice, this list of conditions and the following
-//       disclaimer in the documentation and/or other materials provided
-//       with the distribution.
-//     * Neither the name of Google Inc. nor the names of its
-//       contributors may be used to endorse or promote products derived
-//       from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#include "v8.h"
-
-#include "api.h"
-#include "bootstrapper.h"
-#include "debug.h"
-#include "execution.h"
-#include "v8threads.h"
-#include "regexp-stack.h"
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/v8.h"
+
+#include "src/api.h"
+#include "src/bootstrapper.h"
+#include "src/debug.h"
+#include "src/execution.h"
+#include "src/regexp-stack.h"
+#include "src/v8threads.h"
 
 namespace v8 {
 
 
+namespace {
+
 // Track whether this V8 instance has ever called v8::Locker. This allows the
 // API code to verify that the lock is always held when V8 is being entered.
-bool Locker::active_ = false;
+base::Atomic32 g_locker_was_ever_used_ = 0;
+
+}  // namespace
 
 
 // Once the Locker is initialized, the current thread will be guaranteed to have
 // the lock for a given isolate.
 void Locker::Initialize(v8::Isolate* isolate) {
-  ASSERT(isolate != NULL);
+  DCHECK(isolate != NULL);
   has_lock_= false;
   top_level_ = true;
   isolate_ = reinterpret_cast<i::Isolate*>(isolate);
   // Record that the Locker has been used at least once.
-  active_ = true;
+  base::NoBarrier_Store(&g_locker_was_ever_used_, 1);
   // Get the big lock if necessary.
   if (!isolate_->thread_manager()->IsLockedByCurrentThread()) {
     isolate_->thread_manager()->Lock();
     has_lock_ = true;
 
-    // Make sure that V8 is initialized.  Archiving of threads interferes
-    // with deserialization by adding additional root pointers, so we must
-    // initialize here, before anyone can call ~Locker() or Unlocker().
-    if (!isolate_->IsInitialized()) {
-      isolate_->Enter();
-      V8::Initialize();
-      isolate_->Exit();
-    }
-
     // This may be a locker within an unlocker in which case we have to
     // get the saved state for this thread and restore it.
     if (isolate_->thread_manager()->RestoreThread()) {
@@ -74,33 +46,26 @@ void Locker::Initialize(v8::Isolate* isolate) {
       isolate_->stack_guard()->ClearThread(access);
       isolate_->stack_guard()->InitThread(access);
     }
-    if (isolate_->IsDefaultIsolate()) {
-      // This only enters if not yet entered.
-      internal::Isolate::EnterDefaultIsolate();
-    }
   }
-  ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
+  DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
 }
 
 
 bool Locker::IsLocked(v8::Isolate* isolate) {
-  ASSERT(isolate != NULL);
+  DCHECK(isolate != NULL);
   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
   return internal_isolate->thread_manager()->IsLockedByCurrentThread();
 }
 
 
 bool Locker::IsActive() {
-  return active_;
+  return !!base::NoBarrier_Load(&g_locker_was_ever_used_);
 }
 
 
 Locker::~Locker() {
-  ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
+  DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
   if (has_lock_) {
-    if (isolate_->IsDefaultIsolate()) {
-      isolate_->Exit();
-    }
     if (top_level_) {
       isolate_->thread_manager()->FreeThreadResources();
     } else {
@@ -112,36 +77,18 @@ Locker::~Locker() {
 
 
 void Unlocker::Initialize(v8::Isolate* isolate) {
-  ASSERT(isolate != NULL);
+  DCHECK(isolate != NULL);
   isolate_ = reinterpret_cast<i::Isolate*>(isolate);
-  ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
-  if (isolate_->IsDefaultIsolate()) {
-    isolate_->Exit();
-  }
+  DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
   isolate_->thread_manager()->ArchiveThread();
   isolate_->thread_manager()->Unlock();
 }
 
 
 Unlocker::~Unlocker() {
-  ASSERT(!isolate_->thread_manager()->IsLockedByCurrentThread());
+  DCHECK(!isolate_->thread_manager()->IsLockedByCurrentThread());
   isolate_->thread_manager()->Lock();
   isolate_->thread_manager()->RestoreThread();
-  if (isolate_->IsDefaultIsolate()) {
-    isolate_->Enter();
-  }
-}
-
-
-void Locker::StartPreemption(v8::Isolate* isolate, int every_n_ms) {
-  v8::internal::ContextSwitcher::StartPreemption(
-      reinterpret_cast<i::Isolate*>(isolate), every_n_ms);
-}
-
-
-void Locker::StopPreemption(v8::Isolate* isolate) {
-  v8::internal::ContextSwitcher::StopPreemption(
-      reinterpret_cast<i::Isolate*>(isolate));
 }
 
 
@@ -149,7 +96,7 @@ namespace internal {
 
 
 bool ThreadManager::RestoreThread() {
-  ASSERT(IsLockedByCurrentThread());
+  DCHECK(IsLockedByCurrentThread());
   // First check whether the current thread has been 'lazily archived', i.e.
   // not archived at all.  If that is the case we put the state storage we
   // had prepared back in the free list, since we didn't need it after all.
@@ -157,8 +104,8 @@ bool ThreadManager::RestoreThread() {
     lazily_archived_thread_ = ThreadId::Invalid();
     Isolate::PerIsolateThreadData* per_thread =
         isolate_->FindPerThreadDataForThisThread();
-    ASSERT(per_thread != NULL);
-    ASSERT(per_thread->thread_state() == lazily_archived_thread_state_);
+    DCHECK(per_thread != NULL);
+    DCHECK(per_thread->thread_state() == lazily_archived_thread_state_);
     lazily_archived_thread_state_->set_id(ThreadId::Invalid());
     lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST);
     lazily_archived_thread_state_ = NULL;
@@ -187,15 +134,13 @@ bool ThreadManager::RestoreThread() {
   from = isolate_->handle_scope_implementer()->RestoreThread(from);
   from = isolate_->RestoreThread(from);
   from = Relocatable::RestoreState(isolate_, from);
-#ifdef ENABLE_DEBUGGER_SUPPORT
   from = isolate_->debug()->RestoreDebug(from);
-#endif
   from = isolate_->stack_guard()->RestoreStackGuard(from);
   from = isolate_->regexp_stack()->RestoreStack(from);
   from = isolate_->bootstrapper()->RestoreState(from);
   per_thread->set_thread_state(NULL);
   if (state->terminate_on_restore()) {
-    isolate_->stack_guard()->TerminateExecution();
+    isolate_->stack_guard()->RequestTerminateExecution();
     state->set_terminate_on_restore(false);
   }
   state->set_id(ThreadId::Invalid());
@@ -208,7 +153,7 @@ bool ThreadManager::RestoreThread() {
 void ThreadManager::Lock() {
   mutex_.Lock();
   mutex_owner_ = ThreadId::Current();
-  ASSERT(IsLockedByCurrentThread());
+  DCHECK(IsLockedByCurrentThread());
 }
 
 
@@ -221,9 +166,7 @@ void ThreadManager::Unlock() {
 static int ArchiveSpacePerThread() {
   return HandleScopeImplementer::ArchiveSpacePerThread() +
                         Isolate::ArchiveSpacePerThread() +
-#ifdef ENABLE_DEBUGGER_SUPPORT
                           Debug::ArchiveSpacePerThread() +
-#endif
                      StackGuard::ArchiveSpacePerThread() +
                     RegExpStack::ArchiveSpacePerThread() +
                    Bootstrapper::ArchiveSpacePerThread() +
@@ -323,9 +266,9 @@ void ThreadManager::DeleteThreadStateList(ThreadState* anchor) {
 
 
 void ThreadManager::ArchiveThread() {
-  ASSERT(lazily_archived_thread_.Equals(ThreadId::Invalid()));
-  ASSERT(!IsArchived());
-  ASSERT(IsLockedByCurrentThread());
+  DCHECK(lazily_archived_thread_.Equals(ThreadId::Invalid()));
+  DCHECK(!IsArchived());
+  DCHECK(IsLockedByCurrentThread());
   ThreadState* state = GetFreeThreadState();
   state->Unlink();
   Isolate::PerIsolateThreadData* per_thread =
@@ -333,14 +276,14 @@ void ThreadManager::ArchiveThread() {
   per_thread->set_thread_state(state);
   lazily_archived_thread_ = ThreadId::Current();
   lazily_archived_thread_state_ = state;
-  ASSERT(state->id().Equals(ThreadId::Invalid()));
+  DCHECK(state->id().Equals(ThreadId::Invalid()));
   state->set_id(CurrentId());
-  ASSERT(!state->id().Equals(ThreadId::Invalid()));
+  DCHECK(!state->id().Equals(ThreadId::Invalid()));
 }
 
 
 void ThreadManager::EagerlyArchiveThread() {
-  ASSERT(IsLockedByCurrentThread());
+  DCHECK(IsLockedByCurrentThread());
   ThreadState* state = lazily_archived_thread_state_;
   state->LinkInto(ThreadState::IN_USE_LIST);
   char* to = state->data();
@@ -349,9 +292,7 @@ void ThreadManager::EagerlyArchiveThread() {
   to = isolate_->handle_scope_implementer()->ArchiveThread(to);
   to = isolate_->ArchiveThread(to);
   to = Relocatable::ArchiveState(isolate_, to);
-#ifdef ENABLE_DEBUGGER_SUPPORT
   to = isolate_->debug()->ArchiveDebug(to);
-#endif
   to = isolate_->stack_guard()->ArchiveStackGuard(to);
   to = isolate_->regexp_stack()->ArchiveStack(to);
   to = isolate_->bootstrapper()->ArchiveState(to);
@@ -361,11 +302,12 @@ void ThreadManager::EagerlyArchiveThread() {
 
 
 void ThreadManager::FreeThreadResources() {
+  DCHECK(!isolate_->has_pending_exception());
+  DCHECK(!isolate_->external_caught_exception());
+  DCHECK(isolate_->try_catch_handler() == NULL);
   isolate_->handle_scope_implementer()->FreeThreadResources();
   isolate_->FreeThreadResources();
-#ifdef ENABLE_DEBUGGER_SUPPORT
   isolate_->debug()->FreeThreadResources();
-#endif
   isolate_->stack_guard()->FreeThreadResources();
   isolate_->regexp_stack()->FreeThreadResources();
   isolate_->bootstrapper()->FreeThreadResources();
@@ -419,63 +361,5 @@ void ThreadManager::TerminateExecution(ThreadId thread_id) {
 }
 
 
-ContextSwitcher::ContextSwitcher(Isolate* isolate, int every_n_ms)
-  : Thread("v8:CtxtSwitcher"),
-    keep_going_(true),
-    sleep_ms_(every_n_ms),
-    isolate_(isolate) {
-}
-
-
-// Set the scheduling interval of V8 threads. This function starts the
-// ContextSwitcher thread if needed.
-void ContextSwitcher::StartPreemption(Isolate* isolate, int every_n_ms) {
-  ASSERT(Locker::IsLocked(reinterpret_cast<v8::Isolate*>(isolate)));
-  if (isolate->context_switcher() == NULL) {
-    // If the ContextSwitcher thread is not running at the moment start it now.
-    isolate->set_context_switcher(new ContextSwitcher(isolate, every_n_ms));
-    isolate->context_switcher()->Start();
-  } else {
-    // ContextSwitcher thread is already running, so we just change the
-    // scheduling interval.
-    isolate->context_switcher()->sleep_ms_ = every_n_ms;
-  }
-}
-
-
-// Disable preemption of V8 threads. If multiple threads want to use V8 they
-// must cooperatively schedule amongst them from this point on.
-void ContextSwitcher::StopPreemption(Isolate* isolate) {
-  ASSERT(Locker::IsLocked(reinterpret_cast<v8::Isolate*>(isolate)));
-  if (isolate->context_switcher() != NULL) {
-    // The ContextSwitcher thread is running. We need to stop it and release
-    // its resources.
-    isolate->context_switcher()->keep_going_ = false;
-    // Wait for the ContextSwitcher thread to exit.
-    isolate->context_switcher()->Join();
-    // Thread has exited, now we can delete it.
-    delete(isolate->context_switcher());
-    isolate->set_context_switcher(NULL);
-  }
-}
-
-
-// Main loop of the ContextSwitcher thread: Preempt the currently running V8
-// thread at regular intervals.
-void ContextSwitcher::Run() {
-  while (keep_going_) {
-    OS::Sleep(sleep_ms_);
-    isolate()->stack_guard()->Preempt();
-  }
-}
-
-
-// Acknowledge the preemption by the receiving thread.
-void ContextSwitcher::PreemptionReceived() {
-  // There is currently no accounting being done for this. But could be in the
-  // future, which is why we leave this in.
-}
-
-
 }  // namespace internal
 }  // namespace v8