LCOV - code coverage report
Current view: top level - src - v8threads.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 149 169 88.2 %
Date: 2017-04-26 Functions: 21 29 72.4 %

          Line data    Source code
       1             : // Copyright 2012 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/v8threads.h"
       6             : 
       7             : #include "src/api.h"
       8             : #include "src/bootstrapper.h"
       9             : #include "src/debug/debug.h"
      10             : #include "src/execution.h"
      11             : #include "src/isolate-inl.h"
      12             : #include "src/regexp/regexp-stack.h"
      13             : #include "src/visitors.h"
      14             : 
      15             : namespace v8 {
      16             : 
      17             : 
      18             : namespace {
      19             : 
      20             : // Track whether this V8 instance has ever called v8::Locker. This allows the
      21             : // API code to verify that the lock is always held when V8 is being entered.
      22             : base::Atomic32 g_locker_was_ever_used_ = 0;
      23             : 
      24             : }  // namespace
      25             : 
      26             : 
      27             : // Once the Locker is initialized, the current thread will be guaranteed to have
      28             : // the lock for a given isolate.
      29        9876 : void Locker::Initialize(v8::Isolate* isolate) {
      30             :   DCHECK(isolate != NULL);
      31        9876 :   has_lock_ = false;
      32        9876 :   top_level_ = true;
      33        9876 :   isolate_ = reinterpret_cast<i::Isolate*>(isolate);
      34             :   // Record that the Locker has been used at least once.
      35             :   base::NoBarrier_Store(&g_locker_was_ever_used_, 1);
      36             :   // Get the big lock if necessary.
      37       26020 :   if (!isolate_->thread_manager()->IsLockedByCurrentThread()) {
      38       16138 :     isolate_->thread_manager()->Lock();
      39        8075 :     has_lock_ = true;
      40             : 
      41             :     // This may be a locker within an unlocker in which case we have to
      42             :     // get the saved state for this thread and restore it.
      43       16150 :     if (isolate_->thread_manager()->RestoreThread()) {
      44        1212 :       top_level_ = false;
      45             :     } else {
      46        6863 :       internal::ExecutionAccess access(isolate_);
      47        6863 :       isolate_->stack_guard()->ClearThread(access);
      48        6863 :       isolate_->stack_guard()->InitThread(access);
      49             :     }
      50             :   }
      51             :   DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
      52        9887 : }
      53             : 
      54             : 
      55        3667 : bool Locker::IsLocked(v8::Isolate* isolate) {
      56             :   DCHECK(isolate != NULL);
      57        3667 :   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
      58        3667 :   return internal_isolate->thread_manager()->IsLockedByCurrentThread();
      59             : }
      60             : 
      61             : 
      62   745613427 : bool Locker::IsActive() {
      63   745613427 :   return !!base::NoBarrier_Load(&g_locker_was_ever_used_);
      64             : }
      65             : 
      66             : 
      67        9887 : Locker::~Locker() {
      68             :   DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
      69        9887 :   if (has_lock_) {
      70        8075 :     if (top_level_) {
      71       16150 :       isolate_->thread_manager()->FreeThreadResources();
      72             :     } else {
      73        2424 :       isolate_->thread_manager()->ArchiveThread();
      74             :     }
      75       16150 :     isolate_->thread_manager()->Unlock();
      76             :   }
      77        9886 : }
      78             : 
      79             : 
      80       23755 : void Unlocker::Initialize(v8::Isolate* isolate) {
      81             :   DCHECK(isolate != NULL);
      82       23755 :   isolate_ = reinterpret_cast<i::Isolate*>(isolate);
      83             :   DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
      84       47510 :   isolate_->thread_manager()->ArchiveThread();
      85       47510 :   isolate_->thread_manager()->Unlock();
      86       23755 : }
      87             : 
      88             : 
      89       23755 : Unlocker::~Unlocker() {
      90             :   DCHECK(!isolate_->thread_manager()->IsLockedByCurrentThread());
      91       47510 :   isolate_->thread_manager()->Lock();
      92       47510 :   isolate_->thread_manager()->RestoreThread();
      93       23755 : }
      94             : 
      95             : 
      96             : namespace internal {
      97             : 
      98             : 
      99       31830 : bool ThreadManager::RestoreThread() {
     100             :   DCHECK(IsLockedByCurrentThread());
     101             :   // First check whether the current thread has been 'lazily archived', i.e.
     102             :   // not archived at all.  If that is the case we put the state storage we
     103             :   // had prepared back in the free list, since we didn't need it after all.
     104       63660 :   if (lazily_archived_thread_.Equals(ThreadId::Current())) {
     105        2393 :     lazily_archived_thread_ = ThreadId::Invalid();
     106             :     Isolate::PerIsolateThreadData* per_thread =
     107       92689 :         isolate_->FindPerThreadDataForThisThread();
     108             :     DCHECK(per_thread != NULL);
     109             :     DCHECK(per_thread->thread_state() == lazily_archived_thread_state_);
     110        2393 :     lazily_archived_thread_state_->set_id(ThreadId::Invalid());
     111        2393 :     lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST);
     112        2393 :     lazily_archived_thread_state_ = NULL;
     113             :     per_thread->set_thread_state(NULL);
     114        2393 :     return true;
     115             :   }
     116             : 
     117             :   // Make sure that the preemption thread cannot modify the thread state while
     118             :   // it is being archived or restored.
     119       29437 :   ExecutionAccess access(isolate_);
     120             : 
     121             :   // If there is another thread that was lazily archived then we have to really
     122             :   // archive it now.
     123       29437 :   if (lazily_archived_thread_.IsValid()) {
     124       22574 :     EagerlyArchiveThread();
     125             :   }
     126       45528 :   Isolate::PerIsolateThreadData* per_thread =
     127       29437 :       isolate_->FindPerThreadDataForThisThread();
     128       52391 :   if (per_thread == NULL || per_thread->thread_state() == NULL) {
     129             :     // This is a new thread.
     130        6863 :     isolate_->stack_guard()->InitThread(access);
     131        6863 :     return false;
     132             :   }
     133       45148 :   ThreadState* state = per_thread->thread_state();
     134             :   char* from = state->data();
     135       45148 :   from = isolate_->handle_scope_implementer()->RestoreThread(from);
     136       22574 :   from = isolate_->RestoreThread(from);
     137       22574 :   from = Relocatable::RestoreState(isolate_, from);
     138       45148 :   from = isolate_->debug()->RestoreDebug(from);
     139       22574 :   from = isolate_->stack_guard()->RestoreStackGuard(from);
     140       45148 :   from = isolate_->regexp_stack()->RestoreStack(from);
     141       45148 :   from = isolate_->bootstrapper()->RestoreState(from);
     142             :   per_thread->set_thread_state(NULL);
     143       22574 :   if (state->terminate_on_restore()) {
     144           0 :     isolate_->stack_guard()->RequestTerminateExecution();
     145             :     state->set_terminate_on_restore(false);
     146             :   }
     147             :   state->set_id(ThreadId::Invalid());
     148             :   state->Unlink();
     149             :   state->LinkInto(ThreadState::FREE_LIST);
     150       22574 :   return true;
     151             : }
     152             : 
     153             : 
     154       31821 : void ThreadManager::Lock() {
     155       31821 :   mutex_.Lock();
     156       31830 :   mutex_owner_ = ThreadId::Current();
     157             :   DCHECK(IsLockedByCurrentThread());
     158       31830 : }
     159             : 
     160             : 
     161       31830 : void ThreadManager::Unlock() {
     162       31830 :   mutex_owner_ = ThreadId::Invalid();
     163       31830 :   mutex_.Unlock();
     164       31829 : }
     165             : 
     166             : 
     167        1280 : static int ArchiveSpacePerThread() {
     168        1280 :   return HandleScopeImplementer::ArchiveSpacePerThread() +
     169        1280 :                         Isolate::ArchiveSpacePerThread() +
     170        1280 :                           Debug::ArchiveSpacePerThread() +
     171        1280 :                      StackGuard::ArchiveSpacePerThread() +
     172        1280 :                     RegExpStack::ArchiveSpacePerThread() +
     173        1280 :                    Bootstrapper::ArchiveSpacePerThread() +
     174        1280 :                     Relocatable::ArchiveSpacePerThread();
     175             : }
     176             : 
     177             : 
     178           0 : ThreadState::ThreadState(ThreadManager* thread_manager)
     179             :     : id_(ThreadId::Invalid()),
     180             :       terminate_on_restore_(false),
     181             :       data_(NULL),
     182             :       next_(this),
     183             :       previous_(this),
     184      122844 :       thread_manager_(thread_manager) {
     185           0 : }
     186             : 
     187             : 
     188           0 : ThreadState::~ThreadState() {
     189      119850 :   DeleteArray<char>(data_);
     190           0 : }
     191             : 
     192             : 
     193        1280 : void ThreadState::AllocateSpace() {
     194        1280 :   data_ = NewArray<char>(ArchiveSpacePerThread());
     195        1280 : }
     196             : 
     197             : 
     198           0 : void ThreadState::Unlink() {
     199       47541 :   next_->previous_ = previous_;
     200       47541 :   previous_->next_ = next_;
     201           0 : }
     202             : 
     203             : 
     204           0 : void ThreadState::LinkInto(List list) {
     205             :   ThreadState* flying_anchor =
     206             :       list == FREE_LIST ? thread_manager_->free_anchor_
     207       47541 :                         : thread_manager_->in_use_anchor_;
     208       47541 :   next_ = flying_anchor->next_;
     209       47541 :   previous_ = flying_anchor;
     210       47541 :   flying_anchor->next_ = this;
     211       47541 :   next_->previous_ = this;
     212           0 : }
     213             : 
     214             : 
     215       24967 : ThreadState* ThreadManager::GetFreeThreadState() {
     216       24967 :   ThreadState* gotten = free_anchor_->next_;
     217       24967 :   if (gotten == free_anchor_) {
     218        1280 :     ThreadState* new_thread_state = new ThreadState(this);
     219        1280 :     new_thread_state->AllocateSpace();
     220        1280 :     return new_thread_state;
     221             :   }
     222             :   return gotten;
     223             : }
     224             : 
     225             : 
     226             : // Gets the first in the list of archived threads.
     227         151 : ThreadState* ThreadManager::FirstThreadStateInUse() {
     228      333124 :   return in_use_anchor_->Next();
     229             : }
     230             : 
     231             : 
     232           0 : ThreadState* ThreadState::Next() {
     233      338056 :   if (next_ == thread_manager_->in_use_anchor_) return NULL;
     234           0 :   return next_;
     235             : }
     236             : 
     237             : 
     238             : // Thread ids must start with 1, because in TLS having thread id 0 can't
     239             : // be distinguished from not having a thread id at all (since NULL is
     240             : // defined as 0.)
     241       60782 : ThreadManager::ThreadManager()
     242             :     : mutex_owner_(ThreadId::Invalid()),
     243             :       lazily_archived_thread_(ThreadId::Invalid()),
     244             :       lazily_archived_thread_state_(NULL),
     245             :       free_anchor_(NULL),
     246      182346 :       in_use_anchor_(NULL) {
     247      121564 :   free_anchor_ = new ThreadState(this);
     248      121564 :   in_use_anchor_ = new ThreadState(this);
     249       60782 : }
     250             : 
     251             : 
     252      118570 : ThreadManager::~ThreadManager() {
     253       59285 :   DeleteThreadStateList(free_anchor_);
     254       59285 :   DeleteThreadStateList(in_use_anchor_);
     255       59285 : }
     256             : 
     257             : 
     258      118570 : void ThreadManager::DeleteThreadStateList(ThreadState* anchor) {
     259             :   // The list starts and ends with the anchor.
     260      238420 :   for (ThreadState* current = anchor->next_; current != anchor;) {
     261        1280 :     ThreadState* next = current->next_;
     262        2560 :     delete current;
     263             :     current = next;
     264             :   }
     265      237140 :   delete anchor;
     266      118570 : }
     267             : 
     268             : 
     269       24967 : void ThreadManager::ArchiveThread() {
     270             :   DCHECK(lazily_archived_thread_.Equals(ThreadId::Invalid()));
     271             :   DCHECK(!IsArchived());
     272             :   DCHECK(IsLockedByCurrentThread());
     273       24967 :   ThreadState* state = GetFreeThreadState();
     274             :   state->Unlink();
     275             :   Isolate::PerIsolateThreadData* per_thread =
     276       24967 :       isolate_->FindOrAllocatePerThreadDataForThisThread();
     277             :   per_thread->set_thread_state(state);
     278       24967 :   lazily_archived_thread_ = ThreadId::Current();
     279       24967 :   lazily_archived_thread_state_ = state;
     280             :   DCHECK(state->id().Equals(ThreadId::Invalid()));
     281             :   state->set_id(CurrentId());
     282             :   DCHECK(!state->id().Equals(ThreadId::Invalid()));
     283       24967 : }
     284             : 
     285             : 
     286       22574 : void ThreadManager::EagerlyArchiveThread() {
     287             :   DCHECK(IsLockedByCurrentThread());
     288       45148 :   ThreadState* state = lazily_archived_thread_state_;
     289             :   state->LinkInto(ThreadState::IN_USE_LIST);
     290             :   char* to = state->data();
     291             :   // Ensure that data containing GC roots are archived first, and handle them
     292             :   // in ThreadManager::Iterate(RootVisitor*).
     293       90296 :   to = isolate_->handle_scope_implementer()->ArchiveThread(to);
     294       22574 :   to = isolate_->ArchiveThread(to);
     295       22574 :   to = Relocatable::ArchiveState(isolate_, to);
     296       45148 :   to = isolate_->debug()->ArchiveDebug(to);
     297       22574 :   to = isolate_->stack_guard()->ArchiveStackGuard(to);
     298       45148 :   to = isolate_->regexp_stack()->ArchiveStack(to);
     299       45148 :   to = isolate_->bootstrapper()->ArchiveState(to);
     300       22574 :   lazily_archived_thread_ = ThreadId::Invalid();
     301       22574 :   lazily_archived_thread_state_ = NULL;
     302       22574 : }
     303             : 
     304             : 
     305        6863 : void ThreadManager::FreeThreadResources() {
     306             :   DCHECK(!isolate_->has_pending_exception());
     307             :   DCHECK(!isolate_->external_caught_exception());
     308             :   DCHECK(isolate_->try_catch_handler() == NULL);
     309       20589 :   isolate_->handle_scope_implementer()->FreeThreadResources();
     310        6863 :   isolate_->FreeThreadResources();
     311             :   isolate_->debug()->FreeThreadResources();
     312        6863 :   isolate_->stack_guard()->FreeThreadResources();
     313        6863 :   isolate_->regexp_stack()->FreeThreadResources();
     314       13726 :   isolate_->bootstrapper()->FreeThreadResources();
     315        6863 : }
     316             : 
     317             : 
     318           0 : bool ThreadManager::IsArchived() {
     319           0 :   Isolate::PerIsolateThreadData* data =
     320           0 :       isolate_->FindPerThreadDataForThisThread();
     321           0 :   return data != NULL && data->thread_state() != NULL;
     322             : }
     323             : 
     324      241585 : void ThreadManager::Iterate(RootVisitor* v) {
     325             :   // Expecting no threads during serialization/deserialization
     326      487219 :   for (ThreadState* state = FirstThreadStateInUse();
     327             :        state != NULL;
     328             :        state = state->Next()) {
     329             :     char* data = state->data();
     330        4049 :     data = HandleScopeImplementer::Iterate(v, data);
     331        4049 :     data = isolate_->Iterate(v, data);
     332        4049 :     data = Relocatable::Iterate(v, data);
     333             :   }
     334      241585 : }
     335             : 
     336             : 
     337       91237 : void ThreadManager::IterateArchivedThreads(ThreadVisitor* v) {
     338      183508 :   for (ThreadState* state = FirstThreadStateInUse();
     339             :        state != NULL;
     340             :        state = state->Next()) {
     341             :     char* data = state->data();
     342        1034 :     data += HandleScopeImplementer::ArchiveSpacePerThread();
     343        1034 :     isolate_->IterateThread(v, data);
     344             :   }
     345       91237 : }
     346             : 
     347             : 
     348           0 : ThreadId ThreadManager::CurrentId() {
     349       24967 :   return ThreadId::Current();
     350             : }
     351             : 
     352             : 
     353           0 : void ThreadManager::TerminateExecution(ThreadId thread_id) {
     354           0 :   for (ThreadState* state = FirstThreadStateInUse();
     355             :        state != NULL;
     356             :        state = state->Next()) {
     357           0 :     if (thread_id.Equals(state->id())) {
     358             :       state->set_terminate_on_restore(true);
     359             :     }
     360             :   }
     361           0 : }
     362             : 
     363             : 
     364             : }  // namespace internal
     365             : }  // namespace v8

Generated by: LCOV version 1.10