Commit fd72b13d authored by Pan, Tao's avatar Pan, Tao Committed by V8 LUCI CQ

[tiering] Early Sparkplug compilation if Sparkplug compiled

We record Sparkplug compiled into SFI which will be saved in disk cache, once deserializes SFI from disk cache, and the SFI was Sparkplug compiled, we trigger concurrent batch Sparkplug compilation, and directly allocate feedback vector on the first call.
This CL can improve Speedometer2 by +2%.

Change-Id: I89b0ffc6d7a107a1b8c131529e02cd7eb2890888
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3725612Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Tao Pan <tao.pan@intel.com>
Cr-Commit-Position: refs/heads/main@{#82122}
parent a1392fa1
......@@ -256,13 +256,6 @@ BaselineBatchCompiler::~BaselineBatchCompiler() {
void BaselineBatchCompiler::EnqueueFunction(Handle<JSFunction> function) {
Handle<SharedFunctionInfo> shared(function->shared(), isolate_);
// Early return if the function is compiled with baseline already or it is not
// suitable for baseline compilation.
if (shared->HasBaselineCode()) return;
// If we're already compiling this function, return.
if (shared->is_sparkplug_compiling()) return;
if (!CanCompileWithBaseline(isolate_, *shared)) return;
// Immediately compile the function if batch compilation is disabled.
if (!is_enabled()) {
IsCompiledScope is_compiled_scope(
......@@ -271,36 +264,9 @@ void BaselineBatchCompiler::EnqueueFunction(Handle<JSFunction> function) {
&is_compiled_scope);
return;
}
int estimated_size;
{
DisallowHeapAllocation no_gc;
estimated_size = BaselineCompiler::EstimateInstructionSize(
shared->GetBytecodeArray(isolate_));
}
estimated_instruction_size_ += estimated_size;
if (FLAG_trace_baseline_batch_compilation) {
CodeTracer::Scope trace_scope(isolate_->GetCodeTracer());
PrintF(trace_scope.file(),
"[Baseline batch compilation] Enqueued function ");
function->PrintName(trace_scope.file());
PrintF(trace_scope.file(),
" with estimated size %d (current budget: %d/%d)\n", estimated_size,
estimated_instruction_size_,
FLAG_baseline_batch_compilation_threshold.value());
}
if (ShouldCompileBatch()) {
if (FLAG_trace_baseline_batch_compilation) {
CodeTracer::Scope trace_scope(isolate_->GetCodeTracer());
PrintF(trace_scope.file(),
"[Baseline batch compilation] Compiling current batch of %d "
"functions\n",
(last_index_ + 1));
}
if (ShouldCompileBatch(*shared)) {
if (FLAG_concurrent_sparkplug) {
Enqueue(shared);
concurrent_compiler_->CompileBatch(compilation_queue_, last_index_);
ClearBatch();
CompileBatchConcurrent(*shared);
} else {
CompileBatch(function);
}
......@@ -309,6 +275,15 @@ void BaselineBatchCompiler::EnqueueFunction(Handle<JSFunction> function) {
}
}
void BaselineBatchCompiler::EnqueueSFI(SharedFunctionInfo shared) {
if (!FLAG_concurrent_sparkplug || !is_enabled()) return;
if (ShouldCompileBatch(shared)) {
CompileBatchConcurrent(shared);
} else {
Enqueue(Handle<SharedFunctionInfo>(shared, isolate_));
}
}
void BaselineBatchCompiler::Enqueue(Handle<SharedFunctionInfo> shared) {
EnsureQueueCapacity();
compilation_queue_->Set(last_index_++, HeapObjectReference::Weak(*shared));
......@@ -351,9 +326,48 @@ void BaselineBatchCompiler::CompileBatch(Handle<JSFunction> function) {
ClearBatch();
}
bool BaselineBatchCompiler::ShouldCompileBatch() const {
return estimated_instruction_size_ >=
FLAG_baseline_batch_compilation_threshold;
void BaselineBatchCompiler::CompileBatchConcurrent(SharedFunctionInfo shared) {
Enqueue(Handle<SharedFunctionInfo>(shared, isolate_));
concurrent_compiler_->CompileBatch(compilation_queue_, last_index_);
ClearBatch();
}
bool BaselineBatchCompiler::ShouldCompileBatch(SharedFunctionInfo shared) {
// Early return if the function is compiled with baseline already or it is not
// suitable for baseline compilation.
if (shared.HasBaselineCode()) return false;
// If we're already compiling this function, return.
if (shared.is_sparkplug_compiling()) return false;
if (!CanCompileWithBaseline(isolate_, shared)) return false;
int estimated_size;
{
DisallowHeapAllocation no_gc;
estimated_size = BaselineCompiler::EstimateInstructionSize(
shared.GetBytecodeArray(isolate_));
}
estimated_instruction_size_ += estimated_size;
if (FLAG_trace_baseline_batch_compilation) {
CodeTracer::Scope trace_scope(isolate_->GetCodeTracer());
PrintF(trace_scope.file(), "[Baseline batch compilation] Enqueued SFI %s",
shared.DebugNameCStr().get());
PrintF(trace_scope.file(),
" with estimated size %d (current budget: %d/%d)\n", estimated_size,
estimated_instruction_size_,
FLAG_baseline_batch_compilation_threshold.value());
}
if (estimated_instruction_size_ >=
FLAG_baseline_batch_compilation_threshold) {
if (FLAG_trace_baseline_batch_compilation) {
CodeTracer::Scope trace_scope(isolate_->GetCodeTracer());
PrintF(trace_scope.file(),
"[Baseline batch compilation] Compiling current batch of %d "
"functions\n",
(last_index_ + 1));
}
return true;
}
return false;
}
bool BaselineBatchCompiler::MaybeCompileFunction(MaybeObject maybe_sfi) {
......
......@@ -25,6 +25,7 @@ class BaselineBatchCompiler {
~BaselineBatchCompiler();
// Enqueues SharedFunctionInfo of |function| for compilation.
void EnqueueFunction(Handle<JSFunction> function);
void EnqueueSFI(SharedFunctionInfo shared);
void set_enabled(bool enabled) { enabled_ = enabled; }
bool is_enabled() { return enabled_; }
......@@ -41,11 +42,14 @@ class BaselineBatchCompiler {
// Returns true if the current batch exceeds the threshold and should be
// compiled.
bool ShouldCompileBatch() const;
bool ShouldCompileBatch(SharedFunctionInfo shared);
// Compiles the current batch.
void CompileBatch(Handle<JSFunction> function);
// Compiles the current batch concurrently.
void CompileBatchConcurrent(SharedFunctionInfo shared);
// Resets the current batch.
void ClearBatch();
......
......@@ -381,6 +381,7 @@ void TieringManager::OnInterruptTick(Handle<JSFunction> function) {
Compiler::CompileBaseline(isolate_, function, Compiler::CLEAR_EXCEPTION,
&is_compiled_scope);
}
function->shared().set_sparkplug_compiled(true);
}
// We only tier up beyond sparkplug if we already had a feedback vector.
......
......@@ -4,6 +4,7 @@
#include "src/objects/js-function.h"
#include "src/baseline/baseline-batch-compiler.h"
#include "src/codegen/compiler.h"
#include "src/diagnostics/code-tracer.h"
#include "src/execution/isolate.h"
......@@ -607,7 +608,8 @@ void JSFunction::InitializeFeedbackCell(
// We also need a feedback vector for certain log events, collecting type
// profile and more precise code coverage.
FLAG_log_function_events || !isolate->is_best_effort_code_coverage() ||
isolate->is_collecting_type_profile();
isolate->is_collecting_type_profile() ||
function->shared().sparkplug_compiled();
if (needs_feedback_vector) {
CreateAndAttachFeedbackVector(isolate, function, is_compiled_scope);
......@@ -615,6 +617,18 @@ void JSFunction::InitializeFeedbackCell(
EnsureClosureFeedbackCellArray(function,
reset_budget_for_feedback_allocation);
}
if (function->shared().sparkplug_compiled() &&
CanCompileWithBaseline(isolate, function->shared()) &&
!function->ActiveTierIsBaseline()) {
if (FLAG_baseline_batch_compilation) {
isolate->baseline_batch_compiler()->EnqueueFunction(function);
} else {
IsCompiledScope is_compiled_scope(
function->shared().is_compiled_scope(isolate));
Compiler::CompileBaseline(isolate, function, Compiler::CLEAR_EXCEPTION,
&is_compiled_scope);
}
}
}
namespace {
......
......@@ -267,6 +267,9 @@ BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags2, is_sparkplug_compiling,
BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags2, maglev_compilation_failed,
SharedFunctionInfo::MaglevCompilationFailedBit)
BIT_FIELD_ACCESSORS(SharedFunctionInfo, flags2, sparkplug_compiled,
SharedFunctionInfo::SparkplugCompiledBit)
BIT_FIELD_ACCESSORS(SharedFunctionInfo, relaxed_flags, syntax_kind,
SharedFunctionInfo::FunctionSyntaxKindBits)
......
......@@ -449,6 +449,8 @@ class SharedFunctionInfo
DECL_BOOLEAN_ACCESSORS(is_sparkplug_compiling)
DECL_BOOLEAN_ACCESSORS(maglev_compilation_failed)
DECL_BOOLEAN_ACCESSORS(sparkplug_compiled)
// Is this function a top-level function (scripts, evals).
DECL_BOOLEAN_ACCESSORS(is_toplevel)
......
......@@ -44,6 +44,7 @@ bitfield struct SharedFunctionInfoFlags2 extends uint8 {
has_static_private_methods_or_accessors: bool: 1 bit;
is_sparkplug_compiling: bool: 1 bit;
maglev_compilation_failed: bool: 1 bit;
sparkplug_compiled: bool: 1 bit;
}
@generateBodyDescriptor
......
......@@ -9,6 +9,7 @@
#include "src/base/logging.h"
#include "src/base/platform/elapsed-timer.h"
#include "src/base/platform/platform.h"
#include "src/baseline/baseline-batch-compiler.h"
#include "src/codegen/background-merge-task.h"
#include "src/common/globals.h"
#include "src/handles/maybe-handles.h"
......@@ -413,6 +414,21 @@ void FinalizeDeserialization(Isolate* isolate,
}
}
void BaselineBatchCompileIfSparkplugCompiled(Isolate* isolate, Script script) {
// Here is main thread, we trigger early baseline compilation only in
// concurrent sparkplug and baseline batch compilation mode which consumes
// little main thread execution time.
if (FLAG_concurrent_sparkplug && FLAG_baseline_batch_compilation) {
SharedFunctionInfo::ScriptIterator iter(isolate, script);
for (SharedFunctionInfo info = iter.Next(); !info.is_null();
info = iter.Next()) {
if (info.sparkplug_compiled() && CanCompileWithBaseline(isolate, info)) {
isolate->baseline_batch_compiler()->EnqueueSFI(info);
}
}
}
}
} // namespace
MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
......@@ -454,7 +470,8 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::Deserialize(
if (FLAG_profile_deserialization) PrintF("[Deserializing failed]\n");
return MaybeHandle<SharedFunctionInfo>();
}
BaselineBatchCompileIfSparkplugCompiled(isolate,
Script::cast(result->script()));
if (FLAG_profile_deserialization) {
double ms = timer.Elapsed().InMillisecondsF();
int length = cached_data->length();
......@@ -584,6 +601,7 @@ MaybeHandle<SharedFunctionInfo> CodeSerializer::FinishOffThreadDeserialize(
// Fix up the script list to include the newly deserialized script.
Handle<WeakArrayList> list = isolate->factory()->script_list();
for (Handle<Script> script : data.scripts) {
BaselineBatchCompileIfSparkplugCompiled(isolate, *script);
DCHECK(data.persistent_handles->Contains(script.location()));
list = WeakArrayList::AddToEnd(isolate, list,
MaybeObjectHandle::Weak(script));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment