Index: net/proxy/proxy_resolver_v8.cc |
diff --git a/net/proxy/proxy_resolver_v8.cc b/net/proxy/proxy_resolver_v8.cc |
index 693fbb24837ff84b01f7ffd4bd5018c6e3b77944..2bb858c46ead631ed73d9cdedd77756b9501f0f5 100644 |
--- a/net/proxy/proxy_resolver_v8.cc |
+++ b/net/proxy/proxy_resolver_v8.cc |
@@ -10,6 +10,7 @@ |
#include "base/basictypes.h" |
#include "base/compiler_specific.h" |
#include "base/debug/leak_annotations.h" |
+#include "base/lazy_instance.h" |
#include "base/logging.h" |
#include "base/strings/string_tokenizer.h" |
#include "base/strings/string_util.h" |
@@ -345,6 +346,57 @@ bool IsPlainHostName(const std::string& hostname_utf8) { |
return !ParseIPLiteralToNumber(hostname_utf8, &unused); |
} |
+// All instances of ProxyResolverV8 share the same v8::Isolate. This isolate is |
+// created lazily the first time it is needed and lives until process shutdown. |
+// This creation might happen from any thread, as ProxyResolverV8 is typically |
+// run in a threadpool. |
+// |
+// TODO(eroman): The lazily created isolate is never freed. Instead it should be |
+// disposed once there are no longer any ProxyResolverV8 referencing it. |
+class SharedIsolateFactory { |
+ public: |
+ SharedIsolateFactory() : has_initialized_v8_(false) {} |
+ |
+ // Lazily creates a v8::Isolate, or returns the already created instance. |
+ v8::Isolate* GetSharedIsolate() { |
+ base::AutoLock l(lock_); |
+ |
+ if (!holder_) { |
+ // Do one-time initialization for V8. |
+ if (!has_initialized_v8_) { |
+#ifdef V8_USE_EXTERNAL_STARTUP_DATA |
+ gin::IsolateHolder::LoadV8Snapshot(); |
+#endif |
+ |
+ gin::IsolateHolder::Initialize( |
+ gin::IsolateHolder::kNonStrictMode, |
+ gin::ArrayBufferAllocator::SharedInstance()); |
+ |
+ has_initialized_v8_ = true; |
+ } |
+ |
+ holder_.reset(new gin::IsolateHolder); |
+ } |
+ |
+ return holder_->isolate(); |
+ } |
+ |
+ v8::Isolate* GetSharedIsolateWithoutCreating() { |
+ base::AutoLock l(lock_); |
+ return holder_ ? holder_->isolate() : NULL; |
+ } |
+ |
+ private: |
+ base::Lock lock_; |
+ scoped_ptr<gin::IsolateHolder> holder_; |
+ bool has_initialized_v8_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(SharedIsolateFactory); |
+}; |
+ |
+base::LazyInstance<SharedIsolateFactory>::Leaky g_isolate_factory = |
+ LAZY_INSTANCE_INITIALIZER; |
+ |
} // namespace |
// ProxyResolverV8::Context --------------------------------------------------- |
@@ -789,7 +841,8 @@ int ProxyResolverV8::SetPacScript( |
return ERR_PAC_SCRIPT_FAILED; |
// Try parsing the PAC script. |
- scoped_ptr<Context> context(new Context(this, GetDefaultIsolate())); |
+ scoped_ptr<Context> context( |
+ new Context(this, g_isolate_factory.Get().GetSharedIsolate())); |
int rv = context->InitV8(script_data); |
if (rv == OK) |
context_.reset(context.release()); |
@@ -797,45 +850,30 @@ int ProxyResolverV8::SetPacScript( |
} |
// static |
-void ProxyResolverV8::EnsureIsolateCreated() { |
- if (g_proxy_resolver_isolate_) |
- return; |
- gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode, |
- gin::ArrayBufferAllocator::SharedInstance()); |
- g_proxy_resolver_isolate_ = new gin::IsolateHolder; |
- ANNOTATE_LEAKING_OBJECT_PTR(g_proxy_resolver_isolate_); |
-} |
- |
-// static |
-v8::Isolate* ProxyResolverV8::GetDefaultIsolate() { |
- DCHECK(g_proxy_resolver_isolate_) |
- << "Must call ProxyResolverV8::EnsureIsolateCreated() first"; |
- return g_proxy_resolver_isolate_->isolate(); |
-} |
- |
-gin::IsolateHolder* ProxyResolverV8::g_proxy_resolver_isolate_ = NULL; |
- |
-// static |
size_t ProxyResolverV8::GetTotalHeapSize() { |
- if (!g_proxy_resolver_isolate_) |
+ v8::Isolate* isolate = |
+ g_isolate_factory.Get().GetSharedIsolateWithoutCreating(); |
+ if (!isolate) |
return 0; |
- v8::Locker locked(g_proxy_resolver_isolate_->isolate()); |
- v8::Isolate::Scope isolate_scope(g_proxy_resolver_isolate_->isolate()); |
+ v8::Locker locked(isolate); |
+ v8::Isolate::Scope isolate_scope(isolate); |
v8::HeapStatistics heap_statistics; |
- g_proxy_resolver_isolate_->isolate()->GetHeapStatistics(&heap_statistics); |
+ isolate->GetHeapStatistics(&heap_statistics); |
return heap_statistics.total_heap_size(); |
} |
// static |
size_t ProxyResolverV8::GetUsedHeapSize() { |
- if (!g_proxy_resolver_isolate_) |
+ v8::Isolate* isolate = |
+ g_isolate_factory.Get().GetSharedIsolateWithoutCreating(); |
+ if (!isolate) |
return 0; |
- v8::Locker locked(g_proxy_resolver_isolate_->isolate()); |
- v8::Isolate::Scope isolate_scope(g_proxy_resolver_isolate_->isolate()); |
+ v8::Locker locked(isolate); |
+ v8::Isolate::Scope isolate_scope(isolate); |
v8::HeapStatistics heap_statistics; |
- g_proxy_resolver_isolate_->isolate()->GetHeapStatistics(&heap_statistics); |
+ isolate->GetHeapStatistics(&heap_statistics); |
return heap_statistics.used_heap_size(); |
} |