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_->IsDefaultIsolate()) { |
65 // This only enters if not yet entered. | |
66 internal::Isolate::EnterDefaultIsolate(); | |
67 } else if (!isolate_->IsInitialized()) { | |
68 isolate_->Enter(); | |
78 V8::Initialize(); | 69 V8::Initialize(); |
70 isolate_->Exit(); | |
79 } | 71 } |
72 | |
80 // This may be a locker within an unlocker in which case we have to | 73 // 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. | 74 // get the saved state for this thread and restore it. |
82 if (isolate->thread_manager()->RestoreThread()) { | 75 if (isolate_->thread_manager()->RestoreThread()) { |
83 top_level_ = false; | 76 top_level_ = false; |
84 } else { | 77 } else { |
85 internal::ExecutionAccess access(isolate); | 78 internal::ExecutionAccess access(isolate_); |
86 isolate->stack_guard()->ClearThread(access); | 79 isolate_->stack_guard()->ClearThread(access); |
87 isolate->stack_guard()->InitThread(access); | 80 isolate_->stack_guard()->InitThread(access); |
88 } | 81 } |
89 } | 82 } |
90 ASSERT(isolate->thread_manager()->IsLockedByCurrentThread()); | 83 ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread()); |
91 } | 84 } |
92 | 85 |
93 | 86 |
94 bool Locker::IsLocked() { | 87 bool Locker::IsLocked(v8::Isolate* isolate) { |
95 return internal::Isolate::Current()->thread_manager()-> | 88 i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); |
96 IsLockedByCurrentThread(); | 89 if (internal_isolate == NULL) { |
90 internal_isolate = i::Isolate::GetDefaultIsolateForLocking(); | |
91 } | |
92 return internal_isolate->thread_manager()-> | |
Vitaly Repeshko
2011/04/21 21:15:27
nit: Fits on a single line?
| |
93 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_) { |
106 if (top_level_) { | 100 if (top_level_) { |
107 isolate->thread_manager()->FreeThreadResources(); | 101 isolate_->thread_manager()->FreeThreadResources(); |
108 } else { | 102 } else { |
109 isolate->thread_manager()->ArchiveThread(); | 103 isolate_->thread_manager()->ArchiveThread(); |
110 } | 104 } |
111 isolate->thread_manager()->Unlock(); | 105 isolate_->thread_manager()->Unlock(); |
112 } | 106 } |
113 } | 107 } |
114 | 108 |
115 | 109 |
116 Unlocker::Unlocker() { | 110 Unlocker::Unlocker(v8::Isolate* isolate) |
117 internal::Isolate* isolate = internal::Isolate::Current(); | 111 : isolate_(reinterpret_cast<i::Isolate*>(isolate)) { |
118 ASSERT(isolate->thread_manager()->IsLockedByCurrentThread()); | 112 if (isolate_ == NULL) |
Vitaly Repeshko
2011/04/21 21:15:27
nit: Use {}.
| |
119 isolate->thread_manager()->ArchiveThread(); | 113 isolate_ = i::Isolate::GetDefaultIsolateForLocking(); |
120 isolate->thread_manager()->Unlock(); | 114 |
115 ASSERT(isolate_->thread_manager()->IsLockedByCurrentThread()); | |
116 isolate_->thread_manager()->ArchiveThread(); | |
117 isolate_->thread_manager()->Unlock(); | |
121 } | 118 } |
122 | 119 |
123 | 120 |
121 | |
Vitaly Repeshko
2011/04/21 21:15:27
nit: Remove extra blank line.
| |
124 Unlocker::~Unlocker() { | 122 Unlocker::~Unlocker() { |
125 // TODO(isolates): check it's the isolate we unlocked. | 123 ASSERT(!isolate_->thread_manager()->IsLockedByCurrentThread()); |
126 internal::Isolate* isolate = internal::Isolate::Current(); | 124 isolate_->thread_manager()->Lock(); |
127 ASSERT(!isolate->thread_manager()->IsLockedByCurrentThread()); | 125 isolate_->thread_manager()->RestoreThread(); |
128 isolate->thread_manager()->Lock(); | |
129 isolate->thread_manager()->RestoreThread(); | |
130 } | 126 } |
131 | 127 |
132 | 128 |
133 void Locker::StartPreemption(int every_n_ms) { | 129 void Locker::StartPreemption(int every_n_ms) { |
134 v8::internal::ContextSwitcher::StartPreemption(every_n_ms); | 130 v8::internal::ContextSwitcher::StartPreemption(every_n_ms); |
135 } | 131 } |
136 | 132 |
137 | 133 |
138 void Locker::StopPreemption() { | 134 void Locker::StopPreemption() { |
139 v8::internal::ContextSwitcher::StopPreemption(); | 135 v8::internal::ContextSwitcher::StopPreemption(); |
140 } | 136 } |
141 | 137 |
142 | 138 |
143 namespace internal { | 139 namespace internal { |
144 | 140 |
145 | 141 |
142 | |
Vitaly Repeshko
2011/04/21 21:15:27
Same nit.
| |
146 bool ThreadManager::RestoreThread() { | 143 bool ThreadManager::RestoreThread() { |
144 ASSERT(IsLockedByCurrentThread()); | |
147 // First check whether the current thread has been 'lazily archived', ie | 145 // 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 | 146 // 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. | 147 // had prepared back in the free list, since we didn't need it after all. |
150 if (lazily_archived_thread_.Equals(ThreadId::Current())) { | 148 if (lazily_archived_thread_.Equals(ThreadId::Current())) { |
151 lazily_archived_thread_ = ThreadId::Invalid(); | 149 lazily_archived_thread_ = ThreadId::Invalid(); |
152 ASSERT(Isolate::CurrentPerIsolateThreadData()->thread_state() == | 150 Isolate::PerIsolateThreadData* per_thread = |
153 lazily_archived_thread_state_); | 151 isolate_->FindPerThreadDataForThisThread(); |
152 ASSERT(per_thread != NULL); | |
153 ASSERT(per_thread->thread_state() == lazily_archived_thread_state_); | |
154 lazily_archived_thread_state_->set_id(ThreadId::Invalid()); | 154 lazily_archived_thread_state_->set_id(ThreadId::Invalid()); |
155 lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST); | 155 lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST); |
156 lazily_archived_thread_state_ = NULL; | 156 lazily_archived_thread_state_ = NULL; |
157 Isolate::CurrentPerIsolateThreadData()->set_thread_state(NULL); | 157 per_thread->set_thread_state(NULL); |
158 return true; | 158 return true; |
159 } | 159 } |
160 | 160 |
161 // Make sure that the preemption thread cannot modify the thread state while | 161 // Make sure that the preemption thread cannot modify the thread state while |
162 // it is being archived or restored. | 162 // it is being archived or restored. |
163 ExecutionAccess access(isolate_); | 163 ExecutionAccess access(isolate_); |
164 | 164 |
165 // If there is another thread that was lazily archived then we have to really | 165 // If there is another thread that was lazily archived then we have to really |
166 // archive it now. | 166 // archive it now. |
167 if (lazily_archived_thread_.IsValid()) { | 167 if (lazily_archived_thread_.IsValid()) { |
168 EagerlyArchiveThread(); | 168 EagerlyArchiveThread(); |
169 } | 169 } |
170 Isolate::PerIsolateThreadData* per_thread = | 170 Isolate::PerIsolateThreadData* per_thread = |
171 Isolate::CurrentPerIsolateThreadData(); | 171 isolate_->FindPerThreadDataForThisThread(); |
172 if (per_thread == NULL || per_thread->thread_state() == NULL) { | 172 if (per_thread == NULL || per_thread->thread_state() == NULL) { |
173 // This is a new thread. | 173 // This is a new thread. |
174 isolate_->stack_guard()->InitThread(access); | 174 isolate_->stack_guard()->InitThread(access); |
175 return false; | 175 return false; |
176 } | 176 } |
177 ThreadState* state = per_thread->thread_state(); | 177 ThreadState* state = per_thread->thread_state(); |
178 char* from = state->data(); | 178 char* from = state->data(); |
179 from = isolate_->handle_scope_implementer()->RestoreThread(from); | 179 from = isolate_->handle_scope_implementer()->RestoreThread(from); |
180 from = isolate_->RestoreThread(from); | 180 from = isolate_->RestoreThread(from); |
181 from = Relocatable::RestoreState(from); | 181 from = Relocatable::RestoreState(isolate_, from); |
182 #ifdef ENABLE_DEBUGGER_SUPPORT | 182 #ifdef ENABLE_DEBUGGER_SUPPORT |
183 from = isolate_->debug()->RestoreDebug(from); | 183 from = isolate_->debug()->RestoreDebug(from); |
184 #endif | 184 #endif |
185 from = isolate_->stack_guard()->RestoreStackGuard(from); | 185 from = isolate_->stack_guard()->RestoreStackGuard(from); |
186 from = isolate_->regexp_stack()->RestoreStack(from); | 186 from = isolate_->regexp_stack()->RestoreStack(from); |
187 from = isolate_->bootstrapper()->RestoreState(from); | 187 from = isolate_->bootstrapper()->RestoreState(from); |
188 per_thread->set_thread_state(NULL); | 188 per_thread->set_thread_state(NULL); |
189 if (state->terminate_on_restore()) { | 189 if (state->terminate_on_restore()) { |
190 isolate_->stack_guard()->TerminateExecution(); | 190 isolate_->stack_guard()->TerminateExecution(); |
191 state->set_terminate_on_restore(false); | 191 state->set_terminate_on_restore(false); |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
293 | 293 |
294 | 294 |
295 ThreadManager::~ThreadManager() { | 295 ThreadManager::~ThreadManager() { |
296 // TODO(isolates): Destroy mutexes. | 296 // TODO(isolates): Destroy mutexes. |
297 } | 297 } |
298 | 298 |
299 | 299 |
300 void ThreadManager::ArchiveThread() { | 300 void ThreadManager::ArchiveThread() { |
301 ASSERT(lazily_archived_thread_.Equals(ThreadId::Invalid())); | 301 ASSERT(lazily_archived_thread_.Equals(ThreadId::Invalid())); |
302 ASSERT(!IsArchived()); | 302 ASSERT(!IsArchived()); |
303 ASSERT(IsLockedByCurrentThread()); | |
303 ThreadState* state = GetFreeThreadState(); | 304 ThreadState* state = GetFreeThreadState(); |
304 state->Unlink(); | 305 state->Unlink(); |
305 Isolate::CurrentPerIsolateThreadData()->set_thread_state(state); | 306 Isolate::PerIsolateThreadData* per_thread = |
307 isolate_->FindOrAllocatePerThreadDataForThisThread(); | |
308 per_thread->set_thread_state(state); | |
306 lazily_archived_thread_ = ThreadId::Current(); | 309 lazily_archived_thread_ = ThreadId::Current(); |
307 lazily_archived_thread_state_ = state; | 310 lazily_archived_thread_state_ = state; |
308 ASSERT(state->id().Equals(ThreadId::Invalid())); | 311 ASSERT(state->id().Equals(ThreadId::Invalid())); |
309 state->set_id(CurrentId()); | 312 state->set_id(CurrentId()); |
310 ASSERT(!state->id().Equals(ThreadId::Invalid())); | 313 ASSERT(!state->id().Equals(ThreadId::Invalid())); |
311 } | 314 } |
312 | 315 |
313 | 316 |
314 void ThreadManager::EagerlyArchiveThread() { | 317 void ThreadManager::EagerlyArchiveThread() { |
318 ASSERT(IsLockedByCurrentThread()); | |
315 ThreadState* state = lazily_archived_thread_state_; | 319 ThreadState* state = lazily_archived_thread_state_; |
316 state->LinkInto(ThreadState::IN_USE_LIST); | 320 state->LinkInto(ThreadState::IN_USE_LIST); |
317 char* to = state->data(); | 321 char* to = state->data(); |
318 // Ensure that data containing GC roots are archived first, and handle them | 322 // Ensure that data containing GC roots are archived first, and handle them |
319 // in ThreadManager::Iterate(ObjectVisitor*). | 323 // in ThreadManager::Iterate(ObjectVisitor*). |
320 to = isolate_->handle_scope_implementer()->ArchiveThread(to); | 324 to = isolate_->handle_scope_implementer()->ArchiveThread(to); |
321 to = isolate_->ArchiveThread(to); | 325 to = isolate_->ArchiveThread(to); |
322 to = Relocatable::ArchiveState(to); | 326 to = Relocatable::ArchiveState(isolate_, to); |
323 #ifdef ENABLE_DEBUGGER_SUPPORT | 327 #ifdef ENABLE_DEBUGGER_SUPPORT |
324 to = isolate_->debug()->ArchiveDebug(to); | 328 to = isolate_->debug()->ArchiveDebug(to); |
325 #endif | 329 #endif |
326 to = isolate_->stack_guard()->ArchiveStackGuard(to); | 330 to = isolate_->stack_guard()->ArchiveStackGuard(to); |
327 to = isolate_->regexp_stack()->ArchiveStack(to); | 331 to = isolate_->regexp_stack()->ArchiveStack(to); |
328 to = isolate_->bootstrapper()->ArchiveState(to); | 332 to = isolate_->bootstrapper()->ArchiveState(to); |
329 lazily_archived_thread_ = ThreadId::Invalid(); | 333 lazily_archived_thread_ = ThreadId::Invalid(); |
330 lazily_archived_thread_state_ = NULL; | 334 lazily_archived_thread_state_ = NULL; |
331 } | 335 } |
332 | 336 |
333 | 337 |
334 void ThreadManager::FreeThreadResources() { | 338 void ThreadManager::FreeThreadResources() { |
335 isolate_->handle_scope_implementer()->FreeThreadResources(); | 339 isolate_->handle_scope_implementer()->FreeThreadResources(); |
336 isolate_->FreeThreadResources(); | 340 isolate_->FreeThreadResources(); |
337 #ifdef ENABLE_DEBUGGER_SUPPORT | 341 #ifdef ENABLE_DEBUGGER_SUPPORT |
338 isolate_->debug()->FreeThreadResources(); | 342 isolate_->debug()->FreeThreadResources(); |
339 #endif | 343 #endif |
340 isolate_->stack_guard()->FreeThreadResources(); | 344 isolate_->stack_guard()->FreeThreadResources(); |
341 isolate_->regexp_stack()->FreeThreadResources(); | 345 isolate_->regexp_stack()->FreeThreadResources(); |
342 isolate_->bootstrapper()->FreeThreadResources(); | 346 isolate_->bootstrapper()->FreeThreadResources(); |
343 } | 347 } |
344 | 348 |
345 | 349 |
346 bool ThreadManager::IsArchived() { | 350 bool ThreadManager::IsArchived() { |
347 Isolate::PerIsolateThreadData* data = Isolate::CurrentPerIsolateThreadData(); | 351 Isolate::PerIsolateThreadData* data = |
352 isolate_->FindPerThreadDataForThisThread(); | |
348 return data != NULL && data->thread_state() != NULL; | 353 return data != NULL && data->thread_state() != NULL; |
349 } | 354 } |
350 | 355 |
351 | |
352 void ThreadManager::Iterate(ObjectVisitor* v) { | 356 void ThreadManager::Iterate(ObjectVisitor* v) { |
353 // Expecting no threads during serialization/deserialization | 357 // Expecting no threads during serialization/deserialization |
354 for (ThreadState* state = FirstThreadStateInUse(); | 358 for (ThreadState* state = FirstThreadStateInUse(); |
355 state != NULL; | 359 state != NULL; |
356 state = state->Next()) { | 360 state = state->Next()) { |
357 char* data = state->data(); | 361 char* data = state->data(); |
358 data = HandleScopeImplementer::Iterate(v, data); | 362 data = HandleScopeImplementer::Iterate(v, data); |
359 data = isolate_->Iterate(v, data); | 363 data = isolate_->Iterate(v, data); |
360 data = Relocatable::Iterate(v, data); | 364 data = Relocatable::Iterate(v, data); |
361 } | 365 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
444 // Acknowledge the preemption by the receiving thread. | 448 // Acknowledge the preemption by the receiving thread. |
445 void ContextSwitcher::PreemptionReceived() { | 449 void ContextSwitcher::PreemptionReceived() { |
446 ASSERT(Locker::IsLocked()); | 450 ASSERT(Locker::IsLocked()); |
447 // There is currently no accounting being done for this. But could be in the | 451 // There is currently no accounting being done for this. But could be in the |
448 // future, which is why we leave this in. | 452 // future, which is why we leave this in. |
449 } | 453 } |
450 | 454 |
451 | 455 |
452 } // namespace internal | 456 } // namespace internal |
453 } // namespace v8 | 457 } // namespace v8 |
OLD | NEW |