50
45
// Constructor for the Locker object. Once the Locker is constructed the
51
// current thread will be guaranteed to have the big V8 lock.
52
Locker::Locker() : has_lock_(false), top_level_(true) {
46
// current thread will be guaranteed to have the lock for a given isolate.
47
Locker::Locker(v8::Isolate* isolate)
50
isolate_(reinterpret_cast<i::Isolate*>(isolate)) {
51
if (isolate_ == NULL) {
52
isolate_ = i::Isolate::GetDefaultIsolateForLocking();
53
54
// Record that the Locker has been used at least once.
55
56
// Get the big lock if necessary.
56
if (!internal::ThreadManager::IsLockedByCurrentThread()) {
57
internal::ThreadManager::Lock();
57
if (!isolate_->thread_manager()->IsLockedByCurrentThread()) {
58
isolate_->thread_manager()->Lock();
59
61
// Make sure that V8 is initialized. Archiving of threads interferes
60
62
// with deserialization by adding additional root pointers, so we must
61
63
// initialize here, before anyone can call ~Locker() or Unlocker().
62
if (!internal::V8::IsRunning()) {
64
if (!isolate_->IsInitialized()) {
65
70
// This may be a locker within an unlocker in which case we have to
66
71
// get the saved state for this thread and restore it.
67
if (internal::ThreadManager::RestoreThread()) {
72
if (isolate_->thread_manager()->RestoreThread()) {
68
73
top_level_ = false;
70
internal::ExecutionAccess access;
71
internal::StackGuard::ClearThread(access);
72
internal::StackGuard::InitThread(access);
75
ASSERT(internal::ThreadManager::IsLockedByCurrentThread());
77
// Make sure this thread is assigned a thread id.
78
internal::ThreadManager::AssignId();
82
bool Locker::IsLocked() {
83
return internal::ThreadManager::IsLockedByCurrentThread();
75
internal::ExecutionAccess access(isolate_);
76
isolate_->stack_guard()->ClearThread(access);
77
isolate_->stack_guard()->InitThread(access);
79
if (isolate_->IsDefaultIsolate()) {
80
// This only enters if not yet entered.
81
internal::Isolate::EnterDefaultIsolate();
84
ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
88
bool Locker::IsLocked(v8::Isolate* isolate) {
89
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
90
if (internal_isolate == NULL) {
91
internal_isolate = i::Isolate::GetDefaultIsolateForLocking();
93
return internal_isolate->thread_manager()->IsLockedByCurrentThread();
97
bool Locker::IsActive() {
87
102
Locker::~Locker() {
88
ASSERT(internal::ThreadManager::IsLockedByCurrentThread());
103
ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
105
if (isolate_->IsDefaultIsolate()) {
91
internal::ThreadManager::FreeThreadResources();
109
isolate_->thread_manager()->FreeThreadResources();
93
internal::ThreadManager::ArchiveThread();
111
isolate_->thread_manager()->ArchiveThread();
95
internal::ThreadManager::Unlock();
113
isolate_->thread_manager()->Unlock();
100
Unlocker::Unlocker() {
101
ASSERT(internal::ThreadManager::IsLockedByCurrentThread());
102
internal::ThreadManager::ArchiveThread();
103
internal::ThreadManager::Unlock();
118
Unlocker::Unlocker(v8::Isolate* isolate)
119
: isolate_(reinterpret_cast<i::Isolate*>(isolate)) {
120
if (isolate_ == NULL) {
121
isolate_ = i::Isolate::GetDefaultIsolateForLocking();
123
ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread());
124
if (isolate_->IsDefaultIsolate()) {
127
isolate_->thread_manager()->ArchiveThread();
128
isolate_->thread_manager()->Unlock();
107
132
Unlocker::~Unlocker() {
108
ASSERT(!internal::ThreadManager::IsLockedByCurrentThread());
109
internal::ThreadManager::Lock();
110
internal::ThreadManager::RestoreThread();
133
ASSERT(!isolate_->thread_manager()->IsLockedByCurrentThread());
134
isolate_->thread_manager()->Lock();
135
isolate_->thread_manager()->RestoreThread();
136
if (isolate_->IsDefaultIsolate()) {
127
155
bool ThreadManager::RestoreThread() {
156
ASSERT(IsLockedByCurrentThread());
128
157
// First check whether the current thread has been 'lazily archived', ie
129
158
// not archived at all. If that is the case we put the state storage we
130
159
// had prepared back in the free list, since we didn't need it after all.
131
if (lazily_archived_thread_.IsSelf()) {
132
lazily_archived_thread_.Initialize(ThreadHandle::INVALID);
133
ASSERT(Thread::GetThreadLocal(thread_state_key) ==
134
lazily_archived_thread_state_);
135
lazily_archived_thread_state_->set_id(kInvalidId);
160
if (lazily_archived_thread_.Equals(ThreadId::Current())) {
161
lazily_archived_thread_ = ThreadId::Invalid();
162
Isolate::PerIsolateThreadData* per_thread =
163
isolate_->FindPerThreadDataForThisThread();
164
ASSERT(per_thread != NULL);
165
ASSERT(per_thread->thread_state() == lazily_archived_thread_state_);
166
lazily_archived_thread_state_->set_id(ThreadId::Invalid());
136
167
lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST);
137
168
lazily_archived_thread_state_ = NULL;
138
Thread::SetThreadLocal(thread_state_key, NULL);
169
per_thread->set_thread_state(NULL);
142
173
// Make sure that the preemption thread cannot modify the thread state while
143
174
// it is being archived or restored.
144
ExecutionAccess access;
175
ExecutionAccess access(isolate_);
146
177
// If there is another thread that was lazily archived then we have to really
147
178
// archive it now.
148
179
if (lazily_archived_thread_.IsValid()) {
149
180
EagerlyArchiveThread();
152
reinterpret_cast<ThreadState*>(Thread::GetThreadLocal(thread_state_key));
182
Isolate::PerIsolateThreadData* per_thread =
183
isolate_->FindPerThreadDataForThisThread();
184
if (per_thread == NULL || per_thread->thread_state() == NULL) {
154
185
// This is a new thread.
155
StackGuard::InitThread(access);
186
isolate_->stack_guard()->InitThread(access);
189
ThreadState* state = per_thread->thread_state();
158
190
char* from = state->data();
159
from = HandleScopeImplementer::RestoreThread(from);
160
from = Top::RestoreThread(from);
161
from = Relocatable::RestoreState(from);
191
from = isolate_->handle_scope_implementer()->RestoreThread(from);
192
from = isolate_->RestoreThread(from);
193
from = Relocatable::RestoreState(isolate_, from);
162
194
#ifdef ENABLE_DEBUGGER_SUPPORT
163
from = Debug::RestoreDebug(from);
195
from = isolate_->debug()->RestoreDebug(from);
165
from = StackGuard::RestoreStackGuard(from);
166
from = RegExpStack::RestoreStack(from);
167
from = Bootstrapper::RestoreState(from);
168
Thread::SetThreadLocal(thread_state_key, NULL);
197
from = isolate_->stack_guard()->RestoreStackGuard(from);
198
from = isolate_->regexp_stack()->RestoreStack(from);
199
from = isolate_->bootstrapper()->RestoreState(from);
200
per_thread->set_thread_state(NULL);
169
201
if (state->terminate_on_restore()) {
170
StackGuard::TerminateExecution();
202
isolate_->stack_guard()->TerminateExecution();
171
203
state->set_terminate_on_restore(false);
173
state->set_id(kInvalidId);
205
state->set_id(ThreadId::Invalid());
175
207
state->LinkInto(ThreadState::FREE_LIST);
260
292
// Thread ids must start with 1, because in TLS having thread id 0 can't
261
293
// be distinguished from not having a thread id at all (since NULL is
262
294
// defined as 0.)
263
int ThreadManager::last_id_ = 0;
264
Mutex* ThreadManager::mutex_ = OS::CreateMutex();
265
ThreadHandle ThreadManager::mutex_owner_(ThreadHandle::INVALID);
266
ThreadHandle ThreadManager::lazily_archived_thread_(ThreadHandle::INVALID);
267
ThreadState* ThreadManager::lazily_archived_thread_state_ = NULL;
295
ThreadManager::ThreadManager()
296
: mutex_(OS::CreateMutex()),
297
mutex_owner_(ThreadId::Invalid()),
298
lazily_archived_thread_(ThreadId::Invalid()),
299
lazily_archived_thread_state_(NULL),
301
in_use_anchor_(NULL) {
302
free_anchor_ = new ThreadState(this);
303
in_use_anchor_ = new ThreadState(this);
307
ThreadManager::~ThreadManager() {
310
delete in_use_anchor_;
270
314
void ThreadManager::ArchiveThread() {
271
ASSERT(!lazily_archived_thread_.IsValid());
315
ASSERT(lazily_archived_thread_.Equals(ThreadId::Invalid()));
272
316
ASSERT(!IsArchived());
273
ThreadState* state = ThreadState::GetFree();
317
ASSERT(IsLockedByCurrentThread());
318
ThreadState* state = GetFreeThreadState();
275
Thread::SetThreadLocal(thread_state_key, reinterpret_cast<void*>(state));
276
lazily_archived_thread_.Initialize(ThreadHandle::SELF);
320
Isolate::PerIsolateThreadData* per_thread =
321
isolate_->FindOrAllocatePerThreadDataForThisThread();
322
per_thread->set_thread_state(state);
323
lazily_archived_thread_ = ThreadId::Current();
277
324
lazily_archived_thread_state_ = state;
278
ASSERT(state->id() == kInvalidId);
325
ASSERT(state->id().Equals(ThreadId::Invalid()));
279
326
state->set_id(CurrentId());
280
ASSERT(state->id() != kInvalidId);
327
ASSERT(!state->id().Equals(ThreadId::Invalid()));
284
331
void ThreadManager::EagerlyArchiveThread() {
332
ASSERT(IsLockedByCurrentThread());
285
333
ThreadState* state = lazily_archived_thread_state_;
286
334
state->LinkInto(ThreadState::IN_USE_LIST);
287
335
char* to = state->data();
288
336
// Ensure that data containing GC roots are archived first, and handle them
289
337
// in ThreadManager::Iterate(ObjectVisitor*).
290
to = HandleScopeImplementer::ArchiveThread(to);
291
to = Top::ArchiveThread(to);
292
to = Relocatable::ArchiveState(to);
338
to = isolate_->handle_scope_implementer()->ArchiveThread(to);
339
to = isolate_->ArchiveThread(to);
340
to = Relocatable::ArchiveState(isolate_, to);
293
341
#ifdef ENABLE_DEBUGGER_SUPPORT
294
to = Debug::ArchiveDebug(to);
342
to = isolate_->debug()->ArchiveDebug(to);
296
to = StackGuard::ArchiveStackGuard(to);
297
to = RegExpStack::ArchiveStack(to);
298
to = Bootstrapper::ArchiveState(to);
299
lazily_archived_thread_.Initialize(ThreadHandle::INVALID);
344
to = isolate_->stack_guard()->ArchiveStackGuard(to);
345
to = isolate_->regexp_stack()->ArchiveStack(to);
346
to = isolate_->bootstrapper()->ArchiveState(to);
347
lazily_archived_thread_ = ThreadId::Invalid();
300
348
lazily_archived_thread_state_ = NULL;
304
352
void ThreadManager::FreeThreadResources() {
305
HandleScopeImplementer::FreeThreadResources();
306
Top::FreeThreadResources();
353
isolate_->handle_scope_implementer()->FreeThreadResources();
354
isolate_->FreeThreadResources();
307
355
#ifdef ENABLE_DEBUGGER_SUPPORT
308
Debug::FreeThreadResources();
356
isolate_->debug()->FreeThreadResources();
310
StackGuard::FreeThreadResources();
311
RegExpStack::FreeThreadResources();
312
Bootstrapper::FreeThreadResources();
358
isolate_->stack_guard()->FreeThreadResources();
359
isolate_->regexp_stack()->FreeThreadResources();
360
isolate_->bootstrapper()->FreeThreadResources();
316
364
bool ThreadManager::IsArchived() {
317
return Thread::HasThreadLocal(thread_state_key);
365
Isolate::PerIsolateThreadData* data =
366
isolate_->FindPerThreadDataForThisThread();
367
return data != NULL && data->thread_state() != NULL;
321
370
void ThreadManager::Iterate(ObjectVisitor* v) {
322
371
// Expecting no threads during serialization/deserialization
323
for (ThreadState* state = ThreadState::FirstInUse();
372
for (ThreadState* state = FirstThreadStateInUse();
325
374
state = state->Next()) {
326
375
char* data = state->data();
327
376
data = HandleScopeImplementer::Iterate(v, data);
328
data = Top::Iterate(v, data);
377
data = isolate_->Iterate(v, data);
329
378
data = Relocatable::Iterate(v, data);
334
383
void ThreadManager::IterateArchivedThreads(ThreadVisitor* v) {
335
for (ThreadState* state = ThreadState::FirstInUse();
384
for (ThreadState* state = FirstThreadStateInUse();
337
386
state = state->Next()) {
338
387
char* data = state->data();
339
388
data += HandleScopeImplementer::ArchiveSpacePerThread();
340
Top::IterateThread(v, data);
345
int ThreadManager::CurrentId() {
346
return Thread::GetThreadLocalInt(thread_id_key);
350
void ThreadManager::AssignId() {
352
ASSERT(Locker::IsLocked());
353
int thread_id = ++last_id_;
354
ASSERT(thread_id > 0); // see the comment near last_id_ definition.
355
Thread::SetThreadLocalInt(thread_id_key, thread_id);
356
Top::set_thread_id(thread_id);
361
bool ThreadManager::HasId() {
362
return Thread::HasThreadLocal(thread_id_key);
366
void ThreadManager::TerminateExecution(int thread_id) {
367
for (ThreadState* state = ThreadState::FirstInUse();
389
isolate_->IterateThread(v, data);
394
ThreadId ThreadManager::CurrentId() {
395
return ThreadId::Current();
399
void ThreadManager::TerminateExecution(ThreadId thread_id) {
400
for (ThreadState* state = FirstThreadStateInUse();
369
402
state = state->Next()) {
370
if (thread_id == state->id()) {
403
if (thread_id.Equals(state->id())) {
371
404
state->set_terminate_on_restore(true);
377
// This is the ContextSwitcher singleton. There is at most a single thread
378
// running which delivers preemption events to V8 threads.
379
ContextSwitcher* ContextSwitcher::singleton_ = NULL;
382
ContextSwitcher::ContextSwitcher(int every_n_ms)
410
ContextSwitcher::ContextSwitcher(Isolate* isolate, int every_n_ms)
383
411
: Thread("v8:CtxtSwitcher"),
384
412
keep_going_(true),
385
sleep_ms_(every_n_ms) {
413
sleep_ms_(every_n_ms),
389
418
// Set the scheduling interval of V8 threads. This function starts the
390
419
// ContextSwitcher thread if needed.
391
420
void ContextSwitcher::StartPreemption(int every_n_ms) {
392
ASSERT(Locker::IsLocked());
393
if (singleton_ == NULL) {
421
Isolate* isolate = Isolate::Current();
422
ASSERT(Locker::IsLocked(reinterpret_cast<v8::Isolate*>(isolate)));
423
if (isolate->context_switcher() == NULL) {
394
424
// If the ContextSwitcher thread is not running at the moment start it now.
395
singleton_ = new ContextSwitcher(every_n_ms);
425
isolate->set_context_switcher(new ContextSwitcher(isolate, every_n_ms));
426
isolate->context_switcher()->Start();
398
428
// ContextSwitcher thread is already running, so we just change the
399
429
// scheduling interval.
400
singleton_->sleep_ms_ = every_n_ms;
430
isolate->context_switcher()->sleep_ms_ = every_n_ms;