[compiler] Off-thread deserialization ♥️ Isolate cache
Make off-thread deserialization play well with the Isolate compilation cache, by moving the Finish call into GetSharedFunctionInfoForScript. This means that a) The isolate cache is checked before the Finish, allowing it to be hit, and b) Results of off-thread deserializations are written into the Isolate cache. Bug: chromium:1075999 Change-Id: I535935180bbe77f3e718253830e649bd62857634 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3094006 Commit-Queue: Leszek Swirski <leszeks@chromium.org> Auto-Submit: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Camillo Bruni <cbruni@chromium.org> Cr-Commit-Position: refs/heads/master@{#76341}
This commit is contained in:
parent
a69080060d
commit
df2b169b3f
@ -2420,42 +2420,45 @@ MaybeLocal<UnboundScript> ScriptCompiler::CompileUnboundInternal(
|
||||
|
||||
i::Handle<i::String> str = Utils::OpenHandle(*(source->source_string));
|
||||
|
||||
std::unique_ptr<i::AlignedCachedData> cached_data;
|
||||
if (options == kConsumeCodeCache) {
|
||||
if (source->consume_cache_task) {
|
||||
// If there's a cache consume task, finish it
|
||||
i::MaybeHandle<i::SharedFunctionInfo> maybe_function_info =
|
||||
source->consume_cache_task->impl_->Finish(isolate, str,
|
||||
source->resource_options);
|
||||
i::Handle<i::SharedFunctionInfo> result;
|
||||
if (maybe_function_info.ToHandle(&result)) {
|
||||
RETURN_ESCAPED(ToApiHandle<UnboundScript>(result));
|
||||
}
|
||||
// If the above failed, then we must have rejected the cache. Continue
|
||||
// with normal compilation, disabling the code cache consumption.
|
||||
source->cached_data->rejected = true;
|
||||
options = kNoCompileOptions;
|
||||
} else {
|
||||
DCHECK(source->cached_data);
|
||||
// AlignedCachedData takes care of pointer-aligning the data.
|
||||
cached_data.reset(new i::AlignedCachedData(source->cached_data->data,
|
||||
source->cached_data->length));
|
||||
}
|
||||
}
|
||||
|
||||
i::Handle<i::SharedFunctionInfo> result;
|
||||
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileScript");
|
||||
i::ScriptDetails script_details = GetScriptDetails(
|
||||
isolate, source->resource_name, source->resource_line_offset,
|
||||
source->resource_column_offset, source->source_map_url,
|
||||
source->host_defined_options, source->resource_options);
|
||||
i::MaybeHandle<i::SharedFunctionInfo> maybe_function_info =
|
||||
i::Compiler::GetSharedFunctionInfoForScript(
|
||||
isolate, str, script_details, nullptr, cached_data.get(), options,
|
||||
no_cache_reason, i::NOT_NATIVES_CODE);
|
||||
|
||||
i::MaybeHandle<i::SharedFunctionInfo> maybe_function_info;
|
||||
if (options == kConsumeCodeCache) {
|
||||
source->cached_data->rejected = cached_data->rejected();
|
||||
DCHECK_EQ(no_cache_reason, NoCacheReason::kNoCacheNoReason);
|
||||
if (source->consume_cache_task) {
|
||||
// Take ownership of the internal deserialization task and clear it off
|
||||
// the consume task on the source.
|
||||
DCHECK_NOT_NULL(source->consume_cache_task->impl_);
|
||||
std::unique_ptr<i::BackgroundDeserializeTask> deserialize_task =
|
||||
std::move(source->consume_cache_task->impl_);
|
||||
maybe_function_info =
|
||||
i::Compiler::GetSharedFunctionInfoForScriptWithDeserializeTask(
|
||||
isolate, str, script_details, deserialize_task.get(), options,
|
||||
no_cache_reason, i::NOT_NATIVES_CODE);
|
||||
source->cached_data->rejected = deserialize_task->rejected();
|
||||
} else {
|
||||
DCHECK(source->cached_data);
|
||||
// AlignedCachedData takes care of pointer-aligning the data.
|
||||
auto cached_data = std::make_unique<i::AlignedCachedData>(
|
||||
source->cached_data->data, source->cached_data->length);
|
||||
maybe_function_info =
|
||||
i::Compiler::GetSharedFunctionInfoForScriptWithCachedData(
|
||||
isolate, str, script_details, cached_data.get(), options,
|
||||
no_cache_reason, i::NOT_NATIVES_CODE);
|
||||
source->cached_data->rejected = cached_data->rejected();
|
||||
}
|
||||
} else {
|
||||
// Compile without any cache.
|
||||
maybe_function_info = i::Compiler::GetSharedFunctionInfoForScript(
|
||||
isolate, str, script_details, options, no_cache_reason,
|
||||
i::NOT_NATIVES_CODE);
|
||||
}
|
||||
|
||||
has_pending_exception = !maybe_function_info.ToHandle(&result);
|
||||
RETURN_ON_FAILED_EXECUTION(UnboundScript);
|
||||
RETURN_ESCAPED(ToApiHandle<UnboundScript>(result));
|
||||
|
@ -2830,13 +2830,10 @@ MaybeHandle<SharedFunctionInfo> CompileScriptOnBothBackgroundAndMainThread(
|
||||
return maybe_result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
|
||||
MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScriptImpl(
|
||||
Isolate* isolate, Handle<String> source,
|
||||
const ScriptDetails& script_details, v8::Extension* extension,
|
||||
AlignedCachedData* cached_data,
|
||||
AlignedCachedData* cached_data, BackgroundDeserializeTask* deserialize_task,
|
||||
ScriptCompiler::CompileOptions compile_options,
|
||||
ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag natives) {
|
||||
ScriptCompileTimerScope compile_timer(isolate, no_cache_reason);
|
||||
@ -2844,9 +2841,12 @@ MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
|
||||
if (compile_options == ScriptCompiler::kNoCompileOptions ||
|
||||
compile_options == ScriptCompiler::kEagerCompile) {
|
||||
DCHECK_NULL(cached_data);
|
||||
DCHECK_NULL(deserialize_task);
|
||||
} else {
|
||||
DCHECK(compile_options == ScriptCompiler::kConsumeCodeCache);
|
||||
DCHECK(cached_data);
|
||||
DCHECK_EQ(compile_options, ScriptCompiler::kConsumeCodeCache);
|
||||
// Have to have exactly one of cached_data or deserialize_task.
|
||||
DCHECK(cached_data || deserialize_task);
|
||||
DCHECK(!(cached_data && deserialize_task));
|
||||
DCHECK_NULL(extension);
|
||||
}
|
||||
int source_length = source->length();
|
||||
@ -2882,17 +2882,26 @@ MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
|
||||
RCS_SCOPE(isolate, RuntimeCallCounterId::kCompileDeserialize);
|
||||
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
|
||||
"V8.CompileDeserialize");
|
||||
Handle<SharedFunctionInfo> inner_result;
|
||||
if (CodeSerializer::Deserialize(isolate, cached_data, source,
|
||||
script_details.origin_options)
|
||||
.ToHandle(&inner_result) &&
|
||||
inner_result->is_compiled()) {
|
||||
// Promote to per-isolate compilation cache.
|
||||
is_compiled_scope = inner_result->is_compiled_scope(isolate);
|
||||
DCHECK(is_compiled_scope.is_compiled());
|
||||
compilation_cache->PutScript(source, language_mode, inner_result);
|
||||
maybe_result = inner_result;
|
||||
if (deserialize_task) {
|
||||
// If there's a cache consume task, finish it.
|
||||
maybe_result = deserialize_task->Finish(isolate, source,
|
||||
script_details.origin_options);
|
||||
} else {
|
||||
maybe_result = CodeSerializer::Deserialize(
|
||||
isolate, cached_data, source, script_details.origin_options);
|
||||
}
|
||||
|
||||
bool consuming_code_cache_succeeded = false;
|
||||
Handle<SharedFunctionInfo> result;
|
||||
if (maybe_result.ToHandle(&result)) {
|
||||
is_compiled_scope = result->is_compiled_scope(isolate);
|
||||
if (is_compiled_scope.is_compiled()) {
|
||||
consuming_code_cache_succeeded = true;
|
||||
// Promote to per-isolate compilation cache.
|
||||
compilation_cache->PutScript(source, language_mode, result);
|
||||
}
|
||||
}
|
||||
if (!consuming_code_cache_succeeded) {
|
||||
// Deserializer failed. Fall through to compile.
|
||||
compile_timer.set_consuming_code_cache_failed();
|
||||
}
|
||||
@ -2937,6 +2946,51 @@ MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
|
||||
return maybe_result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
|
||||
Isolate* isolate, Handle<String> source,
|
||||
const ScriptDetails& script_details,
|
||||
ScriptCompiler::CompileOptions compile_options,
|
||||
ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag natives) {
|
||||
return GetSharedFunctionInfoForScriptImpl(
|
||||
isolate, source, script_details, nullptr, nullptr, nullptr,
|
||||
compile_options, no_cache_reason, natives);
|
||||
}
|
||||
|
||||
MaybeHandle<SharedFunctionInfo>
|
||||
Compiler::GetSharedFunctionInfoForScriptWithExtension(
|
||||
Isolate* isolate, Handle<String> source,
|
||||
const ScriptDetails& script_details, v8::Extension* extension,
|
||||
ScriptCompiler::CompileOptions compile_options, NativesFlag natives) {
|
||||
return GetSharedFunctionInfoForScriptImpl(
|
||||
isolate, source, script_details, extension, nullptr, nullptr,
|
||||
compile_options, ScriptCompiler::kNoCacheBecauseV8Extension, natives);
|
||||
}
|
||||
|
||||
MaybeHandle<SharedFunctionInfo>
|
||||
Compiler::GetSharedFunctionInfoForScriptWithCachedData(
|
||||
Isolate* isolate, Handle<String> source,
|
||||
const ScriptDetails& script_details, AlignedCachedData* cached_data,
|
||||
ScriptCompiler::CompileOptions compile_options,
|
||||
ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag natives) {
|
||||
return GetSharedFunctionInfoForScriptImpl(
|
||||
isolate, source, script_details, nullptr, cached_data, nullptr,
|
||||
compile_options, no_cache_reason, natives);
|
||||
}
|
||||
|
||||
MaybeHandle<SharedFunctionInfo>
|
||||
Compiler::GetSharedFunctionInfoForScriptWithDeserializeTask(
|
||||
Isolate* isolate, Handle<String> source,
|
||||
const ScriptDetails& script_details,
|
||||
BackgroundDeserializeTask* deserialize_task,
|
||||
ScriptCompiler::CompileOptions compile_options,
|
||||
ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag natives) {
|
||||
return GetSharedFunctionInfoForScriptImpl(
|
||||
isolate, source, script_details, nullptr, nullptr, deserialize_task,
|
||||
compile_options, no_cache_reason, natives);
|
||||
}
|
||||
|
||||
// static
|
||||
MaybeHandle<JSFunction> Compiler::GetWrappedFunction(
|
||||
Handle<String> source, Handle<FixedArray> arguments,
|
||||
|
@ -160,9 +160,40 @@ class V8_EXPORT_PRIVATE Compiler : public AllStatic {
|
||||
|
||||
// Create a shared function info object for a String source.
|
||||
static MaybeHandle<SharedFunctionInfo> GetSharedFunctionInfoForScript(
|
||||
Isolate* isolate, Handle<String> source,
|
||||
const ScriptDetails& script_details,
|
||||
ScriptCompiler::CompileOptions compile_options,
|
||||
ScriptCompiler::NoCacheReason no_cache_reason,
|
||||
NativesFlag is_natives_code);
|
||||
|
||||
// Create a shared function info object for a String source.
|
||||
static MaybeHandle<SharedFunctionInfo>
|
||||
GetSharedFunctionInfoForScriptWithExtension(
|
||||
Isolate* isolate, Handle<String> source,
|
||||
const ScriptDetails& script_details, v8::Extension* extension,
|
||||
AlignedCachedData* cached_data,
|
||||
ScriptCompiler::CompileOptions compile_options,
|
||||
NativesFlag is_natives_code);
|
||||
|
||||
// Create a shared function info object for a String source and serialized
|
||||
// cached data. The cached data may be rejected, in which case this function
|
||||
// will set cached_data->rejected() to true.
|
||||
static MaybeHandle<SharedFunctionInfo>
|
||||
GetSharedFunctionInfoForScriptWithCachedData(
|
||||
Isolate* isolate, Handle<String> source,
|
||||
const ScriptDetails& script_details, AlignedCachedData* cached_data,
|
||||
ScriptCompiler::CompileOptions compile_options,
|
||||
ScriptCompiler::NoCacheReason no_cache_reason,
|
||||
NativesFlag is_natives_code);
|
||||
|
||||
// Create a shared function info object for a String source and a task that
|
||||
// has deserialized cached data on a background thread. The cached data from
|
||||
// the task may be rejected, in which case this function will set
|
||||
// deserialize_task->rejected() to true.
|
||||
static MaybeHandle<SharedFunctionInfo>
|
||||
GetSharedFunctionInfoForScriptWithDeserializeTask(
|
||||
Isolate* isolate, Handle<String> source,
|
||||
const ScriptDetails& script_details,
|
||||
BackgroundDeserializeTask* deserialize_task,
|
||||
ScriptCompiler::CompileOptions compile_options,
|
||||
ScriptCompiler::NoCacheReason no_cache_reason,
|
||||
NativesFlag is_natives_code);
|
||||
@ -571,6 +602,8 @@ class V8_EXPORT_PRIVATE BackgroundDeserializeTask {
|
||||
Handle<String> source,
|
||||
ScriptOriginOptions origin_options);
|
||||
|
||||
bool rejected() const { return cached_data_.rejected(); }
|
||||
|
||||
private:
|
||||
Isolate* isolate_for_local_isolate_;
|
||||
AlignedCachedData cached_data_;
|
||||
|
@ -34,9 +34,8 @@ static MaybeHandle<SharedFunctionInfo> GetFunctionInfo(Isolate* isolate,
|
||||
ScriptOriginOptions(false, true));
|
||||
script_details.repl_mode = repl_mode;
|
||||
return Compiler::GetSharedFunctionInfoForScript(
|
||||
isolate, source, script_details, nullptr, nullptr,
|
||||
ScriptCompiler::kNoCompileOptions, ScriptCompiler::kNoCacheNoReason,
|
||||
NOT_NATIVES_CODE);
|
||||
isolate, source, script_details, ScriptCompiler::kNoCompileOptions,
|
||||
ScriptCompiler::kNoCacheNoReason, NOT_NATIVES_CODE);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
@ -760,8 +760,8 @@ MaybeLocal<UnboundScript> CompileInspectorScript(Isolate* v8_isolate,
|
||||
{
|
||||
i::AlignedCachedData* cached_data = nullptr;
|
||||
i::MaybeHandle<i::SharedFunctionInfo> maybe_function_info =
|
||||
i::Compiler::GetSharedFunctionInfoForScript(
|
||||
isolate, str, i::ScriptDetails(), nullptr, cached_data,
|
||||
i::Compiler::GetSharedFunctionInfoForScriptWithCachedData(
|
||||
isolate, str, i::ScriptDetails(), cached_data,
|
||||
ScriptCompiler::kNoCompileOptions,
|
||||
ScriptCompiler::kNoCacheBecauseInspector,
|
||||
i::FLAG_expose_inspector_scripts ? i::NOT_NATIVES_CODE
|
||||
|
@ -4129,10 +4129,9 @@ bool Genesis::CompileExtension(Isolate* isolate, v8::Extension* extension) {
|
||||
Handle<String> script_name =
|
||||
factory->NewStringFromUtf8(name).ToHandleChecked();
|
||||
MaybeHandle<SharedFunctionInfo> maybe_function_info =
|
||||
Compiler::GetSharedFunctionInfoForScript(
|
||||
isolate, source, ScriptDetails(script_name), extension, nullptr,
|
||||
ScriptCompiler::kNoCompileOptions,
|
||||
ScriptCompiler::kNoCacheBecauseV8Extension, EXTENSION_CODE);
|
||||
Compiler::GetSharedFunctionInfoForScriptWithExtension(
|
||||
isolate, source, ScriptDetails(script_name), extension,
|
||||
ScriptCompiler::kNoCompileOptions, EXTENSION_CODE);
|
||||
if (!maybe_function_info.ToHandle(&function_info)) return false;
|
||||
cache->Add(isolate, name, function_info);
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ static Handle<JSFunction> Compile(const char* source) {
|
||||
.ToHandleChecked();
|
||||
Handle<SharedFunctionInfo> shared =
|
||||
Compiler::GetSharedFunctionInfoForScript(
|
||||
isolate, source_code, ScriptDetails(), nullptr, nullptr,
|
||||
isolate, source_code, ScriptDetails(),
|
||||
v8::ScriptCompiler::kNoCompileOptions,
|
||||
ScriptCompiler::kNoCacheNoReason, NOT_NATIVES_CODE)
|
||||
.ToHandleChecked();
|
||||
|
@ -73,7 +73,7 @@ static Handle<JSFunction> Compile(const char* source) {
|
||||
.ToHandleChecked();
|
||||
Handle<SharedFunctionInfo> shared =
|
||||
Compiler::GetSharedFunctionInfoForScript(
|
||||
isolate, source_code, ScriptDetails(), nullptr, nullptr,
|
||||
isolate, source_code, ScriptDetails(),
|
||||
v8::ScriptCompiler::kNoCompileOptions,
|
||||
ScriptCompiler::kNoCacheNoReason, NOT_NATIVES_CODE)
|
||||
.ToHandleChecked();
|
||||
|
@ -1574,8 +1574,8 @@ static Handle<SharedFunctionInfo> CompileScript(
|
||||
Isolate* isolate, Handle<String> source,
|
||||
const ScriptDetails& script_details, AlignedCachedData* cached_data,
|
||||
v8::ScriptCompiler::CompileOptions options) {
|
||||
return Compiler::GetSharedFunctionInfoForScript(
|
||||
isolate, source, script_details, nullptr, cached_data, options,
|
||||
return Compiler::GetSharedFunctionInfoForScriptWithCachedData(
|
||||
isolate, source, script_details, cached_data, options,
|
||||
ScriptCompiler::kNoCacheNoReason, NOT_NATIVES_CODE)
|
||||
.ToHandleChecked();
|
||||
}
|
||||
@ -1586,7 +1586,7 @@ static Handle<SharedFunctionInfo> CompileScriptAndProduceCache(
|
||||
v8::ScriptCompiler::CompileOptions options) {
|
||||
Handle<SharedFunctionInfo> sfi =
|
||||
Compiler::GetSharedFunctionInfoForScript(
|
||||
isolate, source, script_details, nullptr, nullptr, options,
|
||||
isolate, source, script_details, options,
|
||||
ScriptCompiler::kNoCacheNoReason, NOT_NATIVES_CODE)
|
||||
.ToHandleChecked();
|
||||
std::unique_ptr<ScriptCompiler::CachedData> cached_data(
|
||||
|
Loading…
Reference in New Issue
Block a user