• 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 #include "src/heap/cppgc/heap.h"
6 
7 #include "src/heap/base/stack.h"
8 #include "src/heap/cppgc/garbage-collector.h"
9 #include "src/heap/cppgc/gc-invoker.h"
10 #include "src/heap/cppgc/heap-object-header.h"
11 #include "src/heap/cppgc/heap-visitor.h"
12 #include "src/heap/cppgc/marker.h"
13 #include "src/heap/cppgc/marking-verifier.h"
14 #include "src/heap/cppgc/prefinalizer-handler.h"
15 
16 namespace cppgc {
17 
18 namespace {
19 
VerifyCustomSpaces(const std::vector<std::unique_ptr<CustomSpaceBase>> & custom_spaces)20 void VerifyCustomSpaces(
21     const std::vector<std::unique_ptr<CustomSpaceBase>>& custom_spaces) {
22   // Ensures that user-provided custom spaces have indices that form a sequence
23   // starting at 0.
24 #ifdef DEBUG
25   for (size_t i = 0; i < custom_spaces.size(); ++i) {
26     DCHECK_EQ(i, custom_spaces[i]->GetCustomSpaceIndex().value);
27   }
28 #endif  // DEBUG
29 }
30 
31 }  // namespace
32 
Create(std::shared_ptr<cppgc::Platform> platform,cppgc::Heap::HeapOptions options)33 std::unique_ptr<Heap> Heap::Create(std::shared_ptr<cppgc::Platform> platform,
34                                    cppgc::Heap::HeapOptions options) {
35   DCHECK(platform.get());
36   VerifyCustomSpaces(options.custom_spaces);
37   return std::make_unique<internal::Heap>(std::move(platform),
38                                           std::move(options));
39 }
40 
ForceGarbageCollectionSlow(const char * source,const char * reason,Heap::StackState stack_state)41 void Heap::ForceGarbageCollectionSlow(const char* source, const char* reason,
42                                       Heap::StackState stack_state) {
43   internal::Heap::From(this)->CollectGarbage(
44       {internal::GarbageCollector::Config::CollectionType::kMajor, stack_state,
45        internal::GarbageCollector::Config::MarkingType::kAtomic,
46        internal::GarbageCollector::Config::SweepingType::kAtomic});
47 }
48 
GetAllocationHandle()49 AllocationHandle& Heap::GetAllocationHandle() {
50   return internal::Heap::From(this)->object_allocator();
51 }
52 
53 namespace internal {
54 
55 namespace {
56 
57 class Unmarker final : private HeapVisitor<Unmarker> {
58   friend class HeapVisitor<Unmarker>;
59 
60  public:
Unmarker(RawHeap * heap)61   explicit Unmarker(RawHeap* heap) { Traverse(heap); }
62 
63  private:
VisitHeapObjectHeader(HeapObjectHeader * header)64   bool VisitHeapObjectHeader(HeapObjectHeader* header) {
65     if (header->IsMarked()) header->Unmark();
66     return true;
67   }
68 };
69 
CheckConfig(Heap::Config config)70 void CheckConfig(Heap::Config config) {
71   CHECK_WITH_MSG(
72       (config.collection_type != Heap::Config::CollectionType::kMinor) ||
73           (config.stack_state == Heap::Config::StackState::kNoHeapPointers),
74       "Minor GCs with stack is currently not supported");
75 }
76 
77 }  // namespace
78 
Heap(std::shared_ptr<cppgc::Platform> platform,cppgc::Heap::HeapOptions options)79 Heap::Heap(std::shared_ptr<cppgc::Platform> platform,
80            cppgc::Heap::HeapOptions options)
81     : HeapBase(platform, options.custom_spaces, options.stack_support),
82       gc_invoker_(this, platform_.get(), options.stack_support),
83       growing_(&gc_invoker_, stats_collector_.get(),
84                options.resource_constraints) {}
85 
~Heap()86 Heap::~Heap() {
87   NoGCScope no_gc(*this);
88   // Finish already running GC if any, but don't finalize live objects.
89   sweeper_.FinishIfRunning();
90 }
91 
CollectGarbage(Config config)92 void Heap::CollectGarbage(Config config) {
93   DCHECK_EQ(Config::MarkingType::kAtomic, config.marking_type);
94   CheckConfig(config);
95 
96   if (in_no_gc_scope()) return;
97 
98   config_ = config;
99 
100   if (!gc_in_progress_) StartGarbageCollection(config);
101 
102   DCHECK(marker_);
103 
104   FinalizeGarbageCollection(config.stack_state);
105 }
106 
StartIncrementalGarbageCollection(Config config)107 void Heap::StartIncrementalGarbageCollection(Config config) {
108   DCHECK_NE(Config::MarkingType::kAtomic, config.marking_type);
109   CheckConfig(config);
110 
111   if (gc_in_progress_ || in_no_gc_scope()) return;
112 
113   config_ = config;
114 
115   StartGarbageCollection(config);
116 }
117 
FinalizeIncrementalGarbageCollectionIfRunning(Config config)118 void Heap::FinalizeIncrementalGarbageCollectionIfRunning(Config config) {
119   if (!gc_in_progress_) return;
120 
121   DCHECK(!in_no_gc_scope());
122 
123   DCHECK_NE(Config::MarkingType::kAtomic, config_.marking_type);
124   config_ = config;
125   FinalizeGarbageCollection(config.stack_state);
126 }
127 
StartGarbageCollection(Config config)128 void Heap::StartGarbageCollection(Config config) {
129   DCHECK(!gc_in_progress_);
130 
131   DCHECK(!in_no_gc_scope());
132 
133   // Finish sweeping in case it is still running.
134   sweeper_.FinishIfRunning();
135 
136   gc_in_progress_ = true;
137   epoch_++;
138 
139 #if defined(CPPGC_YOUNG_GENERATION)
140   if (config.collection_type == Config::CollectionType::kMajor)
141     Unmarker unmarker(&raw_heap());
142 #endif
143 
144   const Marker::MarkingConfig marking_config{
145       config.collection_type, config.stack_state, config.marking_type};
146   marker_ = MarkerFactory::CreateAndStartMarking<Marker>(
147       AsBase(), platform_.get(), marking_config);
148 }
149 
FinalizeGarbageCollection(Config::StackState stack_state)150 void Heap::FinalizeGarbageCollection(Config::StackState stack_state) {
151   DCHECK(gc_in_progress_);
152   DCHECK(!in_no_gc_scope());
153   config_.stack_state = stack_state;
154   DCHECK(marker_);
155   {
156     // Pre finalizers are forbidden from allocating objects. Note that this also
157     // guard atomic pause marking below, meaning that no internal method or
158     // external callbacks are allowed to allocate new objects.
159     ObjectAllocator::NoAllocationScope no_allocation_scope_(object_allocator_);
160     marker_->FinishMarking(stack_state);
161     prefinalizer_handler_->InvokePreFinalizers();
162   }
163   marker_.reset();
164   // TODO(chromium:1056170): replace build flag with dedicated flag.
165 #if DEBUG
166   MarkingVerifier verifier(*this);
167   verifier.Run(stack_state);
168 #endif
169   {
170     NoGCScope no_gc(*this);
171     const Sweeper::SweepingConfig sweeping_config{
172         config_.sweeping_type,
173         Sweeper::SweepingConfig::CompactableSpaceHandling::kSweep};
174     sweeper_.Start(sweeping_config);
175   }
176   gc_in_progress_ = false;
177 }
178 
DisableHeapGrowingForTesting()179 void Heap::DisableHeapGrowingForTesting() { growing_.DisableForTesting(); }
180 
181 }  // namespace internal
182 }  // namespace cppgc
183