OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/proxy/proxy_resolver_v8.h" | 5 #include "net/proxy/proxy_resolver_v8.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cstdio> | 8 #include <cstdio> |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
12 #include "base/debug/leak_annotations.h" | 12 #include "base/debug/leak_annotations.h" |
| 13 #include "base/lazy_instance.h" |
13 #include "base/logging.h" | 14 #include "base/logging.h" |
14 #include "base/strings/string_tokenizer.h" | 15 #include "base/strings/string_tokenizer.h" |
15 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
16 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
17 #include "base/synchronization/lock.h" | 18 #include "base/synchronization/lock.h" |
18 #include "gin/array_buffer.h" | 19 #include "gin/array_buffer.h" |
19 #include "gin/public/isolate_holder.h" | 20 #include "gin/public/isolate_holder.h" |
20 #include "net/base/net_errors.h" | 21 #include "net/base/net_errors.h" |
21 #include "net/base/net_log.h" | 22 #include "net/base/net_log.h" |
22 #include "net/base/net_util.h" | 23 #include "net/base/net_util.h" |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 bool IsPlainHostName(const std::string& hostname_utf8) { | 339 bool IsPlainHostName(const std::string& hostname_utf8) { |
339 if (hostname_utf8.find('.') != std::string::npos) | 340 if (hostname_utf8.find('.') != std::string::npos) |
340 return false; | 341 return false; |
341 | 342 |
342 // IPv6 literals might not contain any periods, however are not considered | 343 // IPv6 literals might not contain any periods, however are not considered |
343 // plain host names. | 344 // plain host names. |
344 IPAddressNumber unused; | 345 IPAddressNumber unused; |
345 return !ParseIPLiteralToNumber(hostname_utf8, &unused); | 346 return !ParseIPLiteralToNumber(hostname_utf8, &unused); |
346 } | 347 } |
347 | 348 |
| 349 // All instances of ProxyResolverV8 share the same v8::Isolate. This isolate is |
| 350 // created lazily the first time it is needed and lives until process shutdown. |
| 351 // This creation might happen from any thread, as ProxyResolverV8 is typically |
| 352 // run in a threadpool. |
| 353 // |
| 354 // TODO(eroman): The lazily created isolate is never freed. Instead it should be |
| 355 // disposed once there are no longer any ProxyResolverV8 referencing it. |
| 356 class SharedIsolateFactory { |
| 357 public: |
| 358 SharedIsolateFactory() : has_initialized_v8_(false) {} |
| 359 |
| 360 // Lazily creates a v8::Isolate, or returns the already created instance. |
| 361 v8::Isolate* GetSharedIsolate() { |
| 362 base::AutoLock l(lock_); |
| 363 |
| 364 if (!holder_) { |
| 365 // Do one-time initialization for V8. |
| 366 if (!has_initialized_v8_) { |
| 367 #ifdef V8_USE_EXTERNAL_STARTUP_DATA |
| 368 gin::IsolateHolder::LoadV8Snapshot(); |
| 369 #endif |
| 370 |
| 371 gin::IsolateHolder::Initialize( |
| 372 gin::IsolateHolder::kNonStrictMode, |
| 373 gin::ArrayBufferAllocator::SharedInstance()); |
| 374 |
| 375 has_initialized_v8_ = true; |
| 376 } |
| 377 |
| 378 holder_.reset(new gin::IsolateHolder); |
| 379 } |
| 380 |
| 381 return holder_->isolate(); |
| 382 } |
| 383 |
| 384 v8::Isolate* GetSharedIsolateWithoutCreating() { |
| 385 base::AutoLock l(lock_); |
| 386 return holder_ ? holder_->isolate() : NULL; |
| 387 } |
| 388 |
| 389 private: |
| 390 base::Lock lock_; |
| 391 scoped_ptr<gin::IsolateHolder> holder_; |
| 392 bool has_initialized_v8_; |
| 393 |
| 394 DISALLOW_COPY_AND_ASSIGN(SharedIsolateFactory); |
| 395 }; |
| 396 |
| 397 base::LazyInstance<SharedIsolateFactory>::Leaky g_isolate_factory = |
| 398 LAZY_INSTANCE_INITIALIZER; |
| 399 |
348 } // namespace | 400 } // namespace |
349 | 401 |
350 // ProxyResolverV8::Context --------------------------------------------------- | 402 // ProxyResolverV8::Context --------------------------------------------------- |
351 | 403 |
352 class ProxyResolverV8::Context { | 404 class ProxyResolverV8::Context { |
353 public: | 405 public: |
354 Context(ProxyResolverV8* parent, v8::Isolate* isolate) | 406 Context(ProxyResolverV8* parent, v8::Isolate* isolate) |
355 : parent_(parent), | 407 : parent_(parent), |
356 isolate_(isolate) { | 408 isolate_(isolate) { |
357 DCHECK(isolate); | 409 DCHECK(isolate); |
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 const scoped_refptr<ProxyResolverScriptData>& script_data, | 834 const scoped_refptr<ProxyResolverScriptData>& script_data, |
783 const CompletionCallback& /*callback*/) { | 835 const CompletionCallback& /*callback*/) { |
784 DCHECK(script_data.get()); | 836 DCHECK(script_data.get()); |
785 DCHECK(js_bindings_); | 837 DCHECK(js_bindings_); |
786 | 838 |
787 context_.reset(); | 839 context_.reset(); |
788 if (script_data->utf16().empty()) | 840 if (script_data->utf16().empty()) |
789 return ERR_PAC_SCRIPT_FAILED; | 841 return ERR_PAC_SCRIPT_FAILED; |
790 | 842 |
791 // Try parsing the PAC script. | 843 // Try parsing the PAC script. |
792 scoped_ptr<Context> context(new Context(this, GetDefaultIsolate())); | 844 scoped_ptr<Context> context( |
| 845 new Context(this, g_isolate_factory.Get().GetSharedIsolate())); |
793 int rv = context->InitV8(script_data); | 846 int rv = context->InitV8(script_data); |
794 if (rv == OK) | 847 if (rv == OK) |
795 context_.reset(context.release()); | 848 context_.reset(context.release()); |
796 return rv; | 849 return rv; |
797 } | 850 } |
798 | 851 |
799 // static | 852 // static |
800 void ProxyResolverV8::EnsureIsolateCreated() { | |
801 if (g_proxy_resolver_isolate_) | |
802 return; | |
803 gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode, | |
804 gin::ArrayBufferAllocator::SharedInstance()); | |
805 g_proxy_resolver_isolate_ = new gin::IsolateHolder; | |
806 ANNOTATE_LEAKING_OBJECT_PTR(g_proxy_resolver_isolate_); | |
807 } | |
808 | |
809 // static | |
810 v8::Isolate* ProxyResolverV8::GetDefaultIsolate() { | |
811 DCHECK(g_proxy_resolver_isolate_) | |
812 << "Must call ProxyResolverV8::EnsureIsolateCreated() first"; | |
813 return g_proxy_resolver_isolate_->isolate(); | |
814 } | |
815 | |
816 gin::IsolateHolder* ProxyResolverV8::g_proxy_resolver_isolate_ = NULL; | |
817 | |
818 // static | |
819 size_t ProxyResolverV8::GetTotalHeapSize() { | 853 size_t ProxyResolverV8::GetTotalHeapSize() { |
820 if (!g_proxy_resolver_isolate_) | 854 v8::Isolate* isolate = |
| 855 g_isolate_factory.Get().GetSharedIsolateWithoutCreating(); |
| 856 if (!isolate) |
821 return 0; | 857 return 0; |
822 | 858 |
823 v8::Locker locked(g_proxy_resolver_isolate_->isolate()); | 859 v8::Locker locked(isolate); |
824 v8::Isolate::Scope isolate_scope(g_proxy_resolver_isolate_->isolate()); | 860 v8::Isolate::Scope isolate_scope(isolate); |
825 v8::HeapStatistics heap_statistics; | 861 v8::HeapStatistics heap_statistics; |
826 g_proxy_resolver_isolate_->isolate()->GetHeapStatistics(&heap_statistics); | 862 isolate->GetHeapStatistics(&heap_statistics); |
827 return heap_statistics.total_heap_size(); | 863 return heap_statistics.total_heap_size(); |
828 } | 864 } |
829 | 865 |
830 // static | 866 // static |
831 size_t ProxyResolverV8::GetUsedHeapSize() { | 867 size_t ProxyResolverV8::GetUsedHeapSize() { |
832 if (!g_proxy_resolver_isolate_) | 868 v8::Isolate* isolate = |
| 869 g_isolate_factory.Get().GetSharedIsolateWithoutCreating(); |
| 870 if (!isolate) |
833 return 0; | 871 return 0; |
834 | 872 |
835 v8::Locker locked(g_proxy_resolver_isolate_->isolate()); | 873 v8::Locker locked(isolate); |
836 v8::Isolate::Scope isolate_scope(g_proxy_resolver_isolate_->isolate()); | 874 v8::Isolate::Scope isolate_scope(isolate); |
837 v8::HeapStatistics heap_statistics; | 875 v8::HeapStatistics heap_statistics; |
838 g_proxy_resolver_isolate_->isolate()->GetHeapStatistics(&heap_statistics); | 876 isolate->GetHeapStatistics(&heap_statistics); |
839 return heap_statistics.used_heap_size(); | 877 return heap_statistics.used_heap_size(); |
840 } | 878 } |
841 | 879 |
842 } // namespace net | 880 } // namespace net |
OLD | NEW |