Skip to content

Commit

Permalink
Add V8ArrayBufferCageReservationExperiment
Browse files Browse the repository at this point in the history
When enabled, this experiment will attempt to reserve a huge region of
virtual memory during process startup and record the size of the largest
region that could be reserved into UMA. This data will then be used to
determine whether ArrayBuffer backing stores and WASM memory buffers
can be "caged" inside a large contiguous virtual memory region.

Bug: 1218005
Change-Id: I3a8f9c799d0cd0c3566294e72ac069a6106ec26f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2944939
Commit-Queue: Samuel Groß <saelo@google.com>
Reviewed-by: Ross McIlroy <rmcilroy@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#892083}
  • Loading branch information
Samuel Groß authored and Chromium LUCI CQ committed Jun 14, 2021
1 parent 7ddeb25 commit 4299c68
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 0 deletions.
5 changes: 5 additions & 0 deletions gin/gin_features.cc
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,9 @@ const base::FeatureParam<int> kV8ScriptDelayMs{&kV8ScriptAblation,
const base::FeatureParam<double> kV8ScriptDelayFraction{
&kV8ScriptAblation, "V8ScriptDelayFraction", 0.0};

// Experiment to determine the maximum size of the ArrayBuffer cage.
const base::Feature kV8ArrayBufferCageReservationExperiment{
"V8ArrayBufferCageReservationExperiment",
base::FEATURE_DISABLED_BY_DEFAULT};

} // namespace features
1 change: 1 addition & 0 deletions gin/gin_features.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ GIN_EXPORT extern const base::FeatureParam<int> kV8ScriptDelayMs;
GIN_EXPORT extern const base::FeatureParam<double> kV8ScriptDelayFraction;
GIN_EXPORT extern const base::Feature kV8ShortBuiltinCalls;
GIN_EXPORT extern const base::Feature kV8UntrustedCodeMitigations;
GIN_EXPORT extern const base::Feature kV8ArrayBufferCageReservationExperiment;

} // namespace features

Expand Down
39 changes: 39 additions & 0 deletions gin/v8_initializer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include <memory>

#include "base/allocator/partition_allocator/page_allocator.h"
#include "base/check.h"
#include "base/debug/alias.h"
#include "base/debug/crash_logging.h"
Expand All @@ -17,6 +18,7 @@
#include "base/files/file_path.h"
#include "base/files/memory_mapped_file.h"
#include "base/lazy_instance.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/path_service.h"
Expand Down Expand Up @@ -204,6 +206,38 @@ void SetV8FlagsFormatted(const char* format, ...) {
v8::V8::SetFlagsFromString(buffer, length - 1);
}

void RunArrayBufferCageReservationExperiment() {
// TODO(1218005) remove this function 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 kExaBytes = 1024 * kTeraBytes;

constexpr size_t kCageMaxSize = 1 * kExaBytes;
constexpr size_t kCageMinSize = 8 * kGigaBytes;

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
}

} // namespace

// static
Expand All @@ -212,6 +246,11 @@ 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)) {
Expand Down
17 changes: 17 additions & 0 deletions tools/metrics/histograms/histograms_xml/v8/histograms.xml
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,23 @@ reviews. Googlers can read more about this at go/gwsq-gerrit.
</summary>
</histogram>

<histogram name="V8.MaxArrayBufferCageReservationSize" units="GB"
expires_after="2022-06-30">
<owner>saelo@chromium.org</owner>
<owner>ishell@chromium.org</owner>
<summary>
Largest possible size of the virtual memory region for an ArrayBuffer cage.

Measured and reported at process startup, right before initializing V8, by
attempting to reserve memory regions with decreasing size until the
reservation succeeds, then immediately freeing it again.

This experiment is part of the V8 Heap Sandbox and the V8 ArrayBuffer Caging
proposal. Its goal is to estimate the maximum possible size of an
ArrayBuffer cage region.
</summary>
</histogram>

<histogram name="V8.MemoryExternalFragmentationCodeSpace" units="%"
expires_after="2020-03-01">
<owner>hpayer@chromium.org</owner>
Expand Down

0 comments on commit 4299c68

Please sign in to comment.