V8 Project
v8threads.cc
Go to the documentation of this file.
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 // Track whether this V8 instance has ever called v8::Locker. This allows the
18 // API code to verify that the lock is always held when V8 is being entered.
19 bool Locker::active_ = false;
20 
21 
22 // Once the Locker is initialized, the current thread will be guaranteed to have
23 // the lock for a given isolate.
25  DCHECK(isolate != NULL);
26  has_lock_= false;
27  top_level_ = true;
28  isolate_ = reinterpret_cast<i::Isolate*>(isolate);
29  // Record that the Locker has been used at least once.
30  active_ = true;
31  // Get the big lock if necessary.
34  has_lock_ = true;
35 
36  // Make sure that V8 is initialized. Archiving of threads interferes
37  // with deserialization by adding additional root pointers, so we must
38  // initialize here, before anyone can call ~Locker() or Unlocker().
39  if (!isolate_->IsInitialized()) {
40  isolate_->Enter();
42  isolate_->Exit();
43  }
44 
45  // This may be a locker within an unlocker in which case we have to
46  // get the saved state for this thread and restore it.
48  top_level_ = false;
49  } else {
50  internal::ExecutionAccess access(isolate_);
51  isolate_->stack_guard()->ClearThread(access);
52  isolate_->stack_guard()->InitThread(access);
53  }
54  }
56 }
57 
58 
59 bool Locker::IsLocked(v8::Isolate* isolate) {
60  DCHECK(isolate != NULL);
61  i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);
62  return internal_isolate->thread_manager()->IsLockedByCurrentThread();
63 }
64 
65 
67  return active_;
68 }
69 
70 
73  if (has_lock_) {
74  if (top_level_) {
76  } else {
78  }
80  }
81 }
82 
83 
85  DCHECK(isolate != NULL);
86  isolate_ = reinterpret_cast<i::Isolate*>(isolate);
90 }
91 
92 
97 }
98 
99 
100 namespace internal {
101 
102 
105  // First check whether the current thread has been 'lazily archived', i.e.
106  // not archived at all. If that is the case we put the state storage we
107  // had prepared back in the free list, since we didn't need it after all.
110  Isolate::PerIsolateThreadData* per_thread =
112  DCHECK(per_thread != NULL);
113  DCHECK(per_thread->thread_state() == lazily_archived_thread_state_);
117  per_thread->set_thread_state(NULL);
118  return true;
119  }
120 
121  // Make sure that the preemption thread cannot modify the thread state while
122  // it is being archived or restored.
123  ExecutionAccess access(isolate_);
124 
125  // If there is another thread that was lazily archived then we have to really
126  // archive it now.
127  if (lazily_archived_thread_.IsValid()) {
129  }
130  Isolate::PerIsolateThreadData* per_thread =
132  if (per_thread == NULL || per_thread->thread_state() == NULL) {
133  // This is a new thread.
134  isolate_->stack_guard()->InitThread(access);
135  return false;
136  }
137  ThreadState* state = per_thread->thread_state();
138  char* from = state->data();
140  from = isolate_->RestoreThread(from);
141  from = Relocatable::RestoreState(isolate_, from);
142  from = isolate_->debug()->RestoreDebug(from);
143  from = isolate_->stack_guard()->RestoreStackGuard(from);
144  from = isolate_->regexp_stack()->RestoreStack(from);
145  from = isolate_->bootstrapper()->RestoreState(from);
146  per_thread->set_thread_state(NULL);
147  if (state->terminate_on_restore()) {
148  isolate_->stack_guard()->RequestTerminateExecution();
149  state->set_terminate_on_restore(false);
150  }
151  state->set_id(ThreadId::Invalid());
152  state->Unlink();
154  return true;
155 }
156 
157 
159  mutex_.Lock();
162 }
163 
164 
167  mutex_.Unlock();
168 }
169 
170 
171 static int ArchiveSpacePerThread() {
179 }
180 
181 
183  : id_(ThreadId::Invalid()),
184  terminate_on_restore_(false),
185  data_(NULL),
186  next_(this),
187  previous_(this),
188  thread_manager_(thread_manager) {
189 }
190 
191 
193  DeleteArray<char>(data_);
194 }
195 
196 
198  data_ = NewArray<char>(ArchiveSpacePerThread());
199 }
200 
201 
204  previous_->next_ = next_;
205 }
206 
207 
209  ThreadState* flying_anchor =
212  next_ = flying_anchor->next_;
213  previous_ = flying_anchor;
214  flying_anchor->next_ = this;
215  next_->previous_ = this;
216 }
217 
218 
220  ThreadState* gotten = free_anchor_->next_;
221  if (gotten == free_anchor_) {
222  ThreadState* new_thread_state = new ThreadState(this);
223  new_thread_state->AllocateSpace();
224  return new_thread_state;
225  }
226  return gotten;
227 }
228 
229 
230 // Gets the first in the list of archived threads.
232  return in_use_anchor_->Next();
233 }
234 
235 
237  if (next_ == thread_manager_->in_use_anchor_) return NULL;
238  return next_;
239 }
240 
241 
242 // Thread ids must start with 1, because in TLS having thread id 0 can't
243 // be distinguished from not having a thread id at all (since NULL is
244 // defined as 0.)
246  : mutex_owner_(ThreadId::Invalid()),
247  lazily_archived_thread_(ThreadId::Invalid()),
248  lazily_archived_thread_state_(NULL),
249  free_anchor_(NULL),
250  in_use_anchor_(NULL) {
251  free_anchor_ = new ThreadState(this);
252  in_use_anchor_ = new ThreadState(this);
253 }
254 
255 
259 }
260 
261 
263  // The list starts and ends with the anchor.
264  for (ThreadState* current = anchor->next_; current != anchor;) {
265  ThreadState* next = current->next_;
266  delete current;
267  current = next;
268  }
269  delete anchor;
270 }
271 
272 
275  DCHECK(!IsArchived());
277  ThreadState* state = GetFreeThreadState();
278  state->Unlink();
279  Isolate::PerIsolateThreadData* per_thread =
281  per_thread->set_thread_state(state);
284  DCHECK(state->id().Equals(ThreadId::Invalid()));
285  state->set_id(CurrentId());
286  DCHECK(!state->id().Equals(ThreadId::Invalid()));
287 }
288 
289 
294  char* to = state->data();
295  // Ensure that data containing GC roots are archived first, and handle them
296  // in ThreadManager::Iterate(ObjectVisitor*).
299  to = Relocatable::ArchiveState(isolate_, to);
301  to = isolate_->stack_guard()->ArchiveStackGuard(to);
303  to = isolate_->bootstrapper()->ArchiveState(to);
306 }
307 
308 
311  DCHECK(!isolate_->external_caught_exception());
316  isolate_->stack_guard()->FreeThreadResources();
318  isolate_->bootstrapper()->FreeThreadResources();
319 }
320 
321 
325  return data != NULL && data->thread_state() != NULL;
326 }
327 
328 
330  // Expecting no threads during serialization/deserialization
331  for (ThreadState* state = FirstThreadStateInUse();
332  state != NULL;
333  state = state->Next()) {
334  char* data = state->data();
335  data = HandleScopeImplementer::Iterate(v, data);
336  data = isolate_->Iterate(v, data);
337  data = Relocatable::Iterate(v, data);
338  }
339 }
340 
341 
343  for (ThreadState* state = FirstThreadStateInUse();
344  state != NULL;
345  state = state->Next()) {
346  char* data = state->data();
348  isolate_->IterateThread(v, data);
349  }
350 }
351 
352 
354  return ThreadId::Current();
355 }
356 
357 
359  for (ThreadState* state = FirstThreadStateInUse();
360  state != NULL;
361  state = state->Next()) {
362  if (thread_id.Equals(state->id())) {
363  state->set_terminate_on_restore(true);
364  }
365  }
366 }
367 
368 
369 } // namespace internal
370 } // namespace v8
Isolate represents an isolated instance of the V8 engine.
Definition: v8.h:4356
void Initialize(Isolate *isolate)
Definition: v8threads.cc:24
bool top_level_
Definition: v8.h:5716
bool has_lock_
Definition: v8.h:5715
static bool active_
Definition: v8.h:5719
internal::Isolate * isolate_
Definition: v8.h:5717
static bool IsLocked(Isolate *isolate)
Returns whether or not the locker for a given isolate, is locked by the current thread.
Definition: v8threads.cc:59
static bool IsActive()
Returns whether v8::Locker is being used by this V8 instance.
Definition: v8threads.cc:66
internal::Isolate * isolate_
Definition: v8.h:5688
void Initialize(Isolate *isolate)
Definition: v8threads.cc:84
static bool Initialize()
Initializes V8.
Definition: api.cc:5058
char * ArchiveDebug(char *to)
Definition: debug.cc:571
void FreeThreadResources()
Definition: debug.h:452
static int ArchiveSpacePerThread()
Definition: debug.cc:586
char * RestoreDebug(char *from)
Definition: debug.cc:579
char * ArchiveThread(char *to)
Definition: api.cc:7529
void Iterate(v8::internal::ObjectVisitor *v)
Definition: api.cc:7590
char * RestoreThread(char *from)
Definition: api.cc:7546
HandleScopeImplementer * handle_scope_implementer()
Definition: isolate.h:901
StackGuard * stack_guard()
Definition: isolate.h:872
PerIsolateThreadData * FindPerThreadDataForThisThread()
Definition: isolate.cc:135
static int ArchiveSpacePerThread()
Definition: isolate.h:683
void IterateThread(ThreadVisitor *v, char *t)
Definition: isolate.cc:174
char * RestoreThread(char *from)
Definition: isolate.cc:1380
void FreeThreadResources()
Definition: isolate.h:684
void Iterate(ObjectVisitor *v)
Definition: isolate.cc:206
char * ArchiveThread(char *to)
Definition: isolate.cc:1369
RegExpStack * regexp_stack()
Definition: isolate.h:960
v8::TryCatch * try_catch_handler()
Definition: isolate.h:593
PerIsolateThreadData * FindOrAllocatePerThreadDataForThisThread()
Definition: isolate.cc:119
ThreadManager * thread_manager()
Definition: isolate.h:921
Bootstrapper * bootstrapper()
Definition: isolate.h:856
bool has_pending_exception()
Definition: isolate.h:581
char * ArchiveStack(char *to)
Definition: regexp-stack.cc:35
char * RestoreStack(char *from)
Definition: regexp-stack.cc:43
static int ArchiveSpacePerThread()
Definition: regexp-stack.h:63
static ThreadId Invalid()
Definition: isolate.h:188
static ThreadId Current()
Definition: isolate.h:185
void IterateArchivedThreads(ThreadVisitor *v)
Definition: v8threads.cc:342
ThreadState * FirstThreadStateInUse()
Definition: v8threads.cc:231
ThreadState * lazily_archived_thread_state_
Definition: v8threads.h:102
ThreadState * in_use_anchor_
Definition: v8threads.h:110
void TerminateExecution(ThreadId thread_id)
Definition: v8threads.cc:358
void DeleteThreadStateList(ThreadState *anchor)
Definition: v8threads.cc:262
ThreadState * free_anchor_
Definition: v8threads.h:108
void Iterate(ObjectVisitor *v)
Definition: v8threads.cc:329
ThreadState * GetFreeThreadState()
Definition: v8threads.cc:219
void set_id(ThreadId id)
Definition: v8threads.h:23
ThreadState * previous_
Definition: v8threads.h:45
void LinkInto(List list)
Definition: v8threads.cc:208
void set_terminate_on_restore(bool terminate_on_restore)
Definition: v8threads.h:28
ThreadState * next_
Definition: v8threads.h:44
ThreadState * Next()
Definition: v8threads.cc:236
ThreadManager * thread_manager_
Definition: v8threads.h:47
ThreadState(ThreadManager *thread_manager)
Definition: v8threads.cc:182
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in only print modified registers Trace simulator debug messages Implied by trace sim abort randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot A filename with extra code to be included in the A file to write the raw snapshot bytes to(mksnapshot only)") DEFINE_STRING(raw_context_file
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define DCHECK(condition)
Definition: logging.h:205
static int ArchiveSpacePerThread()
Definition: v8threads.cc:171
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20