OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 20 matching lines...) Expand all Loading... |
31 | 31 |
32 #include "ast.h" | 32 #include "ast.h" |
33 #include "bootstrapper.h" | 33 #include "bootstrapper.h" |
34 #include "codegen.h" | 34 #include "codegen.h" |
35 #include "compilation-cache.h" | 35 #include "compilation-cache.h" |
36 #include "debug.h" | 36 #include "debug.h" |
37 #include "deoptimizer.h" | 37 #include "deoptimizer.h" |
38 #include "heap-profiler.h" | 38 #include "heap-profiler.h" |
39 #include "hydrogen.h" | 39 #include "hydrogen.h" |
40 #include "isolate.h" | 40 #include "isolate.h" |
| 41 #include "lazy-instance.h" |
41 #include "lithium-allocator.h" | 42 #include "lithium-allocator.h" |
42 #include "log.h" | 43 #include "log.h" |
43 #include "messages.h" | 44 #include "messages.h" |
| 45 #include "platform.h" |
44 #include "regexp-stack.h" | 46 #include "regexp-stack.h" |
45 #include "runtime-profiler.h" | 47 #include "runtime-profiler.h" |
46 #include "scopeinfo.h" | 48 #include "scopeinfo.h" |
47 #include "serialize.h" | 49 #include "serialize.h" |
48 #include "simulator.h" | 50 #include "simulator.h" |
49 #include "spaces.h" | 51 #include "spaces.h" |
50 #include "stub-cache.h" | 52 #include "stub-cache.h" |
51 #include "version.h" | 53 #include "version.h" |
52 #include "vm-state-inl.h" | 54 #include "vm-state-inl.h" |
53 | 55 |
54 | 56 |
55 namespace v8 { | 57 namespace v8 { |
56 namespace internal { | 58 namespace internal { |
57 | 59 |
| 60 struct GlobalState { |
| 61 Thread::LocalStorageKey per_isolate_thread_data_key; |
| 62 Thread::LocalStorageKey isolate_key; |
| 63 Thread::LocalStorageKey thread_id_key; |
| 64 Isolate* default_isolate; |
| 65 Isolate::ThreadDataTable* thread_data_table; |
| 66 Mutex* mutex; |
| 67 }; |
| 68 |
| 69 struct InitializeGlobalState { |
| 70 static void Construct(GlobalState* state) { |
| 71 state->isolate_key = Thread::CreateThreadLocalKey(); |
| 72 state->thread_id_key = Thread::CreateThreadLocalKey(); |
| 73 state->per_isolate_thread_data_key = Thread::CreateThreadLocalKey(); |
| 74 state->thread_data_table = new Isolate::ThreadDataTable(); |
| 75 state->default_isolate = new Isolate(); |
| 76 state->mutex = OS::CreateMutex(); |
| 77 // Can't use SetIsolateThreadLocals(default_isolate_, NULL) here |
| 78 // because a non-null thread data may be already set. |
| 79 Thread::SetThreadLocal(state->isolate_key, state->default_isolate); |
| 80 } |
| 81 }; |
| 82 |
| 83 static LazyInstance<GlobalState, InitializeGlobalState>::type global_state; |
| 84 |
58 Atomic32 ThreadId::highest_thread_id_ = 0; | 85 Atomic32 ThreadId::highest_thread_id_ = 0; |
59 | 86 |
60 int ThreadId::AllocateThreadId() { | 87 int ThreadId::AllocateThreadId() { |
61 int new_id = NoBarrier_AtomicIncrement(&highest_thread_id_, 1); | 88 int new_id = NoBarrier_AtomicIncrement(&highest_thread_id_, 1); |
62 return new_id; | 89 return new_id; |
63 } | 90 } |
64 | 91 |
65 | 92 |
66 int ThreadId::GetCurrentThreadId() { | 93 int ThreadId::GetCurrentThreadId() { |
67 int thread_id = Thread::GetThreadLocalInt(Isolate::thread_id_key_); | 94 const GlobalState& global = global_state.Get(); |
| 95 int thread_id = Thread::GetThreadLocalInt(global.thread_id_key); |
68 if (thread_id == 0) { | 96 if (thread_id == 0) { |
69 thread_id = AllocateThreadId(); | 97 thread_id = AllocateThreadId(); |
70 Thread::SetThreadLocalInt(Isolate::thread_id_key_, thread_id); | 98 Thread::SetThreadLocalInt(global.thread_id_key, thread_id); |
71 } | 99 } |
72 return thread_id; | 100 return thread_id; |
73 } | 101 } |
74 | 102 |
75 | 103 |
76 ThreadLocalTop::ThreadLocalTop() { | 104 ThreadLocalTop::ThreadLocalTop() { |
77 InitializeInternal(); | 105 InitializeInternal(); |
78 // This flag may be set using v8::V8::IgnoreOutOfMemoryException() | 106 // This flag may be set using v8::V8::IgnoreOutOfMemoryException() |
79 // before an isolate is initialized. The initialize methods below do | 107 // before an isolate is initialized. The initialize methods below do |
80 // not touch it to preserve its value. | 108 // not touch it to preserve its value. |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 FreeStoreAllocationPolicy::Delete(p); | 332 FreeStoreAllocationPolicy::Delete(p); |
305 return; | 333 return; |
306 } | 334 } |
307 PreallocatedStorage* storage = reinterpret_cast<PreallocatedStorage*>(p) - 1; | 335 PreallocatedStorage* storage = reinterpret_cast<PreallocatedStorage*>(p) - 1; |
308 ASSERT(storage->next_->previous_ == storage); | 336 ASSERT(storage->next_->previous_ == storage); |
309 ASSERT(storage->previous_->next_ == storage); | 337 ASSERT(storage->previous_->next_ == storage); |
310 storage->Unlink(); | 338 storage->Unlink(); |
311 storage->LinkTo(&free_list_); | 339 storage->LinkTo(&free_list_); |
312 } | 340 } |
313 | 341 |
314 | |
315 Isolate* Isolate::default_isolate_ = NULL; | |
316 Thread::LocalStorageKey Isolate::isolate_key_; | |
317 Thread::LocalStorageKey Isolate::thread_id_key_; | |
318 Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_; | |
319 Mutex* Isolate::process_wide_mutex_ = OS::CreateMutex(); | |
320 Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL; | |
321 | |
322 | |
323 class IsolateInitializer { | |
324 public: | |
325 IsolateInitializer() { | |
326 Isolate::EnsureDefaultIsolate(); | |
327 } | |
328 }; | |
329 | |
330 static IsolateInitializer* EnsureDefaultIsolateAllocated() { | |
331 // TODO(isolates): Use the system threading API to do this once? | |
332 static IsolateInitializer static_initializer; | |
333 return &static_initializer; | |
334 } | |
335 | |
336 // This variable only needed to trigger static intialization. | |
337 static IsolateInitializer* static_initializer = EnsureDefaultIsolateAllocated(); | |
338 | |
339 | |
340 | |
341 | |
342 | |
343 Isolate::PerIsolateThreadData* Isolate::AllocatePerIsolateThreadData( | 342 Isolate::PerIsolateThreadData* Isolate::AllocatePerIsolateThreadData( |
344 ThreadId thread_id) { | 343 ThreadId thread_id) { |
345 ASSERT(!thread_id.Equals(ThreadId::Invalid())); | 344 ASSERT(!thread_id.Equals(ThreadId::Invalid())); |
346 PerIsolateThreadData* per_thread = new PerIsolateThreadData(this, thread_id); | 345 PerIsolateThreadData* per_thread = new PerIsolateThreadData(this, thread_id); |
347 { | 346 { |
348 ScopedLock lock(process_wide_mutex_); | 347 GlobalState* const global = global_state.Pointer(); |
349 ASSERT(thread_data_table_->Lookup(this, thread_id) == NULL); | 348 ScopedLock lock(global->mutex); |
350 thread_data_table_->Insert(per_thread); | 349 ASSERT(global->thread_data_table->Lookup(this, thread_id) == NULL); |
351 ASSERT(thread_data_table_->Lookup(this, thread_id) == per_thread); | 350 global->thread_data_table->Insert(per_thread); |
| 351 ASSERT(global->thread_data_table->Lookup(this, thread_id) == per_thread); |
352 } | 352 } |
353 return per_thread; | 353 return per_thread; |
354 } | 354 } |
355 | 355 |
356 | 356 |
357 Isolate::PerIsolateThreadData* | 357 Isolate::PerIsolateThreadData* |
358 Isolate::FindOrAllocatePerThreadDataForThisThread() { | 358 Isolate::FindOrAllocatePerThreadDataForThisThread() { |
359 ThreadId thread_id = ThreadId::Current(); | 359 ThreadId thread_id = ThreadId::Current(); |
360 PerIsolateThreadData* per_thread = NULL; | 360 PerIsolateThreadData* per_thread = NULL; |
361 { | 361 { |
362 ScopedLock lock(process_wide_mutex_); | 362 GlobalState* const global = global_state.Pointer(); |
363 per_thread = thread_data_table_->Lookup(this, thread_id); | 363 ScopedLock lock(global->mutex); |
| 364 per_thread = global->thread_data_table->Lookup(this, thread_id); |
364 if (per_thread == NULL) { | 365 if (per_thread == NULL) { |
365 per_thread = AllocatePerIsolateThreadData(thread_id); | 366 per_thread = AllocatePerIsolateThreadData(thread_id); |
366 } | 367 } |
367 } | 368 } |
368 return per_thread; | 369 return per_thread; |
369 } | 370 } |
370 | 371 |
371 | 372 |
372 Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThisThread() { | 373 Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThisThread() { |
373 ThreadId thread_id = ThreadId::Current(); | 374 ThreadId thread_id = ThreadId::Current(); |
374 PerIsolateThreadData* per_thread = NULL; | 375 PerIsolateThreadData* per_thread = NULL; |
375 { | 376 { |
376 ScopedLock lock(process_wide_mutex_); | 377 GlobalState* const global = global_state.Pointer(); |
377 per_thread = thread_data_table_->Lookup(this, thread_id); | 378 ScopedLock lock(global->mutex); |
| 379 per_thread = global->thread_data_table->Lookup(this, thread_id); |
378 } | 380 } |
379 return per_thread; | 381 return per_thread; |
380 } | 382 } |
381 | 383 |
382 | 384 |
| 385 bool Isolate::IsDefaultIsolate() const { |
| 386 return this == global_state.Get().default_isolate; |
| 387 } |
| 388 |
| 389 |
383 void Isolate::EnsureDefaultIsolate() { | 390 void Isolate::EnsureDefaultIsolate() { |
384 ScopedLock lock(process_wide_mutex_); | 391 GlobalState* const global = global_state.Pointer(); |
385 if (default_isolate_ == NULL) { | |
386 isolate_key_ = Thread::CreateThreadLocalKey(); | |
387 thread_id_key_ = Thread::CreateThreadLocalKey(); | |
388 per_isolate_thread_data_key_ = Thread::CreateThreadLocalKey(); | |
389 thread_data_table_ = new Isolate::ThreadDataTable(); | |
390 default_isolate_ = new Isolate(); | |
391 } | |
392 // Can't use SetIsolateThreadLocals(default_isolate_, NULL) here | 392 // Can't use SetIsolateThreadLocals(default_isolate_, NULL) here |
393 // becase a non-null thread data may be already set. | 393 // because a non-null thread data may be already set. |
394 if (Thread::GetThreadLocal(isolate_key_) == NULL) { | 394 if (Thread::GetThreadLocal(global->isolate_key) == NULL) { |
395 Thread::SetThreadLocal(isolate_key_, default_isolate_); | 395 Thread::SetThreadLocal(global->isolate_key, global->default_isolate); |
396 } | 396 } |
397 } | 397 } |
398 | 398 |
399 | 399 |
400 #ifdef ENABLE_DEBUGGER_SUPPORT | 400 #ifdef ENABLE_DEBUGGER_SUPPORT |
401 Debugger* Isolate::GetDefaultIsolateDebugger() { | 401 Debugger* Isolate::GetDefaultIsolateDebugger() { |
402 EnsureDefaultIsolate(); | 402 EnsureDefaultIsolate(); |
403 return default_isolate_->debugger(); | 403 return global_state.Pointer()->default_isolate->debugger(); |
404 } | 404 } |
405 #endif | 405 #endif |
406 | 406 |
407 | 407 |
408 StackGuard* Isolate::GetDefaultIsolateStackGuard() { | 408 StackGuard* Isolate::GetDefaultIsolateStackGuard() { |
409 EnsureDefaultIsolate(); | 409 EnsureDefaultIsolate(); |
410 return default_isolate_->stack_guard(); | 410 return global_state.Pointer()->default_isolate->stack_guard(); |
| 411 } |
| 412 |
| 413 |
| 414 Thread::LocalStorageKey Isolate::isolate_key() { |
| 415 return global_state.Get().isolate_key; |
| 416 } |
| 417 |
| 418 |
| 419 Thread::LocalStorageKey Isolate::thread_id_key() { |
| 420 return global_state.Get().thread_id_key; |
| 421 } |
| 422 |
| 423 |
| 424 Thread::LocalStorageKey Isolate::per_isolate_thread_data_key() { |
| 425 return global_state.Get().per_isolate_thread_data_key; |
411 } | 426 } |
412 | 427 |
413 | 428 |
414 void Isolate::EnterDefaultIsolate() { | 429 void Isolate::EnterDefaultIsolate() { |
415 EnsureDefaultIsolate(); | 430 EnsureDefaultIsolate(); |
416 ASSERT(default_isolate_ != NULL); | 431 Isolate* const default_isolate = global_state.Pointer()->default_isolate; |
| 432 ASSERT(default_isolate != NULL); |
417 | 433 |
418 PerIsolateThreadData* data = CurrentPerIsolateThreadData(); | 434 PerIsolateThreadData* data = CurrentPerIsolateThreadData(); |
419 // If not yet in default isolate - enter it. | 435 // If not yet in default isolate - enter it. |
420 if (data == NULL || data->isolate() != default_isolate_) { | 436 if (data == NULL || data->isolate() != default_isolate) { |
421 default_isolate_->Enter(); | 437 default_isolate->Enter(); |
422 } | 438 } |
423 } | 439 } |
424 | 440 |
425 | 441 |
426 Isolate* Isolate::GetDefaultIsolateForLocking() { | 442 Isolate* Isolate::GetDefaultIsolateForLocking() { |
427 EnsureDefaultIsolate(); | 443 EnsureDefaultIsolate(); |
428 return default_isolate_; | 444 return global_state.Pointer()->default_isolate; |
429 } | 445 } |
430 | 446 |
431 | 447 |
432 Address Isolate::get_address_from_id(Isolate::AddressId id) { | 448 Address Isolate::get_address_from_id(Isolate::AddressId id) { |
433 return isolate_addresses_[id]; | 449 return isolate_addresses_[id]; |
434 } | 450 } |
435 | 451 |
436 | 452 |
437 char* Isolate::Iterate(ObjectVisitor* v, char* thread_storage) { | 453 char* Isolate::Iterate(ObjectVisitor* v, char* thread_storage) { |
438 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage); | 454 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage); |
(...skipping 1101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1540 // Temporarily set this isolate as current so that various parts of | 1556 // Temporarily set this isolate as current so that various parts of |
1541 // the isolate can access it in their destructors without having a | 1557 // the isolate can access it in their destructors without having a |
1542 // direct pointer. We don't use Enter/Exit here to avoid | 1558 // direct pointer. We don't use Enter/Exit here to avoid |
1543 // initializing the thread data. | 1559 // initializing the thread data. |
1544 PerIsolateThreadData* saved_data = CurrentPerIsolateThreadData(); | 1560 PerIsolateThreadData* saved_data = CurrentPerIsolateThreadData(); |
1545 Isolate* saved_isolate = UncheckedCurrent(); | 1561 Isolate* saved_isolate = UncheckedCurrent(); |
1546 SetIsolateThreadLocals(this, NULL); | 1562 SetIsolateThreadLocals(this, NULL); |
1547 | 1563 |
1548 Deinit(); | 1564 Deinit(); |
1549 | 1565 |
1550 { ScopedLock lock(process_wide_mutex_); | 1566 { ScopedLock lock(global_state.Pointer()->mutex); |
1551 thread_data_table_->RemoveAllThreads(this); | 1567 global_state.Pointer()->thread_data_table->RemoveAllThreads(this); |
1552 } | 1568 } |
1553 | 1569 |
1554 if (!IsDefaultIsolate()) { | 1570 if (!IsDefaultIsolate()) { |
1555 delete this; | 1571 delete this; |
1556 } | 1572 } |
1557 | 1573 |
1558 // Restore the previous current isolate. | 1574 // Restore the previous current isolate. |
1559 SetIsolateThreadLocals(saved_isolate, saved_data); | 1575 SetIsolateThreadLocals(saved_isolate, saved_data); |
1560 } | 1576 } |
1561 | 1577 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1594 logger_->TearDown(); | 1610 logger_->TearDown(); |
1595 | 1611 |
1596 // The default isolate is re-initializable due to legacy API. | 1612 // The default isolate is re-initializable due to legacy API. |
1597 state_ = UNINITIALIZED; | 1613 state_ = UNINITIALIZED; |
1598 } | 1614 } |
1599 } | 1615 } |
1600 | 1616 |
1601 | 1617 |
1602 void Isolate::SetIsolateThreadLocals(Isolate* isolate, | 1618 void Isolate::SetIsolateThreadLocals(Isolate* isolate, |
1603 PerIsolateThreadData* data) { | 1619 PerIsolateThreadData* data) { |
1604 Thread::SetThreadLocal(isolate_key_, isolate); | 1620 const GlobalState& global = global_state.Get(); |
1605 Thread::SetThreadLocal(per_isolate_thread_data_key_, data); | 1621 Thread::SetThreadLocal(global.isolate_key, isolate); |
| 1622 Thread::SetThreadLocal(global.per_isolate_thread_data_key, data); |
1606 } | 1623 } |
1607 | 1624 |
1608 | 1625 |
1609 Isolate::~Isolate() { | 1626 Isolate::~Isolate() { |
1610 TRACE_ISOLATE(destructor); | 1627 TRACE_ISOLATE(destructor); |
1611 | 1628 |
1612 // Has to be called while counters_ are still alive. | 1629 // Has to be called while counters_ are still alive. |
1613 zone_.DeleteKeptSegment(); | 1630 zone_.DeleteKeptSegment(); |
1614 | 1631 |
1615 delete[] assembler_spare_buffer_; | 1632 delete[] assembler_spare_buffer_; |
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1952 | 1969 |
1953 #ifdef DEBUG | 1970 #ifdef DEBUG |
1954 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \ | 1971 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \ |
1955 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_); | 1972 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_); |
1956 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET) | 1973 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET) |
1957 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET) | 1974 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET) |
1958 #undef ISOLATE_FIELD_OFFSET | 1975 #undef ISOLATE_FIELD_OFFSET |
1959 #endif | 1976 #endif |
1960 | 1977 |
1961 } } // namespace v8::internal | 1978 } } // namespace v8::internal |
OLD | NEW |