5 #include "src/v8threads.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" 22 base::Atomic32 g_locker_was_ever_used_ = 0;
29 void Locker::Initialize(v8::Isolate* isolate) {
30 DCHECK_NOT_NULL(isolate);
33 isolate_ =
reinterpret_cast<i::Isolate*
>(isolate);
35 base::Relaxed_Store(&g_locker_was_ever_used_, 1);
37 if (!isolate_->thread_manager()->IsLockedByCurrentThread()) {
38 isolate_->thread_manager()->Lock();
43 if (isolate_->thread_manager()->RestoreThread()) {
46 internal::ExecutionAccess access(isolate_);
47 isolate_->stack_guard()->ClearThread(access);
48 isolate_->thread_manager()->InitThread(access);
51 DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
55 bool Locker::IsLocked(v8::Isolate* isolate) {
56 DCHECK_NOT_NULL(isolate);
58 return internal_isolate->thread_manager()->IsLockedByCurrentThread();
62 bool Locker::IsActive() {
63 return !!base::Relaxed_Load(&g_locker_was_ever_used_);
68 DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
71 isolate_->thread_manager()->FreeThreadResources();
73 isolate_->thread_manager()->ArchiveThread();
75 isolate_->thread_manager()->Unlock();
80 void Unlocker::Initialize(v8::Isolate* isolate) {
81 DCHECK_NOT_NULL(isolate);
82 isolate_ =
reinterpret_cast<i::Isolate*
>(isolate);
83 DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
84 isolate_->thread_manager()->ArchiveThread();
85 isolate_->thread_manager()->Unlock();
89 Unlocker::~Unlocker() {
90 DCHECK(!isolate_->thread_manager()->IsLockedByCurrentThread());
91 isolate_->thread_manager()->Lock();
92 isolate_->thread_manager()->RestoreThread();
98 void ThreadManager::InitThread(
const ExecutionAccess& lock) {
99 isolate_->stack_guard()->InitThread(lock);
100 isolate_->debug()->InitThread(lock);
103 bool ThreadManager::RestoreThread() {
104 DCHECK(IsLockedByCurrentThread());
108 if (lazily_archived_thread_.Equals(ThreadId::Current())) {
109 lazily_archived_thread_ = ThreadId::Invalid();
110 Isolate::PerIsolateThreadData* per_thread =
111 isolate_->FindPerThreadDataForThisThread();
112 DCHECK_NOT_NULL(per_thread);
113 DCHECK(per_thread->thread_state() == lazily_archived_thread_state_);
114 lazily_archived_thread_state_->set_id(ThreadId::Invalid());
115 lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST);
116 lazily_archived_thread_state_ =
nullptr;
117 per_thread->set_thread_state(
nullptr);
123 ExecutionAccess access(isolate_);
127 if (lazily_archived_thread_.IsValid()) {
128 EagerlyArchiveThread();
130 Isolate::PerIsolateThreadData* per_thread =
131 isolate_->FindPerThreadDataForThisThread();
132 if (per_thread ==
nullptr || per_thread->thread_state() ==
nullptr) {
137 ThreadState* state = per_thread->thread_state();
138 char* from = state->data();
139 from = isolate_->handle_scope_implementer()->RestoreThread(from);
140 from = isolate_->RestoreThread(from);
141 from = Relocatable::RestoreState(isolate_, from);
142 from = isolate_->debug()->RestoreDebug(from);
143 from = isolate_->stack_guard()->RestoreStackGuard(from);
144 from = isolate_->regexp_stack()->RestoreStack(from);
145 from = isolate_->bootstrapper()->RestoreState(from);
146 per_thread->set_thread_state(
nullptr);
147 if (state->terminate_on_restore()) {
148 isolate_->stack_guard()->RequestTerminateExecution();
149 state->set_terminate_on_restore(
false);
151 state->set_id(ThreadId::Invalid());
153 state->LinkInto(ThreadState::FREE_LIST);
158 void ThreadManager::Lock() {
160 mutex_owner_ = ThreadId::Current();
161 DCHECK(IsLockedByCurrentThread());
165 void ThreadManager::Unlock() {
166 mutex_owner_ = ThreadId::Invalid();
171 static int ArchiveSpacePerThread() {
172 return HandleScopeImplementer::ArchiveSpacePerThread() +
173 Isolate::ArchiveSpacePerThread() +
174 Debug::ArchiveSpacePerThread() +
175 StackGuard::ArchiveSpacePerThread() +
176 RegExpStack::ArchiveSpacePerThread() +
177 Bootstrapper::ArchiveSpacePerThread() +
178 Relocatable::ArchiveSpacePerThread();
181 ThreadState::ThreadState(ThreadManager* thread_manager)
182 : id_(ThreadId::Invalid()),
183 terminate_on_restore_(false),
187 thread_manager_(thread_manager) {}
189 ThreadState::~ThreadState() {
190 DeleteArray<char>(data_);
194 void ThreadState::AllocateSpace() {
195 data_ = NewArray<char>(ArchiveSpacePerThread());
199 void ThreadState::Unlink() {
200 next_->previous_ = previous_;
201 previous_->next_ = next_;
205 void ThreadState::LinkInto(List list) {
206 ThreadState* flying_anchor =
207 list == FREE_LIST ? thread_manager_->free_anchor_
208 : thread_manager_->in_use_anchor_;
209 next_ = flying_anchor->next_;
210 previous_ = flying_anchor;
211 flying_anchor->next_ =
this;
212 next_->previous_ =
this;
216 ThreadState* ThreadManager::GetFreeThreadState() {
217 ThreadState* gotten = free_anchor_->next_;
218 if (gotten == free_anchor_) {
219 ThreadState* new_thread_state =
new ThreadState(
this);
220 new_thread_state->AllocateSpace();
221 return new_thread_state;
228 ThreadState* ThreadManager::FirstThreadStateInUse() {
229 return in_use_anchor_->Next();
233 ThreadState* ThreadState::Next() {
234 if (next_ == thread_manager_->in_use_anchor_)
return nullptr;
241 ThreadManager::ThreadManager(Isolate* isolate)
242 : mutex_owner_(ThreadId::Invalid()),
243 lazily_archived_thread_(ThreadId::Invalid()),
244 lazily_archived_thread_state_(nullptr),
245 free_anchor_(nullptr),
246 in_use_anchor_(nullptr),
248 free_anchor_ =
new ThreadState(
this);
249 in_use_anchor_ =
new ThreadState(
this);
253 ThreadManager::~ThreadManager() {
254 DeleteThreadStateList(free_anchor_);
255 DeleteThreadStateList(in_use_anchor_);
259 void ThreadManager::DeleteThreadStateList(ThreadState* anchor) {
261 for (ThreadState* current = anchor->next_; current != anchor;) {
262 ThreadState* next = current->next_;
270 void ThreadManager::ArchiveThread() {
271 DCHECK(lazily_archived_thread_.Equals(ThreadId::Invalid()));
272 DCHECK(!IsArchived());
273 DCHECK(IsLockedByCurrentThread());
274 ThreadState* state = GetFreeThreadState();
276 Isolate::PerIsolateThreadData* per_thread =
277 isolate_->FindOrAllocatePerThreadDataForThisThread();
278 per_thread->set_thread_state(state);
279 lazily_archived_thread_ = ThreadId::Current();
280 lazily_archived_thread_state_ = state;
281 DCHECK(state->id().Equals(ThreadId::Invalid()));
282 state->set_id(CurrentId());
283 DCHECK(!state->id().Equals(ThreadId::Invalid()));
287 void ThreadManager::EagerlyArchiveThread() {
288 DCHECK(IsLockedByCurrentThread());
289 ThreadState* state = lazily_archived_thread_state_;
290 state->LinkInto(ThreadState::IN_USE_LIST);
291 char* to = state->data();
294 to = isolate_->handle_scope_implementer()->ArchiveThread(to);
295 to = isolate_->ArchiveThread(to);
296 to = Relocatable::ArchiveState(isolate_, to);
297 to = isolate_->debug()->ArchiveDebug(to);
298 to = isolate_->stack_guard()->ArchiveStackGuard(to);
299 to = isolate_->regexp_stack()->ArchiveStack(to);
300 to = isolate_->bootstrapper()->ArchiveState(to);
301 lazily_archived_thread_ = ThreadId::Invalid();
302 lazily_archived_thread_state_ =
nullptr;
306 void ThreadManager::FreeThreadResources() {
307 DCHECK(!isolate_->has_pending_exception());
308 DCHECK(!isolate_->external_caught_exception());
309 DCHECK_NULL(isolate_->try_catch_handler());
310 isolate_->handle_scope_implementer()->FreeThreadResources();
311 isolate_->FreeThreadResources();
312 isolate_->debug()->FreeThreadResources();
313 isolate_->stack_guard()->FreeThreadResources();
314 isolate_->regexp_stack()->FreeThreadResources();
315 isolate_->bootstrapper()->FreeThreadResources();
319 bool ThreadManager::IsArchived() {
320 Isolate::PerIsolateThreadData* data =
321 isolate_->FindPerThreadDataForThisThread();
322 return data !=
nullptr && data->thread_state() !=
nullptr;
325 void ThreadManager::Iterate(RootVisitor* v) {
327 for (ThreadState* state = FirstThreadStateInUse(); state !=
nullptr;
328 state = state->Next()) {
329 char* data = state->data();
330 data = HandleScopeImplementer::Iterate(v, data);
331 data = isolate_->Iterate(v, data);
332 data = Relocatable::Iterate(v, data);
337 void ThreadManager::IterateArchivedThreads(ThreadVisitor* v) {
338 for (ThreadState* state = FirstThreadStateInUse(); state !=
nullptr;
339 state = state->Next()) {
340 char* data = state->data();
341 data += HandleScopeImplementer::ArchiveSpacePerThread();
342 isolate_->IterateThread(v, data);
347 ThreadId ThreadManager::CurrentId() {
348 return ThreadId::Current();
352 void ThreadManager::TerminateExecution(ThreadId thread_id) {
353 for (ThreadState* state = FirstThreadStateInUse(); state !=
nullptr;
354 state = state->Next()) {
355 if (thread_id.Equals(state->id())) {
356 state->set_terminate_on_restore(
true);