• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
9 static_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 
24 namespace v8 {
25 
26 class Isolate;
27 
28 namespace internal {
29 
30 class CppMarkingState;
31 
32 // A C++ heap implementation used with V8 to implement unified heap.
33 class 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 
MetricRecorderAdapter(CppHeap & cpp_heap)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 
From(v8::CppHeap * heap)104   static CppHeap* From(v8::CppHeap* heap) {
105     return static_cast<CppHeap*>(heap);
106   }
From(const v8::CppHeap * heap)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 
AsBase()120   HeapBase& AsBase() { return *this; }
AsBase()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;
ResetAllocatedObjectSize(size_t)154   void ResetAllocatedObjectSize(size_t) final {}
155 
156   MetricRecorderAdapter* GetMetricRecorder() const;
157 
wrapper_descriptor()158   v8::WrapperDescriptor wrapper_descriptor() const {
159     return wrapper_descriptor_;
160   }
161 
isolate()162   Isolate* isolate() const { return isolate_; }
163 
164   std::unique_ptr<CppMarkingState> CreateCppMarkingState();
165   std::unique_ptr<CppMarkingState> CreateCppMarkingStateForMutatorThread();
166 
167  private:
FinalizeIncrementalGarbageCollectionIfNeeded(cppgc::Heap::StackState)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 
205 DEFINE_OPERATORS_FOR_FLAGS(CppHeap::GarbageCollectionFlags)
206 
207 }  // namespace internal
208 }  // namespace v8
209 
210 #endif  // V8_HEAP_CPPGC_JS_CPP_HEAP_H_
211