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