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