Revision: 17049
Author: [email protected]
Date: Tue Oct 1 14:26:53 2013 UTC
Log: lazy instantiation of the default isolate
this cl also moves all accesses to the default isolate behind
EnsureDefaultIsolate
[email protected]
BUG=
Review URL: https://codereview.chromium.org/24999002
http://code.google.com/p/v8/source/detail?r=17049
Modified:
/branches/bleeding_edge/src/api.cc
/branches/bleeding_edge/src/isolate.cc
/branches/bleeding_edge/src/isolate.h
/branches/bleeding_edge/src/v8.cc
/branches/bleeding_edge/src/v8.h
=======================================
--- /branches/bleeding_edge/src/api.cc Tue Oct 1 09:56:04 2013 UTC
+++ /branches/bleeding_edge/src/api.cc Tue Oct 1 14:26:53 2013 UTC
@@ -5007,14 +5007,13 @@
bool v8::V8::Dispose() {
- i::Isolate* isolate = i::Isolate::Current();
- if (!ApiCheck(isolate != NULL && isolate->IsDefaultIsolate(),
+ i::Isolate* isolate = i::Isolate::UncheckedCurrent();
+ if (!ApiCheck(isolate == NULL || isolate->IsDefaultIsolate(),
"v8::V8::Dispose()",
"Use v8::Isolate::Dispose() for a non-default isolate.")) {
return false;
}
- i::V8::TearDown();
- return true;
+ return i::V8::TearDown();
}
=======================================
--- /branches/bleeding_edge/src/isolate.cc Tue Oct 1 13:54:53 2013 UTC
+++ /branches/bleeding_edge/src/isolate.cc Tue Oct 1 14:26:53 2013 UTC
@@ -330,7 +330,6 @@
storage->LinkTo(&free_list_);
}
-Isolate* Isolate::default_isolate_ = NULL;
Thread::LocalStorageKey Isolate::isolate_key_;
Thread::LocalStorageKey Isolate::thread_id_key_;
Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
@@ -348,6 +347,7 @@
= kDefaultIsolateUninitialized;
Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL;
Atomic32 Isolate::isolate_counter_ = 0;
+Atomic32 Isolate::living_isolates_ = 0;
Isolate::PerIsolateThreadData*
Isolate::FindOrAllocatePerThreadDataForThisThread() {
@@ -390,61 +390,72 @@
}
-void Isolate::EnsureDefaultIsolate() {
+Isolate* Isolate::EnsureDefaultIsolate() {
+ static Isolate* default_isolate_ = NULL;
LockGuard<Mutex> lock_guard(&process_wide_mutex_);
CHECK(default_isolate_status_ != kDefaultIsolateCrashIfInitialized);
if (default_isolate_ == NULL) {
- isolate_key_ = Thread::CreateThreadLocalKey();
- thread_id_key_ = Thread::CreateThreadLocalKey();
- per_isolate_thread_data_key_ = Thread::CreateThreadLocalKey();
-#ifdef DEBUG
- PerThreadAssertScopeBase::thread_local_key =
Thread::CreateThreadLocalKey();
-#endif // DEBUG
- thread_data_table_ = new Isolate::ThreadDataTable();
- default_isolate_ = new Isolate();
+ default_isolate_ = new Isolate(true);
}
// Can't use SetIsolateThreadLocals(default_isolate_, NULL) here
// because a non-null thread data may be already set.
if (Thread::GetThreadLocal(isolate_key_) == NULL) {
Thread::SetThreadLocal(isolate_key_, default_isolate_);
}
+
+ return default_isolate_;
+}
+
+
+void Isolate::InitializeThreadLocalStorage() {
+ // Double checked locking on existence of thread_data_table_.
+ if (thread_data_table_ != NULL) return;
+ LockGuard<Mutex> lock_guard(&process_wide_mutex_);
+ if (thread_data_table_ != NULL) return;
+ isolate_key_ = Thread::CreateThreadLocalKey();
+ thread_id_key_ = Thread::CreateThreadLocalKey();
+ per_isolate_thread_data_key_ = Thread::CreateThreadLocalKey();
+#ifdef DEBUG
+ PerThreadAssertScopeBase::thread_local_key =
Thread::CreateThreadLocalKey();
+#endif // DEBUG
+ thread_data_table_ = new Isolate::ThreadDataTable();
+ CHECK(thread_data_table_ != NULL);
}
+
+// TODO(dcarney): Remove this with default_isolate_ and Isolate::Current.
struct StaticInitializer {
StaticInitializer() {
- Isolate::EnsureDefaultIsolate();
+ Isolate::InitializeThreadLocalStorage();
}
} static_initializer;
#ifdef ENABLE_DEBUGGER_SUPPORT
Debugger* Isolate::GetDefaultIsolateDebugger() {
- EnsureDefaultIsolate();
- return default_isolate_->debugger();
+ return EnsureDefaultIsolate()->debugger();
}
#endif
StackGuard* Isolate::GetDefaultIsolateStackGuard() {
- EnsureDefaultIsolate();
- return default_isolate_->stack_guard();
+ return EnsureDefaultIsolate()->stack_guard();
}
void Isolate::EnterDefaultIsolate() {
- EnsureDefaultIsolate();
- ASSERT(default_isolate_ != NULL);
+ Isolate* default_isolate = EnsureDefaultIsolate();
+ ASSERT(default_isolate != NULL);
PerIsolateThreadData* data = CurrentPerIsolateThreadData();
// If not yet in default isolate - enter it.
- if (data == NULL || data->isolate() != default_isolate_) {
- default_isolate_->Enter();
+ if (data == NULL || data->isolate() != default_isolate) {
+ default_isolate->Enter();
}
}
v8::Isolate* Isolate::GetDefaultIsolateForLocking() {
- EnsureDefaultIsolate();
- return reinterpret_cast<v8::Isolate*>(default_isolate_);
+ return reinterpret_cast<v8::Isolate*>(EnsureDefaultIsolate());
}
@@ -1734,7 +1745,7 @@
#endif
-Isolate::Isolate()
+Isolate::Isolate(bool is_default_isolate)
: state_(UNINITIALIZED),
embedder_data_(NULL),
entry_stack_(NULL),
@@ -1784,6 +1795,7 @@
has_fatal_error_(false),
use_crankshaft_(true),
initialized_from_snapshot_(false),
+ is_default_isolate_(is_default_isolate),
cpu_profiler_(NULL),
heap_profiler_(NULL),
function_entry_hook_(NULL),
@@ -1791,7 +1803,10 @@
optimizing_compiler_thread_(NULL),
sweeper_thread_(NULL),
stress_deopt_count_(0) {
+ InitializeThreadLocalStorage();
+
id_ = NoBarrier_AtomicIncrement(&isolate_counter_, 1);
+ NoBarrier_AtomicIncrement(&living_isolates_, 1);
TRACE_ISOLATE(constructor);
memset(isolate_addresses_, 0,
@@ -1974,7 +1989,7 @@
// The entry stack must be empty when we get here,
// except for the default isolate, where it can
// still contain up to one entry stack item
- ASSERT(entry_stack_ == NULL || this == default_isolate_);
+ ASSERT(entry_stack_ == NULL || is_default_isolate_);
ASSERT(entry_stack_ == NULL || entry_stack_->previous_item == NULL);
delete entry_stack_;
@@ -2059,6 +2074,8 @@
delete debug_;
debug_ = NULL;
#endif
+
+ NoBarrier_AtomicIncrement(&living_isolates_, -1);
}
=======================================
--- /branches/bleeding_edge/src/isolate.h Tue Oct 1 13:54:53 2013 UTC
+++ /branches/bleeding_edge/src/isolate.h Tue Oct 1 14:26:53 2013 UTC
@@ -491,14 +491,17 @@
static void GlobalTearDown();
- bool IsDefaultIsolate() const { return this == default_isolate_; }
+ bool IsDefaultIsolate() const { return is_default_isolate_; }
static void SetCrashIfDefaultIsolateInitialized();
// Ensures that process-wide resources and the default isolate have been
// allocated. It is only necessary to call this method in rare cases, for
// example if you are using V8 from within the body of a static
initializer.
// Safe to call multiple times.
- static void EnsureDefaultIsolate();
+ static Isolate* EnsureDefaultIsolate();
+
+ // Initialize all thread local variables
+ static void InitializeThreadLocalStorage();
// Find the PerThread for this particular (isolate, thread) combination
// If one does not yet exist, return null.
@@ -1124,8 +1127,12 @@
// Given an address occupied by a live code object, return that object.
Object* FindCodeObject(Address a);
+ static Atomic32 GetLivingIsolates() {
+ return Acquire_Load(&living_isolates_);
+ }
+
private:
- Isolate();
+ explicit Isolate(bool is_default_isolate = false);
friend struct GlobalState;
friend struct InitializeGlobalState;
@@ -1190,11 +1197,11 @@
static Thread::LocalStorageKey per_isolate_thread_data_key_;
static Thread::LocalStorageKey isolate_key_;
static Thread::LocalStorageKey thread_id_key_;
- static Isolate* default_isolate_;
static ThreadDataTable* thread_data_table_;
// A global counter for all generated Isolates, might overflow.
static Atomic32 isolate_counter_;
+ static Atomic32 living_isolates_;
void Deinit();
@@ -1306,6 +1313,9 @@
// True if this isolate was initialized from a snapshot.
bool initialized_from_snapshot_;
+ // True only for the default isolate.
+ bool is_default_isolate_;
+
// Time stamp at initialization.
double time_millis_at_init_;
=======================================
--- /branches/bleeding_edge/src/v8.cc Mon Sep 30 14:06:43 2013 UTC
+++ /branches/bleeding_edge/src/v8.cc Tue Oct 1 14:26:53 2013 UTC
@@ -79,16 +79,24 @@
}
-void V8::TearDown() {
- Isolate* isolate = Isolate::Current();
- ASSERT(isolate->IsDefaultIsolate());
- if (!isolate->IsInitialized()) return;
+bool V8::TearDown() {
+ Isolate* isolate = Isolate::UncheckedCurrent();
+ if (isolate != NULL) {
+ ASSERT(isolate->IsDefaultIsolate());
+ if (isolate->IsInitialized()) isolate->TearDown();
+ delete isolate;
+ }
+
+ // V8 was never initialized, nothing to do.
+ if (Acquire_Load(&init_once) == ONCE_STATE_UNINITIALIZED) return true;
+
+ // TODO(dcarney): Everything below this should be in some sort of
mutex...
+ Atomic32 living_isolates = Isolate::GetLivingIsolates();
- // The isolate has to be torn down before clearing the LOperand
+ // All isolates have to be torn down before clearing the LOperand
// caches so that the optimizing compiler thread (if running)
// doesn't see an inconsistent view of the lithium instructions.
- isolate->TearDown();
- delete isolate;
+ if (living_isolates != 0) return false;
ElementsAccessor::TearDown();
LOperand::TearDownCaches();
@@ -100,6 +108,7 @@
call_completed_callbacks_ = NULL;
Sampler::TearDown();
+ return true;
}
=======================================
--- /branches/bleeding_edge/src/v8.h Tue Sep 10 11:13:55 2013 UTC
+++ /branches/bleeding_edge/src/v8.h Tue Oct 1 14:26:53 2013 UTC
@@ -81,7 +81,7 @@
// initial state is created by reading the deserialized data into an
// empty heap.
static bool Initialize(Deserializer* des);
- static void TearDown();
+ static bool TearDown();
// Report process out of memory. Implementation found in api.cc.
static void FatalProcessOutOfMemory(const char* location,
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.