Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / v8 / src / v8threads.cc
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/v8.h"
6
7 #include "src/api.h"
8 #include "src/bootstrapper.h"
9 #include "src/debug.h"
10 #include "src/execution.h"
11 #include "src/regexp-stack.h"
12 #include "src/v8threads.h"
13
14 namespace v8 {
15
16
17 namespace {
18
19 // Track whether this V8 instance has ever called v8::Locker. This allows the
20 // API code to verify that the lock is always held when V8 is being entered.
21 base::Atomic32 g_locker_was_ever_used_ = 0;
22
23 }  // namespace
24
25
26 // Once the Locker is initialized, the current thread will be guaranteed to have
27 // the lock for a given isolate.
28 void Locker::Initialize(v8::Isolate* isolate) {
29   DCHECK(isolate != NULL);
30   has_lock_= false;
31   top_level_ = true;
32   isolate_ = reinterpret_cast<i::Isolate*>(isolate);
33   // Record that the Locker has been used at least once.
34   base::NoBarrier_Store(&g_locker_was_ever_used_, 1);
35   // Get the big lock if necessary.
36   if (!isolate_->thread_manager()->IsLockedByCurrentThread()) {
37     isolate_->thread_manager()->Lock();
38     has_lock_ = true;
39
40     // This may be a locker within an unlocker in which case we have to
41     // get the saved state for this thread and restore it.
42     if (isolate_->thread_manager()->RestoreThread()) {
43       top_level_ = false;
44     } else {
45       internal::ExecutionAccess access(isolate_);
46       isolate_->stack_guard()->ClearThread(access);
47       isolate_->stack_guard()->InitThread(access);
48     }
49   }
50   DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
51 }
52
53
54 bool Locker::IsLocked(v8::Isolate* isolate) {
55   DCHECK(isolate != NULL);
56   i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
57   return internal_isolate->thread_manager()->IsLockedByCurrentThread();
58 }
59
60
61 bool Locker::IsActive() {
62   return !!base::NoBarrier_Load(&g_locker_was_ever_used_);
63 }
64
65
66 Locker::~Locker() {
67   DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
68   if (has_lock_) {
69     if (top_level_) {
70       isolate_->thread_manager()->FreeThreadResources();
71     } else {
72       isolate_->thread_manager()->ArchiveThread();
73     }
74     isolate_->thread_manager()->Unlock();
75   }
76 }
77
78
79 void Unlocker::Initialize(v8::Isolate* isolate) {
80   DCHECK(isolate != NULL);
81   isolate_ = reinterpret_cast<i::Isolate*>(isolate);
82   DCHECK(isolate_->thread_manager()->IsLockedByCurrentThread());
83   isolate_->thread_manager()->ArchiveThread();
84   isolate_->thread_manager()->Unlock();
85 }
86
87
88 Unlocker::~Unlocker() {
89   DCHECK(!isolate_->thread_manager()->IsLockedByCurrentThread());
90   isolate_->thread_manager()->Lock();
91   isolate_->thread_manager()->RestoreThread();
92 }
93
94
95 namespace internal {
96
97
98 bool ThreadManager::RestoreThread() {
99   DCHECK(IsLockedByCurrentThread());
100   // First check whether the current thread has been 'lazily archived', i.e.
101   // not archived at all.  If that is the case we put the state storage we
102   // had prepared back in the free list, since we didn't need it after all.
103   if (lazily_archived_thread_.Equals(ThreadId::Current())) {
104     lazily_archived_thread_ = ThreadId::Invalid();
105     Isolate::PerIsolateThreadData* per_thread =
106         isolate_->FindPerThreadDataForThisThread();
107     DCHECK(per_thread != NULL);
108     DCHECK(per_thread->thread_state() == lazily_archived_thread_state_);
109     lazily_archived_thread_state_->set_id(ThreadId::Invalid());
110     lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST);
111     lazily_archived_thread_state_ = NULL;
112     per_thread->set_thread_state(NULL);
113     return true;
114   }
115
116   // Make sure that the preemption thread cannot modify the thread state while
117   // it is being archived or restored.
118   ExecutionAccess access(isolate_);
119
120   // If there is another thread that was lazily archived then we have to really
121   // archive it now.
122   if (lazily_archived_thread_.IsValid()) {
123     EagerlyArchiveThread();
124   }
125   Isolate::PerIsolateThreadData* per_thread =
126       isolate_->FindPerThreadDataForThisThread();
127   if (per_thread == NULL || per_thread->thread_state() == NULL) {
128     // This is a new thread.
129     isolate_->stack_guard()->InitThread(access);
130     return false;
131   }
132   ThreadState* state = per_thread->thread_state();
133   char* from = state->data();
134   from = isolate_->handle_scope_implementer()->RestoreThread(from);
135   from = isolate_->RestoreThread(from);
136   from = Relocatable::RestoreState(isolate_, from);
137   from = isolate_->debug()->RestoreDebug(from);
138   from = isolate_->stack_guard()->RestoreStackGuard(from);
139   from = isolate_->regexp_stack()->RestoreStack(from);
140   from = isolate_->bootstrapper()->RestoreState(from);
141   per_thread->set_thread_state(NULL);
142   if (state->terminate_on_restore()) {
143     isolate_->stack_guard()->RequestTerminateExecution();
144     state->set_terminate_on_restore(false);
145   }
146   state->set_id(ThreadId::Invalid());
147   state->Unlink();
148   state->LinkInto(ThreadState::FREE_LIST);
149   return true;
150 }
151
152
153 void ThreadManager::Lock() {
154   mutex_.Lock();
155   mutex_owner_ = ThreadId::Current();
156   DCHECK(IsLockedByCurrentThread());
157 }
158
159
160 void ThreadManager::Unlock() {
161   mutex_owner_ = ThreadId::Invalid();
162   mutex_.Unlock();
163 }
164
165
166 static int ArchiveSpacePerThread() {
167   return HandleScopeImplementer::ArchiveSpacePerThread() +
168                         Isolate::ArchiveSpacePerThread() +
169                           Debug::ArchiveSpacePerThread() +
170                      StackGuard::ArchiveSpacePerThread() +
171                     RegExpStack::ArchiveSpacePerThread() +
172                    Bootstrapper::ArchiveSpacePerThread() +
173                     Relocatable::ArchiveSpacePerThread();
174 }
175
176
177 ThreadState::ThreadState(ThreadManager* thread_manager)
178     : id_(ThreadId::Invalid()),
179       terminate_on_restore_(false),
180       data_(NULL),
181       next_(this),
182       previous_(this),
183       thread_manager_(thread_manager) {
184 }
185
186
187 ThreadState::~ThreadState() {
188   DeleteArray<char>(data_);
189 }
190
191
192 void ThreadState::AllocateSpace() {
193   data_ = NewArray<char>(ArchiveSpacePerThread());
194 }
195
196
197 void ThreadState::Unlink() {
198   next_->previous_ = previous_;
199   previous_->next_ = next_;
200 }
201
202
203 void ThreadState::LinkInto(List list) {
204   ThreadState* flying_anchor =
205       list == FREE_LIST ? thread_manager_->free_anchor_
206                         : thread_manager_->in_use_anchor_;
207   next_ = flying_anchor->next_;
208   previous_ = flying_anchor;
209   flying_anchor->next_ = this;
210   next_->previous_ = this;
211 }
212
213
214 ThreadState* ThreadManager::GetFreeThreadState() {
215   ThreadState* gotten = free_anchor_->next_;
216   if (gotten == free_anchor_) {
217     ThreadState* new_thread_state = new ThreadState(this);
218     new_thread_state->AllocateSpace();
219     return new_thread_state;
220   }
221   return gotten;
222 }
223
224
225 // Gets the first in the list of archived threads.
226 ThreadState* ThreadManager::FirstThreadStateInUse() {
227   return in_use_anchor_->Next();
228 }
229
230
231 ThreadState* ThreadState::Next() {
232   if (next_ == thread_manager_->in_use_anchor_) return NULL;
233   return next_;
234 }
235
236
237 // Thread ids must start with 1, because in TLS having thread id 0 can't
238 // be distinguished from not having a thread id at all (since NULL is
239 // defined as 0.)
240 ThreadManager::ThreadManager()
241     : mutex_owner_(ThreadId::Invalid()),
242       lazily_archived_thread_(ThreadId::Invalid()),
243       lazily_archived_thread_state_(NULL),
244       free_anchor_(NULL),
245       in_use_anchor_(NULL) {
246   free_anchor_ = new ThreadState(this);
247   in_use_anchor_ = new ThreadState(this);
248 }
249
250
251 ThreadManager::~ThreadManager() {
252   DeleteThreadStateList(free_anchor_);
253   DeleteThreadStateList(in_use_anchor_);
254 }
255
256
257 void ThreadManager::DeleteThreadStateList(ThreadState* anchor) {
258   // The list starts and ends with the anchor.
259   for (ThreadState* current = anchor->next_; current != anchor;) {
260     ThreadState* next = current->next_;
261     delete current;
262     current = next;
263   }
264   delete anchor;
265 }
266
267
268 void ThreadManager::ArchiveThread() {
269   DCHECK(lazily_archived_thread_.Equals(ThreadId::Invalid()));
270   DCHECK(!IsArchived());
271   DCHECK(IsLockedByCurrentThread());
272   ThreadState* state = GetFreeThreadState();
273   state->Unlink();
274   Isolate::PerIsolateThreadData* per_thread =
275       isolate_->FindOrAllocatePerThreadDataForThisThread();
276   per_thread->set_thread_state(state);
277   lazily_archived_thread_ = ThreadId::Current();
278   lazily_archived_thread_state_ = state;
279   DCHECK(state->id().Equals(ThreadId::Invalid()));
280   state->set_id(CurrentId());
281   DCHECK(!state->id().Equals(ThreadId::Invalid()));
282 }
283
284
285 void ThreadManager::EagerlyArchiveThread() {
286   DCHECK(IsLockedByCurrentThread());
287   ThreadState* state = lazily_archived_thread_state_;
288   state->LinkInto(ThreadState::IN_USE_LIST);
289   char* to = state->data();
290   // Ensure that data containing GC roots are archived first, and handle them
291   // in ThreadManager::Iterate(ObjectVisitor*).
292   to = isolate_->handle_scope_implementer()->ArchiveThread(to);
293   to = isolate_->ArchiveThread(to);
294   to = Relocatable::ArchiveState(isolate_, to);
295   to = isolate_->debug()->ArchiveDebug(to);
296   to = isolate_->stack_guard()->ArchiveStackGuard(to);
297   to = isolate_->regexp_stack()->ArchiveStack(to);
298   to = isolate_->bootstrapper()->ArchiveState(to);
299   lazily_archived_thread_ = ThreadId::Invalid();
300   lazily_archived_thread_state_ = NULL;
301 }
302
303
304 void ThreadManager::FreeThreadResources() {
305   DCHECK(!isolate_->has_pending_exception());
306   DCHECK(!isolate_->external_caught_exception());
307   DCHECK(isolate_->try_catch_handler() == NULL);
308   isolate_->handle_scope_implementer()->FreeThreadResources();
309   isolate_->FreeThreadResources();
310   isolate_->debug()->FreeThreadResources();
311   isolate_->stack_guard()->FreeThreadResources();
312   isolate_->regexp_stack()->FreeThreadResources();
313   isolate_->bootstrapper()->FreeThreadResources();
314 }
315
316
317 bool ThreadManager::IsArchived() {
318   Isolate::PerIsolateThreadData* data =
319       isolate_->FindPerThreadDataForThisThread();
320   return data != NULL && data->thread_state() != NULL;
321 }
322
323
324 void ThreadManager::Iterate(ObjectVisitor* v) {
325   // Expecting no threads during serialization/deserialization
326   for (ThreadState* state = FirstThreadStateInUse();
327        state != NULL;
328        state = state->Next()) {
329     char* data = state->data();
330     data = HandleScopeImplementer::Iterate(v, data);
331     data = isolate_->Iterate(v, data);
332     data = Relocatable::Iterate(v, data);
333   }
334 }
335
336
337 void ThreadManager::IterateArchivedThreads(ThreadVisitor* v) {
338   for (ThreadState* state = FirstThreadStateInUse();
339        state != NULL;
340        state = state->Next()) {
341     char* data = state->data();
342     data += HandleScopeImplementer::ArchiveSpacePerThread();
343     isolate_->IterateThread(v, data);
344   }
345 }
346
347
348 ThreadId ThreadManager::CurrentId() {
349   return ThreadId::Current();
350 }
351
352
353 void ThreadManager::TerminateExecution(ThreadId thread_id) {
354   for (ThreadState* state = FirstThreadStateInUse();
355        state != NULL;
356        state = state->Next()) {
357     if (thread_id.Equals(state->id())) {
358       state->set_terminate_on_restore(true);
359     }
360   }
361 }
362
363
364 }  // namespace internal
365 }  // namespace v8