Chromium Code Reviews| Index: src/v8threads.cc |
| diff --git a/src/v8threads.cc b/src/v8threads.cc |
| index 4b033fcf0bd703cf12b5bdccfb116784b5a31d9a..0f73338b765c641c64c9ed390f17a82d6d495e0e 100644 |
| --- a/src/v8threads.cc |
| +++ b/src/v8threads.cc |
| @@ -44,89 +44,109 @@ bool Locker::active_ = false; |
| // Constructor for the Locker object. Once the Locker is constructed the |
| // current thread will be guaranteed to have the big V8 lock. |
| -Locker::Locker() : has_lock_(false), top_level_(true) { |
| - // TODO(isolates): When Locker has Isolate parameter and it is provided, grab |
| - // that one instead of using the current one. |
| - // We pull default isolate for Locker constructor w/o p[arameter. |
| +Locker::Locker() |
| + : has_lock_(false), top_level_(true), |
|
Vitaly Repeshko
2011/04/15 00:29:39
nit: Reformat with one initializer per line if the
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| + isolate_(internal::Isolate::GetDefaultIsolateForLocking()) { |
| + // We pull default isolate for Locker constructor w/o parameter. |
| // A thread should not enter an isolate before acquiring a lock, |
| // in cases which mandate using Lockers. |
| // So getting a lock is the first thing threads do in a scenario where |
| // multple threads share an isolate. Hence, we need to access |
| // 'locking isolate' before we can actually enter into default isolate. |
| - internal::Isolate* isolate = internal::Isolate::GetDefaultIsolateForLocking(); |
| - ASSERT(isolate != NULL); |
| + ASSERT(isolate_ != NULL); |
| + Init(); |
| +} |
| + |
|
Vitaly Repeshko
2011/04/15 00:29:39
nit: Two blank lines.
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| +Locker::Locker(v8::Isolate* isolate) |
| + : has_lock_(false), top_level_(false), |
| + isolate_(reinterpret_cast<i::Isolate*>(isolate)) { |
| + ASSERT(isolate_ != NULL); |
| + Init(); |
| +} |
| +void Locker::Init() { |
| // Record that the Locker has been used at least once. |
| active_ = true; |
| + |
| + isolate_->EnsurePreinitializedForThisThread(); |
| // Get the big lock if necessary. |
| - if (!isolate->thread_manager()->IsLockedByCurrentThread()) { |
| - isolate->thread_manager()->Lock(); |
| + if (!isolate_->thread_manager()->IsLockedByCurrentThread()) { |
| + isolate_->thread_manager()->Lock(); |
| has_lock_ = true; |
| - if (isolate->IsDefaultIsolate()) { |
| - // This only enters if not yet entered. |
| - internal::Isolate::EnterDefaultIsolate(); |
| - } |
| - |
| - ASSERT(internal::Thread::HasThreadLocal( |
| - internal::Isolate::thread_id_key())); |
| - |
| // 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()) { |
| + if (isolate_->IsDefaultIsolate()) { |
| + // This only enters if not yet entered. |
| + internal::Isolate::EnterDefaultIsolate(); |
| + } else if (!isolate_->IsInitialized()) { |
| + isolate_->Enter(); |
| V8::Initialize(); |
|
Vitaly Repeshko
2011/04/15 00:29:39
I really don't like that we're doing a global init
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| + 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()) { |
| + if (isolate_->thread_manager()->RestoreThread()) { |
| top_level_ = false; |
| } else { |
| - internal::ExecutionAccess access(isolate); |
| - isolate->stack_guard()->ClearThread(access); |
| - isolate->stack_guard()->InitThread(access); |
| + internal::ExecutionAccess access(isolate_); |
| + isolate_->stack_guard()->ClearThread(access); |
| + isolate_->stack_guard()->InitThread(access); |
| } |
| } |
| - ASSERT(isolate->thread_manager()->IsLockedByCurrentThread()); |
| + ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread()); |
| } |
| bool Locker::IsLocked() { |
| - return internal::Isolate::Current()->thread_manager()-> |
| - IsLockedByCurrentThread(); |
| + return IsLocked(reinterpret_cast<v8::Isolate*>( |
| + i::Isolate::GetDefaultIsolateForLocking())); |
| +} |
| + |
| +bool Locker::IsLocked(v8::Isolate* isolate) { |
| + i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); |
| + internal_isolate->EnsurePreinitializedForThisThread(); |
| + return internal_isolate->thread_manager()-> |
| + IsLockedByCurrentThread(); |
| } |
| Locker::~Locker() { |
| - // TODO(isolate): this should use a field storing the isolate it |
| - // locked instead. |
| - internal::Isolate* isolate = internal::Isolate::Current(); |
| - ASSERT(isolate->thread_manager()->IsLockedByCurrentThread()); |
| + ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread()); |
| if (has_lock_) { |
| if (top_level_) { |
| - isolate->thread_manager()->FreeThreadResources(); |
| + isolate_->thread_manager()->FreeThreadResources(); |
| } else { |
| - isolate->thread_manager()->ArchiveThread(); |
| + isolate_->thread_manager()->ArchiveThread(); |
| } |
| - isolate->thread_manager()->Unlock(); |
| + isolate_->thread_manager()->Unlock(); |
| } |
| } |
| -Unlocker::Unlocker() { |
| - internal::Isolate* isolate = internal::Isolate::Current(); |
| - ASSERT(isolate->thread_manager()->IsLockedByCurrentThread()); |
| - isolate->thread_manager()->ArchiveThread(); |
| - isolate->thread_manager()->Unlock(); |
| +Unlocker::Unlocker() : isolate_(i::Isolate::GetDefaultIsolateForLocking()) { |
| + Init(); |
| +} |
| + |
| +Unlocker::Unlocker(v8::Isolate* isolate) |
| + : isolate_(reinterpret_cast<i::Isolate*>(isolate)) { |
| + Init(); |
| +} |
| + |
| + |
| +void Unlocker::Init() { |
| + ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread()); |
| + isolate_->thread_manager()->ArchiveThread(); |
| + isolate_->thread_manager()->Unlock(); |
| } |
| Unlocker::~Unlocker() { |
| - // TODO(isolates): check it's the isolate we unlocked. |
| - internal::Isolate* isolate = internal::Isolate::Current(); |
| - ASSERT(!isolate->thread_manager()->IsLockedByCurrentThread()); |
| - isolate->thread_manager()->Lock(); |
| - isolate->thread_manager()->RestoreThread(); |
| + ASSERT(!isolate_->thread_manager()->IsLockedByCurrentThread()); |
| + isolate_->thread_manager()->Lock(); |
| + isolate_->thread_manager()->RestoreThread(); |
| } |
| @@ -143,18 +163,22 @@ void Locker::StopPreemption() { |
| namespace internal { |
| + |
| bool ThreadManager::RestoreThread() { |
| + ASSERT(IsLockedByCurrentThread()); |
| // First check whether the current thread has been 'lazily archived', ie |
| // 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. |
| if (lazily_archived_thread_.Equals(ThreadId::Current())) { |
| lazily_archived_thread_ = ThreadId::Invalid(); |
| - ASSERT(Isolate::CurrentPerIsolateThreadData()->thread_state() == |
| - lazily_archived_thread_state_); |
| + Isolate::PerIsolateThreadData* per_thread = |
| + isolate_->FindPerThreadDataForThisThread(); |
| + ASSERT(per_thread != NULL); |
| + ASSERT(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; |
| - Isolate::CurrentPerIsolateThreadData()->set_thread_state(NULL); |
| + per_thread->set_thread_state(NULL); |
| return true; |
| } |
| @@ -164,11 +188,11 @@ bool ThreadManager::RestoreThread() { |
| // If there is another thread that was lazily archived then we have to really |
| // archive it now. |
| - if (lazily_archived_thread_.IsValid()) { |
| + if (!lazily_archived_thread_.Equals(ThreadId::Invalid())) { |
|
Vitaly Repeshko
2011/04/15 00:29:39
Accidental edit? IsValid() should work.
Dmitry Lomov
2011/04/19 01:50:47
Done.
|
| EagerlyArchiveThread(); |
| } |
| Isolate::PerIsolateThreadData* per_thread = |
| - Isolate::CurrentPerIsolateThreadData(); |
| + isolate_->FindPerThreadDataForThisThread(); |
| if (per_thread == NULL || per_thread->thread_state() == NULL) { |
| // This is a new thread. |
| isolate_->stack_guard()->InitThread(access); |
| @@ -178,7 +202,7 @@ bool ThreadManager::RestoreThread() { |
| char* from = state->data(); |
| from = isolate_->handle_scope_implementer()->RestoreThread(from); |
| from = isolate_->RestoreThread(from); |
| - from = Relocatable::RestoreState(from); |
| + from = Relocatable::RestoreState(isolate_, from); |
| #ifdef ENABLE_DEBUGGER_SUPPORT |
| from = isolate_->debug()->RestoreDebug(from); |
| #endif |
| @@ -300,9 +324,12 @@ ThreadManager::~ThreadManager() { |
| void ThreadManager::ArchiveThread() { |
| ASSERT(lazily_archived_thread_.Equals(ThreadId::Invalid())); |
| ASSERT(!IsArchived()); |
| + ASSERT(IsLockedByCurrentThread()); |
| ThreadState* state = GetFreeThreadState(); |
| state->Unlink(); |
| - Isolate::CurrentPerIsolateThreadData()->set_thread_state(state); |
| + Isolate::PerIsolateThreadData* per_thread = |
| + isolate_->FindOrAllocatePerThreadDataForThisThread(); |
| + per_thread->set_thread_state(state); |
| lazily_archived_thread_ = ThreadId::Current(); |
| lazily_archived_thread_state_ = state; |
| ASSERT(state->id().Equals(ThreadId::Invalid())); |
| @@ -312,6 +339,7 @@ void ThreadManager::ArchiveThread() { |
| void ThreadManager::EagerlyArchiveThread() { |
| + ASSERT(IsLockedByCurrentThread()); |
| ThreadState* state = lazily_archived_thread_state_; |
| state->LinkInto(ThreadState::IN_USE_LIST); |
| char* to = state->data(); |
| @@ -319,7 +347,7 @@ void ThreadManager::EagerlyArchiveThread() { |
| // in ThreadManager::Iterate(ObjectVisitor*). |
| to = isolate_->handle_scope_implementer()->ArchiveThread(to); |
| to = isolate_->ArchiveThread(to); |
| - to = Relocatable::ArchiveState(to); |
| + to = Relocatable::ArchiveState(isolate_, to); |
| #ifdef ENABLE_DEBUGGER_SUPPORT |
| to = isolate_->debug()->ArchiveDebug(to); |
| #endif |
| @@ -344,11 +372,11 @@ void ThreadManager::FreeThreadResources() { |
| bool ThreadManager::IsArchived() { |
| - Isolate::PerIsolateThreadData* data = Isolate::CurrentPerIsolateThreadData(); |
| + Isolate::PerIsolateThreadData* data = |
| + isolate_->FindPerThreadDataForThisThread(); |
| return data != NULL && data->thread_state() != NULL; |
| } |
| - |
| void ThreadManager::Iterate(ObjectVisitor* v) { |
| // Expecting no threads during serialization/deserialization |
| for (ThreadState* state = FirstThreadStateInUse(); |