diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-02-02 12:21:57 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-02-12 08:13:00 +0000 |
commit | 606d85f2a5386472314d39923da28c70c60dc8e7 (patch) | |
tree | a8f4d7bf997f349f45605e6058259fba0630e4d7 /chromium/gin | |
parent | 5786336dda477d04fb98483dca1a5426eebde2d7 (diff) | |
download | qtwebengine-chromium-606d85f2a5386472314d39923da28c70c60dc8e7.tar.gz |
BASELINE: Update Chromium to 96.0.4664.181
Change-Id: I762cd1da89d73aa6313b4a753fe126c34833f046
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/gin')
47 files changed, 648 insertions, 297 deletions
diff --git a/chromium/gin/BUILD.gn b/chromium/gin/BUILD.gn index c6059fdb0e0..18af92cf184 100644 --- a/chromium/gin/BUILD.gn +++ b/chromium/gin/BUILD.gn @@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//base/allocator/allocator.gni") import("//testing/test.gni") import("//tools/v8_context_snapshot/v8_context_snapshot.gni") import("//v8/gni/v8.gni") @@ -71,6 +72,13 @@ component("gin") { "wrapper_info.cc", ] + if (use_partition_alloc) { + sources += [ + "v8_platform_page_allocator.cc", + "v8_platform_page_allocator.h", + ] + } + if (v8_use_external_startup_data) { data = [ "$root_out_dir/snapshot_blob.bin" ] } @@ -151,6 +159,13 @@ test("gin_unittests") { "//v8", ] + if (use_partition_alloc) { + sources += [ "v8_platform_page_allocator_unittest.cc" ] + if (target_cpu == "arm64" && (is_linux || is_android)) { + deps += [ "//base:arm_bti_testfunctions" ] + } + } + configs += [ "//tools/v8_context_snapshot:use_v8_context_snapshot", "//v8:external_startup_data", @@ -169,11 +184,7 @@ test("gin_unittests") { # On Android, the APK must bundle the startup data. if (is_android) { - if (use_v8_context_snapshot) { - deps += [ "//tools/v8_context_snapshot:v8_context_snapshot_assets" ] - } else { - deps += [ "//v8:v8_external_startup_data_assets" ] - } + deps += [ "//v8:v8_external_startup_data_assets" ] } if (is_fuchsia) { diff --git a/chromium/gin/arguments.cc b/chromium/gin/arguments.cc index 07335c7cfe2..3a2ba9b160b 100644 --- a/chromium/gin/arguments.cc +++ b/chromium/gin/arguments.cc @@ -6,6 +6,10 @@ #include "base/strings/stringprintf.h" #include "gin/converter.h" +#include "v8/include/v8-exception.h" +#include "v8/include/v8-isolate.h" +#include "v8/include/v8-object.h" +#include "v8/include/v8-template.h" namespace gin { diff --git a/chromium/gin/arguments_unittest.cc b/chromium/gin/arguments_unittest.cc index 144e9af03cc..77062c93a91 100644 --- a/chromium/gin/arguments_unittest.cc +++ b/chromium/gin/arguments_unittest.cc @@ -9,7 +9,13 @@ #include "gin/object_template_builder.h" #include "gin/public/isolate_holder.h" #include "gin/test/v8_test.h" -#include "v8/include/v8.h" +#include "v8/include/v8-context.h" +#include "v8/include/v8-forward.h" +#include "v8/include/v8-function.h" +#include "v8/include/v8-object.h" +#include "v8/include/v8-primitive.h" +#include "v8/include/v8-script.h" +#include "v8/include/v8-template.h" namespace gin { diff --git a/chromium/gin/array_buffer.h b/chromium/gin/array_buffer.h index aef43319737..8dfcf65b5b5 100644 --- a/chromium/gin/array_buffer.h +++ b/chromium/gin/array_buffer.h @@ -12,7 +12,8 @@ #include "base/memory/ref_counted.h" #include "gin/converter.h" #include "gin/gin_export.h" -#include "v8/include/v8.h" +#include "v8/include/v8-array-buffer.h" +#include "v8/include/v8-forward.h" namespace gin { diff --git a/chromium/gin/converter.cc b/chromium/gin/converter.cc index dd7bf46f85d..f8695228a4d 100644 --- a/chromium/gin/converter.cc +++ b/chromium/gin/converter.cc @@ -7,7 +7,14 @@ #include <stdint.h> #include "base/strings/string_util.h" -#include "v8/include/v8.h" +#include "v8/include/v8-array-buffer.h" +#include "v8/include/v8-external.h" +#include "v8/include/v8-function.h" +#include "v8/include/v8-maybe.h" +#include "v8/include/v8-object.h" +#include "v8/include/v8-primitive.h" +#include "v8/include/v8-promise.h" +#include "v8/include/v8-value.h" using v8::ArrayBuffer; using v8::Boolean; diff --git a/chromium/gin/converter.h b/chromium/gin/converter.h index 18068d8da0d..3621dae8192 100644 --- a/chromium/gin/converter.h +++ b/chromium/gin/converter.h @@ -16,7 +16,9 @@ #include "base/notreached.h" #include "base/strings/string_piece.h" #include "gin/gin_export.h" -#include "v8/include/v8.h" +#include "v8/include/v8-container.h" +#include "v8/include/v8-forward.h" +#include "v8/include/v8-isolate.h" namespace gin { diff --git a/chromium/gin/converter_unittest.cc b/chromium/gin/converter_unittest.cc index 195d719ea3c..3cae6318c32 100644 --- a/chromium/gin/converter_unittest.cc +++ b/chromium/gin/converter_unittest.cc @@ -20,7 +20,12 @@ #include "gin/wrappable.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "v8/include/v8.h" +#include "v8/include/v8-container.h" +#include "v8/include/v8-forward.h" +#include "v8/include/v8-function.h" +#include "v8/include/v8-isolate.h" +#include "v8/include/v8-primitive.h" +#include "v8/include/v8-template.h" namespace gin { diff --git a/chromium/gin/data_object_builder.h b/chromium/gin/data_object_builder.h index 3f384b04ff5..47d2d7a8913 100644 --- a/chromium/gin/data_object_builder.h +++ b/chromium/gin/data_object_builder.h @@ -11,7 +11,8 @@ #include "base/strings/string_piece.h" #include "gin/converter.h" #include "gin/gin_export.h" -#include "v8/include/v8.h" +#include "v8/include/v8-forward.h" +#include "v8/include/v8-object.h" namespace gin { diff --git a/chromium/gin/data_object_builder_unittest.cc b/chromium/gin/data_object_builder_unittest.cc index 74762741edc..824a08ebd8a 100644 --- a/chromium/gin/data_object_builder_unittest.cc +++ b/chromium/gin/data_object_builder_unittest.cc @@ -9,6 +9,8 @@ #include "gin/dictionary.h" #include "gin/public/isolate_holder.h" #include "gin/test/v8_test.h" +#include "v8/include/v8-context.h" +#include "v8/include/v8-function.h" namespace gin { namespace { diff --git a/chromium/gin/debug_impl.cc b/chromium/gin/debug_impl.cc index ca0577ea4ca..451744c1d85 100644 --- a/chromium/gin/debug_impl.cc +++ b/chromium/gin/debug_impl.cc @@ -4,6 +4,12 @@ #include "gin/debug_impl.h" +#include "build/build_config.h" + +#if defined(OS_WIN) +#include "v8/include/v8-initialization.h" +#endif + namespace gin { namespace { diff --git a/chromium/gin/debug_impl.h b/chromium/gin/debug_impl.h index fafb98cd8e0..581292b57b4 100644 --- a/chromium/gin/debug_impl.h +++ b/chromium/gin/debug_impl.h @@ -6,7 +6,7 @@ #define GIN_DEBUG_IMPL_H_ #include "gin/public/debug.h" -#include "v8/include/v8.h" +#include "v8/include/v8-callbacks.h" namespace gin { diff --git a/chromium/gin/function_template.h b/chromium/gin/function_template.h index 5c554a52632..db630d26942 100644 --- a/chromium/gin/function_template.h +++ b/chromium/gin/function_template.h @@ -14,7 +14,10 @@ #include "gin/arguments.h" #include "gin/converter.h" #include "gin/gin_export.h" -#include "v8/include/v8.h" +#include "v8/include/v8-external.h" +#include "v8/include/v8-forward.h" +#include "v8/include/v8-persistent-handle.h" +#include "v8/include/v8-template.h" namespace gin { diff --git a/chromium/gin/gin_features.cc b/chromium/gin/gin_features.cc index 55c519e5a14..3f1949547b0 100644 --- a/chromium/gin/gin_features.cc +++ b/chromium/gin/gin_features.cc @@ -15,6 +15,10 @@ const base::Feature kV8OptimizeJavascript{"V8OptimizeJavascript", const base::Feature kV8FlushBytecode{"V8FlushBytecode", base::FEATURE_ENABLED_BY_DEFAULT}; +// Enables flushing of baseline code in V8. +const base::Feature kV8FlushBaselineCode{"V8FlushBaselineCode", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables finalizing streaming JS compilations on a background thread. const base::Feature kV8OffThreadFinalization{"V8OffThreadFinalization", base::FEATURE_ENABLED_BY_DEFAULT}; @@ -25,7 +29,7 @@ const base::Feature kV8LazyFeedbackAllocation{"V8LazyFeedbackAllocation", // Enables concurrent inlining in TurboFan. const base::Feature kV8ConcurrentInlining{"V8ConcurrentInlining", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // Enables per-context marking worklists in V8 GC. const base::Feature kV8PerContextMarkingWorklist{ @@ -43,13 +47,11 @@ const base::Feature kV8ReduceConcurrentMarkingTasks{ const base::Feature kV8NoReclaimUnmodifiedWrappers{ "V8NoReclaimUnmodifiedWrappers", base::FEATURE_DISABLED_BY_DEFAULT}; -// Enables concurrent heap access and allocation. -const base::Feature kV8LocalHeaps{"V8LocalHeaps", - base::FEATURE_ENABLED_BY_DEFAULT}; - -// Enables TurboFan's direct heap access. -const base::Feature kV8TurboDirectHeapAccess{"V8TurboDirectHeapAccess", - base::FEATURE_ENABLED_BY_DEFAULT}; +// Enables W^X code memory protection in V8. +// This is enabled in V8 by default. To test the performance impact, we are +// going to disable this feature in a finch experiment. +const base::Feature kV8CodeMemoryWriteProtection{ + "V8CodeMemoryWriteProtection", base::FEATURE_ENABLED_BY_DEFAULT}; // Enables fallback to a breadth-first regexp engine on excessive backtracking. const base::Feature kV8ExperimentalRegexpEngine{ @@ -77,10 +79,6 @@ const base::Feature kV8ShortBuiltinCalls{"V8ShortBuiltinCalls", const base::Feature kV8TurboFastApiCalls{"V8TurboFastApiCalls", base::FEATURE_DISABLED_BY_DEFAULT}; -// Enables untrusted code mitigations. -const base::Feature kV8UntrustedCodeMitigations{ - "V8UntrustedCodeMitigations", base::FEATURE_DISABLED_BY_DEFAULT}; - // Artificially delays script execution. const base::Feature kV8ScriptAblation{"V8ScriptAblation", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -91,14 +89,28 @@ 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}; - // Enables slow histograms that provide detailed information at increased // runtime overheads. const base::Feature kV8SlowHistograms{"V8SlowHistograms", base::FEATURE_DISABLED_BY_DEFAULT}; +// Multiple finch experiments might use slow-histograms. We introduce +// separate feature flags to circumvent finch limitations. +const base::Feature kV8SlowHistogramsSparkplug{ + "V8SlowHistogramsSparkplug", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kV8SlowHistogramsSparkplugAndroid{ + "V8SlowHistogramsSparkplugAndroid", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kV8SlowHistogramsScriptAblation{ + "V8SlowHistogramsScriptAblation", base::FEATURE_DISABLED_BY_DEFAULT}; + +// Enables the V8 virtual memory cage. +const base::Feature kV8VirtualMemoryCage { + "V8VirtualMemoryCage", +#if defined(V8_HEAP_SANDBOX) + // The cage is required for the V8 Heap Sandbox. + base::FEATURE_ENABLED_BY_DEFAULT +#else + base::FEATURE_DISABLED_BY_DEFAULT +#endif +}; } // namespace features diff --git a/chromium/gin/gin_features.h b/chromium/gin/gin_features.h index 2eb9e36d580..5aa231d63ba 100644 --- a/chromium/gin/gin_features.h +++ b/chromium/gin/gin_features.h @@ -11,14 +11,14 @@ namespace features { -GIN_EXPORT extern const base::Feature kV8ArrayBufferCageReservationExperiment; GIN_EXPORT extern const base::Feature kV8ConcurrentInlining; GIN_EXPORT extern const base::Feature kV8ExperimentalRegexpEngine; GIN_EXPORT extern const base::Feature kV8FlushBytecode; +GIN_EXPORT extern const base::Feature kV8FlushBaselineCode; GIN_EXPORT extern const base::Feature kV8FlushEmbeddedBlobICache; GIN_EXPORT extern const base::Feature kV8LazyFeedbackAllocation; -GIN_EXPORT extern const base::Feature kV8LocalHeaps; GIN_EXPORT extern const base::Feature kV8NoReclaimUnmodifiedWrappers; +GIN_EXPORT extern const base::Feature kV8CodeMemoryWriteProtection; GIN_EXPORT extern const base::Feature kV8OffThreadFinalization; GIN_EXPORT extern const base::Feature kV8OptimizeJavascript; GIN_EXPORT extern const base::Feature kV8PerContextMarkingWorklist; @@ -29,12 +29,14 @@ GIN_EXPORT extern const base::FeatureParam<int> kV8ScriptDelayMs; GIN_EXPORT extern const base::FeatureParam<int> kV8ScriptDelayOnceMs; GIN_EXPORT extern const base::Feature kV8ShortBuiltinCalls; GIN_EXPORT extern const base::Feature kV8SlowHistograms; +GIN_EXPORT extern const base::Feature kV8SlowHistogramsSparkplug; +GIN_EXPORT extern const base::Feature kV8SlowHistogramsSparkplugAndroid; +GIN_EXPORT extern const base::Feature kV8SlowHistogramsScriptAblation; GIN_EXPORT extern const base::Feature kV8Sparkplug; GIN_EXPORT extern const base::Feature kV8SparkplugNeedsShortBuiltinCalls; -GIN_EXPORT extern const base::Feature kV8TurboDirectHeapAccess; GIN_EXPORT extern const base::Feature kV8TurboFastApiCalls; GIN_EXPORT extern const base::Feature kV8Turboprop; -GIN_EXPORT extern const base::Feature kV8UntrustedCodeMitigations; +GIN_EXPORT extern const base::Feature kV8VirtualMemoryCage; } // namespace features diff --git a/chromium/gin/interceptor.h b/chromium/gin/interceptor.h index 2d14ccee300..ff6dcc32384 100644 --- a/chromium/gin/interceptor.h +++ b/chromium/gin/interceptor.h @@ -11,7 +11,7 @@ #include <vector> #include "gin/gin_export.h" -#include "v8/include/v8.h" +#include "v8/include/v8-forward.h" namespace gin { diff --git a/chromium/gin/interceptor_unittest.cc b/chromium/gin/interceptor_unittest.cc index 03b0505b65c..c72f190be60 100644 --- a/chromium/gin/interceptor_unittest.cc +++ b/chromium/gin/interceptor_unittest.cc @@ -16,6 +16,8 @@ #include "gin/try_catch.h" #include "gin/wrappable.h" #include "testing/gtest/include/gtest/gtest.h" +#include "v8/include/v8-function.h" +#include "v8/include/v8-script.h" #include "v8/include/v8-util.h" namespace gin { diff --git a/chromium/gin/isolate_holder.cc b/chromium/gin/isolate_holder.cc index f86478fb865..e9382446381 100644 --- a/chromium/gin/isolate_holder.cc +++ b/chromium/gin/isolate_holder.cc @@ -23,6 +23,8 @@ #include "gin/v8_initializer.h" #include "gin/v8_isolate_memory_dump_provider.h" #include "gin/v8_shared_memory_dump_provider.h" +#include "v8/include/v8-isolate.h" +#include "v8/include/v8-snapshot.h" namespace gin { diff --git a/chromium/gin/modules/console.cc b/chromium/gin/modules/console.cc index 7e3087fb982..249429e2819 100644 --- a/chromium/gin/modules/console.cc +++ b/chromium/gin/modules/console.cc @@ -9,6 +9,7 @@ #include "base/strings/string_util.h" #include "gin/arguments.h" #include "gin/converter.h" +#include "v8/include/v8-template.h" namespace gin { diff --git a/chromium/gin/modules/console.h b/chromium/gin/modules/console.h index 4b68aa1a54f..e4f70904caa 100644 --- a/chromium/gin/modules/console.h +++ b/chromium/gin/modules/console.h @@ -6,7 +6,7 @@ #define GIN_MODULES_CONSOLE_H_ #include "gin/gin_export.h" -#include "v8/include/v8.h" +#include "v8/include/v8-forward.h" namespace gin { diff --git a/chromium/gin/object_template_builder.cc b/chromium/gin/object_template_builder.cc index 9add555497b..28f286b08e8 100644 --- a/chromium/gin/object_template_builder.cc +++ b/chromium/gin/object_template_builder.cc @@ -184,6 +184,12 @@ ObjectTemplateBuilder& ObjectTemplateBuilder::SetImpl( return *this; } +ObjectTemplateBuilder& ObjectTemplateBuilder::SetImpl(v8::Local<v8::Name> name, + v8::Local<v8::Data> val) { + template_->Set(name, val); + return *this; +} + ObjectTemplateBuilder& ObjectTemplateBuilder::SetPropertyImpl( const base::StringPiece& name, v8::Local<v8::FunctionTemplate> getter, v8::Local<v8::FunctionTemplate> setter) { diff --git a/chromium/gin/object_template_builder.h b/chromium/gin/object_template_builder.h index 6cddf3068b0..33bfd24ffee 100644 --- a/chromium/gin/object_template_builder.h +++ b/chromium/gin/object_template_builder.h @@ -15,7 +15,7 @@ #include "gin/converter.h" #include "gin/function_template.h" #include "gin/gin_export.h" -#include "v8/include/v8.h" +#include "v8/include/v8-forward.h" namespace gin { @@ -70,6 +70,14 @@ class GIN_EXPORT ObjectTemplateBuilder { return SetImpl( name, internal::CreateFunctionTemplate(isolate_, callback, type_name_)); } + + template <typename T> + ObjectTemplateBuilder& SetMethod(v8::Local<v8::Name> name, + const T& callback) { + return SetImpl( + name, internal::CreateFunctionTemplate(isolate_, callback, type_name_)); + } + template<typename T> ObjectTemplateBuilder& SetProperty(const base::StringPiece& name, const T& getter) { @@ -111,6 +119,8 @@ class GIN_EXPORT ObjectTemplateBuilder { private: ObjectTemplateBuilder& SetImpl(const base::StringPiece& name, v8::Local<v8::Data> val); + ObjectTemplateBuilder& SetImpl(v8::Local<v8::Name> name, + v8::Local<v8::Data> val); ObjectTemplateBuilder& SetPropertyImpl( const base::StringPiece& name, v8::Local<v8::FunctionTemplate> getter, v8::Local<v8::FunctionTemplate> setter); diff --git a/chromium/gin/per_context_data.h b/chromium/gin/per_context_data.h index 69a8806171f..4ce53d80fc8 100644 --- a/chromium/gin/per_context_data.h +++ b/chromium/gin/per_context_data.h @@ -7,7 +7,7 @@ #include "base/supports_user_data.h" #include "gin/gin_export.h" -#include "v8/include/v8.h" +#include "v8/include/v8-forward.h" namespace gin { diff --git a/chromium/gin/per_context_data_unittest.cc b/chromium/gin/per_context_data_unittest.cc index 831ad1cb697..02098b68678 100644 --- a/chromium/gin/per_context_data_unittest.cc +++ b/chromium/gin/per_context_data_unittest.cc @@ -7,7 +7,8 @@ #include "gin/public/context_holder.h" #include "gin/public/isolate_holder.h" #include "gin/test/v8_test.h" -#include "v8/include/v8.h" +#include "v8/include/v8-context.h" +#include "v8/include/v8-isolate.h" namespace gin { diff --git a/chromium/gin/per_isolate_data.cc b/chromium/gin/per_isolate_data.cc index 3b0e22a14e6..014830e69e9 100644 --- a/chromium/gin/per_isolate_data.cc +++ b/chromium/gin/per_isolate_data.cc @@ -13,6 +13,7 @@ #include "gin/public/gin_embedders.h" #include "gin/v8_foreground_task_runner.h" #include "gin/v8_foreground_task_runner_with_locker.h" +#include "v8/include/v8-isolate.h" using v8::ArrayBuffer; using v8::Eternal; diff --git a/chromium/gin/per_isolate_data.h b/chromium/gin/per_isolate_data.h index a3324402d70..f792533c229 100644 --- a/chromium/gin/per_isolate_data.h +++ b/chromium/gin/per_isolate_data.h @@ -14,7 +14,8 @@ #include "gin/public/isolate_holder.h" #include "gin/public/wrapper_info.h" #include "gin/v8_foreground_task_runner_base.h" -#include "v8/include/v8.h" +#include "v8/include/v8-array-buffer.h" +#include "v8/include/v8-forward.h" namespace gin { diff --git a/chromium/gin/public/context_holder.h b/chromium/gin/public/context_holder.h index 9f2d4dcd283..b71e4954dc4 100644 --- a/chromium/gin/public/context_holder.h +++ b/chromium/gin/public/context_holder.h @@ -9,7 +9,9 @@ #include <memory> #include "gin/gin_export.h" -#include "v8/include/v8.h" +#include "v8/include/v8-context.h" +#include "v8/include/v8-forward.h" +#include "v8/include/v8-persistent-handle.h" namespace gin { diff --git a/chromium/gin/public/debug.h b/chromium/gin/public/debug.h index 4e567876f7a..669c6ae2fee 100644 --- a/chromium/gin/public/debug.h +++ b/chromium/gin/public/debug.h @@ -9,7 +9,7 @@ #include "build/build_config.h" #include "gin/gin_export.h" -#include "v8/include/v8.h" +#include "v8/include/v8-callbacks.h" namespace gin { diff --git a/chromium/gin/public/isolate_holder.h b/chromium/gin/public/isolate_holder.h index 41e516899dc..f0a7d0c05fa 100644 --- a/chromium/gin/public/isolate_holder.h +++ b/chromium/gin/public/isolate_holder.h @@ -10,12 +10,17 @@ #include "base/memory/ref_counted.h" #include "gin/gin_export.h" #include "gin/public/v8_idle_task_runner.h" -#include "v8/include/v8.h" +#include "v8/include/v8-array-buffer.h" +#include "v8/include/v8-forward.h" namespace base { class SingleThreadTaskRunner; } +namespace v8 { +class SnapshotCreator; +} + namespace gin { class PerIsolateData; diff --git a/chromium/gin/public/v8_platform.h b/chromium/gin/public/v8_platform.h index fa0e7faad92..c9b535eb083 100644 --- a/chromium/gin/public/v8_platform.h +++ b/chromium/gin/public/v8_platform.h @@ -9,6 +9,7 @@ #include "base/compiler_specific.h" #include "base/lazy_instance.h" #include "gin/gin_export.h" +#include "gin/v8_platform_page_allocator.h" #include "v8/include/v8-platform.h" namespace gin { @@ -24,9 +25,15 @@ class GIN_EXPORT V8Platform : public v8::Platform { // v8::Platform implementation. // Some configurations do not use page_allocator. #if BUILDFLAG(USE_PARTITION_ALLOC) - v8::PageAllocator* GetPageAllocator() override; + // GetPageAllocator returns gin::PageAllocator instead of v8::PageAllocator, + // so we can be sure that the allocator used employs security features such as + // enabling Arm's Branch Target Instructions for executable pages. This is + // verified in the tests for gin::PageAllocator. + PageAllocator* GetPageAllocator() override; void OnCriticalMemoryPressure() override; + v8::ZoneBackingAllocator* GetZoneBackingAllocator() override; #endif + std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner( v8::Isolate*) override; int NumberOfWorkerThreads() override; diff --git a/chromium/gin/public/wrapper_info.h b/chromium/gin/public/wrapper_info.h index 4a1f55f32b1..acee1955642 100644 --- a/chromium/gin/public/wrapper_info.h +++ b/chromium/gin/public/wrapper_info.h @@ -7,7 +7,7 @@ #include "gin/gin_export.h" #include "gin/public/gin_embedders.h" -#include "v8/include/v8.h" +#include "v8/include/v8-forward.h" namespace gin { diff --git a/chromium/gin/runner.h b/chromium/gin/runner.h index c860f193572..b6351ac667a 100644 --- a/chromium/gin/runner.h +++ b/chromium/gin/runner.h @@ -10,7 +10,8 @@ #include "base/memory/weak_ptr.h" #include "gin/gin_export.h" #include "gin/public/context_holder.h" -#include "v8/include/v8.h" +#include "v8/include/v8-forward.h" +#include "v8/include/v8-isolate.h" namespace gin { diff --git a/chromium/gin/shell_runner.cc b/chromium/gin/shell_runner.cc index e4e84a62270..41fd75f31b5 100644 --- a/chromium/gin/shell_runner.cc +++ b/chromium/gin/shell_runner.cc @@ -10,6 +10,7 @@ #include "gin/per_context_data.h" #include "gin/public/context_holder.h" #include "gin/try_catch.h" +#include "v8/include/v8-script.h" using v8::Context; using v8::HandleScope; diff --git a/chromium/gin/try_catch.cc b/chromium/gin/try_catch.cc index 821719294cf..d15f004ce15 100644 --- a/chromium/gin/try_catch.cc +++ b/chromium/gin/try_catch.cc @@ -7,6 +7,7 @@ #include <sstream> #include "gin/converter.h" +#include "v8/include/v8-message.h" namespace { diff --git a/chromium/gin/try_catch.h b/chromium/gin/try_catch.h index c0e1dea80b1..4f0656cb653 100644 --- a/chromium/gin/try_catch.h +++ b/chromium/gin/try_catch.h @@ -8,7 +8,7 @@ #include <string> #include "gin/gin_export.h" -#include "v8/include/v8.h" +#include "v8/include/v8-exception.h" namespace gin { diff --git a/chromium/gin/v8_foreground_task_runner.cc b/chromium/gin/v8_foreground_task_runner.cc index 4d93e27b64b..0a40b8e0176 100644 --- a/chromium/gin/v8_foreground_task_runner.cc +++ b/chromium/gin/v8_foreground_task_runner.cc @@ -32,9 +32,9 @@ void V8ForegroundTaskRunner::PostNonNestableTask( void V8ForegroundTaskRunner::PostDelayedTask(std::unique_ptr<v8::Task> task, double delay_in_seconds) { - task_runner_->PostDelayedTask( - FROM_HERE, base::BindOnce(&v8::Task::Run, std::move(task)), - base::TimeDelta::FromSecondsD(delay_in_seconds)); + task_runner_->PostDelayedTask(FROM_HERE, + base::BindOnce(&v8::Task::Run, std::move(task)), + base::Seconds(delay_in_seconds)); } void V8ForegroundTaskRunner::PostNonNestableDelayedTask( @@ -42,7 +42,7 @@ void V8ForegroundTaskRunner::PostNonNestableDelayedTask( double delay_in_seconds) { task_runner_->PostNonNestableDelayedTask( FROM_HERE, base::BindOnce(&v8::Task::Run, std::move(task)), - base::TimeDelta::FromSecondsD(delay_in_seconds)); + base::Seconds(delay_in_seconds)); } void V8ForegroundTaskRunner::PostIdleTask(std::unique_ptr<v8::IdleTask> task) { diff --git a/chromium/gin/v8_foreground_task_runner_with_locker.cc b/chromium/gin/v8_foreground_task_runner_with_locker.cc index a7e6c4dc0f2..a769c81328b 100644 --- a/chromium/gin/v8_foreground_task_runner_with_locker.cc +++ b/chromium/gin/v8_foreground_task_runner_with_locker.cc @@ -8,7 +8,7 @@ #include "base/callback_helpers.h" #include "base/single_thread_task_runner.h" #include "base/threading/thread_task_runner_handle.h" -#include "v8/include/v8.h" +#include "v8/include/v8-locker.h" namespace gin { @@ -70,7 +70,7 @@ void V8ForegroundTaskRunnerWithLocker::PostDelayedTask( FROM_HERE, base::BindOnce(RunWithLocker, base::Unretained(isolate_), std::move(task)), - base::TimeDelta::FromSecondsD(delay_in_seconds)); + base::Seconds(delay_in_seconds)); } void V8ForegroundTaskRunnerWithLocker::PostIdleTask( 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 diff --git a/chromium/gin/v8_initializer.h b/chromium/gin/v8_initializer.h index 2918c623568..955be10e118 100644 --- a/chromium/gin/v8_initializer.h +++ b/chromium/gin/v8_initializer.h @@ -9,11 +9,15 @@ #include "base/files/file.h" #include "base/files/memory_mapped_file.h" +#include "build/build_config.h" #include "gin/array_buffer.h" #include "gin/gin_export.h" #include "gin/public/isolate_holder.h" #include "gin/public/v8_platform.h" -#include "v8/include/v8.h" + +namespace v8 { +class StartupData; +} namespace gin { diff --git a/chromium/gin/v8_isolate_memory_dump_provider.cc b/chromium/gin/v8_isolate_memory_dump_provider.cc index 3f1f9954af8..d0de05893dc 100644 --- a/chromium/gin/v8_isolate_memory_dump_provider.cc +++ b/chromium/gin/v8_isolate_memory_dump_provider.cc @@ -12,7 +12,9 @@ #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/process_memory_dump.h" #include "gin/public/isolate_holder.h" -#include "v8/include/v8.h" +#include "v8/include/v8-isolate.h" +#include "v8/include/v8-locker.h" +#include "v8/include/v8-statistics.h" namespace gin { diff --git a/chromium/gin/v8_isolate_memory_dump_provider_unittest.cc b/chromium/gin/v8_isolate_memory_dump_provider_unittest.cc index 124cc4fdabb..ec4002c702a 100644 --- a/chromium/gin/v8_isolate_memory_dump_provider_unittest.cc +++ b/chromium/gin/v8_isolate_memory_dump_provider_unittest.cc @@ -12,6 +12,7 @@ #include "base/trace_event/trace_event.h" #include "gin/public/isolate_holder.h" #include "gin/test/v8_test.h" +#include "v8/include/v8-initialization.h" namespace gin { diff --git a/chromium/gin/v8_platform.cc b/chromium/gin/v8_platform.cc index 60f38b2dd01..563888e117d 100644 --- a/chromium/gin/v8_platform.cc +++ b/chromium/gin/v8_platform.cc @@ -6,15 +6,13 @@ #include <algorithm> -#include "base/allocator/partition_allocator/address_space_randomization.h" -#include "base/allocator/partition_allocator/page_allocator.h" -#include "base/allocator/partition_allocator/random.h" #include "base/bind.h" #include "base/bit_cast.h" #include "base/bits.h" #include "base/check_op.h" #include "base/debug/stack_trace.h" #include "base/location.h" +#include "base/memory/nonscannable_memory.h" #include "base/rand_util.h" #include "base/system/sys_info.h" #include "base/task/post_job.h" @@ -25,7 +23,9 @@ #include "base/trace_event/trace_event.h" #include "base/tracing_buildflags.h" #include "build/build_config.h" + #include "gin/per_isolate_data.h" +#include "v8_platform_page_allocator.h" namespace gin { @@ -187,104 +187,8 @@ base::LazyInstance<TimeClamper>::Leaky g_time_clamper = LAZY_INSTANCE_INITIALIZER; #if BUILDFLAG(USE_PARTITION_ALLOC) -base::PageAccessibilityConfiguration GetPageConfig( - v8::PageAllocator::Permission permission) { - switch (permission) { - case v8::PageAllocator::Permission::kRead: - return base::PageRead; - case v8::PageAllocator::Permission::kReadWrite: - return base::PageReadWrite; - case v8::PageAllocator::Permission::kReadWriteExecute: - return base::PageReadWriteExecute; - case v8::PageAllocator::Permission::kReadExecute: - return base::PageReadExecute; - default: - DCHECK_EQ(v8::PageAllocator::Permission::kNoAccess, permission); - return base::PageInaccessible; - } -} - -class PageAllocator : public v8::PageAllocator { - public: - ~PageAllocator() override = default; - - size_t AllocatePageSize() override { - return base::PageAllocationGranularity(); - } - - size_t CommitPageSize() override { return base::SystemPageSize(); } - - void SetRandomMmapSeed(int64_t seed) override { - base::SetMmapSeedForTesting(seed); - } - - void* GetRandomMmapAddr() override { return base::GetRandomPageBase(); } - - void* AllocatePages(void* address, - size_t length, - size_t alignment, - v8::PageAllocator::Permission permissions) override { - if (permissions == v8::PageAllocator::Permission::kNoAccessWillJitLater) { - // We could use this information to conditionally set the MAP_JIT flag - // on Mac-arm64; however this permissions value is intended to be a - // short-term solution, so we continue to set MAP_JIT for all V8 pages - // for now. - permissions = v8::PageAllocator::Permission::kNoAccess; - } - base::PageAccessibilityConfiguration config = GetPageConfig(permissions); - return base::AllocPages(address, length, alignment, config, - base::PageTag::kV8); - } - - bool FreePages(void* address, size_t length) override { - base::FreePages(address, length); - return true; - } - - bool ReleasePages(void* address, size_t length, size_t new_length) override { - DCHECK_LT(new_length, length); - uint8_t* release_base = reinterpret_cast<uint8_t*>(address) + new_length; - size_t release_size = length - new_length; -#if defined(OS_POSIX) || defined(OS_FUCHSIA) - // On POSIX, we can unmap the trailing pages. - base::FreePages(release_base, release_size); -#elif defined(OS_WIN) - // On Windows, we can only de-commit the trailing pages. FreePages() will - // still free all pages in the region including the released tail, so it's - // safe to just decommit the tail. - base::DecommitSystemPages(release_base, release_size, - base::PageUpdatePermissions); -#else -#error Unsupported platform -#endif - return true; - } - - bool SetPermissions(void* address, - size_t length, - Permission permissions) override { - // If V8 sets permissions to none, we can discard the memory. - if (permissions == v8::PageAllocator::Permission::kNoAccess) { - // Use PageKeepPermissionsIfPossible as an optimization, to avoid perf - // regression (see crrev.com/c/2563038 for details). This may cause the - // memory region to still be accessible on certain platforms, but at least - // the physical pages will be discarded. - base::DecommitSystemPages(address, length, - base::PageKeepPermissionsIfPossible); - return true; - } else { - return base::TrySetSystemPagesAccess(address, length, - GetPageConfig(permissions)); - } - } - - bool DiscardSystemPages(void* address, size_t size) override { - base::DiscardSystemPages(address, size); - return true; - } -}; -base::LazyInstance<PageAllocator>::Leaky g_page_allocator = +base::LazyInstance<gin::PageAllocator>::Leaky g_page_allocator = LAZY_INSTANCE_INITIALIZER; #endif // BUILDFLAG(USE_PARTITION_ALLOC) @@ -426,8 +330,7 @@ class V8Platform::TracingControllerImpl : public v8::TracingController { arg_convertables); DCHECK_LE(num_args, 2); base::TimeTicks timestamp = - base::TimeTicks() + - base::TimeDelta::FromMicroseconds(timestampMicroseconds); + base::TimeTicks() + base::Microseconds(timestampMicroseconds); base::trace_event::TraceEventHandle handle = TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP( phase, category_enabled_flag, name, scope, id, bind_id, @@ -461,7 +364,7 @@ V8Platform::V8Platform() : tracing_controller_(new TracingControllerImpl) {} V8Platform::~V8Platform() = default; #if BUILDFLAG(USE_PARTITION_ALLOC) -v8::PageAllocator* V8Platform::GetPageAllocator() { +PageAllocator* V8Platform::GetPageAllocator() { return g_page_allocator.Pointer(); } @@ -472,6 +375,16 @@ void V8Platform::OnCriticalMemoryPressure() { base::ReleaseReservation(); #endif } + +v8::ZoneBackingAllocator* V8Platform::GetZoneBackingAllocator() { + static struct Allocator final : v8::ZoneBackingAllocator { + MallocFn GetMallocFn() const override { + return &base::AllocNonQuarantinable; + } + FreeFn GetFreeFn() const override { return &base::FreeNonQuarantinable; } + } allocator; + return &allocator; +} #endif // BUILDFLAG(USE_PARTITION_ALLOC) std::shared_ptr<v8::TaskRunner> V8Platform::GetForegroundTaskRunner( @@ -516,7 +429,7 @@ void V8Platform::CallDelayedOnWorkerThread(std::unique_ptr<v8::Task> task, base::ThreadPool::PostDelayedTask( FROM_HERE, kDefaultTaskTraits, base::BindOnce(&v8::Task::Run, std::move(task)), - base::TimeDelta::FromSecondsD(delay_in_seconds)); + base::Seconds(delay_in_seconds)); } std::unique_ptr<v8::JobHandle> V8Platform::PostJob( diff --git a/chromium/gin/v8_platform_page_allocator.cc b/chromium/gin/v8_platform_page_allocator.cc new file mode 100644 index 00000000000..49b3ca66144 --- /dev/null +++ b/chromium/gin/v8_platform_page_allocator.cc @@ -0,0 +1,138 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "v8_platform_page_allocator.h" + +#include "base/allocator/partition_allocator/address_space_randomization.h" +#include "base/allocator/partition_allocator/page_allocator_constants.h" +#include "base/allocator/partition_allocator/random.h" +#include "base/check_op.h" +#include "base/cpu.h" + +namespace { + +// Maps the v8 page permissions into a page configuration from base. +base::PageAccessibilityConfiguration GetPageConfig( + v8::PageAllocator::Permission permission) { + switch (permission) { + case v8::PageAllocator::Permission::kRead: + return base::PageRead; + case v8::PageAllocator::Permission::kReadWrite: + return base::PageReadWrite; + case v8::PageAllocator::Permission::kReadWriteExecute: + // at the moment bti-protection is not enabled for this path since some + // projects may still be using non-bti compliant code. + return base::PageReadWriteExecute; + case v8::PageAllocator::Permission::kReadExecute: +#if defined(__ARM_FEATURE_BTI_DEFAULT) + return base::CPU::GetInstanceNoAllocation().has_bti() + ? base::PageReadExecuteProtected + : base::PageReadExecute; +#else + return base::PageReadExecute; +#endif + case v8::PageAllocator::Permission::kNoAccessWillJitLater: + // We could use this information to conditionally set the MAP_JIT flag + // on Mac-arm64; however this permissions value is intended to be a + // short-term solution, so we continue to set MAP_JIT for all V8 pages + // for now. + return base::PageInaccessible; + default: + DCHECK_EQ(v8::PageAllocator::Permission::kNoAccess, permission); + return base::PageInaccessible; + } +} + +} // namespace + +namespace gin { +PageAllocator::~PageAllocator() = default; + +size_t PageAllocator::AllocatePageSize() { + return base::PageAllocationGranularity(); +} + +size_t PageAllocator::CommitPageSize() { + return base::SystemPageSize(); +} + +void PageAllocator::SetRandomMmapSeed(int64_t seed) { + base::SetMmapSeedForTesting(seed); +} + +void* PageAllocator::GetRandomMmapAddr() { + return base::GetRandomPageBase(); +} + +void* PageAllocator::AllocatePages(void* address, + size_t length, + size_t alignment, + v8::PageAllocator::Permission permissions) { + base::PageAccessibilityConfiguration config = GetPageConfig(permissions); + return base::AllocPages(address, length, alignment, config, + base::PageTag::kV8); +} + +bool PageAllocator::FreePages(void* address, size_t length) { + base::FreePages(address, length); + return true; +} + +bool PageAllocator::ReleasePages(void* address, + size_t length, + size_t new_length) { + DCHECK_LT(new_length, length); + uint8_t* release_base = reinterpret_cast<uint8_t*>(address) + new_length; + size_t release_size = length - new_length; +#if defined(OS_POSIX) || defined(OS_FUCHSIA) + // On POSIX, we can unmap the trailing pages. + base::FreePages(release_base, release_size); +#elif defined(OS_WIN) + // On Windows, we can only de-commit the trailing pages. FreePages() will + // still free all pages in the region including the released tail, so it's + // safe to just decommit the tail. + base::DecommitSystemPages(release_base, release_size, + base::PageUpdatePermissions); +#else +#error Unsupported platform +#endif + return true; +} + +bool PageAllocator::SetPermissions(void* address, + size_t length, + Permission permissions) { + // If V8 sets permissions to none, we can discard the memory. + if (permissions == v8::PageAllocator::Permission::kNoAccess) { + // Use PageKeepPermissionsIfPossible as an optimization, to avoid perf + // regression (see crrev.com/c/2563038 for details). This may cause the + // memory region to still be accessible on certain platforms, but at least + // the physical pages will be discarded. + base::DecommitSystemPages(address, length, + base::PageKeepPermissionsIfPossible); + return true; + } else { + return base::TrySetSystemPagesAccess(address, length, + GetPageConfig(permissions)); + } +} + +bool PageAllocator::DiscardSystemPages(void* address, size_t size) { + base::DiscardSystemPages(address, size); + return true; +} + +bool PageAllocator::DecommitPages(void* address, size_t size) { + // V8 expects the pages to be inaccessible and zero-initialized upon next + // access. + base::DecommitAndZeroSystemPages(address, size); + return true; +} + +base::PageAccessibilityConfiguration PageAllocator::GetPageConfigForTesting( + v8::PageAllocator::Permission permission) { + return GetPageConfig(permission); +} + +} // namespace gin diff --git a/chromium/gin/v8_platform_page_allocator.h b/chromium/gin/v8_platform_page_allocator.h new file mode 100644 index 00000000000..dc13666b3b6 --- /dev/null +++ b/chromium/gin/v8_platform_page_allocator.h @@ -0,0 +1,60 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GIN_V8_PLATFROM_PAGE_ALLOCATOR_H_ +#define GIN_V8_PLATFROM_PAGE_ALLOCATOR_H_ + +#include "build/build_config.h" +#include "build/buildflag.h" + +#include "base/allocator/buildflags.h" + +#if BUILDFLAG(USE_PARTITION_ALLOC) + +#include "base/allocator/partition_allocator/page_allocator.h" +#include "gin/gin_export.h" +#include "v8-platform.h" + +namespace gin { + +// A v8::PageAllocator implementation to use with gin. +class GIN_EXPORT PageAllocator final : public v8::PageAllocator { + public: + ~PageAllocator() override; + + size_t AllocatePageSize() override; + + size_t CommitPageSize() override; + + void SetRandomMmapSeed(int64_t seed) override; + + void* GetRandomMmapAddr() override; + + void* AllocatePages(void* address, + size_t length, + size_t alignment, + v8::PageAllocator::Permission permissions) override; + + bool FreePages(void* address, size_t length) override; + + bool ReleasePages(void* address, size_t length, size_t new_length) override; + + bool SetPermissions(void* address, + size_t length, + Permission permissions) override; + + bool DiscardSystemPages(void* address, size_t size) override; + + bool DecommitPages(void* address, size_t size) override; + + // For testing purposes only: Map the v8 page permissions into a page + // configuration from base. + base::PageAccessibilityConfiguration GetPageConfigForTesting( + v8::PageAllocator::Permission permission); +}; +} // namespace gin + +#endif // BUILDFLAG(USE_PARTITION_ALLOC) + +#endif // GIN_V8_PLATFROM_PAGE_ALLOCATOR_H_
\ No newline at end of file diff --git a/chromium/gin/v8_platform_page_allocator_unittest.cc b/chromium/gin/v8_platform_page_allocator_unittest.cc new file mode 100644 index 00000000000..c5c0a256db2 --- /dev/null +++ b/chromium/gin/v8_platform_page_allocator_unittest.cc @@ -0,0 +1,158 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gin/v8_platform_page_allocator.h" + +#include "base/cpu.h" + +#include "testing/gtest/include/gtest/gtest.h" + +// includes for Branch Target Instruction tests +#if defined(ARCH_CPU_ARM64) && (OS_LINUX || OS_ANDROID) +// BTI is only available for AArch64, relevant platform are Android and Linux + +#include "base/allocator/partition_allocator/arm_bti_test_functions.h" +#include "base/allocator/partition_allocator/page_allocator_constants.h" +#if defined(OS_POSIX) +#include <signal.h> +#include "testing/gtest/include/gtest/gtest-death-test.h" +#endif +#endif // defined(ARCH_CPU_ARM64) && (OS_LINUX || OS_ANDROID) + +namespace gin { + +TEST(V8PlatformPageAllocatorTest, VerifyGetPageConfig) { + auto sut = gin::PageAllocator(); + + CHECK_EQ(sut.GetPageConfigForTesting(v8::PageAllocator::kNoAccess), + base::PageInaccessible); + CHECK_EQ(sut.GetPageConfigForTesting(v8::PageAllocator::kRead), + base::PageRead); + CHECK_EQ(sut.GetPageConfigForTesting(v8::PageAllocator::kReadWrite), + base::PageReadWrite); + CHECK_EQ(sut.GetPageConfigForTesting(v8::PageAllocator::kReadWriteExecute), + base::PageReadWriteExecute); + +#if defined(__ARM_FEATURE_BTI_DEFAULT) + CHECK_EQ(sut.GetPageConfigForTesting(v8::PageAllocator::kReadExecute), + base::CPU::GetInstanceNoAllocation().has_bti() + ? base::PageReadExecuteProtected + : base::PageReadExecute); +#else + CHECK_EQ(sut.GetPageConfigForTesting(v8::PageAllocator::kReadExecute), + base::PageReadExecute); +#endif + + CHECK_EQ( + sut.GetPageConfigForTesting(v8::PageAllocator::kNoAccessWillJitLater), + base::PageInaccessible); +} + +#if defined(ARCH_CPU_ARM64) && (OS_LINUX || OS_ANDROID) + +using BTITestFunction = int64_t (*)(int64_t); + +TEST(V8PlatformPageAllocatorBTITest, VerifyReadExecutePagesAreProtected) { + auto page_allocator = gin::PageAllocator(); + + auto const memory_size = base::PageAllocationGranularity(); + auto const memory_alignment = base::PageAllocationGranularity(); + + // Next, map some read-write memory and copy some test helper functions there. + char* const buffer = reinterpret_cast<char*>(page_allocator.AllocatePages( + nullptr, memory_size, memory_alignment, + v8::PageAllocator::Permission::kReadWriteExecute)); + + ptrdiff_t const function_range = + reinterpret_cast<char*>(arm_bti_test_function_end) - + reinterpret_cast<char*>(arm_bti_test_function); + ptrdiff_t const invalid_offset = + reinterpret_cast<char*>(arm_bti_test_function_invalid_offset) - + reinterpret_cast<char*>(arm_bti_test_function); + + // ensure alignment to 4 bytes required by function call convention + EXPECT_EQ(0u, ((uint64_t)buffer) % 4); + EXPECT_EQ(0u, ((uint64_t)function_range) % 4); + EXPECT_EQ(0u, ((uint64_t)invalid_offset) % 4); + + memcpy(buffer, reinterpret_cast<void*>(arm_bti_test_function), + function_range); + + // Next re-protect the page to the permission level to test + page_allocator.SetPermissions(buffer, memory_size, + v8::PageAllocator::Permission::kReadExecute); + + // Attempt to call a function with BTI landing pad. + BTITestFunction const bti_enabled_fn = + reinterpret_cast<BTITestFunction>(buffer); + + // bti_enabled_fn must return 18, no matter if BTI is actually enabled or not. + EXPECT_EQ(bti_enabled_fn(15), 18); + + // Next, attempt to call a function without BTI landing pad. + BTITestFunction const bti_invalid_fn = + reinterpret_cast<BTITestFunction>(buffer + invalid_offset); + + // Expectation for behaviour of bti_invalid_fn depends on the capabilities of + // the actual CPU we are running on. The code that were are trying to execute + // is assembly code and always has BTI enabled. + if (base::CPU::GetInstanceNoAllocation().has_bti()) { +#if defined(OS_POSIX) // signal handling is available on POSIX compliant + // systems only + EXPECT_EXIT({ bti_invalid_fn(15); }, testing::KilledBySignal(SIGILL), + ""); // Should crash with SIGILL. +#endif // defined(OS_POSIX) + } else { + EXPECT_EQ(bti_invalid_fn(15), 17); + } + + page_allocator.FreePages(buffer, memory_size); +} + +TEST(V8PlatformAllocatorBTITest, VerifyReadWriteExecutePagesAreNotProtected) { + auto page_allocator = gin::PageAllocator(); + + auto const memory_size = base::PageAllocationGranularity(); + auto const memory_alignment = base::PageAllocationGranularity(); + + // Next, map some read-write memory and copy some test helper functions there. + char* const buffer = reinterpret_cast<char*>(page_allocator.AllocatePages( + nullptr, memory_size, memory_alignment, + v8::PageAllocator::Permission::kReadWriteExecute)); + + ptrdiff_t const function_range = + reinterpret_cast<char*>(arm_bti_test_function_end) - + reinterpret_cast<char*>(arm_bti_test_function); + ptrdiff_t const invalid_offset = + reinterpret_cast<char*>(arm_bti_test_function_invalid_offset) - + reinterpret_cast<char*>(arm_bti_test_function); + + // ensure alignment to 4 bytes required by function call convention + EXPECT_EQ(0u, ((uint64_t)buffer) % 4); + EXPECT_EQ(0u, ((uint64_t)function_range) % 4); + EXPECT_EQ(0u, ((uint64_t)invalid_offset) % 4); + + memcpy(buffer, reinterpret_cast<void*>(arm_bti_test_function), + function_range); + + // Attempt to call a function with BTI landing pad. + BTITestFunction const bti_enabled_fn = + reinterpret_cast<BTITestFunction>(buffer); + + // bti_enabled_fn must return 18, no matter if BTI is actually enabled or not. + EXPECT_EQ(bti_enabled_fn(15), 18); + + // Next, attempt to call a function without BTI landing pad. + BTITestFunction const bti_invalid_fn = + reinterpret_cast<BTITestFunction>(buffer + invalid_offset); + + // Since permission kReadWriteExecute wont actually cause BTI to be enabled + // for the allocated page, calling this function must return without error. + EXPECT_EQ(bti_invalid_fn(15), 17); + + page_allocator.FreePages(buffer, memory_size); +} +#endif // if defined(ARCH_CPU_ARM64) && (OS_LINUX || OS_ANDROID) + +} // namespace gin diff --git a/chromium/gin/v8_shared_memory_dump_provider.cc b/chromium/gin/v8_shared_memory_dump_provider.cc index 580a88cfb08..f26d5b54942 100644 --- a/chromium/gin/v8_shared_memory_dump_provider.cc +++ b/chromium/gin/v8_shared_memory_dump_provider.cc @@ -9,7 +9,8 @@ #include "base/memory/singleton.h" #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/process_memory_dump.h" -#include "v8/include/v8.h" +#include "v8/include/v8-initialization.h" +#include "v8/include/v8-isolate.h" namespace gin { diff --git a/chromium/gin/wrappable_unittest.cc b/chromium/gin/wrappable_unittest.cc index c26e8ce5280..f4025945952 100644 --- a/chromium/gin/wrappable_unittest.cc +++ b/chromium/gin/wrappable_unittest.cc @@ -13,6 +13,9 @@ #include "gin/test/v8_test.h" #include "gin/try_catch.h" #include "testing/gtest/include/gtest/gtest.h" +#include "v8/include/v8-function.h" +#include "v8/include/v8-message.h" +#include "v8/include/v8-script.h" namespace gin { diff --git a/chromium/gin/wrapper_info.cc b/chromium/gin/wrapper_info.cc index 8e8f5b7c9e9..3405c299960 100644 --- a/chromium/gin/wrapper_info.cc +++ b/chromium/gin/wrapper_info.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "gin/public/wrapper_info.h" +#include "v8/include/v8-object.h" namespace gin { |