v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
v8threads.cc
Go to the documentation of this file.
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
6
7#include "include/v8-locker.h"
8#include "src/api/api.h"
9#include "src/debug/debug.h"
16
17namespace v8 {
18
19namespace {
20
21// Track whether this V8 instance has ever called v8::Locker. This allows the
22// API code to verify that the lock is always held when V8 is being entered.
23base::AtomicWord g_locker_was_ever_used_ = 0;
24
25} // namespace
26
27// Once the Locker is initialized, the current thread will be guaranteed to have
28// the lock for a given isolate.
30 DCHECK_NOT_NULL(isolate);
31 has_lock_ = false;
32 top_level_ = true;
33 isolate_ = reinterpret_cast<i::Isolate*>(isolate);
34
35 // Record that the Locker has been used at least once.
36 base::Relaxed_Store(&g_locker_was_ever_used_, 1);
38
39 // Get the big lock if necessary.
42 has_lock_ = true;
43
44 // This may be a locker within an unlocker in which case we have to
45 // get the saved state for this thread and restore it.
47 top_level_ = false;
48 }
49 }
51}
52
54 DCHECK_NOT_NULL(isolate);
55 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
56 return i_isolate->thread_manager()->IsLockedByCurrentThread();
57}
58
70
78
84
85namespace internal {
86
92
95 // First check whether the current thread has been 'lazily archived', i.e.
96 // not archived at all. If that is the case we put the state storage we
97 // had prepared back in the free list, since we didn't need it after all.
102 DCHECK_NOT_NULL(per_thread);
103 DCHECK(per_thread->thread_state() == lazily_archived_thread_state_);
107 per_thread->set_thread_state(nullptr);
108 return true;
109 }
110
111 // Make sure that the preemption thread cannot modify the thread state while
112 // it is being archived or restored.
114
115 // If there is another thread that was lazily archived then we have to really
116 // archive it now.
119 }
122 if (per_thread == nullptr || per_thread->thread_state() == nullptr) {
123 // This is a new thread.
124 InitThread(access);
125 return false;
126 }
127 // In case multi-cage pointer compression mode is enabled ensure that
128 // current thread's cage base values are properly initialized.
129 PtrComprCageAccessScope ptr_compr_cage_access_scope(isolate_);
130
131 ThreadState* state = per_thread->thread_state();
132 char* from = state->data();
134 from = isolate_->RestoreThread(from);
136 // Stack guard should be restored before Debug, etc. since Debug etc. might
137 // depend on a correct stack guard.
138 from = isolate_->stack_guard()->RestoreStackGuard(from);
139 from = isolate_->debug()->RestoreDebug(from);
140 from = isolate_->regexp_stack()->RestoreStack(from);
141 from = isolate_->bootstrapper()->RestoreState(from);
142 per_thread->set_thread_state(nullptr);
143 state->set_id(ThreadId::Invalid());
144 state->Unlink();
145 state->LinkInto(ThreadState::FREE_LIST);
146 return true;
147}
148
150 mutex_.Lock();
151 mutex_owner_.store(ThreadId::Current(), std::memory_order_relaxed);
153}
154
156 mutex_owner_.store(ThreadId::Invalid(), std::memory_order_relaxed);
157 mutex_.Unlock();
158}
159
168
170 : id_(ThreadId::Invalid()),
171 data_(nullptr),
172 next_(this),
173 previous_(this),
174 thread_manager_(thread_manager) {}
175
177
181
186
188 ThreadState* flying_anchor = list == FREE_LIST
191 next_ = flying_anchor->next_;
192 previous_ = flying_anchor;
193 flying_anchor->next_ = this;
194 next_->previous_ = this;
195}
196
198 ThreadState* gotten = free_anchor_->next_;
199 if (gotten == free_anchor_) {
200 ThreadState* new_thread_state = new ThreadState(this);
201 new_thread_state->AllocateSpace();
202 return new_thread_state;
203 }
204 return gotten;
205}
206
207// Gets the first in the list of archived threads.
211
213 if (next_ == thread_manager_->in_use_anchor_) return nullptr;
214 return next_;
215}
216
217// Thread ids must start with 1, because in TLS having thread id 0 can't
218// be distinguished from not having a thread id at all (since NULL is
219// defined as 0.)
221 : mutex_owner_(ThreadId::Invalid()),
222 lazily_archived_thread_(ThreadId::Invalid()),
223 lazily_archived_thread_state_(nullptr),
224 free_anchor_(nullptr),
225 in_use_anchor_(nullptr),
226 isolate_(isolate) {
227 free_anchor_ = new ThreadState(this);
228 in_use_anchor_ = new ThreadState(this);
229}
230
235
237 // The list starts and ends with the anchor.
238 for (ThreadState* current = anchor->next_; current != anchor;) {
239 ThreadState* next = current->next_;
240 delete current;
241 current = next;
242 }
243 delete anchor;
244}
245
248 DCHECK(!IsArchived());
251 state->Unlink();
254 per_thread->set_thread_state(state);
257 DCHECK_EQ(state->id(), ThreadId::Invalid());
258 state->set_id(CurrentId());
259 DCHECK_NE(state->id(), ThreadId::Invalid());
260}
261
266 char* to = state->data();
267 // Ensure that data containing GC roots are archived first, and handle them
268 // in ThreadManager::Iterate(RootVisitor*).
270 to = isolate_->ArchiveThread(to);
273 to = isolate_->debug()->ArchiveDebug(to);
278}
279
281 // This method might be called on a thread that's not bound to any Isolate
282 // and thus pointer compression schemes might have cage base value unset.
283 // So, allow heap access here to let the checks work.
284 PtrComprCageAccessScope ptr_compr_cage_access_scope(isolate_);
285
294}
295
299 return data != nullptr && data->thread_state() != nullptr;
300}
301
303 // Expecting no threads during serialization/deserialization
304 for (ThreadState* state = FirstThreadStateInUse(); state != nullptr;
305 state = state->Next()) {
306 char* data = state->data();
307 data = HandleScopeImplementer::Iterate(v, data);
308 data = isolate_->Iterate(v, data);
309 data = Relocatable::Iterate(v, data);
310 data = StackGuard::Iterate(v, data);
311 data = Debug::Iterate(v, data);
312 }
313}
314
316 for (ThreadState* state = FirstThreadStateInUse(); state != nullptr;
317 state = state->Next()) {
318 char* data = state->data();
320 isolate_->IterateThread(v, data);
321 }
322}
323
325
326} // namespace internal
327} // namespace v8
Isolate * isolate_
uint8_t data_[MAX_STACK_LENGTH]
void Initialize(Isolate *isolate)
Definition v8threads.cc:29
bool top_level_
Definition v8-locker.h:132
bool has_lock_
Definition v8-locker.h:131
internal::Isolate * isolate_
Definition v8-locker.h:133
static bool IsLocked(Isolate *isolate)
Definition v8threads.cc:53
internal::Isolate * isolate_
Definition v8-locker.h:106
void Initialize(Isolate *isolate)
Definition v8threads.cc:71
void Unlock()
Definition mutex.cc:67
void Lock()
Definition mutex.cc:62
char * RestoreState(char *from)
char * ArchiveState(char *to)
void InitThread(const ExecutionAccess &lock)
Definition debug.h:402
char * ArchiveDebug(char *to)
Definition debug.cc:485
void FreeThreadResources()
Definition debug.h:400
void Iterate(RootVisitor *v)
Definition debug.cc:526
static int ArchiveSpacePerThread()
Definition debug.cc:524
char * RestoreDebug(char *from)
Definition debug.cc:491
V8_EXPORT_PRIVATE void Iterate(v8::internal::RootVisitor *v)
Definition api.cc:12050
char * RestoreThread(char *from)
Definition api.cc:11990
v8::TryCatch * try_catch_handler()
Definition isolate.h:850
RegExpStack * regexp_stack() const
Definition isolate.h:1445
HandleScopeImplementer * handle_scope_implementer() const
Definition isolate.h:1397
Bootstrapper * bootstrapper()
Definition isolate.h:1178
PerIsolateThreadData * FindPerThreadDataForThisThread()
Definition isolate.cc:568
static int ArchiveSpacePerThread()
Definition isolate.h:947
void IterateThread(ThreadVisitor *v, char *t)
Definition isolate.cc:600
ThreadManager * thread_manager() const
Definition isolate.h:1422
char * RestoreThread(char *from)
Definition isolate.cc:3758
void FreeThreadResources()
Definition isolate.h:948
char * ArchiveThread(char *to)
Definition isolate.cc:3752
PerIsolateThreadData * FindOrAllocatePerThreadDataForThisThread()
Definition isolate.cc:536
StackGuard * stack_guard()
Definition isolate.h:1198
void set_was_locker_ever_used()
Definition isolate.h:1732
void Iterate(RootVisitor *v)
Definition isolate.cc:650
Debug * debug() const
Definition isolate.h:1474
char * ArchiveStack(char *to)
static constexpr int ArchiveSpacePerThread()
char * RestoreStack(char *from)
static char * RestoreState(Isolate *isolate, char *from)
Definition objects.cc:4097
static void Iterate(Isolate *isolate, RootVisitor *v)
Definition objects.cc:4108
static int ArchiveSpacePerThread()
Definition objects.cc:4087
static char * ArchiveState(Isolate *isolate, char *to)
Definition objects.cc:4090
static char * Iterate(RootVisitor *v, char *thread_storage)
void InitThread(const ExecutionAccess &lock)
static int ArchiveSpacePerThread()
Definition stack-guard.h:54
char * ArchiveStackGuard(char *to)
char * RestoreStackGuard(char *from)
bool IsValid() const
Definition thread-id.h:23
static ThreadId Current()
Definition thread-id.h:32
static constexpr ThreadId Invalid()
Definition thread-id.h:35
void Iterate(RootVisitor *v)
Definition v8threads.cc:302
void IterateArchivedThreads(ThreadVisitor *v)
Definition v8threads.cc:315
ThreadState * FirstThreadStateInUse()
Definition v8threads.cc:208
ThreadState * lazily_archived_thread_state_
Definition v8threads.h:99
ThreadState * in_use_anchor_
Definition v8threads.h:107
ThreadManager(Isolate *isolate)
Definition v8threads.cc:220
void InitThread(const ExecutionAccess &)
Definition v8threads.cc:87
std::atomic< ThreadId > mutex_owner_
Definition v8threads.h:97
void DeleteThreadStateList(ThreadState *anchor)
Definition v8threads.cc:236
bool IsLockedByCurrentThread() const
Definition v8threads.h:73
V8_EXPORT_PRIVATE void Unlock()
Definition v8threads.cc:155
ThreadState * GetFreeThreadState()
Definition v8threads.cc:197
void set_id(ThreadId id)
Definition v8threads.h:29
ThreadState * previous_
Definition v8threads.h:44
void LinkInto(List list)
Definition v8threads.cc:187
ThreadManager * thread_manager_
Definition v8threads.h:46
ThreadState(ThreadManager *thread_manager)
Definition v8threads.cc:169
LineAndColumn current
Isolate * isolate
LiftoffAssembler::CacheState state
void Relaxed_Store(volatile Atomic8 *ptr, Atomic8 value)
Definition atomicops.h:189
Atomic32 AtomicWord
Definition atomicops.h:76
void DeleteArray(T *array)
Definition allocation.h:63
static int ArchiveSpacePerThread()
Definition v8threads.cc:160
T * NewArray(size_t size)
Definition allocation.h:43
#define DCHECK_NULL(val)
Definition logging.h:491
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_NE(v1, v2)
Definition logging.h:486
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485