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