| 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();
|
| }
|
|
|
|
|