[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 <jgruber@chromium.org>
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79353}
This commit is contained in:
Jakob Gruber 2022-03-03 13:38:02 +01:00 committed by V8 LUCI CQ
parent eda743d06b
commit 995217a31b
6 changed files with 166 additions and 9 deletions

View File

@ -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",

View File

@ -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",

View File

@ -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;

View File

@ -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<LazyCompileDispatcher> 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<InterruptCallback, void*>;
std::queue<InterruptEntry> api_interrupts_queue_;

View File

@ -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<JSFunction> function) : function_(function) {}
void Install(Isolate* isolate) { UNIMPLEMENTED(); }
private:
const Handle<JSFunction> 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<JSFunction> function_;
};
MaglevConcurrentDispatcher::MaglevConcurrentDispatcher(Isolate* isolate)
: isolate_(isolate) {
if (FLAG_concurrent_recompilation && FLAG_maglev) {
job_handle_ = V8::GetCurrentPlatform()->PostJob(
TaskPriority::kUserVisible, std::make_unique<JobTask>(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<JSFunction> function) {
DCHECK(is_enabled());
// TODO(v8:7700): RCS.
// RCS_SCOPE(isolate_, RuntimeCallCounterId::kCompileMaglev);
incoming_queue_.Enqueue(std::make_unique<Job>(function));
job_handle_->NotifyConcurrencyIncrease();
}
void MaglevConcurrentDispatcher::ProcessFinishedJobs() {
while (!outgoing_queue_.IsEmpty()) {
std::unique_ptr<Job> job;
outgoing_queue_.Dequeue(&job);
job->Install(isolate_);
}
}
} // namespace maglev
} // namespace internal
} // namespace v8

View File

@ -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 <memory>
#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<std::unique_ptr<Job>>;
public:
explicit MaglevConcurrentDispatcher(Isolate* isolate);
~MaglevConcurrentDispatcher();
// Called from the main thread.
void EnqueueJob(Handle<JSFunction> function);
// Called from the main thread.
void ProcessFinishedJobs();
bool is_enabled() const { return static_cast<bool>(job_handle_); }
private:
Isolate* const isolate_;
std::unique_ptr<JobHandle> 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_