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 25 matching lines...) Expand all Loading... |
36 | 36 |
37 namespace v8 { | 37 namespace v8 { |
38 | 38 |
39 | 39 |
40 // Track whether this V8 instance has ever called v8::Locker. This allows the | 40 // Track whether this V8 instance has ever called v8::Locker. This allows the |
41 // API code to verify that the lock is always held when V8 is being entered. | 41 // API code to verify that the lock is always held when V8 is being entered. |
42 bool Locker::active_ = false; | 42 bool Locker::active_ = false; |
43 | 43 |
44 | 44 |
45 // Constructor for the Locker object. Once the Locker is constructed the | 45 // Constructor for the Locker object. Once the Locker is constructed the |
46 // current thread will be guaranteed to have the big V8 lock. | 46 // current thread will be guaranteed to have the lock for a given isolate. |
47 Locker::Locker() : has_lock_(false), top_level_(true) { | 47 Locker::Locker(v8::Isolate* isolate) |
48 // TODO(isolates): When Locker has Isolate parameter and it is provided, grab | 48 : has_lock_(false), |
49 // that one instead of using the current one. | 49 top_level_(false), |
50 // We pull default isolate for Locker constructor w/o p[arameter. | 50 isolate_(reinterpret_cast<i::Isolate*>(isolate)) { |
51 // A thread should not enter an isolate before acquiring a lock, | 51 if (isolate_ == NULL) { |
52 // in cases which mandate using Lockers. | 52 isolate_ = i::Isolate::GetDefaultIsolateForLocking(); |
53 // So getting a lock is the first thing threads do in a scenario where | 53 } |
54 // multple threads share an isolate. Hence, we need to access | |
55 // 'locking isolate' before we can actually enter into default isolate. | |
56 internal::Isolate* isolate = internal::Isolate::GetDefaultIsolateForLocking(); | |
57 ASSERT(isolate != NULL); | |
58 | |
59 // Record that the Locker has been used at least once. | 54 // Record that the Locker has been used at least once. |
60 active_ = true; | 55 active_ = true; |
61 // Get the big lock if necessary. | 56 // Get the big lock if necessary. |
62 if (!isolate->thread_manager()->IsLockedByCurrentThread()) { | 57 if (!isolate_->thread_manager()->IsLockedByCurrentThread()) { |
63 isolate->thread_manager()->Lock(); | 58 isolate_->thread_manager()->Lock(); |
64 has_lock_ = true; | 59 has_lock_ = true; |
65 | 60 |
66 if (isolate->IsDefaultIsolate()) { | |
67 // This only enters if not yet entered. | |
68 internal::Isolate::EnterDefaultIsolate(); | |
69 } | |
70 | |
71 ASSERT(internal::Thread::HasThreadLocal( | |
72 internal::Isolate::thread_id_key())); | |
73 | |
74 // Make sure that V8 is initialized. Archiving of threads interferes | 61 // Make sure that V8 is initialized. Archiving of threads interferes |
75 // with deserialization by adding additional root pointers, so we must | 62 // with deserialization by adding additional root pointers, so we must |
76 // initialize here, before anyone can call ~Locker() or Unlocker(). | 63 // initialize here, before anyone can call ~Locker() or Unlocker(). |
77 if (!isolate->IsInitialized()) { | 64 if (!isolate_->IsInitialized()) { |
| 65 isolate_->Enter(); |
78 V8::Initialize(); | 66 V8::Initialize(); |
| 67 isolate_->Exit(); |
79 } | 68 } |
| 69 |
80 // This may be a locker within an unlocker in which case we have to | 70 // This may be a locker within an unlocker in which case we have to |
81 // get the saved state for this thread and restore it. | 71 // get the saved state for this thread and restore it. |
82 if (isolate->thread_manager()->RestoreThread()) { | 72 if (isolate_->thread_manager()->RestoreThread()) { |
83 top_level_ = false; | 73 top_level_ = false; |
84 } else { | 74 } else { |
85 internal::ExecutionAccess access(isolate); | 75 internal::ExecutionAccess access(isolate_); |
86 isolate->stack_guard()->ClearThread(access); | 76 isolate_->stack_guard()->ClearThread(access); |
87 isolate->stack_guard()->InitThread(access); | 77 isolate_->stack_guard()->InitThread(access); |
| 78 } |
| 79 if (isolate_->IsDefaultIsolate()) { |
| 80 // This only enters if not yet entered. |
| 81 internal::Isolate::EnterDefaultIsolate(); |
88 } | 82 } |
89 } | 83 } |
90 ASSERT(isolate->thread_manager()->IsLockedByCurrentThread()); | 84 ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread()); |
91 } | 85 } |
92 | 86 |
93 | 87 |
94 bool Locker::IsLocked() { | 88 bool Locker::IsLocked(v8::Isolate* isolate) { |
95 return internal::Isolate::Current()->thread_manager()-> | 89 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); |
96 IsLockedByCurrentThread(); | 90 if (internal_isolate == NULL) { |
| 91 internal_isolate = i::Isolate::GetDefaultIsolateForLocking(); |
| 92 } |
| 93 return internal_isolate->thread_manager()->IsLockedByCurrentThread(); |
97 } | 94 } |
98 | 95 |
99 | 96 |
100 Locker::~Locker() { | 97 Locker::~Locker() { |
101 // TODO(isolate): this should use a field storing the isolate it | 98 ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread()); |
102 // locked instead. | |
103 internal::Isolate* isolate = internal::Isolate::Current(); | |
104 ASSERT(isolate->thread_manager()->IsLockedByCurrentThread()); | |
105 if (has_lock_) { | 99 if (has_lock_) { |
| 100 if (isolate_->IsDefaultIsolate()) { |
| 101 isolate_->Exit(); |
| 102 } |
106 if (top_level_) { | 103 if (top_level_) { |
107 isolate->thread_manager()->FreeThreadResources(); | 104 isolate_->thread_manager()->FreeThreadResources(); |
108 } else { | 105 } else { |
109 isolate->thread_manager()->ArchiveThread(); | 106 isolate_->thread_manager()->ArchiveThread(); |
110 } | 107 } |
111 isolate->thread_manager()->Unlock(); | 108 isolate_->thread_manager()->Unlock(); |
112 } | 109 } |
113 } | 110 } |
114 | 111 |
115 | 112 |
116 Unlocker::Unlocker() { | 113 Unlocker::Unlocker(v8::Isolate* isolate) |
117 internal::Isolate* isolate = internal::Isolate::Current(); | 114 : isolate_(reinterpret_cast<i::Isolate*>(isolate)) { |
118 ASSERT(isolate->thread_manager()->IsLockedByCurrentThread()); | 115 if (isolate_ == NULL) { |
119 isolate->thread_manager()->ArchiveThread(); | 116 isolate_ = i::Isolate::GetDefaultIsolateForLocking(); |
120 isolate->thread_manager()->Unlock(); | 117 } |
| 118 ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread()); |
| 119 if (isolate_->IsDefaultIsolate()) { |
| 120 isolate_->Exit(); |
| 121 } |
| 122 isolate_->thread_manager()->ArchiveThread(); |
| 123 isolate_->thread_manager()->Unlock(); |
121 } | 124 } |
122 | 125 |
123 | 126 |
124 Unlocker::~Unlocker() { | 127 Unlocker::~Unlocker() { |
125 // TODO(isolates): check it's the isolate we unlocked. | 128 ASSERT(!isolate_->thread_manager()->IsLockedByCurrentThread()); |
126 internal::Isolate* isolate = internal::Isolate::Current(); | 129 isolate_->thread_manager()->Lock(); |
127 ASSERT(!isolate->thread_manager()->IsLockedByCurrentThread()); | 130 isolate_->thread_manager()->RestoreThread(); |
128 isolate->thread_manager()->Lock(); | 131 if (isolate_->IsDefaultIsolate()) { |
129 isolate->thread_manager()->RestoreThread(); | 132 isolate_->Enter(); |
| 133 } |
130 } | 134 } |
131 | 135 |
132 | 136 |
133 void Locker::StartPreemption(int every_n_ms) { | 137 void Locker::StartPreemption(int every_n_ms) { |
134 v8::internal::ContextSwitcher::StartPreemption(every_n_ms); | 138 v8::internal::ContextSwitcher::StartPreemption(every_n_ms); |
135 } | 139 } |
136 | 140 |
137 | 141 |
138 void Locker::StopPreemption() { | 142 void Locker::StopPreemption() { |
139 v8::internal::ContextSwitcher::StopPreemption(); | 143 v8::internal::ContextSwitcher::StopPreemption(); |
140 } | 144 } |
141 | 145 |
142 | 146 |
143 namespace internal { | 147 namespace internal { |
144 | 148 |
145 | 149 |
146 bool ThreadManager::RestoreThread() { | 150 bool ThreadManager::RestoreThread() { |
| 151 ASSERT(IsLockedByCurrentThread()); |
147 // First check whether the current thread has been 'lazily archived', ie | 152 // First check whether the current thread has been 'lazily archived', ie |
148 // not archived at all. If that is the case we put the state storage we | 153 // not archived at all. If that is the case we put the state storage we |
149 // had prepared back in the free list, since we didn't need it after all. | 154 // had prepared back in the free list, since we didn't need it after all. |
150 if (lazily_archived_thread_.Equals(ThreadId::Current())) { | 155 if (lazily_archived_thread_.Equals(ThreadId::Current())) { |
151 lazily_archived_thread_ = ThreadId::Invalid(); | 156 lazily_archived_thread_ = ThreadId::Invalid(); |
152 ASSERT(Isolate::CurrentPerIsolateThreadData()->thread_state() == | 157 Isolate::PerIsolateThreadData* per_thread = |
153 lazily_archived_thread_state_); | 158 isolate_->FindPerThreadDataForThisThread(); |
| 159 ASSERT(per_thread != NULL); |
| 160 ASSERT(per_thread->thread_state() == lazily_archived_thread_state_); |
154 lazily_archived_thread_state_->set_id(ThreadId::Invalid()); | 161 lazily_archived_thread_state_->set_id(ThreadId::Invalid()); |
155 lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST); | 162 lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST); |
156 lazily_archived_thread_state_ = NULL; | 163 lazily_archived_thread_state_ = NULL; |
157 Isolate::CurrentPerIsolateThreadData()->set_thread_state(NULL); | 164 per_thread->set_thread_state(NULL); |
158 return true; | 165 return true; |
159 } | 166 } |
160 | 167 |
161 // Make sure that the preemption thread cannot modify the thread state while | 168 // Make sure that the preemption thread cannot modify the thread state while |
162 // it is being archived or restored. | 169 // it is being archived or restored. |
163 ExecutionAccess access(isolate_); | 170 ExecutionAccess access(isolate_); |
164 | 171 |
165 // If there is another thread that was lazily archived then we have to really | 172 // If there is another thread that was lazily archived then we have to really |
166 // archive it now. | 173 // archive it now. |
167 if (lazily_archived_thread_.IsValid()) { | 174 if (lazily_archived_thread_.IsValid()) { |
168 EagerlyArchiveThread(); | 175 EagerlyArchiveThread(); |
169 } | 176 } |
170 Isolate::PerIsolateThreadData* per_thread = | 177 Isolate::PerIsolateThreadData* per_thread = |
171 Isolate::CurrentPerIsolateThreadData(); | 178 isolate_->FindPerThreadDataForThisThread(); |
172 if (per_thread == NULL || per_thread->thread_state() == NULL) { | 179 if (per_thread == NULL || per_thread->thread_state() == NULL) { |
173 // This is a new thread. | 180 // This is a new thread. |
174 isolate_->stack_guard()->InitThread(access); | 181 isolate_->stack_guard()->InitThread(access); |
175 return false; | 182 return false; |
176 } | 183 } |
177 ThreadState* state = per_thread->thread_state(); | 184 ThreadState* state = per_thread->thread_state(); |
178 char* from = state->data(); | 185 char* from = state->data(); |
179 from = isolate_->handle_scope_implementer()->RestoreThread(from); | 186 from = isolate_->handle_scope_implementer()->RestoreThread(from); |
180 from = isolate_->RestoreThread(from); | 187 from = isolate_->RestoreThread(from); |
181 from = Relocatable::RestoreState(from); | 188 from = Relocatable::RestoreState(isolate_, from); |
182 #ifdef ENABLE_DEBUGGER_SUPPORT | 189 #ifdef ENABLE_DEBUGGER_SUPPORT |
183 from = isolate_->debug()->RestoreDebug(from); | 190 from = isolate_->debug()->RestoreDebug(from); |
184 #endif | 191 #endif |
185 from = isolate_->stack_guard()->RestoreStackGuard(from); | 192 from = isolate_->stack_guard()->RestoreStackGuard(from); |
186 from = isolate_->regexp_stack()->RestoreStack(from); | 193 from = isolate_->regexp_stack()->RestoreStack(from); |
187 from = isolate_->bootstrapper()->RestoreState(from); | 194 from = isolate_->bootstrapper()->RestoreState(from); |
188 per_thread->set_thread_state(NULL); | 195 per_thread->set_thread_state(NULL); |
189 if (state->terminate_on_restore()) { | 196 if (state->terminate_on_restore()) { |
190 isolate_->stack_guard()->TerminateExecution(); | 197 isolate_->stack_guard()->TerminateExecution(); |
191 state->set_terminate_on_restore(false); | 198 state->set_terminate_on_restore(false); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 | 300 |
294 | 301 |
295 ThreadManager::~ThreadManager() { | 302 ThreadManager::~ThreadManager() { |
296 // TODO(isolates): Destroy mutexes. | 303 // TODO(isolates): Destroy mutexes. |
297 } | 304 } |
298 | 305 |
299 | 306 |
300 void ThreadManager::ArchiveThread() { | 307 void ThreadManager::ArchiveThread() { |
301 ASSERT(lazily_archived_thread_.Equals(ThreadId::Invalid())); | 308 ASSERT(lazily_archived_thread_.Equals(ThreadId::Invalid())); |
302 ASSERT(!IsArchived()); | 309 ASSERT(!IsArchived()); |
| 310 ASSERT(IsLockedByCurrentThread()); |
303 ThreadState* state = GetFreeThreadState(); | 311 ThreadState* state = GetFreeThreadState(); |
304 state->Unlink(); | 312 state->Unlink(); |
305 Isolate::CurrentPerIsolateThreadData()->set_thread_state(state); | 313 Isolate::PerIsolateThreadData* per_thread = |
| 314 isolate_->FindOrAllocatePerThreadDataForThisThread(); |
| 315 per_thread->set_thread_state(state); |
306 lazily_archived_thread_ = ThreadId::Current(); | 316 lazily_archived_thread_ = ThreadId::Current(); |
307 lazily_archived_thread_state_ = state; | 317 lazily_archived_thread_state_ = state; |
308 ASSERT(state->id().Equals(ThreadId::Invalid())); | 318 ASSERT(state->id().Equals(ThreadId::Invalid())); |
309 state->set_id(CurrentId()); | 319 state->set_id(CurrentId()); |
310 ASSERT(!state->id().Equals(ThreadId::Invalid())); | 320 ASSERT(!state->id().Equals(ThreadId::Invalid())); |
311 } | 321 } |
312 | 322 |
313 | 323 |
314 void ThreadManager::EagerlyArchiveThread() { | 324 void ThreadManager::EagerlyArchiveThread() { |
| 325 ASSERT(IsLockedByCurrentThread()); |
315 ThreadState* state = lazily_archived_thread_state_; | 326 ThreadState* state = lazily_archived_thread_state_; |
316 state->LinkInto(ThreadState::IN_USE_LIST); | 327 state->LinkInto(ThreadState::IN_USE_LIST); |
317 char* to = state->data(); | 328 char* to = state->data(); |
318 // Ensure that data containing GC roots are archived first, and handle them | 329 // Ensure that data containing GC roots are archived first, and handle them |
319 // in ThreadManager::Iterate(ObjectVisitor*). | 330 // in ThreadManager::Iterate(ObjectVisitor*). |
320 to = isolate_->handle_scope_implementer()->ArchiveThread(to); | 331 to = isolate_->handle_scope_implementer()->ArchiveThread(to); |
321 to = isolate_->ArchiveThread(to); | 332 to = isolate_->ArchiveThread(to); |
322 to = Relocatable::ArchiveState(to); | 333 to = Relocatable::ArchiveState(isolate_, to); |
323 #ifdef ENABLE_DEBUGGER_SUPPORT | 334 #ifdef ENABLE_DEBUGGER_SUPPORT |
324 to = isolate_->debug()->ArchiveDebug(to); | 335 to = isolate_->debug()->ArchiveDebug(to); |
325 #endif | 336 #endif |
326 to = isolate_->stack_guard()->ArchiveStackGuard(to); | 337 to = isolate_->stack_guard()->ArchiveStackGuard(to); |
327 to = isolate_->regexp_stack()->ArchiveStack(to); | 338 to = isolate_->regexp_stack()->ArchiveStack(to); |
328 to = isolate_->bootstrapper()->ArchiveState(to); | 339 to = isolate_->bootstrapper()->ArchiveState(to); |
329 lazily_archived_thread_ = ThreadId::Invalid(); | 340 lazily_archived_thread_ = ThreadId::Invalid(); |
330 lazily_archived_thread_state_ = NULL; | 341 lazily_archived_thread_state_ = NULL; |
331 } | 342 } |
332 | 343 |
333 | 344 |
334 void ThreadManager::FreeThreadResources() { | 345 void ThreadManager::FreeThreadResources() { |
335 isolate_->handle_scope_implementer()->FreeThreadResources(); | 346 isolate_->handle_scope_implementer()->FreeThreadResources(); |
336 isolate_->FreeThreadResources(); | 347 isolate_->FreeThreadResources(); |
337 #ifdef ENABLE_DEBUGGER_SUPPORT | 348 #ifdef ENABLE_DEBUGGER_SUPPORT |
338 isolate_->debug()->FreeThreadResources(); | 349 isolate_->debug()->FreeThreadResources(); |
339 #endif | 350 #endif |
340 isolate_->stack_guard()->FreeThreadResources(); | 351 isolate_->stack_guard()->FreeThreadResources(); |
341 isolate_->regexp_stack()->FreeThreadResources(); | 352 isolate_->regexp_stack()->FreeThreadResources(); |
342 isolate_->bootstrapper()->FreeThreadResources(); | 353 isolate_->bootstrapper()->FreeThreadResources(); |
343 } | 354 } |
344 | 355 |
345 | 356 |
346 bool ThreadManager::IsArchived() { | 357 bool ThreadManager::IsArchived() { |
347 Isolate::PerIsolateThreadData* data = Isolate::CurrentPerIsolateThreadData(); | 358 Isolate::PerIsolateThreadData* data = |
| 359 isolate_->FindPerThreadDataForThisThread(); |
348 return data != NULL && data->thread_state() != NULL; | 360 return data != NULL && data->thread_state() != NULL; |
349 } | 361 } |
350 | 362 |
351 | |
352 void ThreadManager::Iterate(ObjectVisitor* v) { | 363 void ThreadManager::Iterate(ObjectVisitor* v) { |
353 // Expecting no threads during serialization/deserialization | 364 // Expecting no threads during serialization/deserialization |
354 for (ThreadState* state = FirstThreadStateInUse(); | 365 for (ThreadState* state = FirstThreadStateInUse(); |
355 state != NULL; | 366 state != NULL; |
356 state = state->Next()) { | 367 state = state->Next()) { |
357 char* data = state->data(); | 368 char* data = state->data(); |
358 data = HandleScopeImplementer::Iterate(v, data); | 369 data = HandleScopeImplementer::Iterate(v, data); |
359 data = isolate_->Iterate(v, data); | 370 data = isolate_->Iterate(v, data); |
360 data = Relocatable::Iterate(v, data); | 371 data = Relocatable::Iterate(v, data); |
361 } | 372 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
444 // Acknowledge the preemption by the receiving thread. | 455 // Acknowledge the preemption by the receiving thread. |
445 void ContextSwitcher::PreemptionReceived() { | 456 void ContextSwitcher::PreemptionReceived() { |
446 ASSERT(Locker::IsLocked()); | 457 ASSERT(Locker::IsLocked()); |
447 // There is currently no accounting being done for this. But could be in the | 458 // There is currently no accounting being done for this. But could be in the |
448 // future, which is why we leave this in. | 459 // future, which is why we leave this in. |
449 } | 460 } |
450 | 461 |
451 | 462 |
452 } // namespace internal | 463 } // namespace internal |
453 } // namespace v8 | 464 } // namespace v8 |
OLD | NEW |