11cb0ef41Sopenharmony_ci// Copyright 2022 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/maglev/maglev-concurrent-dispatcher.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/codegen/compiler.h" 81cb0ef41Sopenharmony_ci#include "src/compiler/compilation-dependencies.h" 91cb0ef41Sopenharmony_ci#include "src/compiler/js-heap-broker.h" 101cb0ef41Sopenharmony_ci#include "src/execution/isolate.h" 111cb0ef41Sopenharmony_ci#include "src/flags/flags.h" 121cb0ef41Sopenharmony_ci#include "src/handles/persistent-handles.h" 131cb0ef41Sopenharmony_ci#include "src/maglev/maglev-compilation-info.h" 141cb0ef41Sopenharmony_ci#include "src/maglev/maglev-compiler.h" 151cb0ef41Sopenharmony_ci#include "src/maglev/maglev-graph-labeller.h" 161cb0ef41Sopenharmony_ci#include "src/objects/js-function-inl.h" 171cb0ef41Sopenharmony_ci#include "src/utils/identity-map.h" 181cb0ef41Sopenharmony_ci#include "src/utils/locked-queue-inl.h" 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_cinamespace v8 { 211cb0ef41Sopenharmony_cinamespace internal { 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_cinamespace compiler { 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_civoid JSHeapBroker::AttachLocalIsolateForMaglev( 261cb0ef41Sopenharmony_ci maglev::MaglevCompilationInfo* info, LocalIsolate* local_isolate) { 271cb0ef41Sopenharmony_ci set_canonical_handles(info->DetachCanonicalHandles()); 281cb0ef41Sopenharmony_ci DCHECK_NULL(local_isolate_); 291cb0ef41Sopenharmony_ci local_isolate_ = local_isolate; 301cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(local_isolate_); 311cb0ef41Sopenharmony_ci local_isolate_->heap()->AttachPersistentHandles( 321cb0ef41Sopenharmony_ci info->DetachPersistentHandles()); 331cb0ef41Sopenharmony_ci} 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_civoid JSHeapBroker::DetachLocalIsolateForMaglev( 361cb0ef41Sopenharmony_ci maglev::MaglevCompilationInfo* info) { 371cb0ef41Sopenharmony_ci DCHECK_NULL(ph_); 381cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(local_isolate_); 391cb0ef41Sopenharmony_ci std::unique_ptr<PersistentHandles> ph = 401cb0ef41Sopenharmony_ci local_isolate_->heap()->DetachPersistentHandles(); 411cb0ef41Sopenharmony_ci local_isolate_ = nullptr; 421cb0ef41Sopenharmony_ci info->set_canonical_handles(DetachCanonicalHandles()); 431cb0ef41Sopenharmony_ci info->set_persistent_handles(std::move(ph)); 441cb0ef41Sopenharmony_ci} 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci} // namespace compiler 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_cinamespace maglev { 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_cinamespace { 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ciconstexpr char kMaglevCompilerName[] = "Maglev"; 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci// LocalIsolateScope encapsulates the phase where persistent handles are 551cb0ef41Sopenharmony_ci// attached to the LocalHeap inside {local_isolate}. 561cb0ef41Sopenharmony_ciclass V8_NODISCARD LocalIsolateScope final { 571cb0ef41Sopenharmony_ci public: 581cb0ef41Sopenharmony_ci explicit LocalIsolateScope(MaglevCompilationInfo* info, 591cb0ef41Sopenharmony_ci LocalIsolate* local_isolate) 601cb0ef41Sopenharmony_ci : info_(info) { 611cb0ef41Sopenharmony_ci info_->broker()->AttachLocalIsolateForMaglev(info_, local_isolate); 621cb0ef41Sopenharmony_ci } 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci ~LocalIsolateScope() { info_->broker()->DetachLocalIsolateForMaglev(info_); } 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci private: 671cb0ef41Sopenharmony_ci MaglevCompilationInfo* const info_; 681cb0ef41Sopenharmony_ci}; 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci} // namespace 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ciZone* ExportedMaglevCompilationInfo::zone() const { return info_->zone(); } 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_civoid ExportedMaglevCompilationInfo::set_canonical_handles( 751cb0ef41Sopenharmony_ci std::unique_ptr<CanonicalHandlesMap>&& canonical_handles) { 761cb0ef41Sopenharmony_ci info_->set_canonical_handles(std::move(canonical_handles)); 771cb0ef41Sopenharmony_ci} 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci// static 801cb0ef41Sopenharmony_cistd::unique_ptr<MaglevCompilationJob> MaglevCompilationJob::New( 811cb0ef41Sopenharmony_ci Isolate* isolate, Handle<JSFunction> function) { 821cb0ef41Sopenharmony_ci auto info = maglev::MaglevCompilationInfo::New(isolate, function); 831cb0ef41Sopenharmony_ci return std::unique_ptr<MaglevCompilationJob>( 841cb0ef41Sopenharmony_ci new MaglevCompilationJob(std::move(info))); 851cb0ef41Sopenharmony_ci} 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ciMaglevCompilationJob::MaglevCompilationJob( 881cb0ef41Sopenharmony_ci std::unique_ptr<MaglevCompilationInfo>&& info) 891cb0ef41Sopenharmony_ci : OptimizedCompilationJob(kMaglevCompilerName, State::kReadyToPrepare), 901cb0ef41Sopenharmony_ci info_(std::move(info)) { 911cb0ef41Sopenharmony_ci DCHECK(FLAG_maglev); 921cb0ef41Sopenharmony_ci} 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ciMaglevCompilationJob::~MaglevCompilationJob() = default; 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ciCompilationJob::Status MaglevCompilationJob::PrepareJobImpl(Isolate* isolate) { 971cb0ef41Sopenharmony_ci // TODO(v8:7700): Actual return codes. 981cb0ef41Sopenharmony_ci return CompilationJob::SUCCEEDED; 991cb0ef41Sopenharmony_ci} 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ciCompilationJob::Status MaglevCompilationJob::ExecuteJobImpl( 1021cb0ef41Sopenharmony_ci RuntimeCallStats* stats, LocalIsolate* local_isolate) { 1031cb0ef41Sopenharmony_ci LocalIsolateScope scope{info(), local_isolate}; 1041cb0ef41Sopenharmony_ci maglev::MaglevCompiler::Compile(local_isolate, 1051cb0ef41Sopenharmony_ci info()->toplevel_compilation_unit()); 1061cb0ef41Sopenharmony_ci // TODO(v8:7700): Actual return codes. 1071cb0ef41Sopenharmony_ci return CompilationJob::SUCCEEDED; 1081cb0ef41Sopenharmony_ci} 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ciCompilationJob::Status MaglevCompilationJob::FinalizeJobImpl(Isolate* isolate) { 1111cb0ef41Sopenharmony_ci Handle<CodeT> codet; 1121cb0ef41Sopenharmony_ci if (!maglev::MaglevCompiler::GenerateCode(info()->toplevel_compilation_unit()) 1131cb0ef41Sopenharmony_ci .ToHandle(&codet)) { 1141cb0ef41Sopenharmony_ci return CompilationJob::FAILED; 1151cb0ef41Sopenharmony_ci } 1161cb0ef41Sopenharmony_ci info()->function()->set_code(*codet); 1171cb0ef41Sopenharmony_ci return CompilationJob::SUCCEEDED; 1181cb0ef41Sopenharmony_ci} 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ciHandle<JSFunction> MaglevCompilationJob::function() const { 1211cb0ef41Sopenharmony_ci return info_->function(); 1221cb0ef41Sopenharmony_ci} 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci// The JobTask is posted to V8::GetCurrentPlatform(). It's responsible for 1251cb0ef41Sopenharmony_ci// processing the incoming queue on a worker thread. 1261cb0ef41Sopenharmony_ciclass MaglevConcurrentDispatcher::JobTask final : public v8::JobTask { 1271cb0ef41Sopenharmony_ci public: 1281cb0ef41Sopenharmony_ci explicit JobTask(MaglevConcurrentDispatcher* dispatcher) 1291cb0ef41Sopenharmony_ci : dispatcher_(dispatcher) {} 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_ci void Run(JobDelegate* delegate) override { 1321cb0ef41Sopenharmony_ci LocalIsolate local_isolate(isolate(), ThreadKind::kBackground); 1331cb0ef41Sopenharmony_ci DCHECK(local_isolate.heap()->IsParked()); 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci while (!incoming_queue()->IsEmpty() && !delegate->ShouldYield()) { 1361cb0ef41Sopenharmony_ci std::unique_ptr<MaglevCompilationJob> job; 1371cb0ef41Sopenharmony_ci if (!incoming_queue()->Dequeue(&job)) break; 1381cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(job); 1391cb0ef41Sopenharmony_ci RuntimeCallStats* rcs = nullptr; // TODO(v8:7700): Implement. 1401cb0ef41Sopenharmony_ci CompilationJob::Status status = job->ExecuteJob(rcs, &local_isolate); 1411cb0ef41Sopenharmony_ci CHECK_EQ(status, CompilationJob::SUCCEEDED); 1421cb0ef41Sopenharmony_ci outgoing_queue()->Enqueue(std::move(job)); 1431cb0ef41Sopenharmony_ci } 1441cb0ef41Sopenharmony_ci isolate()->stack_guard()->RequestInstallMaglevCode(); 1451cb0ef41Sopenharmony_ci } 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_ci size_t GetMaxConcurrency(size_t) const override { 1481cb0ef41Sopenharmony_ci return incoming_queue()->size(); 1491cb0ef41Sopenharmony_ci } 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci private: 1521cb0ef41Sopenharmony_ci Isolate* isolate() const { return dispatcher_->isolate_; } 1531cb0ef41Sopenharmony_ci QueueT* incoming_queue() const { return &dispatcher_->incoming_queue_; } 1541cb0ef41Sopenharmony_ci QueueT* outgoing_queue() const { return &dispatcher_->outgoing_queue_; } 1551cb0ef41Sopenharmony_ci 1561cb0ef41Sopenharmony_ci MaglevConcurrentDispatcher* const dispatcher_; 1571cb0ef41Sopenharmony_ci const Handle<JSFunction> function_; 1581cb0ef41Sopenharmony_ci}; 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ciMaglevConcurrentDispatcher::MaglevConcurrentDispatcher(Isolate* isolate) 1611cb0ef41Sopenharmony_ci : isolate_(isolate) { 1621cb0ef41Sopenharmony_ci if (FLAG_concurrent_recompilation && FLAG_maglev) { 1631cb0ef41Sopenharmony_ci job_handle_ = V8::GetCurrentPlatform()->PostJob( 1641cb0ef41Sopenharmony_ci TaskPriority::kUserVisible, std::make_unique<JobTask>(this)); 1651cb0ef41Sopenharmony_ci DCHECK(is_enabled()); 1661cb0ef41Sopenharmony_ci } else { 1671cb0ef41Sopenharmony_ci DCHECK(!is_enabled()); 1681cb0ef41Sopenharmony_ci } 1691cb0ef41Sopenharmony_ci} 1701cb0ef41Sopenharmony_ci 1711cb0ef41Sopenharmony_ciMaglevConcurrentDispatcher::~MaglevConcurrentDispatcher() { 1721cb0ef41Sopenharmony_ci if (is_enabled() && job_handle_->IsValid()) { 1731cb0ef41Sopenharmony_ci // Wait for the job handle to complete, so that we know the queue 1741cb0ef41Sopenharmony_ci // pointers are safe. 1751cb0ef41Sopenharmony_ci job_handle_->Cancel(); 1761cb0ef41Sopenharmony_ci } 1771cb0ef41Sopenharmony_ci} 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_civoid MaglevConcurrentDispatcher::EnqueueJob( 1801cb0ef41Sopenharmony_ci std::unique_ptr<MaglevCompilationJob>&& job) { 1811cb0ef41Sopenharmony_ci DCHECK(is_enabled()); 1821cb0ef41Sopenharmony_ci // TODO(v8:7700): RCS. 1831cb0ef41Sopenharmony_ci // RCS_SCOPE(isolate_, RuntimeCallCounterId::kCompileMaglev); 1841cb0ef41Sopenharmony_ci incoming_queue_.Enqueue(std::move(job)); 1851cb0ef41Sopenharmony_ci job_handle_->NotifyConcurrencyIncrease(); 1861cb0ef41Sopenharmony_ci} 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_civoid MaglevConcurrentDispatcher::FinalizeFinishedJobs() { 1891cb0ef41Sopenharmony_ci HandleScope handle_scope(isolate_); 1901cb0ef41Sopenharmony_ci while (!outgoing_queue_.IsEmpty()) { 1911cb0ef41Sopenharmony_ci std::unique_ptr<MaglevCompilationJob> job; 1921cb0ef41Sopenharmony_ci outgoing_queue_.Dequeue(&job); 1931cb0ef41Sopenharmony_ci CompilationJob::Status status = job->FinalizeJob(isolate_); 1941cb0ef41Sopenharmony_ci // TODO(v8:7700): Use the result and check if job succeed 1951cb0ef41Sopenharmony_ci // when all the bytecodes are implemented. 1961cb0ef41Sopenharmony_ci if (status == CompilationJob::SUCCEEDED) { 1971cb0ef41Sopenharmony_ci Compiler::FinalizeMaglevCompilationJob(job.get(), isolate_); 1981cb0ef41Sopenharmony_ci } 1991cb0ef41Sopenharmony_ci } 2001cb0ef41Sopenharmony_ci} 2011cb0ef41Sopenharmony_ci 2021cb0ef41Sopenharmony_ci} // namespace maglev 2031cb0ef41Sopenharmony_ci} // namespace internal 2041cb0ef41Sopenharmony_ci} // namespace v8 205