diff options
Diffstat (limited to 'chromium/gin/v8_initializer.cc')
-rw-r--r-- | chromium/gin/v8_initializer.cc | 241 |
1 files changed, 104 insertions, 137 deletions
diff --git a/chromium/gin/v8_initializer.cc b/chromium/gin/v8_initializer.cc index 6e7261ff6e7..3d8d99cc584 100644 --- a/chromium/gin/v8_initializer.cc +++ b/chromium/gin/v8_initializer.cc @@ -10,6 +10,7 @@ #include <memory> #include "base/allocator/partition_allocator/page_allocator.h" +#include "base/allocator/partition_allocator/partition_address_space.h" #include "base/check.h" #include "base/debug/alias.h" #include "base/debug/crash_logging.h" @@ -28,9 +29,10 @@ #include "base/system/sys_info.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" -#include "base/win/windows_version.h" #include "build/build_config.h" #include "gin/gin_features.h" +#include "v8/include/v8-initialization.h" +#include "v8/include/v8-snapshot.h" #if defined(V8_USE_EXTERNAL_STARTUP_DATA) #if defined(OS_ANDROID) @@ -177,8 +179,7 @@ base::File OpenV8File(const char* file_name, result = OpenV8FileResult::FAILED_OTHER; break; } else if (kMaxOpenAttempts - 1 != attempt) { - base::PlatformThread::Sleep( - base::TimeDelta::FromMilliseconds(kOpenRetryDelayMillis)); + base::PlatformThread::Sleep(base::Milliseconds(kOpenRetryDelayMillis)); } } #endif // defined(OS_ANDROID) @@ -207,48 +208,6 @@ void SetV8FlagsFormatted(const char* format, ...) { v8::V8::SetFlagsFromString(buffer, length - 1); } -void RunArrayBufferCageReservationExperiment() { - // TODO(1218005) remove this function and windows_version.h include once the - // experiment has ended. -#if defined(ARCH_CPU_64_BITS) - constexpr size_t kGigaBytes = 1024 * 1024 * 1024; - constexpr size_t kTeraBytes = 1024 * kGigaBytes; - - constexpr size_t kCageMaxSize = 1 * kTeraBytes; - constexpr size_t kCageMinSize = 8 * kGigaBytes; - -#if defined(OS_WIN) - // Windows prior to Win10 (or possibly Win8/8.1) appears to create page table - // entries when reserving virtual memory, causing unacceptably high memory - // consumption (e.g. ~2GB when reserving 1TB). As such, the experiment is - // only enabled on Win10. - if (base::win::GetVersion() < base::win::Version::WIN10) { - return; - } -#endif - - void* reservation = nullptr; - size_t current_size = kCageMaxSize; - while (!reservation && current_size >= kCageMinSize) { - // The cage reservation will need to be 4GB aligned. - reservation = base::AllocPages(nullptr, current_size, 4 * kGigaBytes, - base::PageInaccessible, base::PageTag::kV8); - if (!reservation) { - current_size /= 2; - } - } - - int result = current_size / kGigaBytes; - if (reservation) { - base::FreePages(reservation, current_size); - } else { - result = 0; - } - - base::UmaHistogramSparse("V8.MaxArrayBufferCageReservationSize", result); -#endif -} - template <size_t N, size_t M> void SetV8FlagsIfOverridden(const base::Feature& feature, const char (&enabling_flag)[N], @@ -272,94 +231,81 @@ void V8Initializer::Initialize(IsolateHolder::ScriptMode mode) { if (v8_is_initialized) return; - if (base::FeatureList::IsEnabled( - features::kV8ArrayBufferCageReservationExperiment)) { - RunArrayBufferCageReservationExperiment(); - } - v8::V8::InitializePlatform(V8Platform::Get()); - if (!base::FeatureList::IsEnabled(features::kV8OptimizeJavascript)) { - // We avoid explicitly passing --opt if kV8OptimizeJavascript is enabled - // since it is the default, and doing so would override flags passed - // explicitly, e.g., via --js-flags=--no-opt. - SetV8Flags("--no-opt"); - } - - if (!base::FeatureList::IsEnabled(features::kV8FlushBytecode)) { - SetV8Flags("--no-flush-bytecode"); - } - - if (base::FeatureList::IsEnabled(features::kV8OffThreadFinalization)) { - SetV8Flags("--finalize-streaming-on-background"); - } - - if (!base::FeatureList::IsEnabled(features::kV8LazyFeedbackAllocation)) { - SetV8Flags("--no-lazy-feedback-allocation"); - } - - if (base::FeatureList::IsEnabled(features::kV8ConcurrentInlining)) { - SetV8Flags("--concurrent_inlining"); - } - - if (base::FeatureList::IsEnabled(features::kV8PerContextMarkingWorklist)) { - SetV8Flags("--stress-per-context-marking-worklist"); - } - - if (base::FeatureList::IsEnabled(features::kV8FlushEmbeddedBlobICache)) { - SetV8Flags("--experimental-flush-embedded-blob-icache"); - } - - if (base::FeatureList::IsEnabled(features::kV8ReduceConcurrentMarkingTasks)) { - SetV8Flags("--gc-experiment-reduce-concurrent-marking-tasks"); - } - - if (base::FeatureList::IsEnabled(features::kV8NoReclaimUnmodifiedWrappers)) { - SetV8Flags("--no-reclaim-unmodified-wrappers"); - } - - if (!base::FeatureList::IsEnabled(features::kV8LocalHeaps)) { - // The --local-heaps flag is enabled by default, so we need to explicitly - // disable it if kV8LocalHeaps is disabled. - // Also disable TurboFan's direct access if local heaps are not enabled. - SetV8Flags("--no-local-heaps --no-turbo-direct-heap-access"); - } - - if (!base::FeatureList::IsEnabled(features::kV8TurboDirectHeapAccess)) { - // The --turbo-direct-heap-access flag is enabled by default, so we need to - // explicitly disable it if kV8TurboDirectHeapAccess is disabled. - SetV8Flags("--no-turbo-direct-heap-access"); - } - - if (!base::FeatureList::IsEnabled(features::kV8ExperimentalRegexpEngine)) { - // The --enable-experimental-regexp-engine-on-excessive-backtracks flag is - // enabled by default, so we need to explicitly disable it if - // kV8ExperimentalRegexpEngine is disabled. - SetV8Flags( - "--no-enable-experimental-regexp-engine-on-excessive-backtracks"); - } - - if (base::FeatureList::IsEnabled(features::kV8TurboFastApiCalls)) { - SetV8Flags("--turbo-fast-api-calls"); - } - - if (base::FeatureList::IsEnabled(features::kV8Turboprop)) { - SetV8Flags("--turboprop"); +#if defined(V8_VIRTUAL_MEMORY_CAGE) + static_assert(ARCH_CPU_64_BITS, + "V8 virtual memory cage can only work in 64-bit builds"); + // For now, creating the virtual memory cage is optional, and we only do it + // if the correpsonding feature is enabled. In the future, it will be + // mandatory when compiling with V8_VIRTUAL_MEMORY_CAGE. + bool v8_cage_is_initialized = false; + if (base::FeatureList::IsEnabled(features::kV8VirtualMemoryCage)) { + v8_cage_is_initialized = v8::V8::InitializeVirtualMemoryCage(); + + // Record the size of the virtual memory cage, in GB. The size will always + // be a power of two, so we use a sparse histogram to capture it. + // If the initialization failed, this API will return zero. + // The main reason for capturing this histogram here instead of having V8 + // do it is that there are no Isolates available yet, which are required + // for recording histograms in V8. + size_t size = v8::V8::GetVirtualMemoryCageSizeInBytes(); + int sizeInGB = size >> 30; + DCHECK(base::bits::IsPowerOfTwo(size)); + DCHECK(size == 0 || sizeInGB > 0); + base::UmaHistogramSparse("V8.VirtualMemoryCageSizeGB", sizeInGB); } +#endif + // We assume that all feature flag defaults correspond to the default + // values of the coresponding V8 flags. + // TODO(cbruni): Fix flag priorities to let --js-flags override feature + // flags. + SetV8FlagsIfOverridden(features::kV8OptimizeJavascript, "--opt", "--no-opt"); + SetV8FlagsIfOverridden(features::kV8FlushBytecode, "--flush-bytecode", + "--no-flush-bytecode"); + SetV8FlagsIfOverridden(features::kV8FlushBaselineCode, + "--flush-baseline-code", "--no-flush-baseline-code"); + SetV8FlagsIfOverridden(features::kV8OffThreadFinalization, + "--finalize-streaming-on-background", + "--no-finalize-streaming-on-background"); + SetV8FlagsIfOverridden(features::kV8LazyFeedbackAllocation, + "--lazy-feedback-allocation", + "--no-lazy-feedback-allocation"); + SetV8FlagsIfOverridden(features::kV8ConcurrentInlining, + "--concurrent_inlining", "--no-concurrent_inlining"); + SetV8FlagsIfOverridden(features::kV8PerContextMarkingWorklist, + "--stress-per-context-marking-worklist", + "--no-stress-per-context-marking-worklist"); + SetV8FlagsIfOverridden(features::kV8FlushEmbeddedBlobICache, + "--experimental-flush-embedded-blob-icache", + "--no-experimental-flush-embedded-blob-icache"); + SetV8FlagsIfOverridden(features::kV8ReduceConcurrentMarkingTasks, + "--gc-experiment-reduce-concurrent-marking-tasks", + "--no-gc-experiment-reduce-concurrent-marking-tasks"); + SetV8FlagsIfOverridden(features::kV8NoReclaimUnmodifiedWrappers, + "--no-reclaim-unmodified-wrappers", + "--reclaim-unmodified-wrappers"); + SetV8FlagsIfOverridden( + features::kV8ExperimentalRegexpEngine, + "--enable-experimental-regexp-engine-on-excessive-backtracks", + "--no-enable-experimental-regexp-engine-on-excessive-backtracks"); + SetV8FlagsIfOverridden(features::kV8TurboFastApiCalls, + "--turbo-fast-api-calls", "--no-turbo-fast-api-calls"); + SetV8FlagsIfOverridden(features::kV8Turboprop, "--turboprop", + "--no-turboprop"); SetV8FlagsIfOverridden(features::kV8Sparkplug, "--sparkplug", "--no-sparkplug"); - - if (base::FeatureList::IsEnabled( - features::kV8SparkplugNeedsShortBuiltinCalls)) { - SetV8Flags("--sparkplug-needs-short-builtins"); - } - - if (base::FeatureList::IsEnabled(features::kV8UntrustedCodeMitigations)) { - SetV8Flags("--untrusted-code-mitigations"); - } else { - SetV8Flags("--no-untrusted-code-mitigations"); - } + SetV8FlagsIfOverridden(features::kV8SparkplugNeedsShortBuiltinCalls, + "--sparkplug-needs-short-builtins", + "--no-sparkplug-needs-short-builtins"); + SetV8FlagsIfOverridden(features::kV8ShortBuiltinCalls, + "--short-builtin-calls", "--no-short-builtin-calls"); + SetV8FlagsIfOverridden(features::kV8CodeMemoryWriteProtection, + "--write-protect-code-memory", + "--no-write-protect-code-memory"); + SetV8FlagsIfOverridden(features::kV8SlowHistograms, "--slow-histograms", + "--no-slow-histograms"); if (base::FeatureList::IsEnabled(features::kV8ScriptAblation)) { if (int delay = features::kV8ScriptDelayMs.Get()) { @@ -373,18 +319,20 @@ void V8Initializer::Initialize(IsolateHolder::ScriptMode mode) { } } - if (!base::FeatureList::IsEnabled(features::kV8ShortBuiltinCalls)) { - // The --short-builtin-calls flag is enabled by default on x64 and arm64 - // desktop configurations, so we need to explicitly disable it if - // kV8ShortBuiltinCalls is disabled. - // On other configurations it's not supported, so we don't try to enable - // it if the feature flag is on. - SetV8Flags("--no-short-builtin-calls"); + // Make sure aliases of kV8SlowHistograms only enable the feature to + // avoid contradicting settings between multiple finch experiments. + bool any_slow_histograms_alias = + base::FeatureList::IsEnabled(features::kV8SlowHistogramsSparkplug) | + base::FeatureList::IsEnabled( + features::kV8SlowHistogramsSparkplugAndroid) | + base::FeatureList::IsEnabled(features::kV8SlowHistogramsScriptAblation); + if (any_slow_histograms_alias) { + SetV8Flags("--slow-histograms"); + } else { + SetV8FlagsIfOverridden(features::kV8SlowHistograms, "--slow-histograms", + "--no-slow-histograms"); } - SetV8FlagsIfOverridden(features::kV8SlowHistograms, "--slow-histograms", - "--no-slow-histograms"); - if (IsolateHolder::kStrictMode == mode) { SetV8Flags("--use_strict"); } @@ -401,6 +349,25 @@ void V8Initializer::Initialize(IsolateHolder::ScriptMode mode) { v8::V8::Initialize(); v8_is_initialized = true; + +#if defined(V8_VIRTUAL_MEMORY_CAGE) + if (v8_cage_is_initialized) { + // When the virtual memory cage is enabled, ArrayBuffers must be located + // inside the cage. To achieve that, PA's ConfigurablePool is created inside + // the cage and Blink will create the ArrayBuffer partition inside that + // Pool if it is enabled. + v8::PageAllocator* cage_page_allocator = + v8::V8::GetVirtualMemoryCagePageAllocator(); + size_t pool_size = base::internal::PartitionAddressSpace:: + ConfigurablePoolReservationSize(); + void* pool_base = cage_page_allocator->AllocatePages( + nullptr, pool_size, pool_size, v8::PageAllocator::kNoAccess); + // The V8 cage is guaranteed to be large enough to host the Pool. + CHECK(pool_base); + base::internal::PartitionAddressSpace::InitConfigurablePool(pool_base, + pool_size); + } +#endif } // static |