0

Reland: [compile hints magic] Enable the compile hints magic comment when producing the code cache

Measurements with the file-based explicit compile hint magic comment
showed regressions in the non-cached loads, but improvements in cached
loads. The running theory is that having more data in the code cache is
beneficial, but compiling it comes with a cost.

Thus, we should enable the compile hints magic comment only when we're
going to produce a code cache afterwards.

Last try: https://chromium-review.googlesource.com/c/chromium/src/+/5712811

This version contains fixes to handle ScriptResources with a CachedMetadataHandler
gracefully.

Bug: 42203853
Change-Id: I3d6f0ea18ae76235873d2baa1882932a454a4381
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5730299
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Commit-Queue: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1332243}
This commit is contained in:
Marja Hölttä
2024-07-24 10:50:53 +00:00
committed by Chromium LUCI CQ
parent 565c3eeaaf
commit 86a32b0d90
19 changed files with 482 additions and 152 deletions

@ -444,9 +444,6 @@ void SetFlags(IsolateHolder::ScriptMode mode,
SetV8Flags("--use_strict");
}
SetV8FlagsIfOverridden(features::kJavaScriptCompileHintsMagic,
"--compile-hints-magic", "--no-compile-hints-magic");
// WebAssembly features.
SetV8FlagsIfOverridden(features::kWebAssemblyInlining,

@ -78,11 +78,15 @@ v8::Local<v8::Module> ModuleRecord::Compile(
}
// TODO(chromium:1406506): Add a compile hints solution for module records.
constexpr bool kMightGenerateCompileHints = false;
const bool v8_compile_hints_magic_comment_runtime_enabled =
RuntimeEnabledFeatures::JavaScriptCompileHintsMagicRuntimeEnabled(
execution_context);
std::tie(compile_options, produce_cache_options, no_cache_reason) =
V8CodeCache::GetCompileOptions(
v8_cache_options, params.CacheHandler(),
params.GetSourceText().length(), params.SourceLocationType(),
params.BaseURL(), kMightGenerateCompileHints);
params.BaseURL(), kMightGenerateCompileHints,
v8_compile_hints_magic_comment_runtime_enabled);
if (!V8ScriptRunner::CompileModule(
isolate, params, text_position, compile_options, no_cache_reason,

@ -475,9 +475,7 @@ bool ScriptStreamer::ConvertEncoding(
v8_compile_hints::V8LocalCompileHintsConsumer*
ResourceScriptStreamer::GetV8LocalCompileHintsConsumerForTest() const {
return compile_hints_
? compile_hints_->GetV8LocalCompileHintsConsumerForTest()
: nullptr;
return compile_hints_->GetV8LocalCompileHintsConsumerForTest();
}
bool ResourceScriptStreamer::IsStreamingStarted() const {
@ -690,20 +688,25 @@ bool ResourceScriptStreamer::TryStartStreamingTask() {
source_ = std::make_unique<v8::ScriptCompiler::StreamedSource>(
std::move(stream_ptr), encoding_);
const bool has_hot_timestamp =
V8CodeCache::HasHotTimestamp(script_resource_->CacheHandler());
compile_hints_ =
v8_compile_hints::CompileHintsForStreaming::Builder(
script_resource_->GetV8CrowdsourcedCompileHintsProducer(),
script_resource_->GetV8CrowdsourcedCompileHintsConsumer(),
script_resource_->Url())
.Build(
(V8CodeCache::HasCompileHints(
script_resource_->CacheHandler(),
CachedMetadataHandler::kAllowUnchecked) &&
V8CodeCache::HasHotTimestamp(script_resource_->CacheHandler()))
? V8CodeCache::GetCachedMetadataForCompileHints(
script_resource_->CacheHandler(),
CachedMetadataHandler::kAllowUnchecked)
: nullptr);
script_resource_->Url(),
script_resource_
->GetV8CompileHintsMagicCommentRuntimeFeatureEnabled())
.Build((V8CodeCache::HasCompileHints(
script_resource_->CacheHandler(),
CachedMetadataHandler::kAllowUnchecked) &&
has_hot_timestamp)
? V8CodeCache::GetCachedMetadataForCompileHints(
script_resource_->CacheHandler(),
CachedMetadataHandler::kAllowUnchecked)
: nullptr,
has_hot_timestamp);
CHECK(compile_hints_);
v8::Isolate* isolate = script_resource_->GetIsolateOrNull();
if (!isolate) {
@ -719,12 +722,9 @@ bool ResourceScriptStreamer::TryStartStreamingTask() {
script_streaming_task =
base::WrapUnique(v8::ScriptCompiler::StartStreaming(
isolate, source_.get(), script_type_,
compile_hints_ ? compile_hints_->compile_options()
: v8::ScriptCompiler::kNoCompileOptions,
compile_hints_ ? compile_hints_->GetCompileHintCallback()
: nullptr,
compile_hints_ ? compile_hints_->GetCompileHintCallbackData()
: nullptr));
compile_hints_->compile_options(),
compile_hints_->GetCompileHintCallback(),
compile_hints_->GetCompileHintCallbackData()));
if (!script_streaming_task) {
// V8 cannot stream the script.
@ -1037,6 +1037,10 @@ BackgroundInlineScriptStreamer::BackgroundInlineScriptStreamer(
? v8::ScriptCompiler::StreamedSource::ONE_BYTE
: v8::ScriptCompiler::StreamedSource::TWO_BYTE);
// We don't generate code caches for inline scripts, so we never pass the
// kFollowCompileHintsMagicComment compile option.
CHECK((compile_options &
v8::ScriptCompiler::kFollowCompileHintsMagicComment) == 0);
task_ = base::WrapUnique(v8::ScriptCompiler::StartStreaming(
isolate, source_.get(), v8::ScriptType::kClassic, compile_options));
}
@ -1153,7 +1157,8 @@ BuildCompileHintsForStreaming(
std::move(builder).Build(
(metadata && V8CodeCache::HasHotCompileHints(*metadata, encoding))
? metadata
: nullptr);
: nullptr,
metadata && V8CodeCache::HasHotTimestamp(*metadata, encoding));
if (metadata) {
absl::variant<Vector<uint8_t>, mojo_base::BigBuffer> drained_data =
std::move(*metadata).DrainSerializedData();
@ -1189,8 +1194,8 @@ class BackgroundResourceScriptStreamer::BackgroundProcessor final
v8::ScriptType script_type,
const String script_url_string,
uint64_t script_resource_identifier,
v8::Isolate* isolate_,
WTF::TextEncoding encoding_,
v8::Isolate* isolate,
WTF::TextEncoding encoding,
std::unique_ptr<v8_compile_hints::CompileHintsForStreaming::Builder>
compile_hints_builder,
CrossThreadWeakHandle<BackgroundResourceScriptStreamer> streamer_handle);
@ -1308,7 +1313,9 @@ class BackgroundResourceScriptStreamer::BackgroundProcessorFactory final
v8_compile_hints::CompileHintsForStreaming::Builder>(
script_resource->GetV8CrowdsourcedCompileHintsProducer(),
script_resource->GetV8CrowdsourcedCompileHintsConsumer(),
script_resource->Url())),
script_resource->Url(),
script_resource
->GetV8CompileHintsMagicCommentRuntimeFeatureEnabled())),
streamer_handle_(std::move(streamer_handle)) {}
BackgroundProcessorFactory(const BackgroundProcessorFactory&) = delete;
BackgroundProcessorFactory& operator=(const BackgroundProcessorFactory&) =
@ -1507,6 +1514,7 @@ bool BackgroundResourceScriptStreamer::BackgroundProcessor::
compile_hints_ = BuildCompileHintsForStreaming(
*compile_hints_builder_, cached_metadata_, encoding_.GetName());
CHECK(compile_hints_);
watcher_ = std::make_unique<mojo::SimpleWatcher>(
FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL);
@ -1651,16 +1659,14 @@ bool BackgroundResourceScriptStreamer::BackgroundProcessor::
std::make_unique<v8::ScriptCompiler::StreamedSource>(
std::move(source_stream), script_source_encoding);
CHECK(compile_hints_);
std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask>
script_streaming_task =
base::WrapUnique(v8::ScriptCompiler::StartStreaming(
isolate_, streamed_source.get(), script_type_,
compile_hints_ ? compile_hints_->compile_options()
: v8::ScriptCompiler::kNoCompileOptions,
compile_hints_ ? compile_hints_->GetCompileHintCallback()
: nullptr,
compile_hints_ ? compile_hints_->GetCompileHintCallbackData()
: nullptr));
compile_hints_->compile_options(),
compile_hints_->GetCompileHintCallback(),
compile_hints_->GetCompileHintCallbackData()));
if (!script_streaming_task) {
// V8 can't stream the script.
body_ = source_stream_ptr_->ReleaseDataPipe();

@ -189,7 +189,7 @@ class ScriptStreamingTest : public testing::Test {
: url_(String("http://streaming-test.example.com/foo" +
base::NumberToString(url_counter_++))) {}
void Init(v8::Isolate* isolate) {
void Init(v8::Isolate* isolate, bool use_response_http_scheme = true) {
auto* properties = MakeGarbageCollected<TestResourceFetcherProperties>();
FetchContext* context = MakeGarbageCollected<MockFetchContext>();
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
@ -214,14 +214,19 @@ class ScriptStreamingTest : public testing::Test {
kNoCompileHintsProducer = nullptr;
constexpr v8_compile_hints::V8CrowdsourcedCompileHintsConsumer*
kNoCompileHintsConsumer = nullptr;
resource_ =
ScriptResource::Fetch(params, fetcher, resource_client_, isolate,
ScriptResource::kAllowStreaming,
kNoCompileHintsProducer, kNoCompileHintsConsumer);
constexpr bool kNoV8CompileHintsMagicCommentRuntimeEnabled = false;
resource_ = ScriptResource::Fetch(
params, fetcher, resource_client_, isolate,
ScriptResource::kAllowStreaming, kNoCompileHintsProducer,
kNoCompileHintsConsumer, kNoV8CompileHintsMagicCommentRuntimeEnabled);
resource_->AddClient(resource_client_, task_runner.get());
ResourceResponse response(url_);
response.SetHttpStatusCode(200);
if (!use_response_http_scheme) {
response.SetCurrentRequestUrl(KURL("file:///something"));
}
resource_->SetResponse(response);
resource_->Loader()->DidReceiveResponse(WrappedResourceResponse(response),
@ -727,6 +732,25 @@ TEST_F(ScriptStreamingTest, ProduceLocalCompileHintsForStreamedScript) {
EXPECT_EQ(1UL, compile_hints.size());
}
TEST_F(ScriptStreamingTest, NullCacheHandler) {
V8TestingScope scope;
// Use setting the responses URL to something else than HTTP(S) to trigger the
// "streaming but no cache handler" corner case.
Init(scope.GetIsolate(), /*use_response_http_scheme=*/false);
EXPECT_FALSE(resource_->CacheHandler());
AppendData("/*this doesn't matter*/");
Finish();
RunUntilResourceLoaded();
EXPECT_TRUE(resource_client_->Finished());
ScriptStreamer* script_streamer = std::get<0>(
ScriptStreamer::TakeFrom(resource_, mojom::blink::ScriptType::kClassic));
ResourceScriptStreamer* resource_script_streamer =
reinterpret_cast<ResourceScriptStreamer*>(script_streamer);
EXPECT_TRUE(resource_script_streamer);
}
INSTANTIATE_TEST_SUITE_P(
All,
InlineScriptStreamingTest,
@ -1002,10 +1026,11 @@ class BackgroundResourceScriptStreamerTest : public testing::Test {
}
constexpr v8_compile_hints::V8CrowdsourcedCompileHintsProducer*
kNoCompileHintsProducer = nullptr;
resource_ = ScriptResource::Fetch(params, fetcher, resource_client_,
isolate, ScriptResource::kAllowStreaming,
kNoCompileHintsProducer,
v8_compile_hints_consumer);
constexpr bool kNoV8CompileHintsMagicCommentRuntimeEnabled = false;
resource_ = ScriptResource::Fetch(
params, fetcher, resource_client_, isolate,
ScriptResource::kAllowStreaming, kNoCompileHintsProducer,
v8_compile_hints_consumer, kNoV8CompileHintsMagicCommentRuntimeEnabled);
resource_->AddClient(resource_client_, main_thread_task_runner.get());
CHECK(dummy_loader_factory->load_started());

@ -159,6 +159,9 @@ constexpr const char* kCacheSetHistogram =
// Check previously stored timestamp (either from the code cache or compile
// hints cache).
bool V8CodeCache::HasHotTimestamp(const CachedMetadataHandler* cache_handler) {
if (!cache_handler) {
return false;
}
scoped_refptr<CachedMetadata> cached_metadata =
cache_handler->GetCachedMetadata(
V8CodeCache::TagForTimeStamp(cache_handler),
@ -175,6 +178,15 @@ bool V8CodeCache::HasHotTimestamp(const CachedMetadataHandler* cache_handler) {
return false;
}
bool V8CodeCache::HasHotTimestamp(const CachedMetadata& data,
const String& encoding) {
if (data.DataTypeID() != CacheTag(kCacheTagCompileHints, encoding) &&
data.DataTypeID() != CacheTag(kCacheTagTimeStamp, encoding)) {
return false;
}
return TimestampIsRecent(&data);
}
bool V8CodeCache::HasCodeCache(
const CachedMetadataHandler* cache_handler,
CachedMetadataHandler::GetCachedMetadataBehavior behavior) {
@ -253,27 +265,45 @@ scoped_refptr<CachedMetadata> V8CodeCache::GetCachedMetadataForCompileHints(
std::tuple<v8::ScriptCompiler::CompileOptions,
V8CodeCache::ProduceCacheOptions,
v8::ScriptCompiler::NoCacheReason>
V8CodeCache::GetCompileOptions(mojom::blink::V8CacheOptions cache_options,
const ClassicScript& classic_script,
bool might_generate_crowdsourced_compile_hints,
bool can_use_crowdsourced_compile_hints) {
V8CodeCache::GetCompileOptions(
mojom::blink::V8CacheOptions cache_options,
const ClassicScript& classic_script,
bool might_generate_crowdsourced_compile_hints,
bool can_use_crowdsourced_compile_hints,
bool v8_compile_hints_magic_comment_runtime_enabled) {
return GetCompileOptions(
cache_options, classic_script.CacheHandler(),
classic_script.SourceText().length(), classic_script.SourceLocationType(),
classic_script.SourceUrl(), might_generate_crowdsourced_compile_hints,
can_use_crowdsourced_compile_hints);
can_use_crowdsourced_compile_hints,
v8_compile_hints_magic_comment_runtime_enabled);
}
namespace {
v8::ScriptCompiler::CompileOptions MaybeAddCompileHintsMagic(
v8::ScriptCompiler::CompileOptions compile_options,
bool v8_compile_hints_magic_comment_runtime_enabled) {
if (v8_compile_hints_magic_comment_runtime_enabled) {
return v8::ScriptCompiler::CompileOptions(
compile_options | v8::ScriptCompiler::kFollowCompileHintsMagicComment);
}
return compile_options;
}
} // namespace
std::tuple<v8::ScriptCompiler::CompileOptions,
V8CodeCache::ProduceCacheOptions,
v8::ScriptCompiler::NoCacheReason>
V8CodeCache::GetCompileOptions(mojom::blink::V8CacheOptions cache_options,
const CachedMetadataHandler* cache_handler,
size_t source_text_length,
ScriptSourceLocationType source_location_type,
const KURL& url,
bool might_generate_crowdsourced_compile_hints,
bool can_use_crowdsourced_compile_hints) {
V8CodeCache::GetCompileOptions(
mojom::blink::V8CacheOptions cache_options,
const CachedMetadataHandler* cache_handler,
size_t source_text_length,
ScriptSourceLocationType source_location_type,
const KURL& url,
bool might_generate_crowdsourced_compile_hints,
bool can_use_crowdsourced_compile_hints,
bool v8_compile_hints_magic_comment_runtime_enabled) {
static const int kMinimalCodeLength = 1024;
v8::ScriptCompiler::NoCacheReason no_cache_reason;
@ -347,8 +377,8 @@ V8CodeCache::GetCompileOptions(mojom::blink::V8CacheOptions cache_options,
RecordCacheGetStatistics(cache_handler);
if (HasCodeCache(cache_handler) &&
no_code_cache_compile_options !=
v8::ScriptCompiler::kProduceCompileHints) {
(no_code_cache_compile_options &
v8::ScriptCompiler::kProduceCompileHints) == 0) {
return std::make_tuple(v8::ScriptCompiler::kConsumeCodeCache,
ProduceCacheOptions::kNoProduceCache,
no_cache_reason);
@ -387,24 +417,35 @@ V8CodeCache::GetCompileOptions(mojom::blink::V8CacheOptions cache_options,
ProduceCacheOptions::kSetTimeStamp,
v8::ScriptCompiler::kNoCacheBecauseCacheTooCold);
}
return std::make_tuple(no_code_cache_compile_options,
ProduceCacheOptions::kSetTimeStamp,
v8::ScriptCompiler::kNoCacheBecauseCacheTooCold);
return std::make_tuple(
MaybeAddCompileHintsMagic(
no_code_cache_compile_options,
v8_compile_hints_magic_comment_runtime_enabled),
ProduceCacheOptions::kSetTimeStamp,
v8::ScriptCompiler::kNoCacheBecauseCacheTooCold);
}
if (local_compile_hints_enabled && HasCompileHints(cache_handler)) {
// In this branch, the timestamp in the compile hints is hot.
return std::make_tuple(
v8::ScriptCompiler::kConsumeCompileHints,
MaybeAddCompileHintsMagic(
v8::ScriptCompiler::kConsumeCompileHints,
v8_compile_hints_magic_comment_runtime_enabled),
ProduceCacheOptions::kProduceCodeCache,
v8::ScriptCompiler::kNoCacheBecauseDeferredProduceCodeCache);
}
return std::make_tuple(
no_code_cache_compile_options, ProduceCacheOptions::kProduceCodeCache,
MaybeAddCompileHintsMagic(
no_code_cache_compile_options,
v8_compile_hints_magic_comment_runtime_enabled),
ProduceCacheOptions::kProduceCodeCache,
v8::ScriptCompiler::kNoCacheBecauseDeferredProduceCodeCache);
}
case mojom::blink::V8CacheOptions::kCodeWithoutHeatCheck:
return std::make_tuple(
no_code_cache_compile_options, ProduceCacheOptions::kProduceCodeCache,
MaybeAddCompileHintsMagic(
no_code_cache_compile_options,
v8_compile_hints_magic_comment_runtime_enabled),
ProduceCacheOptions::kProduceCodeCache,
v8::ScriptCompiler::kNoCacheBecauseDeferredProduceCodeCache);
case mojom::blink::V8CacheOptions::kFullCodeWithoutHeatCheck:
return std::make_tuple(

@ -55,6 +55,8 @@ class CORE_EXPORT V8CodeCache final {
// Returns true iff the CachedMetadataHandler contains a hot time stamp or a
// compile hints cache containing a hot timestamp.
static bool HasHotTimestamp(const CachedMetadataHandler* cache_handler);
static bool HasHotTimestamp(const CachedMetadata& data,
const String& encoding);
// Returns true iff the CachedMetadataHandler contains a code cache
// that can be consumed by V8.
@ -76,20 +78,24 @@ class CORE_EXPORT V8CodeCache final {
static std::tuple<v8::ScriptCompiler::CompileOptions,
ProduceCacheOptions,
v8::ScriptCompiler::NoCacheReason>
GetCompileOptions(mojom::blink::V8CacheOptions,
const ClassicScript&,
bool might_generate_crowdsourced_compile_hints = false,
bool can_use_crowdsourced_compile_hints = false);
GetCompileOptions(
mojom::blink::V8CacheOptions cache_options,
const ClassicScript&,
bool might_generate_crowdsourced_compile_hints = false,
bool can_use_crowdsourced_compile_hints = false,
bool v8_compile_hints_magic_comment_runtime_enabled = false);
static std::tuple<v8::ScriptCompiler::CompileOptions,
ProduceCacheOptions,
v8::ScriptCompiler::NoCacheReason>
GetCompileOptions(mojom::blink::V8CacheOptions,
const CachedMetadataHandler*,
size_t source_text_length,
ScriptSourceLocationType,
const KURL& url,
bool might_generate_crowdsourced_compile_hints = false,
bool can_use_crowdsourced_compile_hints = false);
GetCompileOptions(
mojom::blink::V8CacheOptions cache_options,
const CachedMetadataHandler*,
size_t source_text_length,
ScriptSourceLocationType,
const KURL& url,
bool might_generate_crowdsourced_compile_hints = false,
bool can_use_crowdsourced_compile_hints = false,
bool v8_compile_hints_magic_comment_runtime_enabled = false);
static bool IsFull(const CachedMetadata* metadata);

@ -24,7 +24,8 @@ static bool LocalCompileHintsEnabled() {
CompileHintsForStreaming::Builder::Builder(
V8CrowdsourcedCompileHintsProducer* crowdsourced_compile_hints_producer,
V8CrowdsourcedCompileHintsConsumer* crowdsourced_compile_hints_consumer,
const KURL& resource_url)
const KURL& resource_url,
bool v8_compile_hints_magic_comment_runtime_enabled)
: might_generate_crowdsourced_compile_hints_(
crowdsourced_compile_hints_producer &&
crowdsourced_compile_hints_producer->MightGenerateData()),
@ -34,13 +35,26 @@ CompileHintsForStreaming::Builder::Builder(
crowdsourced_compile_hints_consumer->HasData())
? crowdsourced_compile_hints_consumer->GetDataWithScriptNameHash(
ScriptNameHash(resource_url))
: nullptr) {}
: nullptr),
v8_compile_hints_magic_comment_runtime_enabled_(
v8_compile_hints_magic_comment_runtime_enabled) {}
std::unique_ptr<CompileHintsForStreaming>
CompileHintsForStreaming::Builder::Build(
scoped_refptr<CachedMetadata> cached_metadata) && {
scoped_refptr<CachedMetadata> hot_cached_metadata_for_local_compile_hints,
bool has_hot_timestamp) && {
// hot_cached_metadata_for_local_compile_hints != null implies
// has_hot_timestamp.
CHECK(!hot_cached_metadata_for_local_compile_hints || has_hot_timestamp);
v8::ScriptCompiler::CompileOptions additional_compile_options =
(v8_compile_hints_magic_comment_runtime_enabled_ && has_hot_timestamp)
? v8::ScriptCompiler::kFollowCompileHintsMagicComment
: v8::ScriptCompiler::kNoCompileOptions;
if (might_generate_crowdsourced_compile_hints_) {
return std::make_unique<CompileHintsForStreaming>(base::PassKey<Builder>());
return std::make_unique<CompileHintsForStreaming>(
/*produce_compile_hints=*/true, additional_compile_options,
base::PassKey<Builder>());
}
// We can only consume local or crowdsourced compile hints, but
// not both at the same time. If the page has crowdsourced compile hints,
@ -58,16 +72,16 @@ CompileHintsForStreaming::Builder::Build(
if (crowdsourced_compile_hint_callback_data_) {
return std::make_unique<CompileHintsForStreaming>(
std::move(crowdsourced_compile_hint_callback_data_),
base::PassKey<Builder>());
additional_compile_options, base::PassKey<Builder>());
}
if (LocalCompileHintsEnabled() && cached_metadata) {
if (LocalCompileHintsEnabled() &&
hot_cached_metadata_for_local_compile_hints) {
auto local_compile_hints_consumer =
std::make_unique<v8_compile_hints::V8LocalCompileHintsConsumer>(
cached_metadata.get());
hot_cached_metadata_for_local_compile_hints.get());
if (local_compile_hints_consumer->IsRejected()) {
base::UmaHistogramEnumeration(kStatusHistogram,
Status::kNoCompileHintsStreaming);
return nullptr;
return std::make_unique<CompileHintsForStreaming>(
false, additional_compile_options, base::PassKey<Builder>());
}
// TODO(40286622): It's not clear what we should do if the resource is
// not hot but we have compile hints. 1) Consume compile hints and
@ -75,27 +89,45 @@ CompileHintsForStreaming::Builder::Build(
// compile hints. 2) Ignore existing compile hints (we're anyway not
// creating the code cache yet) and produce new ones.
return std::make_unique<CompileHintsForStreaming>(
std::move(local_compile_hints_consumer), base::PassKey<Builder>());
std::move(local_compile_hints_consumer), additional_compile_options,
base::PassKey<Builder>());
}
if (LocalCompileHintsEnabled()) {
// For producing a local compile hints.
return std::make_unique<CompileHintsForStreaming>(base::PassKey<Builder>());
return std::make_unique<CompileHintsForStreaming>(
/*produce_compile_hints=*/true, additional_compile_options,
base::PassKey<Builder>());
}
base::UmaHistogramEnumeration(kStatusHistogram,
Status::kNoCompileHintsStreaming);
return nullptr;
return std::make_unique<CompileHintsForStreaming>(
/*produce_compile_hints=*/false, additional_compile_options,
base::PassKey<Builder>());
}
CompileHintsForStreaming::CompileHintsForStreaming(base::PassKey<Builder>)
: compile_options_(v8::ScriptCompiler::kProduceCompileHints) {
base::UmaHistogramEnumeration(kStatusHistogram,
Status::kProduceCompileHintsStreaming);
CompileHintsForStreaming::CompileHintsForStreaming(
bool produce_compile_hints,
v8::ScriptCompiler::CompileOptions additional_compile_options,
base::PassKey<Builder>)
: compile_options_(produce_compile_hints
? v8::ScriptCompiler::CompileOptions(
v8::ScriptCompiler::kProduceCompileHints |
additional_compile_options)
: additional_compile_options) {
if (produce_compile_hints) {
base::UmaHistogramEnumeration(kStatusHistogram,
Status::kProduceCompileHintsStreaming);
} else {
base::UmaHistogramEnumeration(kStatusHistogram,
Status::kNoCompileHintsStreaming);
}
}
CompileHintsForStreaming::CompileHintsForStreaming(
std::unique_ptr<V8LocalCompileHintsConsumer> local_compile_hints_consumer,
v8::ScriptCompiler::CompileOptions additional_compile_options,
base::PassKey<Builder>)
: compile_options_(v8::ScriptCompiler::kConsumeCompileHints),
: compile_options_(v8::ScriptCompiler::CompileOptions(
v8::ScriptCompiler::kConsumeCompileHints |
additional_compile_options)),
local_compile_hints_consumer_(std::move(local_compile_hints_consumer)) {
base::UmaHistogramEnumeration(kStatusHistogram,
Status::kConsumeLocalCompileHintsStreaming);
@ -104,8 +136,11 @@ CompileHintsForStreaming::CompileHintsForStreaming(
CompileHintsForStreaming::CompileHintsForStreaming(
std::unique_ptr<V8CrowdsourcedCompileHintsConsumer::DataAndScriptNameHash>
crowdsourced_compile_hint_callback_data,
v8::ScriptCompiler::CompileOptions additional_compile_options,
base::PassKey<Builder>)
: compile_options_(v8::ScriptCompiler::kConsumeCompileHints),
: compile_options_(v8::ScriptCompiler::CompileOptions(
v8::ScriptCompiler::kConsumeCompileHints |
additional_compile_options)),
crowdsourced_compile_hint_callback_data_(
std::move(crowdsourced_compile_hint_callback_data)) {
base::UmaHistogramEnumeration(

@ -36,31 +36,40 @@ class CORE_EXPORT CompileHintsForStreaming {
Builder(
V8CrowdsourcedCompileHintsProducer* crowdsourced_compile_hints_producer,
V8CrowdsourcedCompileHintsConsumer* crowdsourced_compile_hints_consumer,
const KURL& resource_url);
const KURL& resource_url,
bool v8_compile_hints_magic_comment_runtime_enabled);
Builder(const Builder&) = delete;
Builder& operator=(const Builder&) = delete;
~Builder() = default;
// This method can be called on non-main thread.
std::unique_ptr<CompileHintsForStreaming> Build(
scoped_refptr<CachedMetadata> cached_metadata) &&;
scoped_refptr<CachedMetadata>
hot_cached_metadata_for_local_compile_hints,
bool has_hot_timestamp) &&;
private:
const bool might_generate_crowdsourced_compile_hints_;
std::unique_ptr<V8CrowdsourcedCompileHintsConsumer::DataAndScriptNameHash>
crowdsourced_compile_hint_callback_data_;
const bool v8_compile_hints_magic_comment_runtime_enabled_;
};
// For producing compile hints.
explicit CompileHintsForStreaming(base::PassKey<Builder>);
// For producing compile hints or just transmitting the compiler options.
CompileHintsForStreaming(
bool produce_compile_hints,
v8::ScriptCompiler::CompileOptions additional_compile_options,
base::PassKey<Builder>);
// For consuming local compile hints.
CompileHintsForStreaming(
std::unique_ptr<V8LocalCompileHintsConsumer> local_compile_hints_consumer,
v8::ScriptCompiler::CompileOptions additional_compile_options,
base::PassKey<Builder>);
// For consuming crowdsourced compile hints.
CompileHintsForStreaming(
std::unique_ptr<V8CrowdsourcedCompileHintsConsumer::DataAndScriptNameHash>
crowdsourced_compile_hint_callback_data,
v8::ScriptCompiler::CompileOptions additional_compile_options,
base::PassKey<Builder>);
CompileHintsForStreaming(const CompileHintsForStreaming&) = delete;

@ -38,31 +38,71 @@ class CompileHintsForStreamingTest : public ::testing::Test {
test::TaskEnvironment task_environment_;
};
TEST_F(CompileHintsForStreamingTest, NoCrowdsourcedNoLocal) {
TEST_F(CompileHintsForStreamingTest, NoCrowdsourcedNoLocalNoMagicComment1) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndDisableFeature(features::kLocalCompileHints);
auto builder = CompileHintsForStreaming::Builder(
/*crowdsourced_compile_hints_producer=*/nullptr,
/*crowdsourced_compile_hints_consumer=*/nullptr,
KURL("https://example.com/"));
KURL("https://example.com/"),
/*v8_compile_hints_magic_comment_runtime_enabled=*/false);
base::HistogramTester histogram_tester;
auto compile_hints_for_streaming =
std::move(builder).Build(/*cached_metadata=*/nullptr);
auto compile_hints_for_streaming = std::move(builder).Build(
/*cached_metadata=*/nullptr, /*has_hot_timestamp=*/true);
histogram_tester.ExpectUniqueSample(kStatusHistogram,
Status::kNoCompileHintsStreaming, 1);
EXPECT_FALSE(compile_hints_for_streaming);
ASSERT_TRUE(compile_hints_for_streaming);
EXPECT_EQ(v8::ScriptCompiler::kNoCompileOptions,
compile_hints_for_streaming->compile_options());
}
TEST_F(CompileHintsForStreamingTest, ProduceLocal) {
TEST_F(CompileHintsForStreamingTest, NoCrowdsourcedNoLocalNoMagicComment2) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndDisableFeature(features::kLocalCompileHints);
auto builder = CompileHintsForStreaming::Builder(
/*crowdsourced_compile_hints_producer=*/nullptr,
/*crowdsourced_compile_hints_consumer=*/nullptr,
KURL("https://example.com/"),
/*v8_compile_hints_magic_comment_runtime_enabled=*/true);
base::HistogramTester histogram_tester;
auto compile_hints_for_streaming = std::move(builder).Build(
/*cached_metadata=*/nullptr, /*has_hot_timestamp=*/false);
histogram_tester.ExpectUniqueSample(kStatusHistogram,
Status::kNoCompileHintsStreaming, 1);
ASSERT_TRUE(compile_hints_for_streaming);
EXPECT_EQ(v8::ScriptCompiler::kNoCompileOptions,
compile_hints_for_streaming->compile_options());
}
TEST_F(CompileHintsForStreamingTest, NoCrowdsourcedNoLocalButMagicComment) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndDisableFeature(features::kLocalCompileHints);
auto builder = CompileHintsForStreaming::Builder(
/*crowdsourced_compile_hints_producer=*/nullptr,
/*crowdsourced_compile_hints_consumer=*/nullptr,
KURL("https://example.com/"),
/*v8_compile_hints_magic_comment_runtime_enabled=*/true);
base::HistogramTester histogram_tester;
auto compile_hints_for_streaming = std::move(builder).Build(
/*cached_metadata=*/nullptr, /*has_hot_timestamp=*/true);
histogram_tester.ExpectUniqueSample(kStatusHistogram,
Status::kNoCompileHintsStreaming, 1);
ASSERT_TRUE(compile_hints_for_streaming);
EXPECT_EQ(v8::ScriptCompiler::kFollowCompileHintsMagicComment,
compile_hints_for_streaming->compile_options());
}
TEST_F(CompileHintsForStreamingTest, ProduceLocalNoMagicComment) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(features::kLocalCompileHints);
auto builder = CompileHintsForStreaming::Builder(
/*crowdsourced_compile_hints_producer=*/nullptr,
/*crowdsourced_compile_hints_consumer=*/nullptr,
KURL("https://example.com/"));
KURL("https://example.com/"),
/*v8_compile_hints_magic_comment_runtime_enabled=*/true);
base::HistogramTester histogram_tester;
auto compile_hints_for_streaming =
std::move(builder).Build(/*cached_metadata=*/nullptr);
auto compile_hints_for_streaming = std::move(builder).Build(
/*cached_metadata=*/nullptr, /*has_hot_timestamp=*/false);
histogram_tester.ExpectUniqueSample(kStatusHistogram,
Status::kProduceCompileHintsStreaming, 1);
ASSERT_TRUE(compile_hints_for_streaming);
@ -72,13 +112,14 @@ TEST_F(CompileHintsForStreamingTest, ProduceLocal) {
EXPECT_FALSE(compile_hints_for_streaming->GetCompileHintCallbackData());
}
TEST_F(CompileHintsForStreamingTest, ConsumeLocal) {
TEST_F(CompileHintsForStreamingTest, ConsumeLocalNoMagicComment) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(features::kLocalCompileHints);
auto builder = CompileHintsForStreaming::Builder(
/*crowdsourced_compile_hints_producer=*/nullptr,
/*crowdsourced_compile_hints_consumer=*/nullptr,
KURL("https://example.com/"));
KURL("https://example.com/"),
/*v8_compile_hints_magic_comment_runtime_enabled=*/false);
const uint32_t kCacheTagCompileHints = 2;
const uint64_t kDummyTag = 1;
Vector<uint8_t> dummy_data(100);
@ -86,7 +127,7 @@ TEST_F(CompileHintsForStreamingTest, ConsumeLocal) {
kCacheTagCompileHints, dummy_data.data(), dummy_data.size(), kDummyTag);
base::HistogramTester histogram_tester;
auto compile_hints_for_streaming =
std::move(builder).Build(std::move(metadata));
std::move(builder).Build(std::move(metadata), /*has_hot_timestamp=*/true);
histogram_tester.ExpectUniqueSample(
kStatusHistogram, Status::kConsumeLocalCompileHintsStreaming, 1);
ASSERT_TRUE(compile_hints_for_streaming);
@ -98,25 +139,80 @@ TEST_F(CompileHintsForStreamingTest, ConsumeLocal) {
EXPECT_TRUE(compile_hints_for_streaming->GetCompileHintCallbackData());
}
TEST_F(CompileHintsForStreamingTest, FailedToConsumeLocalWrongSize) {
TEST_F(CompileHintsForStreamingTest, ConsumeLocalMagicComment) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(features::kLocalCompileHints);
auto builder = CompileHintsForStreaming::Builder(
/*crowdsourced_compile_hints_producer=*/nullptr,
/*crowdsourced_compile_hints_consumer=*/nullptr,
KURL("https://example.com/"),
/*v8_compile_hints_magic_comment_runtime_enabled=*/true);
const uint32_t kCacheTagCompileHints = 2;
const uint64_t kDummyTag = 1;
Vector<uint8_t> dummy_data(100);
scoped_refptr<CachedMetadata> metadata = CachedMetadata::Create(
kCacheTagCompileHints, dummy_data.data(), dummy_data.size(), kDummyTag);
base::HistogramTester histogram_tester;
auto compile_hints_for_streaming =
std::move(builder).Build(std::move(metadata), /*has_hot_timestamp=*/true);
histogram_tester.ExpectUniqueSample(
kStatusHistogram, Status::kConsumeLocalCompileHintsStreaming, 1);
ASSERT_TRUE(compile_hints_for_streaming);
EXPECT_EQ(compile_hints_for_streaming->compile_options(),
v8::ScriptCompiler::kConsumeCompileHints |
v8::ScriptCompiler::kFollowCompileHintsMagicComment);
EXPECT_EQ(
compile_hints_for_streaming->GetCompileHintCallback(),
v8::CompileHintCallback(V8LocalCompileHintsConsumer::GetCompileHint));
EXPECT_TRUE(compile_hints_for_streaming->GetCompileHintCallbackData());
}
TEST_F(CompileHintsForStreamingTest,
FailedToConsumeLocalWrongSizeNoMagicComment) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(features::kLocalCompileHints);
base::HistogramTester histogram_tester;
auto builder = CompileHintsForStreaming::Builder(
/*crowdsourced_compile_hints_producer=*/nullptr,
/*crowdsourced_compile_hints_consumer=*/nullptr,
KURL("https://example.com/"));
KURL("https://example.com/"),
/*v8_compile_hints_magic_comment_runtime_enabled=*/false);
const uint32_t kCacheTagCompileHints = 2;
const uint64_t kDummyTag = 1;
Vector<uint8_t> dummy_data(1); // Too small.
scoped_refptr<CachedMetadata> metadata = CachedMetadata::Create(
kCacheTagCompileHints, dummy_data.data(), dummy_data.size(), kDummyTag);
auto compile_hints_for_streaming =
std::move(builder).Build(std::move(metadata));
EXPECT_FALSE(compile_hints_for_streaming);
std::move(builder).Build(std::move(metadata), /*has_hot_timestamp=*/true);
EXPECT_TRUE(compile_hints_for_streaming);
EXPECT_EQ(v8::ScriptCompiler::kNoCompileOptions,
compile_hints_for_streaming->compile_options());
}
TEST_F(CompileHintsForStreamingTest, ConsumeCrowdsourcedHint) {
TEST_F(CompileHintsForStreamingTest,
FailedToConsumeLocalWrongSizeMagicComment) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(features::kLocalCompileHints);
base::HistogramTester histogram_tester;
auto builder = CompileHintsForStreaming::Builder(
/*crowdsourced_compile_hints_producer=*/nullptr,
/*crowdsourced_compile_hints_consumer=*/nullptr,
KURL("https://example.com/"),
/*v8_compile_hints_magic_comment_runtime_enabled=*/true);
const uint32_t kCacheTagCompileHints = 2;
const uint64_t kDummyTag = 1;
Vector<uint8_t> dummy_data(1); // Too small.
scoped_refptr<CachedMetadata> metadata = CachedMetadata::Create(
kCacheTagCompileHints, dummy_data.data(), dummy_data.size(), kDummyTag);
auto compile_hints_for_streaming =
std::move(builder).Build(std::move(metadata), /*has_hot_timestamp=*/true);
EXPECT_TRUE(compile_hints_for_streaming);
EXPECT_EQ(v8::ScriptCompiler::kNoCompileOptions |
v8::ScriptCompiler::kFollowCompileHintsMagicComment,
compile_hints_for_streaming->compile_options());
}
TEST_F(CompileHintsForStreamingTest, ConsumeCrowdsourcedHintNoMagicComment) {
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.Initialize();
Page* page = web_view_helper.GetWebView()->GetPage();
@ -131,11 +227,12 @@ TEST_F(CompileHintsForStreamingTest, ConsumeCrowdsourcedHint) {
auto builder = CompileHintsForStreaming::Builder(
crowdsourced_compile_hints_producer, crowdsourced_compile_hints_consumer,
KURL("https://example.com/"));
KURL("https://example.com/"),
/*v8_compile_hints_magic_comment_runtime_enabled=*/true);
base::HistogramTester histogram_tester;
auto compile_hints_for_streaming =
std::move(builder).Build(/*cached_metadata=*/nullptr);
auto compile_hints_for_streaming = std::move(builder).Build(
/*cached_metadata=*/nullptr, /*has_hot_timestamp=*/false);
histogram_tester.ExpectUniqueSample(
kStatusHistogram, Status::kConsumeCrowdsourcedCompileHintsStreaming, 1);
@ -170,9 +267,11 @@ TEST_F(CompileHintsForStreamingTest, PreferCrowdsourcedHints) {
base::HistogramTester histogram_tester;
auto builder = CompileHintsForStreaming::Builder(
crowdsourced_compile_hints_producer, crowdsourced_compile_hints_consumer,
KURL("https://example.com/"));
KURL("https://example.com/"),
/*v8_compile_hints_magic_comment_runtime_enabled=*/true);
auto compile_hints_for_streaming = std::move(builder).Build(metadata);
auto compile_hints_for_streaming =
std::move(builder).Build(metadata, /*has_hot_timestamp=*/true);
// We prefer crowdsourced hints over local hints, if both are available.
histogram_tester.ExpectUniqueSample(
@ -180,13 +279,14 @@ TEST_F(CompileHintsForStreamingTest, PreferCrowdsourcedHints) {
ASSERT_TRUE(compile_hints_for_streaming);
EXPECT_EQ(compile_hints_for_streaming->compile_options(),
v8::ScriptCompiler::kConsumeCompileHints);
v8::ScriptCompiler::kConsumeCompileHints |
v8::ScriptCompiler::kFollowCompileHintsMagicComment);
EXPECT_EQ(compile_hints_for_streaming->GetCompileHintCallback(),
&V8CrowdsourcedCompileHintsConsumer::CompileHintCallback);
EXPECT_TRUE(compile_hints_for_streaming->GetCompileHintCallbackData());
}
TEST_F(CompileHintsForStreamingTest, ProduceCrowdsourcedHint) {
TEST_F(CompileHintsForStreamingTest, ProduceCrowdsourcedHintNoMagicComment) {
// Disable local compile hints, since otherwise we'd always produce compile
// hints anyway, and couldn't test producing compile hints for crowdsourcing
// purposes.
@ -205,24 +305,69 @@ TEST_F(CompileHintsForStreamingTest, ProduceCrowdsourcedHint) {
auto builder = CompileHintsForStreaming::Builder(
crowdsourced_compile_hints_producer, crowdsourced_compile_hints_consumer,
KURL("https://example.com/"));
KURL("https://example.com/"),
/*v8_compile_hints_magic_comment_runtime_enabled=*/true);
base::HistogramTester histogram_tester;
auto compile_hints_for_streaming =
std::move(builder).Build(/*cached_metadata=*/nullptr);
auto compile_hints_for_streaming = std::move(builder).Build(
/*cached_metadata=*/nullptr, /*has_hot_timestamp=*/false);
ASSERT_TRUE(compile_hints_for_streaming);
EXPECT_FALSE(compile_hints_for_streaming->GetCompileHintCallback());
EXPECT_FALSE(compile_hints_for_streaming->GetCompileHintCallbackData());
#if BUILDFLAG(PRODUCE_V8_COMPILE_HINTS)
histogram_tester.ExpectUniqueSample(kStatusHistogram,
Status::kProduceCompileHintsStreaming, 1);
ASSERT_TRUE(compile_hints_for_streaming);
EXPECT_EQ(compile_hints_for_streaming->compile_options(),
v8::ScriptCompiler::kProduceCompileHints);
EXPECT_FALSE(compile_hints_for_streaming->GetCompileHintCallback());
EXPECT_FALSE(compile_hints_for_streaming->GetCompileHintCallbackData());
#else // BUILDFLAG(PRODUCE_V8_COMPILE_HINTS)
histogram_tester.ExpectUniqueSample(kStatusHistogram,
Status::kNoCompileHintsStreaming, 1);
EXPECT_FALSE(compile_hints_for_streaming);
EXPECT_EQ(compile_hints_for_streaming->compile_options(),
v8::ScriptCompiler::kNoCompileOptions);
#endif
}
TEST_F(CompileHintsForStreamingTest, ProduceCrowdsourcedHintMagicComment) {
// Disable local compile hints, since otherwise we'd always produce compile
// hints anyway, and couldn't test producing compile hints for crowdsourcing
// purposes.
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitWithFeatures({features::kForceProduceCompileHints},
{features::kLocalCompileHints});
frame_test_helpers::WebViewHelper web_view_helper;
web_view_helper.Initialize();
Page* page = web_view_helper.GetWebView()->GetPage();
auto* crowdsourced_compile_hints_producer =
&page->GetV8CrowdsourcedCompileHintsProducer();
auto* crowdsourced_compile_hints_consumer =
&page->GetV8CrowdsourcedCompileHintsConsumer();
auto builder = CompileHintsForStreaming::Builder(
crowdsourced_compile_hints_producer, crowdsourced_compile_hints_consumer,
KURL("https://example.com/"),
/*v8_compile_hints_magic_comment_runtime_enabled=*/true);
base::HistogramTester histogram_tester;
auto compile_hints_for_streaming = std::move(builder).Build(
/*cached_metadata=*/nullptr, /*has_hot_timestamp=*/true);
ASSERT_TRUE(compile_hints_for_streaming);
EXPECT_FALSE(compile_hints_for_streaming->GetCompileHintCallback());
EXPECT_FALSE(compile_hints_for_streaming->GetCompileHintCallbackData());
#if BUILDFLAG(PRODUCE_V8_COMPILE_HINTS)
histogram_tester.ExpectUniqueSample(kStatusHistogram,
Status::kProduceCompileHintsStreaming, 1);
EXPECT_EQ(compile_hints_for_streaming->compile_options(),
v8::ScriptCompiler::kProduceCompileHints |
v8::ScriptCompiler::kFollowCompileHintsMagicComment);
#else // BUILDFLAG(PRODUCE_V8_COMPILE_HINTS)
histogram_tester.ExpectUniqueSample(kStatusHistogram,
Status::kNoCompileHintsStreaming, 1);
EXPECT_EQ(compile_hints_for_streaming->compile_options(),
v8::ScriptCompiler::kFollowCompileHintsMagicComment);
#endif
}

@ -157,8 +157,10 @@ v8::MaybeLocal<v8::Script> CompileScriptInternal(
return script;
}
switch (compile_options) {
case v8::ScriptCompiler::kConsumeCompileHints: {
switch (static_cast<int>(compile_options)) {
case v8::ScriptCompiler::kConsumeCompileHints:
case v8::ScriptCompiler::kConsumeCompileHints |
v8::ScriptCompiler::kFollowCompileHintsMagicComment: {
// We can only consume local or crowdsourced compile hints, but
// not both at the same time. If the page has crowdsourced compile hints,
// we won't generate local compile hints, so won't ever have them.
@ -219,10 +221,11 @@ v8::MaybeLocal<v8::Script> CompileScriptInternal(
ExecutionContext::GetCodeCacheHostFromContext(execution_context),
CachedMetadataHandler::kClearPersistentStorage);
// Compile without compile hints.
compile_options = v8::ScriptCompiler::CompileOptions(
compile_options & (~v8::ScriptCompiler::kConsumeCompileHints));
v8::ScriptCompiler::Source source(code, origin);
return v8::ScriptCompiler::Compile(
script_state->GetContext(), &source,
v8::ScriptCompiler::kNoCompileOptions, no_cache_reason);
return v8::ScriptCompiler::Compile(script_state->GetContext(), &source,
compile_options, no_cache_reason);
}
v8::ScriptCompiler::Source source(
code, origin,
@ -231,7 +234,9 @@ v8::MaybeLocal<v8::Script> CompileScriptInternal(
return v8::ScriptCompiler::Compile(script_state->GetContext(), &source,
compile_options, no_cache_reason);
}
case v8::ScriptCompiler::kProduceCompileHints: {
case v8::ScriptCompiler::kProduceCompileHints:
case v8::ScriptCompiler::kProduceCompileHints |
v8::ScriptCompiler::kFollowCompileHintsMagicComment: {
base::UmaHistogramEnumeration(
v8_compile_hints::kStatusHistogram,
v8_compile_hints::Status::kProduceCompileHintsClassicNonStreaming);
@ -240,7 +245,8 @@ v8::MaybeLocal<v8::Script> CompileScriptInternal(
compile_options, no_cache_reason);
}
case v8::ScriptCompiler::kNoCompileOptions:
case v8::ScriptCompiler::kEagerCompile: {
case v8::ScriptCompiler::kEagerCompile:
case v8::ScriptCompiler::kFollowCompileHintsMagicComment: {
base::UmaHistogramEnumeration(
v8_compile_hints::kStatusHistogram,
v8_compile_hints::Status::kNoCompileHintsClassicNonStreaming);
@ -607,18 +613,23 @@ ScriptEvaluationResult V8ScriptRunner::CompileAndRunScript(
V8CodeCache::ProduceCacheOptions produce_cache_options;
v8::ScriptCompiler::NoCacheReason no_cache_reason;
Page* page = frame != nullptr ? frame->GetPage() : nullptr;
bool is_http = classic_script->SourceUrl().ProtocolIsInHTTPFamily();
bool might_generate_crowdsourced_compile_hints =
const bool is_http = classic_script->SourceUrl().ProtocolIsInHTTPFamily();
const bool might_generate_crowdsourced_compile_hints =
is_http && page != nullptr &&
page->GetV8CrowdsourcedCompileHintsProducer().MightGenerateData();
bool can_use_crowdsourced_compile_hints =
const bool can_use_crowdsourced_compile_hints =
is_http && page != nullptr && page->MainFrame() == frame &&
page->GetV8CrowdsourcedCompileHintsConsumer().HasData();
const bool v8_compile_hints_magic_comment_runtime_enabled =
RuntimeEnabledFeatures::JavaScriptCompileHintsMagicRuntimeEnabled(
execution_context);
std::tie(compile_options, produce_cache_options, no_cache_reason) =
V8CodeCache::GetCompileOptions(
execution_context->GetV8CacheOptions(), *classic_script,
might_generate_crowdsourced_compile_hints,
can_use_crowdsourced_compile_hints);
can_use_crowdsourced_compile_hints,
v8_compile_hints_magic_comment_runtime_enabled);
v8::ScriptOrigin origin = classic_script->CreateScriptOrigin(isolate);
v8::MaybeLocal<v8::Value> maybe_result;

@ -46,10 +46,14 @@ void DocumentModuleScriptFetcher::Fetch(
kNoCompileHintsProducer = nullptr;
constexpr v8_compile_hints::V8CrowdsourcedCompileHintsConsumer*
kNoCompileHintsConsumer = nullptr;
const bool v8_compile_hints_magic_comment_runtime_enabled =
RuntimeEnabledFeatures::JavaScriptCompileHintsMagicRuntimeEnabled(
GetExecutionContext());
ScriptResource::Fetch(fetch_params, fetch_client_settings_object_fetcher,
this, GetExecutionContext()->GetIsolate(),
streaming_allowed, kNoCompileHintsProducer,
kNoCompileHintsConsumer);
kNoCompileHintsConsumer,
v8_compile_hints_magic_comment_runtime_enabled);
}
void DocumentModuleScriptFetcher::NotifyFinished(Resource* resource) {

@ -85,10 +85,12 @@ void WorkerModuleScriptFetcher::Fetch(
kNoCompileHintsProducer = nullptr;
constexpr v8_compile_hints::V8CrowdsourcedCompileHintsConsumer*
kNoCompileHintsConsumer = nullptr;
constexpr bool kNoV8CompileHintsMagicCommentRuntimeEnabledFeature = false;
ScriptResource::Fetch(fetch_params, fetch_client_settings_object_fetcher,
this, global_scope_->GetIsolate(),
ScriptResource::kNoStreaming, kNoCompileHintsProducer,
kNoCompileHintsConsumer);
kNoCompileHintsConsumer,
kNoV8CompileHintsMagicCommentRuntimeEnabledFeature);
}
void WorkerModuleScriptFetcher::Trace(Visitor* visitor) const {

@ -47,10 +47,12 @@ void WorkletModuleScriptFetcher::Fetch(
kNoCompileHintsProducer = nullptr;
constexpr v8_compile_hints::V8CrowdsourcedCompileHintsConsumer*
kNoCompileHintsConsumer = nullptr;
constexpr bool kNoV8CompileHintsMagicCommentRuntimeEnabledFeature = false;
ScriptResource::Fetch(fetch_params, fetch_client_settings_object_fetcher,
this, global_scope_->GetIsolate(),
ScriptResource::kNoStreaming, kNoCompileHintsProducer,
kNoCompileHintsConsumer);
kNoCompileHintsConsumer,
kNoV8CompileHintsMagicCommentRuntimeEnabledFeature);
}
void WorkletModuleScriptFetcher::NotifyFinished(Resource* resource) {

@ -944,10 +944,15 @@ Resource* PreloadHelper::StartPreload(ResourceType type,
params.SetRequestContext(mojom::blink::RequestContextType::SCRIPT);
params.SetRequestDestination(network::mojom::RequestDestination::kScript);
const bool v8_compile_hints_magic_comment_runtime_enabled =
RuntimeEnabledFeatures::JavaScriptCompileHintsMagicRuntimeEnabled(
document.GetExecutionContext());
resource = ScriptResource::Fetch(
params, resource_fetcher, nullptr, document.GetAgent().isolate(),
ScriptResource::kAllowStreaming, v8_compile_hints_producer,
v8_compile_hints_consumer);
v8_compile_hints_consumer,
v8_compile_hints_magic_comment_runtime_enabled);
break;
}
case ResourceType::kCSSStyleSheet:

@ -90,9 +90,11 @@ class ResourceLoaderCodeCacheTest : public testing::Test {
kNoCompileHintsProducer = nullptr;
constexpr v8_compile_hints::V8CrowdsourcedCompileHintsConsumer*
kNoCompileHintsConsumer = nullptr;
constexpr bool kNoV8CompileHintsMagicCommentRuntimeEnabledFeature = false;
resource_ = ScriptResource::Fetch(
params, fetcher, nullptr, isolate, ScriptResource::kNoStreaming,
kNoCompileHintsProducer, kNoCompileHintsConsumer);
kNoCompileHintsProducer, kNoCompileHintsConsumer,
kNoV8CompileHintsMagicCommentRuntimeEnabledFeature);
loader_ = resource_->Loader();
response_ = ResourceResponse(url);

@ -103,14 +103,17 @@ ScriptResource* ScriptResource::Fetch(
v8_compile_hints::V8CrowdsourcedCompileHintsProducer*
v8_compile_hints_producer,
v8_compile_hints::V8CrowdsourcedCompileHintsConsumer*
v8_compile_hints_consumer) {
v8_compile_hints_consumer,
bool v8_compile_hints_magic_comment_runtime_enabled) {
DCHECK(IsRequestContextSupported(
params.GetResourceRequest().GetRequestContext()));
auto* resource = To<ScriptResource>(fetcher->RequestResource(
params,
ScriptResourceFactory(isolate, streaming_allowed,
v8_compile_hints_producer,
v8_compile_hints_consumer, params.GetScriptType()),
v8_compile_hints_consumer,
v8_compile_hints_magic_comment_runtime_enabled,
params.GetScriptType()),
client));
return resource;
}
@ -128,7 +131,8 @@ ScriptResource* ScriptResource::CreateForTest(
return MakeGarbageCollected<ScriptResource>(
request, options, decoder_options, isolate, kNoStreaming,
/*v8_compile_hints_producer=*/nullptr,
/*v8_compile_hints_consumer=*/nullptr, script_type);
/*v8_compile_hints_consumer=*/nullptr,
/*v8_compile_hints_magic_comment_runtime_enabled=*/false, script_type);
}
ScriptResource::ScriptResource(
@ -141,6 +145,7 @@ ScriptResource::ScriptResource(
v8_compile_hints_producer,
v8_compile_hints::V8CrowdsourcedCompileHintsConsumer*
v8_compile_hints_consumer,
bool v8_compile_hints_magic_comment_runtime_enabled,
mojom::blink::ScriptType initial_request_script_type)
: TextResource(resource_request,
ResourceType::kScript,
@ -154,7 +159,9 @@ ScriptResource::ScriptResource(
stream_text_decoder_(
std::make_unique<TextResourceDecoder>(decoder_options)),
v8_compile_hints_producer_(v8_compile_hints_producer),
v8_compile_hints_consumer_(v8_compile_hints_consumer) {
v8_compile_hints_consumer_(v8_compile_hints_consumer),
v8_compile_hints_magic_comment_runtime_enabled_(
v8_compile_hints_magic_comment_runtime_enabled) {
static bool script_streaming_enabled =
base::FeatureList::IsEnabled(features::kScriptStreaming);
// TODO(leszeks): This could be static to avoid the cost of feature flag

@ -77,7 +77,8 @@ class CORE_EXPORT ScriptResource final : public TextResource {
v8::Isolate*,
StreamingAllowed,
v8_compile_hints::V8CrowdsourcedCompileHintsProducer*,
v8_compile_hints::V8CrowdsourcedCompileHintsConsumer*);
v8_compile_hints::V8CrowdsourcedCompileHintsConsumer*,
bool v8_compile_hints_magic_comment_runtime_enabled);
// Public for testing
static ScriptResource* CreateForTest(
@ -93,6 +94,7 @@ class CORE_EXPORT ScriptResource final : public TextResource {
StreamingAllowed,
v8_compile_hints::V8CrowdsourcedCompileHintsProducer*,
v8_compile_hints::V8CrowdsourcedCompileHintsConsumer*,
bool v8_compile_hints_magic_comment_runtime_enabled,
mojom::blink::ScriptType);
~ScriptResource() override;
@ -162,6 +164,10 @@ class CORE_EXPORT ScriptResource final : public TextResource {
return v8_compile_hints_consumer_.Get();
}
bool GetV8CompileHintsMagicCommentRuntimeFeatureEnabled() const {
return v8_compile_hints_magic_comment_runtime_enabled_;
}
// Returns the Isolate if set. This may be null.
v8::Isolate* GetIsolateOrNull() { return isolate_if_main_thread_; }
@ -227,6 +233,7 @@ class CORE_EXPORT ScriptResource final : public TextResource {
v8_compile_hints_producer,
v8_compile_hints::V8CrowdsourcedCompileHintsConsumer*
v8_compile_hints_consumer,
bool v8_compile_hints_magic_comment_runtime_enabled,
mojom::blink::ScriptType initial_request_script_type)
: ResourceFactory(ResourceType::kScript,
TextResourceDecoderOptions::kPlainTextContent),
@ -234,6 +241,8 @@ class CORE_EXPORT ScriptResource final : public TextResource {
streaming_allowed_(streaming_allowed),
v8_compile_hints_producer_(v8_compile_hints_producer),
v8_compile_hints_consumer_(v8_compile_hints_consumer),
v8_compile_hints_magic_comment_runtime_enabled_(
v8_compile_hints_magic_comment_runtime_enabled),
initial_request_script_type_(initial_request_script_type) {}
Resource* Create(
@ -243,6 +252,7 @@ class CORE_EXPORT ScriptResource final : public TextResource {
return MakeGarbageCollected<ScriptResource>(
request, options, decoder_options, isolate_, streaming_allowed_,
v8_compile_hints_producer_, v8_compile_hints_consumer_,
v8_compile_hints_magic_comment_runtime_enabled_,
initial_request_script_type_);
}
@ -253,6 +263,12 @@ class CORE_EXPORT ScriptResource final : public TextResource {
v8_compile_hints_producer_;
v8_compile_hints::V8CrowdsourcedCompileHintsConsumer*
v8_compile_hints_consumer_;
// For transmitting the status of the runtime enabled feature to script
// streaming, which can access the ScriptResource but not the
// ExecutionContext.
// TODO(42203853): Remove this once explicit compile hints have launched and
// the feature is always on.
bool v8_compile_hints_magic_comment_runtime_enabled_;
mojom::blink::ScriptType initial_request_script_type_;
};
@ -307,6 +323,13 @@ class CORE_EXPORT ScriptResource final : public TextResource {
Member<v8_compile_hints::V8CrowdsourcedCompileHintsConsumer>
v8_compile_hints_consumer_;
// For transmitting the status of the runtime enabled feature to script
// streaming, which can access the ScriptResource but not the
// ExecutionContext.
// TODO(42203853): Remove this once explicit compile hints have launched and
// the feature is always on.
bool v8_compile_hints_magic_comment_runtime_enabled_;
Member<BackgroundResourceScriptStreamer> background_streamer_;
};

@ -102,10 +102,14 @@ ClassicPendingScript* ClassicPendingScript::Fetch(
compile_hints_producer = &page->GetV8CrowdsourcedCompileHintsProducer();
compile_hints_consumer = &page->GetV8CrowdsourcedCompileHintsConsumer();
}
const bool v8_compile_hints_magic_comment_runtime_enabled =
RuntimeEnabledFeatures::JavaScriptCompileHintsMagicRuntimeEnabled(
element_document.GetExecutionContext());
ScriptResource::Fetch(params, element_document.Fetcher(), pending_script,
context->GetIsolate(), ScriptResource::kAllowStreaming,
compile_hints_producer, compile_hints_consumer);
compile_hints_producer, compile_hints_consumer,
v8_compile_hints_magic_comment_runtime_enabled);
pending_script->CheckState();
return pending_script;
}

@ -218,9 +218,11 @@ void PossiblyFetchBlockedDocWriteScript(
kNoCompileHintsProducer = nullptr;
constexpr v8_compile_hints::V8CrowdsourcedCompileHintsConsumer*
kNoCompileHintsConsumer = nullptr;
constexpr bool kNoV8CompileHintsMagicCommentRuntimeEnabledFeature = false;
ScriptResource::Fetch(params, element_document.Fetcher(), nullptr,
context->GetIsolate(), ScriptResource::kNoStreaming,
kNoCompileHintsProducer, kNoCompileHintsConsumer);
kNoCompileHintsProducer, kNoCompileHintsConsumer,
kNoV8CompileHintsMagicCommentRuntimeEnabledFeature);
}
} // namespace blink