• 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_HEAP_BASE_H_
6 #define V8_HEAP_CPPGC_HEAP_BASE_H_
7 
8 #include <memory>
9 #include <set>
10 
11 #include "include/cppgc/heap-statistics.h"
12 #include "include/cppgc/heap.h"
13 #include "include/cppgc/internal/persistent-node.h"
14 #include "include/cppgc/macros.h"
15 #include "src/base/macros.h"
16 #include "src/heap/cppgc/compactor.h"
17 #include "src/heap/cppgc/garbage-collector.h"
18 #include "src/heap/cppgc/heap-object-header.h"
19 #include "src/heap/cppgc/marker.h"
20 #include "src/heap/cppgc/metric-recorder.h"
21 #include "src/heap/cppgc/object-allocator.h"
22 #include "src/heap/cppgc/platform.h"
23 #include "src/heap/cppgc/process-heap-statistics.h"
24 #include "src/heap/cppgc/process-heap.h"
25 #include "src/heap/cppgc/raw-heap.h"
26 #include "src/heap/cppgc/sweeper.h"
27 #include "v8config.h"  // NOLINT(build/include_directory)
28 
29 #if defined(CPPGC_CAGED_HEAP)
30 #include "src/heap/cppgc/caged-heap.h"
31 #endif
32 
33 #if defined(CPPGC_YOUNG_GENERATION)
34 #include "src/heap/cppgc/remembered-set.h"
35 #endif
36 
37 namespace v8 {
38 namespace base {
39 class LsanPageAllocator;
40 }  // namespace base
41 }  // namespace v8
42 
43 namespace heap {
44 namespace base {
45 class Stack;
46 }  // namespace base
47 }  // namespace heap
48 
49 namespace cppgc {
50 namespace subtle {
51 class DisallowGarbageCollectionScope;
52 class NoGarbageCollectionScope;
53 }  // namespace subtle
54 
55 namespace testing {
56 class Heap;
57 class OverrideEmbedderStackStateScope;
58 }  // namespace testing
59 
60 class Platform;
61 
62 class V8_EXPORT HeapHandle {
63  private:
64   HeapHandle() = default;
65   friend class internal::HeapBase;
66 };
67 
68 namespace internal {
69 
70 class FatalOutOfMemoryHandler;
71 class PageBackend;
72 class PreFinalizerHandler;
73 class StatsCollector;
74 
75 // Base class for heap implementations.
76 class V8_EXPORT_PRIVATE HeapBase : public cppgc::HeapHandle {
77  public:
78   using StackSupport = cppgc::Heap::StackSupport;
79   using MarkingType = cppgc::Heap::MarkingType;
80   using SweepingType = cppgc::Heap::SweepingType;
81 
From(cppgc::HeapHandle & heap_handle)82   static HeapBase& From(cppgc::HeapHandle& heap_handle) {
83     return static_cast<HeapBase&>(heap_handle);
84   }
From(const cppgc::HeapHandle & heap_handle)85   static const HeapBase& From(const cppgc::HeapHandle& heap_handle) {
86     return static_cast<const HeapBase&>(heap_handle);
87   }
88 
89   HeapBase(std::shared_ptr<cppgc::Platform> platform,
90            const std::vector<std::unique_ptr<CustomSpaceBase>>& custom_spaces,
91            StackSupport stack_support, MarkingType marking_support,
92            SweepingType sweeping_support);
93   virtual ~HeapBase();
94 
95   HeapBase(const HeapBase&) = delete;
96   HeapBase& operator=(const HeapBase&) = delete;
97 
raw_heap()98   RawHeap& raw_heap() { return raw_heap_; }
raw_heap()99   const RawHeap& raw_heap() const { return raw_heap_; }
100 
platform()101   cppgc::Platform* platform() { return platform_.get(); }
platform()102   const cppgc::Platform* platform() const { return platform_.get(); }
103 
oom_handler()104   FatalOutOfMemoryHandler& oom_handler() { return *oom_handler_.get(); }
oom_handler()105   const FatalOutOfMemoryHandler& oom_handler() const {
106     return *oom_handler_.get();
107   }
108 
page_backend()109   PageBackend* page_backend() { return page_backend_.get(); }
page_backend()110   const PageBackend* page_backend() const { return page_backend_.get(); }
111 
stats_collector()112   StatsCollector* stats_collector() { return stats_collector_.get(); }
stats_collector()113   const StatsCollector* stats_collector() const {
114     return stats_collector_.get();
115   }
116 
117 #if defined(CPPGC_CAGED_HEAP)
caged_heap()118   CagedHeap& caged_heap() { return caged_heap_; }
caged_heap()119   const CagedHeap& caged_heap() const { return caged_heap_; }
120 #endif
121 
stack()122   heap::base::Stack* stack() { return stack_.get(); }
123 
prefinalizer_handler()124   PreFinalizerHandler* prefinalizer_handler() {
125     return prefinalizer_handler_.get();
126   }
prefinalizer_handler()127   const PreFinalizerHandler* prefinalizer_handler() const {
128     return prefinalizer_handler_.get();
129   }
130 
marker()131   MarkerBase* marker() const { return marker_.get(); }
GetMarkerRefForTesting()132   std::unique_ptr<MarkerBase>& GetMarkerRefForTesting() { return marker_; }
133 
compactor()134   Compactor& compactor() { return compactor_; }
135 
object_allocator()136   ObjectAllocator& object_allocator() { return object_allocator_; }
object_allocator()137   const ObjectAllocator& object_allocator() const { return object_allocator_; }
138 
sweeper()139   Sweeper& sweeper() { return sweeper_; }
sweeper()140   const Sweeper& sweeper() const { return sweeper_; }
141 
GetStrongPersistentRegion()142   PersistentRegion& GetStrongPersistentRegion() {
143     return strong_persistent_region_;
144   }
GetStrongPersistentRegion()145   const PersistentRegion& GetStrongPersistentRegion() const {
146     return strong_persistent_region_;
147   }
GetWeakPersistentRegion()148   PersistentRegion& GetWeakPersistentRegion() {
149     return weak_persistent_region_;
150   }
GetWeakPersistentRegion()151   const PersistentRegion& GetWeakPersistentRegion() const {
152     return weak_persistent_region_;
153   }
GetStrongCrossThreadPersistentRegion()154   CrossThreadPersistentRegion& GetStrongCrossThreadPersistentRegion() {
155     return strong_cross_thread_persistent_region_;
156   }
GetStrongCrossThreadPersistentRegion()157   const CrossThreadPersistentRegion& GetStrongCrossThreadPersistentRegion()
158       const {
159     return strong_cross_thread_persistent_region_;
160   }
GetWeakCrossThreadPersistentRegion()161   CrossThreadPersistentRegion& GetWeakCrossThreadPersistentRegion() {
162     return weak_cross_thread_persistent_region_;
163   }
GetWeakCrossThreadPersistentRegion()164   const CrossThreadPersistentRegion& GetWeakCrossThreadPersistentRegion()
165       const {
166     return weak_cross_thread_persistent_region_;
167   }
168 
169 #if defined(CPPGC_YOUNG_GENERATION)
remembered_set()170   OldToNewRememberedSet& remembered_set() { return remembered_set_; }
171 #endif  // defined(CPPGC_YOUNG_GENERATION)
172 
173   size_t ObjectPayloadSize() const;
174 
stack_support()175   StackSupport stack_support() const { return stack_support_; }
override_stack_state()176   const EmbedderStackState* override_stack_state() const {
177     return override_stack_state_.get();
178   }
179 
180   // Termination drops all roots (clears them out) and runs garbage collections
181   // in a bounded fixed point loop  until no new objects are created in
182   // destructors. Exceeding the loop bound results in a crash.
183   void Terminate();
184 
in_disallow_gc_scope()185   bool in_disallow_gc_scope() const { return disallow_gc_scope_ > 0; }
in_atomic_pause()186   bool in_atomic_pause() const { return in_atomic_pause_; }
187 
188   HeapStatistics CollectStatistics(HeapStatistics::DetailLevel);
189 
stack_state_of_prev_gc()190   EmbedderStackState stack_state_of_prev_gc() const {
191     return stack_state_of_prev_gc_;
192   }
SetStackStateOfPrevGC(EmbedderStackState stack_state)193   void SetStackStateOfPrevGC(EmbedderStackState stack_state) {
194     stack_state_of_prev_gc_ = stack_state;
195   }
196 
stack_end_of_current_gc()197   uintptr_t stack_end_of_current_gc() const { return stack_end_of_current_gc_; }
SetStackEndOfCurrentGC(uintptr_t stack_end)198   void SetStackEndOfCurrentGC(uintptr_t stack_end) {
199     stack_end_of_current_gc_ = stack_end;
200   }
201 
SetInAtomicPauseForTesting(bool value)202   void SetInAtomicPauseForTesting(bool value) { in_atomic_pause_ = value; }
203 
204   virtual void StartIncrementalGarbageCollectionForTesting() = 0;
205   virtual void FinalizeIncrementalGarbageCollectionForTesting(
206       EmbedderStackState) = 0;
207 
SetMetricRecorder(std::unique_ptr<MetricRecorder> histogram_recorder)208   void SetMetricRecorder(std::unique_ptr<MetricRecorder> histogram_recorder) {
209     stats_collector_->SetMetricRecorder(std::move(histogram_recorder));
210   }
211 
GetCreationThreadId()212   int GetCreationThreadId() const { return creation_thread_id_; }
213 
marking_support()214   MarkingType marking_support() const { return marking_support_; }
sweeping_support()215   SweepingType sweeping_support() const { return sweeping_support_; }
216 
217  protected:
218   // Used by the incremental scheduler to finalize a GC if supported.
219   virtual void FinalizeIncrementalGarbageCollectionIfNeeded(
220       cppgc::Heap::StackState) = 0;
221 
in_no_gc_scope()222   bool in_no_gc_scope() const { return no_gc_scope_ > 0; }
223 
IsMarking()224   bool IsMarking() const { return marker_.get(); }
225 
226   // Returns amount of bytes allocated while executing prefinalizers.
227   size_t ExecutePreFinalizers();
228 
229 #if defined(CPPGC_YOUNG_GENERATION)
230   void ResetRememberedSet();
231 #endif  // defined(CPPGC_YOUNG_GENERATION)
232 
233   PageAllocator* page_allocator() const;
234 
235   RawHeap raw_heap_;
236   std::shared_ptr<cppgc::Platform> platform_;
237   std::unique_ptr<FatalOutOfMemoryHandler> oom_handler_;
238 
239 #if defined(LEAK_SANITIZER)
240   std::unique_ptr<v8::base::LsanPageAllocator> lsan_page_allocator_;
241 #endif  // LEAK_SANITIZER
242 
243 #if defined(CPPGC_CAGED_HEAP)
244   CagedHeap caged_heap_;
245 #endif  // CPPGC_CAGED_HEAP
246   std::unique_ptr<PageBackend> page_backend_;
247 
248   // HeapRegistry requires access to page_backend_.
249   HeapRegistry::Subscription heap_registry_subscription_{*this};
250 
251   std::unique_ptr<StatsCollector> stats_collector_;
252   std::unique_ptr<heap::base::Stack> stack_;
253   std::unique_ptr<PreFinalizerHandler> prefinalizer_handler_;
254   std::unique_ptr<MarkerBase> marker_;
255 
256   Compactor compactor_;
257   ObjectAllocator object_allocator_;
258   Sweeper sweeper_;
259 
260   PersistentRegion strong_persistent_region_;
261   PersistentRegion weak_persistent_region_;
262   CrossThreadPersistentRegion strong_cross_thread_persistent_region_;
263   CrossThreadPersistentRegion weak_cross_thread_persistent_region_;
264 
265   ProcessHeapStatisticsUpdater::AllocationObserverImpl
266       allocation_observer_for_PROCESS_HEAP_STATISTICS_;
267 #if defined(CPPGC_YOUNG_GENERATION)
268   OldToNewRememberedSet remembered_set_;
269 #endif  // defined(CPPGC_YOUNG_GENERATION)
270 
271   size_t no_gc_scope_ = 0;
272   size_t disallow_gc_scope_ = 0;
273 
274   const StackSupport stack_support_;
275   EmbedderStackState stack_state_of_prev_gc_ =
276       EmbedderStackState::kNoHeapPointers;
277   std::unique_ptr<EmbedderStackState> override_stack_state_;
278 
279   // Marker that signals end of the interesting stack region in which on-heap
280   // pointers can be found.
281   uintptr_t stack_end_of_current_gc_ = 0;
282 
283   bool in_atomic_pause_ = false;
284 
285   int creation_thread_id_ = v8::base::OS::GetCurrentThreadId();
286 
287   const MarkingType marking_support_;
288   const SweepingType sweeping_support_;
289 
290   friend class MarkerBase::IncrementalMarkingTask;
291   friend class cppgc::subtle::DisallowGarbageCollectionScope;
292   friend class cppgc::subtle::NoGarbageCollectionScope;
293   friend class cppgc::testing::Heap;
294   friend class cppgc::testing::OverrideEmbedderStackStateScope;
295 };
296 
297 }  // namespace internal
298 }  // namespace cppgc
299 
300 #endif  // V8_HEAP_CPPGC_HEAP_BASE_H_
301