1// Copyright 2022 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_MAGLEV_MAGLEV_CONCURRENT_DISPATCHER_H_
6#define V8_MAGLEV_MAGLEV_CONCURRENT_DISPATCHER_H_
7
8#ifdef V8_ENABLE_MAGLEV
9
10#include <memory>
11
12#include "src/codegen/compiler.h"  // For OptimizedCompilationJob.
13#include "src/utils/locked-queue.h"
14
15namespace v8 {
16namespace internal {
17
18class Isolate;
19
20namespace maglev {
21
22class MaglevCompilationInfo;
23
24// TODO(v8:7700): While basic infrastructure now exists, there are many TODOs
25// that should still be addressed soon:
26// - Full tracing support through --trace-opt.
27// - Concurrent codegen.
28// - Concurrent Code object creation (optional?).
29// - Test support for concurrency (see %FinalizeOptimization).
30
31// Exports needed functionality without exposing implementation details.
32class ExportedMaglevCompilationInfo final {
33 public:
34  explicit ExportedMaglevCompilationInfo(MaglevCompilationInfo* info)
35      : info_(info) {}
36
37  Zone* zone() const;
38  void set_canonical_handles(
39      std::unique_ptr<CanonicalHandlesMap>&& canonical_handles);
40
41 private:
42  MaglevCompilationInfo* const info_;
43};
44
45// The job is a single actual compilation task.
46class MaglevCompilationJob final : public OptimizedCompilationJob {
47 public:
48  static std::unique_ptr<MaglevCompilationJob> New(Isolate* isolate,
49                                                   Handle<JSFunction> function);
50  virtual ~MaglevCompilationJob();
51
52  Status PrepareJobImpl(Isolate* isolate) override;
53  Status ExecuteJobImpl(RuntimeCallStats* stats,
54                        LocalIsolate* local_isolate) override;
55  Status FinalizeJobImpl(Isolate* isolate) override;
56
57  Handle<JSFunction> function() const;
58
59 private:
60  explicit MaglevCompilationJob(std::unique_ptr<MaglevCompilationInfo>&& info);
61
62  MaglevCompilationInfo* info() const { return info_.get(); }
63
64  const std::unique_ptr<MaglevCompilationInfo> info_;
65};
66
67// The public API for Maglev concurrent compilation.
68// Keep this as minimal as possible.
69class MaglevConcurrentDispatcher final {
70  class JobTask;
71
72  // TODO(jgruber): There's no reason to use locking queues here, we only use
73  // them for simplicity - consider replacing with lock-free data structures.
74  using QueueT = LockedQueue<std::unique_ptr<MaglevCompilationJob>>;
75
76 public:
77  explicit MaglevConcurrentDispatcher(Isolate* isolate);
78  ~MaglevConcurrentDispatcher();
79
80  // Called from the main thread.
81  void EnqueueJob(std::unique_ptr<MaglevCompilationJob>&& job);
82
83  // Called from the main thread.
84  void FinalizeFinishedJobs();
85
86  bool is_enabled() const { return static_cast<bool>(job_handle_); }
87
88 private:
89  Isolate* const isolate_;
90  std::unique_ptr<JobHandle> job_handle_;
91  QueueT incoming_queue_;
92  QueueT outgoing_queue_;
93};
94
95}  // namespace maglev
96}  // namespace internal
97}  // namespace v8
98
99#endif  // V8_ENABLE_MAGLEV
100
101#endif  // V8_MAGLEV_MAGLEV_CONCURRENT_DISPATCHER_H_
102