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 37namespace v8 { 38namespace base { 39class LsanPageAllocator; 40} // namespace base 41} // namespace v8 42 43namespace heap { 44namespace base { 45class Stack; 46} // namespace base 47} // namespace heap 48 49namespace cppgc { 50namespace subtle { 51class DisallowGarbageCollectionScope; 52class NoGarbageCollectionScope; 53} // namespace subtle 54 55namespace testing { 56class Heap; 57class OverrideEmbedderStackStateScope; 58} // namespace testing 59 60class Platform; 61 62class V8_EXPORT HeapHandle { 63 private: 64 HeapHandle() = default; 65 friend class internal::HeapBase; 66}; 67 68namespace internal { 69 70class FatalOutOfMemoryHandler; 71class PageBackend; 72class PreFinalizerHandler; 73class StatsCollector; 74 75// Base class for heap implementations. 76class 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 82 static HeapBase& From(cppgc::HeapHandle& heap_handle) { 83 return static_cast<HeapBase&>(heap_handle); 84 } 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 98 RawHeap& raw_heap() { return raw_heap_; } 99 const RawHeap& raw_heap() const { return raw_heap_; } 100 101 cppgc::Platform* platform() { return platform_.get(); } 102 const cppgc::Platform* platform() const { return platform_.get(); } 103 104 FatalOutOfMemoryHandler& oom_handler() { return *oom_handler_.get(); } 105 const FatalOutOfMemoryHandler& oom_handler() const { 106 return *oom_handler_.get(); 107 } 108 109 PageBackend* page_backend() { return page_backend_.get(); } 110 const PageBackend* page_backend() const { return page_backend_.get(); } 111 112 StatsCollector* stats_collector() { return stats_collector_.get(); } 113 const StatsCollector* stats_collector() const { 114 return stats_collector_.get(); 115 } 116 117#if defined(CPPGC_CAGED_HEAP) 118 CagedHeap& caged_heap() { return caged_heap_; } 119 const CagedHeap& caged_heap() const { return caged_heap_; } 120#endif 121 122 heap::base::Stack* stack() { return stack_.get(); } 123 124 PreFinalizerHandler* prefinalizer_handler() { 125 return prefinalizer_handler_.get(); 126 } 127 const PreFinalizerHandler* prefinalizer_handler() const { 128 return prefinalizer_handler_.get(); 129 } 130 131 MarkerBase* marker() const { return marker_.get(); } 132 std::unique_ptr<MarkerBase>& GetMarkerRefForTesting() { return marker_; } 133 134 Compactor& compactor() { return compactor_; } 135 136 ObjectAllocator& object_allocator() { return object_allocator_; } 137 const ObjectAllocator& object_allocator() const { return object_allocator_; } 138 139 Sweeper& sweeper() { return sweeper_; } 140 const Sweeper& sweeper() const { return sweeper_; } 141 142 PersistentRegion& GetStrongPersistentRegion() { 143 return strong_persistent_region_; 144 } 145 const PersistentRegion& GetStrongPersistentRegion() const { 146 return strong_persistent_region_; 147 } 148 PersistentRegion& GetWeakPersistentRegion() { 149 return weak_persistent_region_; 150 } 151 const PersistentRegion& GetWeakPersistentRegion() const { 152 return weak_persistent_region_; 153 } 154 CrossThreadPersistentRegion& GetStrongCrossThreadPersistentRegion() { 155 return strong_cross_thread_persistent_region_; 156 } 157 const CrossThreadPersistentRegion& GetStrongCrossThreadPersistentRegion() 158 const { 159 return strong_cross_thread_persistent_region_; 160 } 161 CrossThreadPersistentRegion& GetWeakCrossThreadPersistentRegion() { 162 return weak_cross_thread_persistent_region_; 163 } 164 const CrossThreadPersistentRegion& GetWeakCrossThreadPersistentRegion() 165 const { 166 return weak_cross_thread_persistent_region_; 167 } 168 169#if defined(CPPGC_YOUNG_GENERATION) 170 OldToNewRememberedSet& remembered_set() { return remembered_set_; } 171#endif // defined(CPPGC_YOUNG_GENERATION) 172 173 size_t ObjectPayloadSize() const; 174 175 StackSupport stack_support() const { return stack_support_; } 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 185 bool in_disallow_gc_scope() const { return disallow_gc_scope_ > 0; } 186 bool in_atomic_pause() const { return in_atomic_pause_; } 187 188 HeapStatistics CollectStatistics(HeapStatistics::DetailLevel); 189 190 EmbedderStackState stack_state_of_prev_gc() const { 191 return stack_state_of_prev_gc_; 192 } 193 void SetStackStateOfPrevGC(EmbedderStackState stack_state) { 194 stack_state_of_prev_gc_ = stack_state; 195 } 196 197 uintptr_t stack_end_of_current_gc() const { return stack_end_of_current_gc_; } 198 void SetStackEndOfCurrentGC(uintptr_t stack_end) { 199 stack_end_of_current_gc_ = stack_end; 200 } 201 202 void SetInAtomicPauseForTesting(bool value) { in_atomic_pause_ = value; } 203 204 virtual void StartIncrementalGarbageCollectionForTesting() = 0; 205 virtual void FinalizeIncrementalGarbageCollectionForTesting( 206 EmbedderStackState) = 0; 207 208 void SetMetricRecorder(std::unique_ptr<MetricRecorder> histogram_recorder) { 209 stats_collector_->SetMetricRecorder(std::move(histogram_recorder)); 210 } 211 212 int GetCreationThreadId() const { return creation_thread_id_; } 213 214 MarkingType marking_support() const { return marking_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 222 bool in_no_gc_scope() const { return no_gc_scope_ > 0; } 223 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