1// Copyright 2020 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_HEAP_CPPGC_JS_CPP_HEAP_H_
6#define V8_HEAP_CPPGC_JS_CPP_HEAP_H_
7
8#if CPPGC_IS_STANDALONE
9static_assert(
10    false, "V8 targets can not be built with cppgc_is_standalone set to true.");
11#endif
12
13#include "include/v8-callbacks.h"
14#include "include/v8-cppgc.h"
15#include "include/v8-metrics.h"
16#include "src/base/flags.h"
17#include "src/base/macros.h"
18#include "src/base/optional.h"
19#include "src/heap/cppgc/heap-base.h"
20#include "src/heap/cppgc/marker.h"
21#include "src/heap/cppgc/stats-collector.h"
22#include "src/logging/metrics.h"
23
24namespace v8 {
25
26class Isolate;
27
28namespace internal {
29
30class CppMarkingState;
31
32// A C++ heap implementation used with V8 to implement unified heap.
33class V8_EXPORT_PRIVATE CppHeap final
34    : public cppgc::internal::HeapBase,
35      public v8::CppHeap,
36      public cppgc::internal::StatsCollector::AllocationObserver {
37 public:
38  enum GarbageCollectionFlagValues : uint8_t {
39    kNoFlags = 0,
40    kReduceMemory = 1 << 1,
41    kForced = 1 << 2,
42  };
43
44  using GarbageCollectionFlags = base::Flags<GarbageCollectionFlagValues>;
45  using StackState = cppgc::internal::GarbageCollector::Config::StackState;
46  using CollectionType =
47      cppgc::internal::GarbageCollector::Config::CollectionType;
48
49  class MetricRecorderAdapter final : public cppgc::internal::MetricRecorder {
50   public:
51    static constexpr int kMaxBatchedEvents = 16;
52
53    explicit MetricRecorderAdapter(CppHeap& cpp_heap) : cpp_heap_(cpp_heap) {}
54
55    void AddMainThreadEvent(const GCCycle& cppgc_event) final;
56    void AddMainThreadEvent(const MainThreadIncrementalMark& cppgc_event) final;
57    void AddMainThreadEvent(
58        const MainThreadIncrementalSweep& cppgc_event) final;
59
60    void FlushBatchedIncrementalEvents();
61
62    // The following methods are only used for reporting nested cpp events
63    // through V8. Standalone events are reported directly.
64    bool FullGCMetricsReportPending() const;
65    bool YoungGCMetricsReportPending() const;
66
67    const base::Optional<cppgc::internal::MetricRecorder::GCCycle>
68    ExtractLastFullGcEvent();
69    const base::Optional<cppgc::internal::MetricRecorder::GCCycle>
70    ExtractLastYoungGcEvent();
71    const base::Optional<
72        cppgc::internal::MetricRecorder::MainThreadIncrementalMark>
73    ExtractLastIncrementalMarkEvent();
74
75    void ClearCachedEvents();
76
77   private:
78    Isolate* GetIsolate() const;
79
80    v8::metrics::Recorder::ContextId GetContextId() const;
81
82    CppHeap& cpp_heap_;
83    v8::metrics::GarbageCollectionFullMainThreadBatchedIncrementalMark
84        incremental_mark_batched_events_;
85    v8::metrics::GarbageCollectionFullMainThreadBatchedIncrementalSweep
86        incremental_sweep_batched_events_;
87    base::Optional<cppgc::internal::MetricRecorder::GCCycle>
88        last_full_gc_event_;
89    base::Optional<cppgc::internal::MetricRecorder::GCCycle>
90        last_young_gc_event_;
91    base::Optional<cppgc::internal::MetricRecorder::MainThreadIncrementalMark>
92        last_incremental_mark_event_;
93  };
94
95  class PauseConcurrentMarkingScope final {
96   public:
97    explicit PauseConcurrentMarkingScope(CppHeap*);
98
99   private:
100    base::Optional<cppgc::internal::MarkerBase::PauseConcurrentMarkingScope>
101        pause_scope_;
102  };
103
104  static CppHeap* From(v8::CppHeap* heap) {
105    return static_cast<CppHeap*>(heap);
106  }
107  static const CppHeap* From(const v8::CppHeap* heap) {
108    return static_cast<const CppHeap*>(heap);
109  }
110
111  CppHeap(
112      v8::Platform* platform,
113      const std::vector<std::unique_ptr<cppgc::CustomSpaceBase>>& custom_spaces,
114      const v8::WrapperDescriptor& wrapper_descriptor);
115  ~CppHeap() final;
116
117  CppHeap(const CppHeap&) = delete;
118  CppHeap& operator=(const CppHeap&) = delete;
119
120  HeapBase& AsBase() { return *this; }
121  const HeapBase& AsBase() const { return *this; }
122
123  void AttachIsolate(Isolate* isolate);
124  void DetachIsolate();
125
126  void Terminate();
127
128  void EnableDetachedGarbageCollectionsForTesting();
129
130  void CollectGarbageForTesting(CollectionType, StackState);
131
132  void CollectCustomSpaceStatisticsAtLastGC(
133      std::vector<cppgc::CustomSpaceIndex>,
134      std::unique_ptr<CustomSpaceStatisticsReceiver>);
135
136  void FinishSweepingIfRunning();
137  void FinishSweepingIfOutOfWork();
138
139  void InitializeTracing(
140      cppgc::internal::GarbageCollector::Config::CollectionType,
141      GarbageCollectionFlags);
142  void StartTracing();
143  bool AdvanceTracing(double max_duration);
144  bool IsTracingDone();
145  void TraceEpilogue();
146  void EnterFinalPause(cppgc::EmbedderStackState stack_state);
147  bool FinishConcurrentMarkingIfNeeded();
148
149  void RunMinorGC(StackState);
150
151  // StatsCollector::AllocationObserver interface.
152  void AllocatedObjectSizeIncreased(size_t) final;
153  void AllocatedObjectSizeDecreased(size_t) final;
154  void ResetAllocatedObjectSize(size_t) final {}
155
156  MetricRecorderAdapter* GetMetricRecorder() const;
157
158  v8::WrapperDescriptor wrapper_descriptor() const {
159    return wrapper_descriptor_;
160  }
161
162  Isolate* isolate() const { return isolate_; }
163
164  std::unique_ptr<CppMarkingState> CreateCppMarkingState();
165  std::unique_ptr<CppMarkingState> CreateCppMarkingStateForMutatorThread();
166
167 private:
168  void FinalizeIncrementalGarbageCollectionIfNeeded(
169      cppgc::Heap::StackState) final {
170    // For unified heap, CppHeap shouldn't finalize independently (i.e.
171    // finalization is not needed) thus this method is left empty.
172  }
173
174  void ReportBufferedAllocationSizeIfPossible();
175
176  void StartIncrementalGarbageCollectionForTesting() final;
177  void FinalizeIncrementalGarbageCollectionForTesting(
178      cppgc::EmbedderStackState) final;
179
180  MarkingType SelectMarkingType() const;
181  SweepingType SelectSweepingType() const;
182
183  Isolate* isolate_ = nullptr;
184  bool marking_done_ = false;
185  // |collection_type_| is initialized when marking is in progress.
186  base::Optional<cppgc::internal::GarbageCollector::Config::CollectionType>
187      collection_type_;
188  GarbageCollectionFlags current_gc_flags_;
189
190  // Buffered allocated bytes. Reporting allocated bytes to V8 can trigger a GC
191  // atomic pause. Allocated bytes are buffer in case this is temporarily
192  // prohibited.
193  int64_t buffered_allocated_bytes_ = 0;
194
195  v8::WrapperDescriptor wrapper_descriptor_;
196
197  bool in_detached_testing_mode_ = false;
198  bool force_incremental_marking_for_testing_ = false;
199
200  bool is_in_v8_marking_step_ = false;
201
202  friend class MetricRecorderAdapter;
203};
204
205DEFINE_OPERATORS_FOR_FLAGS(CppHeap::GarbageCollectionFlags)
206
207}  // namespace internal
208}  // namespace v8
209
210#endif  // V8_HEAP_CPPGC_JS_CPP_HEAP_H_
211