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