[compile] Collect RuntimeCallStats for AssembleCode
First this plumbs RuntimeCallStats from the OptimizingCompileDispatcher down through to PipelineCompilationJob which stashes the RuntimeCallStats on the PipelineData. Adds new RCS thread-specific counters: OptimizeAssembleCode and OptimizeBackgroundAssembleCode which are used in PipelineImpl::AssembleCode. Bug: v8:10006 Change-Id: Ieef6d32afddf4b0760e204010b09a85dfec92cf3 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1926030 Commit-Queue: Dan Elphick <delphick@chromium.org> Reviewed-by: Ross McIlroy <rmcilroy@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Reviewed-by: Maya Lekova <mslekova@chromium.org> Reviewed-by: Nico Hartmann <nicohartmann@chromium.org> Cr-Commit-Position: refs/heads/master@{#65221}
This commit is contained in:
parent
5a5d7d182f
commit
cef8ae2483
@ -225,12 +225,13 @@ CompilationJob::Status OptimizedCompilationJob::PrepareJob(Isolate* isolate) {
|
||||
return UpdateState(PrepareJobImpl(isolate), State::kReadyToExecute);
|
||||
}
|
||||
|
||||
CompilationJob::Status OptimizedCompilationJob::ExecuteJob() {
|
||||
CompilationJob::Status OptimizedCompilationJob::ExecuteJob(
|
||||
RuntimeCallStats* stats) {
|
||||
DisallowHeapAccess no_heap_access;
|
||||
// Delegate to the underlying implementation.
|
||||
DCHECK_EQ(state(), State::kReadyToExecute);
|
||||
ScopedTimer t(&time_taken_to_execute_);
|
||||
return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize);
|
||||
return UpdateState(ExecuteJobImpl(stats), State::kReadyToFinalize);
|
||||
}
|
||||
|
||||
CompilationJob::Status OptimizedCompilationJob::FinalizeJob(Isolate* isolate) {
|
||||
@ -742,7 +743,8 @@ bool GetOptimizedCodeNow(OptimizedCompilationJob* job, Isolate* isolate) {
|
||||
"V8.OptimizeNonConcurrent");
|
||||
|
||||
if (job->PrepareJob(isolate) != CompilationJob::SUCCEEDED ||
|
||||
job->ExecuteJob() != CompilationJob::SUCCEEDED ||
|
||||
job->ExecuteJob(isolate->counters()->runtime_call_stats()) !=
|
||||
CompilationJob::SUCCEEDED ||
|
||||
job->FinalizeJob(isolate) != CompilationJob::SUCCEEDED) {
|
||||
if (FLAG_trace_opt) {
|
||||
PrintF("[aborted optimizing ");
|
||||
|
@ -28,6 +28,7 @@ class OptimizedCompilationInfo;
|
||||
class OptimizedCompilationJob;
|
||||
class ParseInfo;
|
||||
class Parser;
|
||||
class RuntimeCallStats;
|
||||
class ScriptData;
|
||||
struct ScriptStreamingData;
|
||||
class TimedHistogram;
|
||||
@ -305,7 +306,7 @@ class OptimizedCompilationJob : public CompilationJob {
|
||||
|
||||
// Executes the compile job. Can be called on a background thread if
|
||||
// can_execute_on_background_thread() returns true.
|
||||
V8_WARN_UNUSED_RESULT Status ExecuteJob();
|
||||
V8_WARN_UNUSED_RESULT Status ExecuteJob(RuntimeCallStats* stats);
|
||||
|
||||
// Finalizes the compile job. Must be called on the main thread.
|
||||
V8_WARN_UNUSED_RESULT Status FinalizeJob(Isolate* isolate);
|
||||
@ -330,7 +331,7 @@ class OptimizedCompilationJob : public CompilationJob {
|
||||
protected:
|
||||
// Overridden by the actual implementation.
|
||||
virtual Status PrepareJobImpl(Isolate* isolate) = 0;
|
||||
virtual Status ExecuteJobImpl() = 0;
|
||||
virtual Status ExecuteJobImpl(RuntimeCallStats* stats) = 0;
|
||||
virtual Status FinalizeJobImpl(Isolate* isolate) = 0;
|
||||
|
||||
private:
|
||||
|
@ -76,7 +76,8 @@ class OptimizingCompileDispatcher::CompileTask : public CancelableTask {
|
||||
dispatcher_->recompilation_delay_));
|
||||
}
|
||||
|
||||
dispatcher_->CompileNext(dispatcher_->NextInput(true));
|
||||
dispatcher_->CompileNext(dispatcher_->NextInput(true),
|
||||
runtime_call_stats_scope.Get());
|
||||
}
|
||||
{
|
||||
base::MutexGuard lock_guard(&dispatcher_->ref_count_mutex_);
|
||||
@ -122,11 +123,12 @@ OptimizedCompilationJob* OptimizingCompileDispatcher::NextInput(
|
||||
return job;
|
||||
}
|
||||
|
||||
void OptimizingCompileDispatcher::CompileNext(OptimizedCompilationJob* job) {
|
||||
void OptimizingCompileDispatcher::CompileNext(OptimizedCompilationJob* job,
|
||||
RuntimeCallStats* stats) {
|
||||
if (!job) return;
|
||||
|
||||
// The function may have already been optimized by OSR. Simply continue.
|
||||
CompilationJob::Status status = job->ExecuteJob();
|
||||
CompilationJob::Status status = job->ExecuteJob(stats);
|
||||
USE(status); // Prevent an unused-variable error.
|
||||
|
||||
{
|
||||
|
@ -19,6 +19,7 @@ namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
class OptimizedCompilationJob;
|
||||
class RuntimeCallStats;
|
||||
class SharedFunctionInfo;
|
||||
|
||||
class V8_EXPORT_PRIVATE OptimizingCompileDispatcher {
|
||||
@ -57,7 +58,7 @@ class V8_EXPORT_PRIVATE OptimizingCompileDispatcher {
|
||||
enum ModeFlag { COMPILE, FLUSH };
|
||||
|
||||
void FlushOutputQueue(bool restore_function_code);
|
||||
void CompileNext(OptimizedCompilationJob* job);
|
||||
void CompileNext(OptimizedCompilationJob* job, RuntimeCallStats* stats);
|
||||
OptimizedCompilationJob* NextInput(bool check_if_flushing = false);
|
||||
|
||||
inline int InputQueueIndex(int i) {
|
||||
|
@ -514,6 +514,16 @@ class PipelineData {
|
||||
return roots_relative_addressing_enabled_;
|
||||
}
|
||||
|
||||
// RuntimeCallStats that is only available during job execution but not
|
||||
// finalization.
|
||||
// TODO(delphick): Currently even during execution this can be nullptr, due to
|
||||
// JSToWasmWrapperCompilationUnit::Execute. Once a table can be extracted
|
||||
// there, this method can DCHECK that it is never nullptr.
|
||||
RuntimeCallStats* runtime_call_stats() const { return runtime_call_stats_; }
|
||||
void set_runtime_call_stats(RuntimeCallStats* stats) {
|
||||
runtime_call_stats_ = stats;
|
||||
}
|
||||
|
||||
private:
|
||||
Isolate* const isolate_;
|
||||
wasm::WasmEngine* const wasm_engine_ = nullptr;
|
||||
@ -585,6 +595,7 @@ class PipelineData {
|
||||
// state. Calculated during instruction selection, applied during code
|
||||
// generation.
|
||||
size_t max_unoptimized_frame_height_ = 0;
|
||||
RuntimeCallStats* runtime_call_stats_ = nullptr;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PipelineData);
|
||||
};
|
||||
@ -946,7 +957,7 @@ class PipelineCompilationJob final : public OptimizedCompilationJob {
|
||||
|
||||
protected:
|
||||
Status PrepareJobImpl(Isolate* isolate) final;
|
||||
Status ExecuteJobImpl() final;
|
||||
Status ExecuteJobImpl(RuntimeCallStats* stats) final;
|
||||
Status FinalizeJobImpl(Isolate* isolate) final;
|
||||
|
||||
// Registers weak object to optimized code dependencies.
|
||||
@ -1061,7 +1072,28 @@ PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl(
|
||||
return SUCCEEDED;
|
||||
}
|
||||
|
||||
PipelineCompilationJob::Status PipelineCompilationJob::ExecuteJobImpl() {
|
||||
namespace {
|
||||
// Ensure that the RuntimeStats table is set on the PipelineData for duration of
|
||||
// the Execute phase and unset immediately afterwards.
|
||||
class PipelineExecuteJobScope {
|
||||
public:
|
||||
PipelineExecuteJobScope(PipelineData* data, RuntimeCallStats* stats)
|
||||
: data_(data) {
|
||||
data_->set_runtime_call_stats(stats);
|
||||
}
|
||||
|
||||
~PipelineExecuteJobScope() { data_->set_runtime_call_stats(nullptr); }
|
||||
|
||||
private:
|
||||
PipelineData* data_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
PipelineCompilationJob::Status PipelineCompilationJob::ExecuteJobImpl(
|
||||
RuntimeCallStats* stats) {
|
||||
// Ensure that the RuntimeCallStats table is only available during execution
|
||||
// and not during finalization as that might be on a different thread.
|
||||
PipelineExecuteJobScope scope(&data_, stats);
|
||||
if (FLAG_concurrent_inlining) {
|
||||
if (!pipeline_.CreateGraph()) {
|
||||
return AbortOptimization(BailoutReason::kGraphBuildingFailed);
|
||||
@ -1077,6 +1109,7 @@ PipelineCompilationJob::Status PipelineCompilationJob::ExecuteJobImpl() {
|
||||
if (!success) return FAILED;
|
||||
|
||||
pipeline_.AssembleCode(linkage_);
|
||||
|
||||
return SUCCEEDED;
|
||||
}
|
||||
|
||||
@ -1154,7 +1187,7 @@ class WasmHeapStubCompilationJob final : public OptimizedCompilationJob {
|
||||
|
||||
protected:
|
||||
Status PrepareJobImpl(Isolate* isolate) final;
|
||||
Status ExecuteJobImpl() final;
|
||||
Status ExecuteJobImpl(RuntimeCallStats* stats) final;
|
||||
Status FinalizeJobImpl(Isolate* isolate) final;
|
||||
|
||||
private:
|
||||
@ -1188,7 +1221,8 @@ CompilationJob::Status WasmHeapStubCompilationJob::PrepareJobImpl(
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
CompilationJob::Status WasmHeapStubCompilationJob::ExecuteJobImpl() {
|
||||
CompilationJob::Status WasmHeapStubCompilationJob::ExecuteJobImpl(
|
||||
RuntimeCallStats* stats) {
|
||||
std::unique_ptr<PipelineStatistics> pipeline_statistics;
|
||||
if (FLAG_turbo_stats || FLAG_turbo_stats_nvp) {
|
||||
pipeline_statistics.reset(new PipelineStatistics(
|
||||
@ -3137,6 +3171,9 @@ std::ostream& operator<<(std::ostream& out,
|
||||
void PipelineImpl::AssembleCode(Linkage* linkage,
|
||||
std::unique_ptr<AssemblerBuffer> buffer) {
|
||||
PipelineData* data = this->data_;
|
||||
RuntimeCallTimerScope scope(data_->runtime_call_stats(),
|
||||
RuntimeCallCounterId::kOptimizeAssembleCode,
|
||||
RuntimeCallStats::kThreadSpecific);
|
||||
data->BeginPhaseKind("V8.TFCodeGeneration");
|
||||
data->InitializeCodeGenerator(linkage, std::move(buffer));
|
||||
|
||||
|
@ -6832,7 +6832,8 @@ MaybeHandle<Code> CompileJSToJSWrapper(Isolate* isolate,
|
||||
Code::JS_TO_JS_FUNCTION, std::move(debug_name),
|
||||
AssemblerOptions::Default(isolate)));
|
||||
|
||||
if (job->ExecuteJob() == CompilationJob::FAILED ||
|
||||
if (job->ExecuteJob(isolate->counters()->runtime_call_stats()) ==
|
||||
CompilationJob::FAILED ||
|
||||
job->FinalizeJob(isolate) == CompilationJob::FAILED) {
|
||||
return {};
|
||||
}
|
||||
@ -6888,7 +6889,8 @@ MaybeHandle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig) {
|
||||
Code::C_WASM_ENTRY, std::move(debug_name),
|
||||
AssemblerOptions::Default(isolate)));
|
||||
|
||||
if (job->ExecuteJob() == CompilationJob::FAILED ||
|
||||
if (job->ExecuteJob(isolate->counters()->runtime_call_stats()) ==
|
||||
CompilationJob::FAILED ||
|
||||
job->FinalizeJob(isolate) == CompilationJob::FAILED) {
|
||||
return {};
|
||||
}
|
||||
|
@ -577,7 +577,8 @@ void RuntimeCallStats::Dump(v8::tracing::TracedValue* value) {
|
||||
in_use_ = false;
|
||||
}
|
||||
|
||||
WorkerThreadRuntimeCallStats::WorkerThreadRuntimeCallStats() = default;
|
||||
WorkerThreadRuntimeCallStats::WorkerThreadRuntimeCallStats()
|
||||
: isolate_thread_id_(ThreadId::Current()) {}
|
||||
|
||||
WorkerThreadRuntimeCallStats::~WorkerThreadRuntimeCallStats() {
|
||||
if (tls_key_) base::Thread::DeleteThreadLocalKey(*tls_key_);
|
||||
@ -591,6 +592,8 @@ base::Thread::LocalStorageKey WorkerThreadRuntimeCallStats::GetKey() {
|
||||
|
||||
RuntimeCallStats* WorkerThreadRuntimeCallStats::NewTable() {
|
||||
DCHECK(TracingFlags::is_runtime_stats_enabled());
|
||||
// Never create a new worker table on the isolate's main thread.
|
||||
DCHECK_NE(ThreadId::Current(), isolate_thread_id_);
|
||||
std::unique_ptr<RuntimeCallStats> new_table =
|
||||
std::make_unique<RuntimeCallStats>(RuntimeCallStats::kWorkerThread);
|
||||
RuntimeCallStats* result = new_table.get();
|
||||
|
@ -1175,6 +1175,10 @@ class WorkerThreadRuntimeCallStats final {
|
||||
base::Mutex mutex_;
|
||||
std::vector<std::unique_ptr<RuntimeCallStats>> tables_;
|
||||
base::Optional<base::Thread::LocalStorageKey> tls_key_;
|
||||
// Since this is for creating worker thread runtime-call stats, record the
|
||||
// main thread ID to ensure we never create a worker RCS table for the main
|
||||
// thread.
|
||||
ThreadId isolate_thread_id_;
|
||||
};
|
||||
|
||||
// Creating a WorkerThreadRuntimeCallStatsScope will provide a thread-local
|
||||
|
@ -276,7 +276,7 @@ JSToWasmWrapperCompilationUnit::~JSToWasmWrapperCompilationUnit() = default;
|
||||
|
||||
void JSToWasmWrapperCompilationUnit::Execute() {
|
||||
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"), "CompileJSToWasmWrapper");
|
||||
CompilationJob::Status status = job_->ExecuteJob();
|
||||
CompilationJob::Status status = job_->ExecuteJob(nullptr);
|
||||
CHECK_EQ(status, CompilationJob::SUCCEEDED);
|
||||
}
|
||||
|
||||
|
36
test/mjsunit/runtime-call-stats.js
Normal file
36
test/mjsunit/runtime-call-stats.js
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2019 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax --runtime-calls-stats --expose-gc
|
||||
|
||||
// Try to exercise the runtime stats code for optimization and GC.
|
||||
|
||||
// Optimize some functions both in the foreground and in the background.
|
||||
function test(x) {
|
||||
return 1 + Math.sin(x);
|
||||
}
|
||||
|
||||
function testConcurrent(x) {
|
||||
return 1 + Math.cos(x);
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(test);
|
||||
test(0.5);
|
||||
test(0.6);
|
||||
%OptimizeFunctionOnNextCall(test);
|
||||
for (var i = 0; i < 100; ++i) {
|
||||
test(0.7);
|
||||
}
|
||||
|
||||
%PrepareFunctionForOptimization(testConcurrent);
|
||||
testConcurrent(0.5);
|
||||
testConcurrent(0.6);
|
||||
%OptimizeFunctionOnNextCall(testConcurrent, 'concurrent');
|
||||
for (var i = 0; i < 100; ++i) {
|
||||
testConcurrent(0.7);
|
||||
}
|
||||
|
||||
%GetOptimizationStatus(testConcurrent, 'sync');
|
||||
|
||||
gc();
|
@ -42,7 +42,7 @@ class BlockingCompilationJob : public OptimizedCompilationJob {
|
||||
// OptimiziedCompilationJob implementation.
|
||||
Status PrepareJobImpl(Isolate* isolate) override { UNREACHABLE(); }
|
||||
|
||||
Status ExecuteJobImpl() override {
|
||||
Status ExecuteJobImpl(RuntimeCallStats* stats) override {
|
||||
blocking_.SetValue(true);
|
||||
semaphore_.Wait();
|
||||
blocking_.SetValue(false);
|
||||
|
Loading…
Reference in New Issue
Block a user