| 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" | |
| 42 #include "lithium-allocator.h" | 41 #include "lithium-allocator.h" |
| 43 #include "log.h" | 42 #include "log.h" |
| 44 #include "messages.h" | 43 #include "messages.h" |
| 45 #include "platform.h" | |
| 46 #include "regexp-stack.h" | 44 #include "regexp-stack.h" |
| 47 #include "runtime-profiler.h" | 45 #include "runtime-profiler.h" |
| 48 #include "scopeinfo.h" | 46 #include "scopeinfo.h" |
| 49 #include "serialize.h" | 47 #include "serialize.h" |
| 50 #include "simulator.h" | 48 #include "simulator.h" |
| 51 #include "spaces.h" | 49 #include "spaces.h" |
| 52 #include "stub-cache.h" | 50 #include "stub-cache.h" |
| 53 #include "version.h" | 51 #include "version.h" |
| 54 #include "vm-state-inl.h" | 52 #include "vm-state-inl.h" |
| 55 | 53 |
| 56 | 54 |
| 57 namespace v8 { | 55 namespace v8 { |
| 58 namespace internal { | 56 namespace internal { |
| 59 | 57 |
| 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 | |
| 85 Atomic32 ThreadId::highest_thread_id_ = 0; | 58 Atomic32 ThreadId::highest_thread_id_ = 0; |
| 86 | 59 |
| 87 int ThreadId::AllocateThreadId() { | 60 int ThreadId::AllocateThreadId() { |
| 88 int new_id = NoBarrier_AtomicIncrement(&highest_thread_id_, 1); | 61 int new_id = NoBarrier_AtomicIncrement(&highest_thread_id_, 1); |
| 89 return new_id; | 62 return new_id; |
| 90 } | 63 } |
| 91 | 64 |
| 92 | 65 |
| 93 int ThreadId::GetCurrentThreadId() { | 66 int ThreadId::GetCurrentThreadId() { |
| 94 const GlobalState& global = global_state.Get(); | 67 int thread_id = Thread::GetThreadLocalInt(Isolate::thread_id_key_); |
| 95 int thread_id = Thread::GetThreadLocalInt(global.thread_id_key); | |
| 96 if (thread_id == 0) { | 68 if (thread_id == 0) { |
| 97 thread_id = AllocateThreadId(); | 69 thread_id = AllocateThreadId(); |
| 98 Thread::SetThreadLocalInt(global.thread_id_key, thread_id); | 70 Thread::SetThreadLocalInt(Isolate::thread_id_key_, thread_id); |
| 99 } | 71 } |
| 100 return thread_id; | 72 return thread_id; |
| 101 } | 73 } |
| 102 | 74 |
| 103 | 75 |
| 104 ThreadLocalTop::ThreadLocalTop() { | 76 ThreadLocalTop::ThreadLocalTop() { |
| 105 InitializeInternal(); | 77 InitializeInternal(); |
| 106 // This flag may be set using v8::V8::IgnoreOutOfMemoryException() | 78 // This flag may be set using v8::V8::IgnoreOutOfMemoryException() |
| 107 // before an isolate is initialized. The initialize methods below do | 79 // before an isolate is initialized. The initialize methods below do |
| 108 // not touch it to preserve its value. | 80 // not touch it to preserve its value. |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 FreeStoreAllocationPolicy::Delete(p); | 304 FreeStoreAllocationPolicy::Delete(p); |
| 333 return; | 305 return; |
| 334 } | 306 } |
| 335 PreallocatedStorage* storage = reinterpret_cast<PreallocatedStorage*>(p) - 1; | 307 PreallocatedStorage* storage = reinterpret_cast<PreallocatedStorage*>(p) - 1; |
| 336 ASSERT(storage->next_->previous_ == storage); | 308 ASSERT(storage->next_->previous_ == storage); |
| 337 ASSERT(storage->previous_->next_ == storage); | 309 ASSERT(storage->previous_->next_ == storage); |
| 338 storage->Unlink(); | 310 storage->Unlink(); |
| 339 storage->LinkTo(&free_list_); | 311 storage->LinkTo(&free_list_); |
| 340 } | 312 } |
| 341 | 313 |
| 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 |
| 342 Isolate::PerIsolateThreadData* Isolate::AllocatePerIsolateThreadData( | 343 Isolate::PerIsolateThreadData* Isolate::AllocatePerIsolateThreadData( |
| 343 ThreadId thread_id) { | 344 ThreadId thread_id) { |
| 344 ASSERT(!thread_id.Equals(ThreadId::Invalid())); | 345 ASSERT(!thread_id.Equals(ThreadId::Invalid())); |
| 345 PerIsolateThreadData* per_thread = new PerIsolateThreadData(this, thread_id); | 346 PerIsolateThreadData* per_thread = new PerIsolateThreadData(this, thread_id); |
| 346 { | 347 { |
| 347 GlobalState* const global = global_state.Pointer(); | 348 ScopedLock lock(process_wide_mutex_); |
| 348 ScopedLock lock(global->mutex); | 349 ASSERT(thread_data_table_->Lookup(this, thread_id) == NULL); |
| 349 ASSERT(global->thread_data_table->Lookup(this, thread_id) == NULL); | 350 thread_data_table_->Insert(per_thread); |
| 350 global->thread_data_table->Insert(per_thread); | 351 ASSERT(thread_data_table_->Lookup(this, thread_id) == 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 GlobalState* const global = global_state.Pointer(); | 362 ScopedLock lock(process_wide_mutex_); |
| 363 ScopedLock lock(global->mutex); | 363 per_thread = thread_data_table_->Lookup(this, thread_id); |
| 364 per_thread = global->thread_data_table->Lookup(this, thread_id); | |
| 365 if (per_thread == NULL) { | 364 if (per_thread == NULL) { |
| 366 per_thread = AllocatePerIsolateThreadData(thread_id); | 365 per_thread = AllocatePerIsolateThreadData(thread_id); |
| 367 } | 366 } |
| 368 } | 367 } |
| 369 return per_thread; | 368 return per_thread; |
| 370 } | 369 } |
| 371 | 370 |
| 372 | 371 |
| 373 Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThisThread() { | 372 Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThisThread() { |
| 374 ThreadId thread_id = ThreadId::Current(); | 373 ThreadId thread_id = ThreadId::Current(); |
| 375 PerIsolateThreadData* per_thread = NULL; | 374 PerIsolateThreadData* per_thread = NULL; |
| 376 { | 375 { |
| 377 GlobalState* const global = global_state.Pointer(); | 376 ScopedLock lock(process_wide_mutex_); |
| 378 ScopedLock lock(global->mutex); | 377 per_thread = thread_data_table_->Lookup(this, thread_id); |
| 379 per_thread = global->thread_data_table->Lookup(this, thread_id); | |
| 380 } | 378 } |
| 381 return per_thread; | 379 return per_thread; |
| 382 } | 380 } |
| 383 | 381 |
| 384 | 382 |
| 385 bool Isolate::IsDefaultIsolate() const { | |
| 386 return this == global_state.Get().default_isolate; | |
| 387 } | |
| 388 | |
| 389 | |
| 390 void Isolate::EnsureDefaultIsolate() { | 383 void Isolate::EnsureDefaultIsolate() { |
| 391 GlobalState* const global = global_state.Pointer(); | 384 ScopedLock lock(process_wide_mutex_); |
| 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 // because a non-null thread data may be already set. | 393 // becase a non-null thread data may be already set. |
| 394 if (Thread::GetThreadLocal(global->isolate_key) == NULL) { | 394 if (Thread::GetThreadLocal(isolate_key_) == NULL) { |
| 395 Thread::SetThreadLocal(global->isolate_key, global->default_isolate); | 395 Thread::SetThreadLocal(isolate_key_, 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 global_state.Pointer()->default_isolate->debugger(); | 403 return 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 global_state.Pointer()->default_isolate->stack_guard(); | 410 return 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; | |
| 426 } | 411 } |
| 427 | 412 |
| 428 | 413 |
| 429 void Isolate::EnterDefaultIsolate() { | 414 void Isolate::EnterDefaultIsolate() { |
| 430 EnsureDefaultIsolate(); | 415 EnsureDefaultIsolate(); |
| 431 Isolate* const default_isolate = global_state.Pointer()->default_isolate; | 416 ASSERT(default_isolate_ != NULL); |
| 432 ASSERT(default_isolate != NULL); | |
| 433 | 417 |
| 434 PerIsolateThreadData* data = CurrentPerIsolateThreadData(); | 418 PerIsolateThreadData* data = CurrentPerIsolateThreadData(); |
| 435 // If not yet in default isolate - enter it. | 419 // If not yet in default isolate - enter it. |
| 436 if (data == NULL || data->isolate() != default_isolate) { | 420 if (data == NULL || data->isolate() != default_isolate_) { |
| 437 default_isolate->Enter(); | 421 default_isolate_->Enter(); |
| 438 } | 422 } |
| 439 } | 423 } |
| 440 | 424 |
| 441 | 425 |
| 442 Isolate* Isolate::GetDefaultIsolateForLocking() { | 426 Isolate* Isolate::GetDefaultIsolateForLocking() { |
| 443 EnsureDefaultIsolate(); | 427 EnsureDefaultIsolate(); |
| 444 return global_state.Pointer()->default_isolate; | 428 return default_isolate_; |
| 445 } | 429 } |
| 446 | 430 |
| 447 | 431 |
| 448 Address Isolate::get_address_from_id(Isolate::AddressId id) { | 432 Address Isolate::get_address_from_id(Isolate::AddressId id) { |
| 449 return isolate_addresses_[id]; | 433 return isolate_addresses_[id]; |
| 450 } | 434 } |
| 451 | 435 |
| 452 | 436 |
| 453 char* Isolate::Iterate(ObjectVisitor* v, char* thread_storage) { | 437 char* Isolate::Iterate(ObjectVisitor* v, char* thread_storage) { |
| 454 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage); | 438 ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage); |
| (...skipping 1102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1557 // Temporarily set this isolate as current so that various parts of | 1541 // Temporarily set this isolate as current so that various parts of |
| 1558 // the isolate can access it in their destructors without having a | 1542 // the isolate can access it in their destructors without having a |
| 1559 // direct pointer. We don't use Enter/Exit here to avoid | 1543 // direct pointer. We don't use Enter/Exit here to avoid |
| 1560 // initializing the thread data. | 1544 // initializing the thread data. |
| 1561 PerIsolateThreadData* saved_data = CurrentPerIsolateThreadData(); | 1545 PerIsolateThreadData* saved_data = CurrentPerIsolateThreadData(); |
| 1562 Isolate* saved_isolate = UncheckedCurrent(); | 1546 Isolate* saved_isolate = UncheckedCurrent(); |
| 1563 SetIsolateThreadLocals(this, NULL); | 1547 SetIsolateThreadLocals(this, NULL); |
| 1564 | 1548 |
| 1565 Deinit(); | 1549 Deinit(); |
| 1566 | 1550 |
| 1567 { ScopedLock lock(global_state.Pointer()->mutex); | 1551 { ScopedLock lock(process_wide_mutex_); |
| 1568 global_state.Pointer()->thread_data_table->RemoveAllThreads(this); | 1552 thread_data_table_->RemoveAllThreads(this); |
| 1569 } | 1553 } |
| 1570 | 1554 |
| 1571 if (!IsDefaultIsolate()) { | 1555 if (!IsDefaultIsolate()) { |
| 1572 delete this; | 1556 delete this; |
| 1573 } | 1557 } |
| 1574 | 1558 |
| 1575 // Restore the previous current isolate. | 1559 // Restore the previous current isolate. |
| 1576 SetIsolateThreadLocals(saved_isolate, saved_data); | 1560 SetIsolateThreadLocals(saved_isolate, saved_data); |
| 1577 } | 1561 } |
| 1578 | 1562 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1611 logger_->TearDown(); | 1595 logger_->TearDown(); |
| 1612 | 1596 |
| 1613 // The default isolate is re-initializable due to legacy API. | 1597 // The default isolate is re-initializable due to legacy API. |
| 1614 state_ = UNINITIALIZED; | 1598 state_ = UNINITIALIZED; |
| 1615 } | 1599 } |
| 1616 } | 1600 } |
| 1617 | 1601 |
| 1618 | 1602 |
| 1619 void Isolate::SetIsolateThreadLocals(Isolate* isolate, | 1603 void Isolate::SetIsolateThreadLocals(Isolate* isolate, |
| 1620 PerIsolateThreadData* data) { | 1604 PerIsolateThreadData* data) { |
| 1621 const GlobalState& global = global_state.Get(); | 1605 Thread::SetThreadLocal(isolate_key_, isolate); |
| 1622 Thread::SetThreadLocal(global.isolate_key, isolate); | 1606 Thread::SetThreadLocal(per_isolate_thread_data_key_, data); |
| 1623 Thread::SetThreadLocal(global.per_isolate_thread_data_key, data); | |
| 1624 } | 1607 } |
| 1625 | 1608 |
| 1626 | 1609 |
| 1627 Isolate::~Isolate() { | 1610 Isolate::~Isolate() { |
| 1628 TRACE_ISOLATE(destructor); | 1611 TRACE_ISOLATE(destructor); |
| 1629 | 1612 |
| 1630 // Has to be called while counters_ are still alive. | 1613 // Has to be called while counters_ are still alive. |
| 1631 zone_.DeleteKeptSegment(); | 1614 zone_.DeleteKeptSegment(); |
| 1632 | 1615 |
| 1633 delete[] assembler_spare_buffer_; | 1616 delete[] assembler_spare_buffer_; |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1973 | 1956 |
| 1974 #ifdef DEBUG | 1957 #ifdef DEBUG |
| 1975 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \ | 1958 #define ISOLATE_FIELD_OFFSET(type, name, ignored) \ |
| 1976 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_); | 1959 const intptr_t Isolate::name##_debug_offset_ = OFFSET_OF(Isolate, name##_); |
| 1977 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET) | 1960 ISOLATE_INIT_LIST(ISOLATE_FIELD_OFFSET) |
| 1978 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET) | 1961 ISOLATE_INIT_ARRAY_LIST(ISOLATE_FIELD_OFFSET) |
| 1979 #undef ISOLATE_FIELD_OFFSET | 1962 #undef ISOLATE_FIELD_OFFSET |
| 1980 #endif | 1963 #endif |
| 1981 | 1964 |
| 1982 } } // namespace v8::internal | 1965 } } // namespace v8::internal |
| OLD | NEW |