| OLD | NEW |
| 1 // Copyright 2008 the V8 project authors. All rights reserved. | 1 // Copyright 2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 | 43 |
| 44 | 44 |
| 45 // Track whether this V8 instance has ever called v8::Locker. This allows the | 45 // Track whether this V8 instance has ever called v8::Locker. This allows the |
| 46 // API code to verify that the lock is always held when V8 is being entered. | 46 // API code to verify that the lock is always held when V8 is being entered. |
| 47 bool Locker::active_ = false; | 47 bool Locker::active_ = false; |
| 48 | 48 |
| 49 | 49 |
| 50 // Constructor for the Locker object. Once the Locker is constructed the | 50 // Constructor for the Locker object. Once the Locker is constructed the |
| 51 // current thread will be guaranteed to have the big V8 lock. | 51 // current thread will be guaranteed to have the big V8 lock. |
| 52 Locker::Locker() : has_lock_(false), top_level_(true) { | 52 Locker::Locker() : has_lock_(false), top_level_(true) { |
| 53 internal::Isolate* isolate = internal::Isolate::Current(); |
| 53 // Record that the Locker has been used at least once. | 54 // Record that the Locker has been used at least once. |
| 54 active_ = true; | 55 active_ = true; |
| 55 // Get the big lock if necessary. | 56 // Get the big lock if necessary. |
| 56 if (!internal::ThreadManager::IsLockedByCurrentThread()) { | 57 if (!internal::ThreadManager::IsLockedByCurrentThread()) { |
| 57 internal::ThreadManager::Lock(); | 58 internal::ThreadManager::Lock(); |
| 58 has_lock_ = true; | 59 has_lock_ = true; |
| 59 // Make sure that V8 is initialized. Archiving of threads interferes | 60 // Make sure that V8 is initialized. Archiving of threads interferes |
| 60 // with deserialization by adding additional root pointers, so we must | 61 // with deserialization by adding additional root pointers, so we must |
| 61 // initialize here, before anyone can call ~Locker() or Unlocker(). | 62 // initialize here, before anyone can call ~Locker() or Unlocker(). |
| 62 if (!internal::V8::IsRunning()) { | 63 if (!internal::V8::IsRunning()) { |
| 63 V8::Initialize(); | 64 V8::Initialize(); |
| 64 } | 65 } |
| 65 // This may be a locker within an unlocker in which case we have to | 66 // This may be a locker within an unlocker in which case we have to |
| 66 // get the saved state for this thread and restore it. | 67 // get the saved state for this thread and restore it. |
| 67 if (internal::ThreadManager::RestoreThread()) { | 68 if (internal::ThreadManager::RestoreThread()) { |
| 68 top_level_ = false; | 69 top_level_ = false; |
| 69 } else { | 70 } else { |
| 70 internal::ExecutionAccess access; | 71 internal::ExecutionAccess access; |
| 71 internal::StackGuard::ClearThread(access); | 72 isolate->stack_guard()->ClearThread(access); |
| 72 internal::StackGuard::InitThread(access); | 73 isolate->stack_guard()->InitThread(access); |
| 73 } | 74 } |
| 74 } | 75 } |
| 75 ASSERT(internal::ThreadManager::IsLockedByCurrentThread()); | 76 ASSERT(internal::ThreadManager::IsLockedByCurrentThread()); |
| 76 | 77 |
| 77 // Make sure this thread is assigned a thread id. | 78 // Make sure this thread is assigned a thread id. |
| 78 internal::ThreadManager::AssignId(); | 79 internal::ThreadManager::AssignId(); |
| 79 } | 80 } |
| 80 | 81 |
| 81 | 82 |
| 82 bool Locker::IsLocked() { | 83 bool Locker::IsLocked() { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 | 119 |
| 119 void Locker::StopPreemption() { | 120 void Locker::StopPreemption() { |
| 120 v8::internal::ContextSwitcher::StopPreemption(); | 121 v8::internal::ContextSwitcher::StopPreemption(); |
| 121 } | 122 } |
| 122 | 123 |
| 123 | 124 |
| 124 namespace internal { | 125 namespace internal { |
| 125 | 126 |
| 126 | 127 |
| 127 bool ThreadManager::RestoreThread() { | 128 bool ThreadManager::RestoreThread() { |
| 129 Isolate* isolate = Isolate::Current(); |
| 128 // First check whether the current thread has been 'lazily archived', ie | 130 // First check whether the current thread has been 'lazily archived', ie |
| 129 // not archived at all. If that is the case we put the state storage we | 131 // not archived at all. If that is the case we put the state storage we |
| 130 // had prepared back in the free list, since we didn't need it after all. | 132 // had prepared back in the free list, since we didn't need it after all. |
| 131 if (lazily_archived_thread_.IsSelf()) { | 133 if (lazily_archived_thread_.IsSelf()) { |
| 132 lazily_archived_thread_.Initialize(ThreadHandle::INVALID); | 134 lazily_archived_thread_.Initialize(ThreadHandle::INVALID); |
| 133 ASSERT(Thread::GetThreadLocal(thread_state_key) == | 135 ASSERT(Thread::GetThreadLocal(thread_state_key) == |
| 134 lazily_archived_thread_state_); | 136 lazily_archived_thread_state_); |
| 135 lazily_archived_thread_state_->set_id(kInvalidId); | 137 lazily_archived_thread_state_->set_id(kInvalidId); |
| 136 lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST); | 138 lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST); |
| 137 lazily_archived_thread_state_ = NULL; | 139 lazily_archived_thread_state_ = NULL; |
| 138 Thread::SetThreadLocal(thread_state_key, NULL); | 140 Thread::SetThreadLocal(thread_state_key, NULL); |
| 139 return true; | 141 return true; |
| 140 } | 142 } |
| 141 | 143 |
| 142 // Make sure that the preemption thread cannot modify the thread state while | 144 // Make sure that the preemption thread cannot modify the thread state while |
| 143 // it is being archived or restored. | 145 // it is being archived or restored. |
| 144 ExecutionAccess access; | 146 ExecutionAccess access; |
| 145 | 147 |
| 146 // If there is another thread that was lazily archived then we have to really | 148 // If there is another thread that was lazily archived then we have to really |
| 147 // archive it now. | 149 // archive it now. |
| 148 if (lazily_archived_thread_.IsValid()) { | 150 if (lazily_archived_thread_.IsValid()) { |
| 149 EagerlyArchiveThread(); | 151 EagerlyArchiveThread(); |
| 150 } | 152 } |
| 151 ThreadState* state = | 153 ThreadState* state = |
| 152 reinterpret_cast<ThreadState*>(Thread::GetThreadLocal(thread_state_key)); | 154 reinterpret_cast<ThreadState*>(Thread::GetThreadLocal(thread_state_key)); |
| 153 if (state == NULL) { | 155 if (state == NULL) { |
| 154 // This is a new thread. | 156 // This is a new thread. |
| 155 StackGuard::InitThread(access); | 157 isolate->stack_guard()->InitThread(access); |
| 156 return false; | 158 return false; |
| 157 } | 159 } |
| 158 Isolate* isolate = Isolate::Current(); | |
| 159 char* from = state->data(); | 160 char* from = state->data(); |
| 160 from = isolate->handle_scope_implementer()->RestoreThread(from); | 161 from = isolate->handle_scope_implementer()->RestoreThread(from); |
| 161 from = Top::RestoreThread(from); | 162 from = Top::RestoreThread(from); |
| 162 from = Relocatable::RestoreState(from); | 163 from = Relocatable::RestoreState(from); |
| 163 #ifdef ENABLE_DEBUGGER_SUPPORT | 164 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 164 from = Debug::RestoreDebug(from); | 165 from = Debug::RestoreDebug(from); |
| 165 #endif | 166 #endif |
| 166 from = StackGuard::RestoreStackGuard(from); | 167 from = isolate->stack_guard()->RestoreStackGuard(from); |
| 167 from = RegExpStack::RestoreStack(from); | 168 from = RegExpStack::RestoreStack(from); |
| 168 from = isolate->bootstrapper()->RestoreState(from); | 169 from = isolate->bootstrapper()->RestoreState(from); |
| 169 Thread::SetThreadLocal(thread_state_key, NULL); | 170 Thread::SetThreadLocal(thread_state_key, NULL); |
| 170 if (state->terminate_on_restore()) { | 171 if (state->terminate_on_restore()) { |
| 171 StackGuard::TerminateExecution(); | 172 isolate->stack_guard()->TerminateExecution(); |
| 172 state->set_terminate_on_restore(false); | 173 state->set_terminate_on_restore(false); |
| 173 } | 174 } |
| 174 state->set_id(kInvalidId); | 175 state->set_id(kInvalidId); |
| 175 state->Unlink(); | 176 state->Unlink(); |
| 176 state->LinkInto(ThreadState::FREE_LIST); | 177 state->LinkInto(ThreadState::FREE_LIST); |
| 177 return true; | 178 return true; |
| 178 } | 179 } |
| 179 | 180 |
| 180 | 181 |
| 181 void ThreadManager::Lock() { | 182 void ThreadManager::Lock() { |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 276 Thread::SetThreadLocal(thread_state_key, reinterpret_cast<void*>(state)); | 277 Thread::SetThreadLocal(thread_state_key, reinterpret_cast<void*>(state)); |
| 277 lazily_archived_thread_.Initialize(ThreadHandle::SELF); | 278 lazily_archived_thread_.Initialize(ThreadHandle::SELF); |
| 278 lazily_archived_thread_state_ = state; | 279 lazily_archived_thread_state_ = state; |
| 279 ASSERT(state->id() == kInvalidId); | 280 ASSERT(state->id() == kInvalidId); |
| 280 state->set_id(CurrentId()); | 281 state->set_id(CurrentId()); |
| 281 ASSERT(state->id() != kInvalidId); | 282 ASSERT(state->id() != kInvalidId); |
| 282 } | 283 } |
| 283 | 284 |
| 284 | 285 |
| 285 void ThreadManager::EagerlyArchiveThread() { | 286 void ThreadManager::EagerlyArchiveThread() { |
| 287 Isolate* isolate = Isolate::Current(); |
| 286 ThreadState* state = lazily_archived_thread_state_; | 288 ThreadState* state = lazily_archived_thread_state_; |
| 287 state->LinkInto(ThreadState::IN_USE_LIST); | 289 state->LinkInto(ThreadState::IN_USE_LIST); |
| 288 Isolate* isolate = Isolate::Current(); | |
| 289 char* to = state->data(); | 290 char* to = state->data(); |
| 290 // Ensure that data containing GC roots are archived first, and handle them | 291 // Ensure that data containing GC roots are archived first, and handle them |
| 291 // in ThreadManager::Iterate(ObjectVisitor*). | 292 // in ThreadManager::Iterate(ObjectVisitor*). |
| 292 to = isolate->handle_scope_implementer()->ArchiveThread(to); | 293 to = isolate->handle_scope_implementer()->ArchiveThread(to); |
| 293 to = Top::ArchiveThread(to); | 294 to = Top::ArchiveThread(to); |
| 294 to = Relocatable::ArchiveState(to); | 295 to = Relocatable::ArchiveState(to); |
| 295 #ifdef ENABLE_DEBUGGER_SUPPORT | 296 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 296 to = Debug::ArchiveDebug(to); | 297 to = Debug::ArchiveDebug(to); |
| 297 #endif | 298 #endif |
| 298 to = StackGuard::ArchiveStackGuard(to); | 299 to = isolate->stack_guard()->ArchiveStackGuard(to); |
| 299 to = RegExpStack::ArchiveStack(to); | 300 to = RegExpStack::ArchiveStack(to); |
| 300 to = isolate->bootstrapper()->ArchiveState(to); | 301 to = isolate->bootstrapper()->ArchiveState(to); |
| 301 lazily_archived_thread_.Initialize(ThreadHandle::INVALID); | 302 lazily_archived_thread_.Initialize(ThreadHandle::INVALID); |
| 302 lazily_archived_thread_state_ = NULL; | 303 lazily_archived_thread_state_ = NULL; |
| 303 } | 304 } |
| 304 | 305 |
| 305 | 306 |
| 306 void ThreadManager::FreeThreadResources() { | 307 void ThreadManager::FreeThreadResources() { |
| 307 Isolate* isolate = Isolate::Current(); | 308 Isolate* isolate = Isolate::Current(); |
| 308 isolate->handle_scope_implementer()->FreeThreadResources(); | 309 isolate->handle_scope_implementer()->FreeThreadResources(); |
| 309 Top::FreeThreadResources(); | 310 Top::FreeThreadResources(); |
| 310 #ifdef ENABLE_DEBUGGER_SUPPORT | 311 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 311 Debug::FreeThreadResources(); | 312 Debug::FreeThreadResources(); |
| 312 #endif | 313 #endif |
| 313 StackGuard::FreeThreadResources(); | 314 isolate->stack_guard()->FreeThreadResources(); |
| 314 RegExpStack::FreeThreadResources(); | 315 RegExpStack::FreeThreadResources(); |
| 315 isolate->bootstrapper()->FreeThreadResources(); | 316 isolate->bootstrapper()->FreeThreadResources(); |
| 316 } | 317 } |
| 317 | 318 |
| 318 | 319 |
| 319 bool ThreadManager::IsArchived() { | 320 bool ThreadManager::IsArchived() { |
| 320 return Thread::HasThreadLocal(thread_state_key); | 321 return Thread::HasThreadLocal(thread_state_key); |
| 321 } | 322 } |
| 322 | 323 |
| 323 | 324 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 singleton_ = NULL; | 441 singleton_ = NULL; |
| 441 } | 442 } |
| 442 } | 443 } |
| 443 | 444 |
| 444 | 445 |
| 445 // Main loop of the ContextSwitcher thread: Preempt the currently running V8 | 446 // Main loop of the ContextSwitcher thread: Preempt the currently running V8 |
| 446 // thread at regular intervals. | 447 // thread at regular intervals. |
| 447 void ContextSwitcher::Run() { | 448 void ContextSwitcher::Run() { |
| 448 while (keep_going_) { | 449 while (keep_going_) { |
| 449 OS::Sleep(sleep_ms_); | 450 OS::Sleep(sleep_ms_); |
| 450 StackGuard::Preempt(); | 451 Isolate::Current()->stack_guard()->Preempt(); |
| 451 } | 452 } |
| 452 } | 453 } |
| 453 | 454 |
| 454 | 455 |
| 455 // Acknowledge the preemption by the receiving thread. | 456 // Acknowledge the preemption by the receiving thread. |
| 456 void ContextSwitcher::PreemptionReceived() { | 457 void ContextSwitcher::PreemptionReceived() { |
| 457 ASSERT(Locker::IsLocked()); | 458 ASSERT(Locker::IsLocked()); |
| 458 // There is currently no accounting being done for this. But could be in the | 459 // There is currently no accounting being done for this. But could be in the |
| 459 // future, which is why we leave this in. | 460 // future, which is why we leave this in. |
| 460 } | 461 } |
| 461 | 462 |
| 462 | 463 |
| 463 } // namespace internal | 464 } // namespace internal |
| 464 } // namespace v8 | 465 } // namespace v8 |
| OLD | NEW |