From 995217a31b1c110de5b1aceae2e0d8fc34a1142d Mon Sep 17 00:00:00 2001 From: Jakob Gruber Date: Thu, 3 Mar 2022 13:38:02 +0100 Subject: [PATCH] [maglev] Add a skeleton MaglevConcurrentDispatcher impl A dispatcher that currently does nothing, installed on the Isolate. The implementation is close to the baseline concurrent compiler; but boilerplate is short enough that a common base class is not worth the additional complexity. Bug: v8:7700 Change-Id: Ia34781e24cb6b1f72e5560fb0afe107bb0486092 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3497690 Auto-Submit: Jakob Gruber Reviewed-by: Leszek Swirski Commit-Queue: Leszek Swirski Cr-Commit-Position: refs/heads/main@{#79353} --- BUILD.gn | 2 + src/DEPS | 1 + src/execution/isolate.cc | 11 ++- src/execution/isolate.h | 26 ++++--- src/maglev/maglev-concurrent-dispatcher.cc | 81 ++++++++++++++++++++++ src/maglev/maglev-concurrent-dispatcher.h | 54 +++++++++++++++ 6 files changed, 166 insertions(+), 9 deletions(-) create mode 100644 src/maglev/maglev-concurrent-dispatcher.cc create mode 100644 src/maglev/maglev-concurrent-dispatcher.h diff --git a/BUILD.gn b/BUILD.gn index eaf48e436d..ab3dd87c39 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -3470,6 +3470,7 @@ v8_header_set("v8_internal_headers") { "src/maglev/maglev-code-generator.h", "src/maglev/maglev-compilation-data.h", "src/maglev/maglev-compiler.h", + "src/maglev/maglev-concurrent-dispatcher.h", "src/maglev/maglev-graph-builder.h", "src/maglev/maglev-graph-labeller.h", "src/maglev/maglev-graph-printer.h", @@ -4493,6 +4494,7 @@ v8_source_set("v8_base_without_compiler") { "src/maglev/maglev-code-generator.cc", "src/maglev/maglev-compilation-data.cc", "src/maglev/maglev-compiler.cc", + "src/maglev/maglev-concurrent-dispatcher.cc", "src/maglev/maglev-graph-builder.cc", "src/maglev/maglev-graph-printer.cc", "src/maglev/maglev-ir.cc", diff --git a/src/DEPS b/src/DEPS index c1f74f73ff..9846e7695c 100644 --- a/src/DEPS +++ b/src/DEPS @@ -53,6 +53,7 @@ include_rules = [ "+src/interpreter/setup-interpreter.h", "-src/maglev", "+src/maglev/maglev.h", + "+src/maglev/maglev-concurrent-dispatcher.h", "-src/regexp", "+src/regexp/regexp.h", "+src/regexp/regexp-flags.h", diff --git a/src/execution/isolate.cc b/src/execution/isolate.cc index db72e556e2..5b1471b564 100644 --- a/src/execution/isolate.cc +++ b/src/execution/isolate.cc @@ -75,6 +75,7 @@ #include "src/logging/log.h" #include "src/logging/metrics.h" #include "src/logging/runtime-call-stats-scope.h" +#include "src/maglev/maglev-concurrent-dispatcher.h" #include "src/numbers/hash-seed-inl.h" #include "src/objects/backing-store.h" #include "src/objects/call-site-info-inl.h" @@ -3366,10 +3367,15 @@ void Isolate::Deinit() { cancelable_task_manager()->CancelAndWait(); } - // Cancel all baseline compiler tasks. + // Cancel all compiler tasks. delete baseline_batch_compiler_; baseline_batch_compiler_ = nullptr; +#ifdef V8_ENABLE_MAGLEV + delete maglev_concurrent_dispatcher_; + maglev_concurrent_dispatcher_ = nullptr; +#endif // V8_ENABLE_MAGLEV + if (lazy_compile_dispatcher_) { lazy_compile_dispatcher_->AbortAll(); lazy_compile_dispatcher_.reset(); @@ -3877,6 +3883,9 @@ bool Isolate::Init(SnapshotData* startup_snapshot_data, this, V8::GetCurrentPlatform(), FLAG_stack_size); } baseline_batch_compiler_ = new baseline::BaselineBatchCompiler(this); +#ifdef V8_ENABLE_MAGLEV + maglev_concurrent_dispatcher_ = new maglev::MaglevConcurrentDispatcher(this); +#endif // V8_ENABLE_MAGLEV #if USE_SIMULATOR simulator_data_ = new SimulatorData; diff --git a/src/execution/isolate.h b/src/execution/isolate.h index ac27ffde82..a75a78de80 100644 --- a/src/execution/isolate.h +++ b/src/execution/isolate.h @@ -87,6 +87,10 @@ namespace heap { class HeapTester; } // namespace heap +namespace maglev { +class MaglevConcurrentDispatcher; +} // namespace maglev + class AddressToIndexHashMap; class AstStringConstants; class Bootstrapper; @@ -103,11 +107,11 @@ class Deoptimizer; class DescriptorLookupCache; class EmbeddedFileWriterInterface; class EternalHandles; +class GlobalHandles; +class GlobalSafepoint; class HandleScopeImplementer; class HeapObjectToIndexHashMap; class HeapProfiler; -class GlobalHandles; -class GlobalSafepoint; class InnerPointerToCodeCache; class LazyCompileDispatcher; class LocalIsolate; @@ -121,7 +125,6 @@ class PersistentHandlesList; class ReadOnlyArtifacts; class RegExpStack; class RootVisitor; -class TieringManager; class SetupIsolateDelegate; class Simulator; class SnapshotData; @@ -130,6 +133,7 @@ class StubCache; class ThreadManager; class ThreadState; class ThreadVisitor; // Defined in v8threads.h +class TieringManager; class TracingCpuProfilerImpl; class UnicodeCache; struct ManagedPtrDestructor; @@ -1463,11 +1467,18 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory { bool IsDeferredHandle(Address* location); #endif // DEBUG - baseline::BaselineBatchCompiler* baseline_batch_compiler() { + baseline::BaselineBatchCompiler* baseline_batch_compiler() const { DCHECK_NOT_NULL(baseline_batch_compiler_); return baseline_batch_compiler_; } +#ifdef V8_ENABLE_MAGLEV + maglev::MaglevConcurrentDispatcher* maglev_concurrent_dispatcher() { + DCHECK_NOT_NULL(maglev_concurrent_dispatcher_); + return maglev_concurrent_dispatcher_; + } +#endif // V8_ENABLE_MAGLEV + bool concurrent_recompilation_enabled() { // Thread is only available with flag enabled. DCHECK(optimizing_compile_dispatcher_ == nullptr || @@ -1733,10 +1744,6 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory { return lazy_compile_dispatcher_.get(); } - baseline::BaselineBatchCompiler* baseline_batch_compiler() const { - return baseline_batch_compiler_; - } - bool IsInAnyContext(Object object, uint32_t index); void ClearKeptObjects(); @@ -2218,6 +2225,9 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory { std::unique_ptr lazy_compile_dispatcher_; baseline::BaselineBatchCompiler* baseline_batch_compiler_ = nullptr; +#ifdef V8_ENABLE_MAGLEV + maglev::MaglevConcurrentDispatcher* maglev_concurrent_dispatcher_ = nullptr; +#endif // V8_ENABLE_MAGLEV using InterruptEntry = std::pair; std::queue api_interrupts_queue_; diff --git a/src/maglev/maglev-concurrent-dispatcher.cc b/src/maglev/maglev-concurrent-dispatcher.cc new file mode 100644 index 0000000000..c75d5de87a --- /dev/null +++ b/src/maglev/maglev-concurrent-dispatcher.cc @@ -0,0 +1,81 @@ +// Copyright 2022 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. + +#include "src/maglev/maglev-concurrent-dispatcher.h" + +#include "src/flags/flags.h" +#include "src/objects/js-function.h" +#include "src/utils/locked-queue-inl.h" + +namespace v8 { +namespace internal { +namespace maglev { + +class MaglevConcurrentDispatcher::Job final { + public: + explicit Job(Handle function) : function_(function) {} + + void Install(Isolate* isolate) { UNIMPLEMENTED(); } + + private: + const Handle function_; +}; + +class MaglevConcurrentDispatcher::JobTask final : public v8::JobTask { + public: + explicit JobTask(MaglevConcurrentDispatcher* dispatcher) + : dispatcher_(dispatcher) {} + + void Run(JobDelegate* delegate) override {} + + size_t GetMaxConcurrency(size_t) const override { + return incoming_queue()->size(); + } + + private: + QueueT* incoming_queue() const { return &dispatcher_->incoming_queue_; } + QueueT* outgoing_queue() const { return &dispatcher_->outgoing_queue_; } + + MaglevConcurrentDispatcher* const dispatcher_; + const Handle function_; +}; + +MaglevConcurrentDispatcher::MaglevConcurrentDispatcher(Isolate* isolate) + : isolate_(isolate) { + if (FLAG_concurrent_recompilation && FLAG_maglev) { + job_handle_ = V8::GetCurrentPlatform()->PostJob( + TaskPriority::kUserVisible, std::make_unique(this)); + DCHECK(is_enabled()); + } else { + DCHECK(!is_enabled()); + } +} + +MaglevConcurrentDispatcher::~MaglevConcurrentDispatcher() { + if (is_enabled() && job_handle_->IsValid()) { + // Wait for the job handle to complete, so that we know the queue + // pointers are safe. + job_handle_->Cancel(); + } +} + +void MaglevConcurrentDispatcher::EnqueueJob(Handle function) { + DCHECK(is_enabled()); + // TODO(v8:7700): RCS. + // RCS_SCOPE(isolate_, RuntimeCallCounterId::kCompileMaglev); + incoming_queue_.Enqueue(std::make_unique(function)); + job_handle_->NotifyConcurrencyIncrease(); +} + +void MaglevConcurrentDispatcher::ProcessFinishedJobs() { + while (!outgoing_queue_.IsEmpty()) { + std::unique_ptr job; + outgoing_queue_.Dequeue(&job); + job->Install(isolate_); + } +} + +} // namespace maglev +} // namespace internal +} // namespace v8 diff --git a/src/maglev/maglev-concurrent-dispatcher.h b/src/maglev/maglev-concurrent-dispatcher.h new file mode 100644 index 0000000000..ff1f8c500b --- /dev/null +++ b/src/maglev/maglev-concurrent-dispatcher.h @@ -0,0 +1,54 @@ +// Copyright 2022 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. + +#ifndef V8_MAGLEV_MAGLEV_CONCURRENT_DISPATCHER_H_ +#define V8_MAGLEV_MAGLEV_CONCURRENT_DISPATCHER_H_ + +#ifdef V8_ENABLE_MAGLEV + +#include + +#include "src/utils/locked-queue.h" + +namespace v8 { +namespace internal { + +class Isolate; + +namespace maglev { + +class MaglevConcurrentDispatcher final { + class Job; + class JobTask; + + // TODO(jgruber): There's no reason to use locking queues here, we only use + // them for simplicity - consider replacing with lock-free data structures. + using QueueT = LockedQueue>; + + public: + explicit MaglevConcurrentDispatcher(Isolate* isolate); + ~MaglevConcurrentDispatcher(); + + // Called from the main thread. + void EnqueueJob(Handle function); + + // Called from the main thread. + void ProcessFinishedJobs(); + + bool is_enabled() const { return static_cast(job_handle_); } + + private: + Isolate* const isolate_; + std::unique_ptr job_handle_; + QueueT incoming_queue_; + QueueT outgoing_queue_; +}; + +} // namespace maglev +} // namespace internal +} // namespace v8 + +#endif // V8_ENABLE_MAGLEV + +#endif // V8_MAGLEV_MAGLEV_CONCURRENT_DISPATCHER_H_