Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(179)

Side by Side Diff: src/v8threads.cc

Issue 6685088: Merge isolates to bleeding_edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/v8threads.h ('k') | src/variables.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 18 matching lines...) Expand all
29 29
30 #include "api.h" 30 #include "api.h"
31 #include "bootstrapper.h" 31 #include "bootstrapper.h"
32 #include "debug.h" 32 #include "debug.h"
33 #include "execution.h" 33 #include "execution.h"
34 #include "v8threads.h" 34 #include "v8threads.h"
35 #include "regexp-stack.h" 35 #include "regexp-stack.h"
36 36
37 namespace v8 { 37 namespace v8 {
38 38
39 static internal::Thread::LocalStorageKey thread_state_key =
40 internal::Thread::CreateThreadLocalKey();
41 static internal::Thread::LocalStorageKey thread_id_key =
42 internal::Thread::CreateThreadLocalKey();
43
44 39
45 // 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
46 // 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.
47 bool Locker::active_ = false; 42 bool Locker::active_ = false;
48 43
49 44
50 // Constructor for the Locker object. Once the Locker is constructed the 45 // Constructor for the Locker object. Once the Locker is constructed the
51 // current thread will be guaranteed to have the big V8 lock. 46 // current thread will be guaranteed to have the big V8 lock.
52 Locker::Locker() : has_lock_(false), top_level_(true) { 47 Locker::Locker() : has_lock_(false), top_level_(true) {
48 // TODO(isolates): When Locker has Isolate parameter and it is provided, grab
49 // that one instead of using the current one.
50 // We pull default isolate for Locker constructor w/o p[arameter.
51 // A thread should not enter an isolate before acquiring a lock,
52 // in cases which mandate using Lockers.
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
55 // 'locking isolate' before we can actually enter into default isolate.
56 internal::Isolate* isolate = internal::Isolate::GetDefaultIsolateForLocking();
57 ASSERT(isolate != NULL);
58
53 // Record that the Locker has been used at least once. 59 // Record that the Locker has been used at least once.
54 active_ = true; 60 active_ = true;
55 // Get the big lock if necessary. 61 // Get the big lock if necessary.
56 if (!internal::ThreadManager::IsLockedByCurrentThread()) { 62 if (!isolate->thread_manager()->IsLockedByCurrentThread()) {
57 internal::ThreadManager::Lock(); 63 isolate->thread_manager()->Lock();
58 has_lock_ = true; 64 has_lock_ = true;
65
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
59 // Make sure that V8 is initialized. Archiving of threads interferes 74 // Make sure that V8 is initialized. Archiving of threads interferes
60 // with deserialization by adding additional root pointers, so we must 75 // with deserialization by adding additional root pointers, so we must
61 // initialize here, before anyone can call ~Locker() or Unlocker(). 76 // initialize here, before anyone can call ~Locker() or Unlocker().
62 if (!internal::V8::IsRunning()) { 77 if (!isolate->IsInitialized()) {
63 V8::Initialize(); 78 V8::Initialize();
64 } 79 }
65 // This may be a locker within an unlocker in which case we have to 80 // This may be a locker within an unlocker in which case we have to
66 // get the saved state for this thread and restore it. 81 // get the saved state for this thread and restore it.
67 if (internal::ThreadManager::RestoreThread()) { 82 if (isolate->thread_manager()->RestoreThread()) {
68 top_level_ = false; 83 top_level_ = false;
69 } else { 84 } else {
70 internal::ExecutionAccess access; 85 internal::ExecutionAccess access(isolate);
71 internal::StackGuard::ClearThread(access); 86 isolate->stack_guard()->ClearThread(access);
72 internal::StackGuard::InitThread(access); 87 isolate->stack_guard()->InitThread(access);
73 } 88 }
74 } 89 }
75 ASSERT(internal::ThreadManager::IsLockedByCurrentThread()); 90 ASSERT(isolate->thread_manager()->IsLockedByCurrentThread());
76
77 // Make sure this thread is assigned a thread id.
78 internal::ThreadManager::AssignId();
79 } 91 }
80 92
81 93
82 bool Locker::IsLocked() { 94 bool Locker::IsLocked() {
83 return internal::ThreadManager::IsLockedByCurrentThread(); 95 return internal::Isolate::Current()->thread_manager()->
96 IsLockedByCurrentThread();
84 } 97 }
85 98
86 99
87 Locker::~Locker() { 100 Locker::~Locker() {
88 ASSERT(internal::ThreadManager::IsLockedByCurrentThread()); 101 // TODO(isolate): this should use a field storing the isolate it
102 // locked instead.
103 internal::Isolate* isolate = internal::Isolate::Current();
104 ASSERT(isolate->thread_manager()->IsLockedByCurrentThread());
89 if (has_lock_) { 105 if (has_lock_) {
90 if (top_level_) { 106 if (top_level_) {
91 internal::ThreadManager::FreeThreadResources(); 107 isolate->thread_manager()->FreeThreadResources();
92 } else { 108 } else {
93 internal::ThreadManager::ArchiveThread(); 109 isolate->thread_manager()->ArchiveThread();
94 } 110 }
95 internal::ThreadManager::Unlock(); 111 isolate->thread_manager()->Unlock();
96 } 112 }
97 } 113 }
98 114
99 115
100 Unlocker::Unlocker() { 116 Unlocker::Unlocker() {
101 ASSERT(internal::ThreadManager::IsLockedByCurrentThread()); 117 internal::Isolate* isolate = internal::Isolate::Current();
102 internal::ThreadManager::ArchiveThread(); 118 ASSERT(isolate->thread_manager()->IsLockedByCurrentThread());
103 internal::ThreadManager::Unlock(); 119 isolate->thread_manager()->ArchiveThread();
120 isolate->thread_manager()->Unlock();
104 } 121 }
105 122
106 123
107 Unlocker::~Unlocker() { 124 Unlocker::~Unlocker() {
108 ASSERT(!internal::ThreadManager::IsLockedByCurrentThread()); 125 // TODO(isolates): check it's the isolate we unlocked.
109 internal::ThreadManager::Lock(); 126 internal::Isolate* isolate = internal::Isolate::Current();
110 internal::ThreadManager::RestoreThread(); 127 ASSERT(!isolate->thread_manager()->IsLockedByCurrentThread());
128 isolate->thread_manager()->Lock();
129 isolate->thread_manager()->RestoreThread();
111 } 130 }
112 131
113 132
114 void Locker::StartPreemption(int every_n_ms) { 133 void Locker::StartPreemption(int every_n_ms) {
115 v8::internal::ContextSwitcher::StartPreemption(every_n_ms); 134 v8::internal::ContextSwitcher::StartPreemption(every_n_ms);
116 } 135 }
117 136
118 137
119 void Locker::StopPreemption() { 138 void Locker::StopPreemption() {
120 v8::internal::ContextSwitcher::StopPreemption(); 139 v8::internal::ContextSwitcher::StopPreemption();
121 } 140 }
122 141
123 142
124 namespace internal { 143 namespace internal {
125 144
126 145
127 bool ThreadManager::RestoreThread() { 146 bool ThreadManager::RestoreThread() {
128 // First check whether the current thread has been 'lazily archived', ie 147 // First check whether the current thread has been 'lazily archived', ie
129 // not archived at all. If that is the case we put the state storage we 148 // not archived at all. If that is the case we put the state storage we
130 // had prepared back in the free list, since we didn't need it after all. 149 // had prepared back in the free list, since we didn't need it after all.
131 if (lazily_archived_thread_.IsSelf()) { 150 if (lazily_archived_thread_.IsSelf()) {
132 lazily_archived_thread_.Initialize(ThreadHandle::INVALID); 151 lazily_archived_thread_.Initialize(ThreadHandle::INVALID);
133 ASSERT(Thread::GetThreadLocal(thread_state_key) == 152 ASSERT(Isolate::CurrentPerIsolateThreadData()->thread_state() ==
134 lazily_archived_thread_state_); 153 lazily_archived_thread_state_);
135 lazily_archived_thread_state_->set_id(kInvalidId); 154 lazily_archived_thread_state_->set_id(kInvalidId);
136 lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST); 155 lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST);
137 lazily_archived_thread_state_ = NULL; 156 lazily_archived_thread_state_ = NULL;
138 Thread::SetThreadLocal(thread_state_key, NULL); 157 Isolate::CurrentPerIsolateThreadData()->set_thread_state(NULL);
139 return true; 158 return true;
140 } 159 }
141 160
142 // 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
143 // it is being archived or restored. 162 // it is being archived or restored.
144 ExecutionAccess access; 163 ExecutionAccess access(isolate_);
145 164
146 // 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
147 // archive it now. 166 // archive it now.
148 if (lazily_archived_thread_.IsValid()) { 167 if (lazily_archived_thread_.IsValid()) {
149 EagerlyArchiveThread(); 168 EagerlyArchiveThread();
150 } 169 }
151 ThreadState* state = 170 Isolate::PerIsolateThreadData* per_thread =
152 reinterpret_cast<ThreadState*>(Thread::GetThreadLocal(thread_state_key)); 171 Isolate::CurrentPerIsolateThreadData();
153 if (state == NULL) { 172 if (per_thread == NULL || per_thread->thread_state() == NULL) {
154 // This is a new thread. 173 // This is a new thread.
155 StackGuard::InitThread(access); 174 isolate_->stack_guard()->InitThread(access);
156 return false; 175 return false;
157 } 176 }
177 ThreadState* state = per_thread->thread_state();
158 char* from = state->data(); 178 char* from = state->data();
159 from = HandleScopeImplementer::RestoreThread(from); 179 from = isolate_->handle_scope_implementer()->RestoreThread(from);
160 from = Top::RestoreThread(from); 180 from = isolate_->RestoreThread(from);
161 from = Relocatable::RestoreState(from); 181 from = Relocatable::RestoreState(from);
162 #ifdef ENABLE_DEBUGGER_SUPPORT 182 #ifdef ENABLE_DEBUGGER_SUPPORT
163 from = Debug::RestoreDebug(from); 183 from = isolate_->debug()->RestoreDebug(from);
164 #endif 184 #endif
165 from = StackGuard::RestoreStackGuard(from); 185 from = isolate_->stack_guard()->RestoreStackGuard(from);
166 from = RegExpStack::RestoreStack(from); 186 from = isolate_->regexp_stack()->RestoreStack(from);
167 from = Bootstrapper::RestoreState(from); 187 from = isolate_->bootstrapper()->RestoreState(from);
168 Thread::SetThreadLocal(thread_state_key, NULL); 188 per_thread->set_thread_state(NULL);
169 if (state->terminate_on_restore()) { 189 if (state->terminate_on_restore()) {
170 StackGuard::TerminateExecution(); 190 isolate_->stack_guard()->TerminateExecution();
171 state->set_terminate_on_restore(false); 191 state->set_terminate_on_restore(false);
172 } 192 }
173 state->set_id(kInvalidId); 193 state->set_id(kInvalidId);
174 state->Unlink(); 194 state->Unlink();
175 state->LinkInto(ThreadState::FREE_LIST); 195 state->LinkInto(ThreadState::FREE_LIST);
176 return true; 196 return true;
177 } 197 }
178 198
179 199
180 void ThreadManager::Lock() { 200 void ThreadManager::Lock() {
181 mutex_->Lock(); 201 mutex_->Lock();
182 mutex_owner_.Initialize(ThreadHandle::SELF); 202 mutex_owner_.Initialize(ThreadHandle::SELF);
183 ASSERT(IsLockedByCurrentThread()); 203 ASSERT(IsLockedByCurrentThread());
184 } 204 }
185 205
186 206
187 void ThreadManager::Unlock() { 207 void ThreadManager::Unlock() {
188 mutex_owner_.Initialize(ThreadHandle::INVALID); 208 mutex_owner_.Initialize(ThreadHandle::INVALID);
189 mutex_->Unlock(); 209 mutex_->Unlock();
190 } 210 }
191 211
192 212
193 static int ArchiveSpacePerThread() { 213 static int ArchiveSpacePerThread() {
194 return HandleScopeImplementer::ArchiveSpacePerThread() + 214 return HandleScopeImplementer::ArchiveSpacePerThread() +
195 Top::ArchiveSpacePerThread() + 215 Isolate::ArchiveSpacePerThread() +
196 #ifdef ENABLE_DEBUGGER_SUPPORT 216 #ifdef ENABLE_DEBUGGER_SUPPORT
197 Debug::ArchiveSpacePerThread() + 217 Debug::ArchiveSpacePerThread() +
198 #endif 218 #endif
199 StackGuard::ArchiveSpacePerThread() + 219 StackGuard::ArchiveSpacePerThread() +
200 RegExpStack::ArchiveSpacePerThread() + 220 RegExpStack::ArchiveSpacePerThread() +
201 Bootstrapper::ArchiveSpacePerThread() + 221 Bootstrapper::ArchiveSpacePerThread() +
202 Relocatable::ArchiveSpacePerThread(); 222 Relocatable::ArchiveSpacePerThread();
203 } 223 }
204 224
205 225
206 ThreadState* ThreadState::free_anchor_ = new ThreadState(); 226 ThreadState::ThreadState(ThreadManager* thread_manager)
207 ThreadState* ThreadState::in_use_anchor_ = new ThreadState(); 227 : id_(ThreadManager::kInvalidId),
208 228 terminate_on_restore_(false),
209 229 next_(this),
210 ThreadState::ThreadState() : id_(ThreadManager::kInvalidId), 230 previous_(this),
211 terminate_on_restore_(false), 231 thread_manager_(thread_manager) {
212 next_(this), previous_(this) {
213 } 232 }
214 233
215 234
216 void ThreadState::AllocateSpace() { 235 void ThreadState::AllocateSpace() {
217 data_ = NewArray<char>(ArchiveSpacePerThread()); 236 data_ = NewArray<char>(ArchiveSpacePerThread());
218 } 237 }
219 238
220 239
221 void ThreadState::Unlink() { 240 void ThreadState::Unlink() {
222 next_->previous_ = previous_; 241 next_->previous_ = previous_;
223 previous_->next_ = next_; 242 previous_->next_ = next_;
224 } 243 }
225 244
226 245
227 void ThreadState::LinkInto(List list) { 246 void ThreadState::LinkInto(List list) {
228 ThreadState* flying_anchor = 247 ThreadState* flying_anchor =
229 list == FREE_LIST ? free_anchor_ : in_use_anchor_; 248 list == FREE_LIST ? thread_manager_->free_anchor_
249 : thread_manager_->in_use_anchor_;
230 next_ = flying_anchor->next_; 250 next_ = flying_anchor->next_;
231 previous_ = flying_anchor; 251 previous_ = flying_anchor;
232 flying_anchor->next_ = this; 252 flying_anchor->next_ = this;
233 next_->previous_ = this; 253 next_->previous_ = this;
234 } 254 }
235 255
236 256
237 ThreadState* ThreadState::GetFree() { 257 ThreadState* ThreadManager::GetFreeThreadState() {
238 ThreadState* gotten = free_anchor_->next_; 258 ThreadState* gotten = free_anchor_->next_;
239 if (gotten == free_anchor_) { 259 if (gotten == free_anchor_) {
240 ThreadState* new_thread_state = new ThreadState(); 260 ThreadState* new_thread_state = new ThreadState(this);
241 new_thread_state->AllocateSpace(); 261 new_thread_state->AllocateSpace();
242 return new_thread_state; 262 return new_thread_state;
243 } 263 }
244 return gotten; 264 return gotten;
245 } 265 }
246 266
247 267
248 // Gets the first in the list of archived threads. 268 // Gets the first in the list of archived threads.
249 ThreadState* ThreadState::FirstInUse() { 269 ThreadState* ThreadManager::FirstThreadStateInUse() {
250 return in_use_anchor_->Next(); 270 return in_use_anchor_->Next();
251 } 271 }
252 272
253 273
254 ThreadState* ThreadState::Next() { 274 ThreadState* ThreadState::Next() {
255 if (next_ == in_use_anchor_) return NULL; 275 if (next_ == thread_manager_->in_use_anchor_) return NULL;
256 return next_; 276 return next_;
257 } 277 }
258 278
259 279
260 // Thread ids must start with 1, because in TLS having thread id 0 can't 280 // Thread ids must start with 1, because in TLS having thread id 0 can't
261 // be distinguished from not having a thread id at all (since NULL is 281 // be distinguished from not having a thread id at all (since NULL is
262 // defined as 0.) 282 // defined as 0.)
263 int ThreadManager::last_id_ = 0; 283 ThreadManager::ThreadManager()
264 Mutex* ThreadManager::mutex_ = OS::CreateMutex(); 284 : mutex_(OS::CreateMutex()),
265 ThreadHandle ThreadManager::mutex_owner_(ThreadHandle::INVALID); 285 mutex_owner_(ThreadHandle::INVALID),
266 ThreadHandle ThreadManager::lazily_archived_thread_(ThreadHandle::INVALID); 286 lazily_archived_thread_(ThreadHandle::INVALID),
267 ThreadState* ThreadManager::lazily_archived_thread_state_ = NULL; 287 lazily_archived_thread_state_(NULL),
288 free_anchor_(NULL),
289 in_use_anchor_(NULL) {
290 free_anchor_ = new ThreadState(this);
291 in_use_anchor_ = new ThreadState(this);
292 }
293
294
295 ThreadManager::~ThreadManager() {
296 // TODO(isolates): Destroy mutexes.
297 }
268 298
269 299
270 void ThreadManager::ArchiveThread() { 300 void ThreadManager::ArchiveThread() {
271 ASSERT(!lazily_archived_thread_.IsValid()); 301 ASSERT(!lazily_archived_thread_.IsValid());
272 ASSERT(!IsArchived()); 302 ASSERT(!IsArchived());
273 ThreadState* state = ThreadState::GetFree(); 303 ThreadState* state = GetFreeThreadState();
274 state->Unlink(); 304 state->Unlink();
275 Thread::SetThreadLocal(thread_state_key, reinterpret_cast<void*>(state)); 305 Isolate::CurrentPerIsolateThreadData()->set_thread_state(state);
276 lazily_archived_thread_.Initialize(ThreadHandle::SELF); 306 lazily_archived_thread_.Initialize(ThreadHandle::SELF);
277 lazily_archived_thread_state_ = state; 307 lazily_archived_thread_state_ = state;
278 ASSERT(state->id() == kInvalidId); 308 ASSERT(state->id() == kInvalidId);
279 state->set_id(CurrentId()); 309 state->set_id(CurrentId());
280 ASSERT(state->id() != kInvalidId); 310 ASSERT(state->id() != kInvalidId);
281 } 311 }
282 312
283 313
284 void ThreadManager::EagerlyArchiveThread() { 314 void ThreadManager::EagerlyArchiveThread() {
285 ThreadState* state = lazily_archived_thread_state_; 315 ThreadState* state = lazily_archived_thread_state_;
286 state->LinkInto(ThreadState::IN_USE_LIST); 316 state->LinkInto(ThreadState::IN_USE_LIST);
287 char* to = state->data(); 317 char* to = state->data();
288 // Ensure that data containing GC roots are archived first, and handle them 318 // Ensure that data containing GC roots are archived first, and handle them
289 // in ThreadManager::Iterate(ObjectVisitor*). 319 // in ThreadManager::Iterate(ObjectVisitor*).
290 to = HandleScopeImplementer::ArchiveThread(to); 320 to = isolate_->handle_scope_implementer()->ArchiveThread(to);
291 to = Top::ArchiveThread(to); 321 to = isolate_->ArchiveThread(to);
292 to = Relocatable::ArchiveState(to); 322 to = Relocatable::ArchiveState(to);
293 #ifdef ENABLE_DEBUGGER_SUPPORT 323 #ifdef ENABLE_DEBUGGER_SUPPORT
294 to = Debug::ArchiveDebug(to); 324 to = isolate_->debug()->ArchiveDebug(to);
295 #endif 325 #endif
296 to = StackGuard::ArchiveStackGuard(to); 326 to = isolate_->stack_guard()->ArchiveStackGuard(to);
297 to = RegExpStack::ArchiveStack(to); 327 to = isolate_->regexp_stack()->ArchiveStack(to);
298 to = Bootstrapper::ArchiveState(to); 328 to = isolate_->bootstrapper()->ArchiveState(to);
299 lazily_archived_thread_.Initialize(ThreadHandle::INVALID); 329 lazily_archived_thread_.Initialize(ThreadHandle::INVALID);
300 lazily_archived_thread_state_ = NULL; 330 lazily_archived_thread_state_ = NULL;
301 } 331 }
302 332
303 333
304 void ThreadManager::FreeThreadResources() { 334 void ThreadManager::FreeThreadResources() {
305 HandleScopeImplementer::FreeThreadResources(); 335 isolate_->handle_scope_implementer()->FreeThreadResources();
306 Top::FreeThreadResources(); 336 isolate_->FreeThreadResources();
307 #ifdef ENABLE_DEBUGGER_SUPPORT 337 #ifdef ENABLE_DEBUGGER_SUPPORT
308 Debug::FreeThreadResources(); 338 isolate_->debug()->FreeThreadResources();
309 #endif 339 #endif
310 StackGuard::FreeThreadResources(); 340 isolate_->stack_guard()->FreeThreadResources();
311 RegExpStack::FreeThreadResources(); 341 isolate_->regexp_stack()->FreeThreadResources();
312 Bootstrapper::FreeThreadResources(); 342 isolate_->bootstrapper()->FreeThreadResources();
313 } 343 }
314 344
315 345
316 bool ThreadManager::IsArchived() { 346 bool ThreadManager::IsArchived() {
317 return Thread::HasThreadLocal(thread_state_key); 347 Isolate::PerIsolateThreadData* data = Isolate::CurrentPerIsolateThreadData();
348 return data != NULL && data->thread_state() != NULL;
318 } 349 }
319 350
320 351
321 void ThreadManager::Iterate(ObjectVisitor* v) { 352 void ThreadManager::Iterate(ObjectVisitor* v) {
322 // Expecting no threads during serialization/deserialization 353 // Expecting no threads during serialization/deserialization
323 for (ThreadState* state = ThreadState::FirstInUse(); 354 for (ThreadState* state = FirstThreadStateInUse();
324 state != NULL; 355 state != NULL;
325 state = state->Next()) { 356 state = state->Next()) {
326 char* data = state->data(); 357 char* data = state->data();
327 data = HandleScopeImplementer::Iterate(v, data); 358 data = HandleScopeImplementer::Iterate(v, data);
328 data = Top::Iterate(v, data); 359 data = isolate_->Iterate(v, data);
329 data = Relocatable::Iterate(v, data); 360 data = Relocatable::Iterate(v, data);
330 } 361 }
331 } 362 }
332 363
333 364
334 void ThreadManager::IterateArchivedThreads(ThreadVisitor* v) { 365 void ThreadManager::IterateArchivedThreads(ThreadVisitor* v) {
335 for (ThreadState* state = ThreadState::FirstInUse(); 366 for (ThreadState* state = FirstThreadStateInUse();
336 state != NULL; 367 state != NULL;
337 state = state->Next()) { 368 state = state->Next()) {
338 char* data = state->data(); 369 char* data = state->data();
339 data += HandleScopeImplementer::ArchiveSpacePerThread(); 370 data += HandleScopeImplementer::ArchiveSpacePerThread();
340 Top::IterateThread(v, data); 371 isolate_->IterateThread(v, data);
341 } 372 }
342 } 373 }
343 374
344 375
345 int ThreadManager::CurrentId() { 376 int ThreadManager::CurrentId() {
346 return Thread::GetThreadLocalInt(thread_id_key); 377 return Thread::GetThreadLocalInt(Isolate::thread_id_key());
347 }
348
349
350 void ThreadManager::AssignId() {
351 if (!HasId()) {
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);
357 }
358 }
359
360
361 bool ThreadManager::HasId() {
362 return Thread::HasThreadLocal(thread_id_key);
363 } 378 }
364 379
365 380
366 void ThreadManager::TerminateExecution(int thread_id) { 381 void ThreadManager::TerminateExecution(int thread_id) {
367 for (ThreadState* state = ThreadState::FirstInUse(); 382 for (ThreadState* state = FirstThreadStateInUse();
368 state != NULL; 383 state != NULL;
369 state = state->Next()) { 384 state = state->Next()) {
370 if (thread_id == state->id()) { 385 if (thread_id == state->id()) {
371 state->set_terminate_on_restore(true); 386 state->set_terminate_on_restore(true);
372 } 387 }
373 } 388 }
374 } 389 }
375 390
376 391
377 // This is the ContextSwitcher singleton. There is at most a single thread 392 ContextSwitcher::ContextSwitcher(Isolate* isolate, int every_n_ms)
378 // running which delivers preemption events to V8 threads. 393 : Thread(isolate, "v8:CtxtSwitcher"),
379 ContextSwitcher* ContextSwitcher::singleton_ = NULL;
380
381
382 ContextSwitcher::ContextSwitcher(int every_n_ms)
383 : Thread("v8:CtxtSwitcher"),
384 keep_going_(true), 394 keep_going_(true),
385 sleep_ms_(every_n_ms) { 395 sleep_ms_(every_n_ms) {
386 } 396 }
387 397
388 398
389 // Set the scheduling interval of V8 threads. This function starts the 399 // Set the scheduling interval of V8 threads. This function starts the
390 // ContextSwitcher thread if needed. 400 // ContextSwitcher thread if needed.
391 void ContextSwitcher::StartPreemption(int every_n_ms) { 401 void ContextSwitcher::StartPreemption(int every_n_ms) {
402 Isolate* isolate = Isolate::Current();
392 ASSERT(Locker::IsLocked()); 403 ASSERT(Locker::IsLocked());
393 if (singleton_ == NULL) { 404 if (isolate->context_switcher() == NULL) {
394 // If the ContextSwitcher thread is not running at the moment start it now. 405 // If the ContextSwitcher thread is not running at the moment start it now.
395 singleton_ = new ContextSwitcher(every_n_ms); 406 isolate->set_context_switcher(new ContextSwitcher(isolate, every_n_ms));
396 singleton_->Start(); 407 isolate->context_switcher()->Start();
397 } else { 408 } else {
398 // ContextSwitcher thread is already running, so we just change the 409 // ContextSwitcher thread is already running, so we just change the
399 // scheduling interval. 410 // scheduling interval.
400 singleton_->sleep_ms_ = every_n_ms; 411 isolate->context_switcher()->sleep_ms_ = every_n_ms;
401 } 412 }
402 } 413 }
403 414
404 415
405 // Disable preemption of V8 threads. If multiple threads want to use V8 they 416 // Disable preemption of V8 threads. If multiple threads want to use V8 they
406 // must cooperatively schedule amongst them from this point on. 417 // must cooperatively schedule amongst them from this point on.
407 void ContextSwitcher::StopPreemption() { 418 void ContextSwitcher::StopPreemption() {
419 Isolate* isolate = Isolate::Current();
408 ASSERT(Locker::IsLocked()); 420 ASSERT(Locker::IsLocked());
409 if (singleton_ != NULL) { 421 if (isolate->context_switcher() != NULL) {
410 // The ContextSwitcher thread is running. We need to stop it and release 422 // The ContextSwitcher thread is running. We need to stop it and release
411 // its resources. 423 // its resources.
412 singleton_->keep_going_ = false; 424 isolate->context_switcher()->keep_going_ = false;
413 singleton_->Join(); // Wait for the ContextSwitcher thread to exit. 425 // Wait for the ContextSwitcher thread to exit.
426 isolate->context_switcher()->Join();
414 // Thread has exited, now we can delete it. 427 // Thread has exited, now we can delete it.
415 delete(singleton_); 428 delete(isolate->context_switcher());
416 singleton_ = NULL; 429 isolate->set_context_switcher(NULL);
417 } 430 }
418 } 431 }
419 432
420 433
421 // Main loop of the ContextSwitcher thread: Preempt the currently running V8 434 // Main loop of the ContextSwitcher thread: Preempt the currently running V8
422 // thread at regular intervals. 435 // thread at regular intervals.
423 void ContextSwitcher::Run() { 436 void ContextSwitcher::Run() {
424 while (keep_going_) { 437 while (keep_going_) {
425 OS::Sleep(sleep_ms_); 438 OS::Sleep(sleep_ms_);
426 StackGuard::Preempt(); 439 isolate()->stack_guard()->Preempt();
427 } 440 }
428 } 441 }
429 442
430 443
431 // Acknowledge the preemption by the receiving thread. 444 // Acknowledge the preemption by the receiving thread.
432 void ContextSwitcher::PreemptionReceived() { 445 void ContextSwitcher::PreemptionReceived() {
433 ASSERT(Locker::IsLocked()); 446 ASSERT(Locker::IsLocked());
434 // There is currently no accounting being done for this. But could be in the 447 // There is currently no accounting being done for this. But could be in the
435 // future, which is why we leave this in. 448 // future, which is why we leave this in.
436 } 449 }
437 450
438 451
439 } // namespace internal 452 } // namespace internal
440 } // namespace v8 453 } // namespace v8
OLDNEW
« no previous file with comments | « src/v8threads.h ('k') | src/variables.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698