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