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-embedder-heap.h" 16 #include "include/v8-metrics.h" 17 #include "src/base/macros.h" 18 #include "src/heap/cppgc/heap-base.h" 19 #include "src/heap/cppgc/stats-collector.h" 20 #include "src/logging/metrics.h" 21 22 namespace v8 { 23 24 class Isolate; 25 26 namespace internal { 27 28 // A C++ heap implementation used with V8 to implement unified heap. 29 class V8_EXPORT_PRIVATE CppHeap final 30 : public cppgc::internal::HeapBase, 31 public v8::CppHeap, 32 public v8::EmbedderHeapTracer, 33 public cppgc::internal::StatsCollector::AllocationObserver { 34 public: 35 class MetricRecorderAdapter final : public cppgc::internal::MetricRecorder { 36 public: 37 static constexpr int kMaxBatchedEvents = 16; 38 MetricRecorderAdapter(CppHeap & cpp_heap)39 explicit MetricRecorderAdapter(CppHeap& cpp_heap) : cpp_heap_(cpp_heap) {} 40 41 void AddMainThreadEvent(const FullCycle& cppgc_event) final; 42 void AddMainThreadEvent(const MainThreadIncrementalMark& cppgc_event) final; 43 void AddMainThreadEvent( 44 const MainThreadIncrementalSweep& cppgc_event) final; 45 46 void FlushBatchedIncrementalEvents(); 47 48 // The following 3 methods are only used for reporting nested cpp events 49 // through V8. Standalone events are reported directly. 50 bool MetricsReportPending() const; 51 52 const base::Optional<cppgc::internal::MetricRecorder::FullCycle> 53 ExtractLastFullGcEvent(); 54 const base::Optional< 55 cppgc::internal::MetricRecorder::MainThreadIncrementalMark> 56 ExtractLastIncrementalMarkEvent(); 57 58 private: 59 Isolate* GetIsolate() const; 60 61 v8::metrics::Recorder::ContextId GetContextId() const; 62 63 CppHeap& cpp_heap_; 64 v8::metrics::GarbageCollectionFullMainThreadBatchedIncrementalMark 65 incremental_mark_batched_events_; 66 v8::metrics::GarbageCollectionFullMainThreadBatchedIncrementalSweep 67 incremental_sweep_batched_events_; 68 base::Optional<cppgc::internal::MetricRecorder::FullCycle> 69 last_full_gc_event_; 70 base::Optional<cppgc::internal::MetricRecorder::MainThreadIncrementalMark> 71 last_incremental_mark_event_; 72 }; 73 From(v8::CppHeap * heap)74 static CppHeap* From(v8::CppHeap* heap) { 75 return static_cast<CppHeap*>(heap); 76 } From(const v8::CppHeap * heap)77 static const CppHeap* From(const v8::CppHeap* heap) { 78 return static_cast<const CppHeap*>(heap); 79 } 80 81 CppHeap( 82 v8::Platform* platform, 83 const std::vector<std::unique_ptr<cppgc::CustomSpaceBase>>& custom_spaces, 84 const v8::WrapperDescriptor& wrapper_descriptor); 85 ~CppHeap() final; 86 87 CppHeap(const CppHeap&) = delete; 88 CppHeap& operator=(const CppHeap&) = delete; 89 AsBase()90 HeapBase& AsBase() { return *this; } AsBase()91 const HeapBase& AsBase() const { return *this; } 92 93 void AttachIsolate(Isolate* isolate); 94 void DetachIsolate(); 95 96 void Terminate(); 97 98 void EnableDetachedGarbageCollectionsForTesting(); 99 100 void CollectGarbageForTesting( 101 cppgc::internal::GarbageCollector::Config::StackState); 102 103 void CollectCustomSpaceStatisticsAtLastGC( 104 std::vector<cppgc::CustomSpaceIndex>, 105 std::unique_ptr<CustomSpaceStatisticsReceiver>); 106 107 void FinishSweepingIfRunning(); 108 109 // v8::EmbedderHeapTracer interface. 110 void RegisterV8References( 111 const std::vector<std::pair<void*, void*> >& embedder_fields) final; 112 void TracePrologue(TraceFlags flags) final; 113 bool AdvanceTracing(double deadline_in_ms) final; 114 bool IsTracingDone() final; 115 void TraceEpilogue(TraceSummary* trace_summary) final; 116 void EnterFinalPause(EmbedderStackState stack_state) final; 117 118 // StatsCollector::AllocationObserver interface. 119 void AllocatedObjectSizeIncreased(size_t) final; 120 void AllocatedObjectSizeDecreased(size_t) final; ResetAllocatedObjectSize(size_t)121 void ResetAllocatedObjectSize(size_t) final {} 122 123 MetricRecorderAdapter* GetMetricRecorder() const; 124 125 private: FinalizeIncrementalGarbageCollectionIfNeeded(cppgc::Heap::StackState)126 void FinalizeIncrementalGarbageCollectionIfNeeded( 127 cppgc::Heap::StackState) final { 128 // For unified heap, CppHeap shouldn't finalize independently (i.e. 129 // finalization is not needed) thus this method is left empty. 130 } 131 132 void ReportBufferedAllocationSizeIfPossible(); 133 134 void StartIncrementalGarbageCollectionForTesting() final; 135 void FinalizeIncrementalGarbageCollectionForTesting(EmbedderStackState) final; 136 137 Isolate* isolate_ = nullptr; 138 bool marking_done_ = false; 139 TraceFlags current_flags_ = TraceFlags::kNoFlags; 140 141 // Buffered allocated bytes. Reporting allocated bytes to V8 can trigger a GC 142 // atomic pause. Allocated bytes are buffer in case this is temporarily 143 // prohibited. 144 int64_t buffered_allocated_bytes_ = 0; 145 146 v8::WrapperDescriptor wrapper_descriptor_; 147 148 bool in_detached_testing_mode_ = false; 149 bool force_incremental_marking_for_testing_ = false; 150 151 bool is_in_v8_marking_step_ = false; 152 153 friend class MetricRecorderAdapter; 154 }; 155 156 } // namespace internal 157 } // namespace v8 158 159 #endif // V8_HEAP_CPPGC_JS_CPP_HEAP_H_ 160