• 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-js/cpp-heap.h"
6 
7 #include "include/cppgc/platform.h"
8 #include "include/v8-platform.h"
9 #include "include/v8.h"
10 #include "src/base/macros.h"
11 #include "src/base/platform/time.h"
12 #include "src/execution/isolate.h"
13 #include "src/flags/flags.h"
14 #include "src/heap/base/stack.h"
15 #include "src/heap/cppgc-js/cpp-snapshot.h"
16 #include "src/heap/cppgc-js/unified-heap-marking-state.h"
17 #include "src/heap/cppgc-js/unified-heap-marking-verifier.h"
18 #include "src/heap/cppgc-js/unified-heap-marking-visitor.h"
19 #include "src/heap/cppgc/concurrent-marker.h"
20 #include "src/heap/cppgc/gc-info-table.h"
21 #include "src/heap/cppgc/heap-base.h"
22 #include "src/heap/cppgc/heap-object-header.h"
23 #include "src/heap/cppgc/marker.h"
24 #include "src/heap/cppgc/marking-state.h"
25 #include "src/heap/cppgc/marking-visitor.h"
26 #include "src/heap/cppgc/object-allocator.h"
27 #include "src/heap/cppgc/prefinalizer-handler.h"
28 #include "src/heap/cppgc/stats-collector.h"
29 #include "src/heap/cppgc/sweeper.h"
30 #include "src/heap/marking-worklist.h"
31 #include "src/heap/sweeper.h"
32 #include "src/init/v8.h"
33 #include "src/profiler/heap-profiler.h"
34 
35 namespace v8 {
36 namespace internal {
37 
38 namespace {
39 
40 class CppgcPlatformAdapter final : public cppgc::Platform {
41  public:
CppgcPlatformAdapter(v8::Isolate * isolate)42   explicit CppgcPlatformAdapter(v8::Isolate* isolate)
43       : platform_(V8::GetCurrentPlatform()), isolate_(isolate) {}
44 
45   CppgcPlatformAdapter(const CppgcPlatformAdapter&) = delete;
46   CppgcPlatformAdapter& operator=(const CppgcPlatformAdapter&) = delete;
47 
GetPageAllocator()48   PageAllocator* GetPageAllocator() final {
49     return platform_->GetPageAllocator();
50   }
51 
MonotonicallyIncreasingTime()52   double MonotonicallyIncreasingTime() final {
53     return platform_->MonotonicallyIncreasingTime();
54   }
55 
GetForegroundTaskRunner()56   std::shared_ptr<TaskRunner> GetForegroundTaskRunner() final {
57     return platform_->GetForegroundTaskRunner(isolate_);
58   }
59 
PostJob(TaskPriority priority,std::unique_ptr<JobTask> job_task)60   std::unique_ptr<JobHandle> PostJob(TaskPriority priority,
61                                      std::unique_ptr<JobTask> job_task) final {
62     return platform_->PostJob(priority, std::move(job_task));
63   }
64 
65  private:
66   v8::Platform* platform_;
67   v8::Isolate* isolate_;
68 };
69 
70 class UnifiedHeapConcurrentMarker
71     : public cppgc::internal::ConcurrentMarkerBase {
72  public:
UnifiedHeapConcurrentMarker(cppgc::internal::HeapBase & heap,cppgc::internal::MarkingWorklists & marking_worklists,cppgc::internal::IncrementalMarkingSchedule & incremental_marking_schedule,cppgc::Platform * platform,UnifiedHeapMarkingState & unified_heap_marking_state)73   UnifiedHeapConcurrentMarker(
74       cppgc::internal::HeapBase& heap,
75       cppgc::internal::MarkingWorklists& marking_worklists,
76       cppgc::internal::IncrementalMarkingSchedule& incremental_marking_schedule,
77       cppgc::Platform* platform,
78       UnifiedHeapMarkingState& unified_heap_marking_state)
79       : cppgc::internal::ConcurrentMarkerBase(
80             heap, marking_worklists, incremental_marking_schedule, platform),
81         unified_heap_marking_state_(unified_heap_marking_state) {}
82 
83   std::unique_ptr<cppgc::Visitor> CreateConcurrentMarkingVisitor(
84       ConcurrentMarkingState&) const final;
85 
86  private:
87   UnifiedHeapMarkingState& unified_heap_marking_state_;
88 };
89 
90 std::unique_ptr<cppgc::Visitor>
CreateConcurrentMarkingVisitor(ConcurrentMarkingState & marking_state) const91 UnifiedHeapConcurrentMarker::CreateConcurrentMarkingVisitor(
92     ConcurrentMarkingState& marking_state) const {
93   return std::make_unique<ConcurrentUnifiedHeapMarkingVisitor>(
94       heap(), marking_state, unified_heap_marking_state_);
95 }
96 
97 class UnifiedHeapMarker final : public cppgc::internal::MarkerBase {
98  public:
99   UnifiedHeapMarker(Key, Heap& v8_heap, cppgc::internal::HeapBase& cpp_heap,
100                     cppgc::Platform* platform, MarkingConfig config);
101 
102   ~UnifiedHeapMarker() final = default;
103 
104   void AddObject(void*);
105 
106  protected:
visitor()107   cppgc::Visitor& visitor() final { return marking_visitor_; }
conservative_visitor()108   cppgc::internal::ConservativeTracingVisitor& conservative_visitor() final {
109     return conservative_marking_visitor_;
110   }
stack_visitor()111   ::heap::base::StackVisitor& stack_visitor() final {
112     return conservative_marking_visitor_;
113   }
114 
115  private:
116   UnifiedHeapMarkingState unified_heap_marking_state_;
117   MutatorUnifiedHeapMarkingVisitor marking_visitor_;
118   cppgc::internal::ConservativeMarkingVisitor conservative_marking_visitor_;
119 };
120 
UnifiedHeapMarker(Key key,Heap & v8_heap,cppgc::internal::HeapBase & heap,cppgc::Platform * platform,MarkingConfig config)121 UnifiedHeapMarker::UnifiedHeapMarker(Key key, Heap& v8_heap,
122                                      cppgc::internal::HeapBase& heap,
123                                      cppgc::Platform* platform,
124                                      MarkingConfig config)
125     : cppgc::internal::MarkerBase(key, heap, platform, config),
126       unified_heap_marking_state_(v8_heap),
127       marking_visitor_(heap, mutator_marking_state_,
128                        unified_heap_marking_state_),
129       conservative_marking_visitor_(heap, mutator_marking_state_,
130                                     marking_visitor_) {
131   concurrent_marker_ = std::make_unique<UnifiedHeapConcurrentMarker>(
132       heap_, marking_worklists_, schedule_, platform_,
133       unified_heap_marking_state_);
134 }
135 
AddObject(void * object)136 void UnifiedHeapMarker::AddObject(void* object) {
137   mutator_marking_state_.MarkAndPush(
138       cppgc::internal::HeapObjectHeader::FromPayload(object));
139 }
140 
141 }  // namespace
142 
CppHeap(v8::Isolate * isolate,const std::vector<std::unique_ptr<cppgc::CustomSpaceBase>> & custom_spaces)143 CppHeap::CppHeap(
144     v8::Isolate* isolate,
145     const std::vector<std::unique_ptr<cppgc::CustomSpaceBase>>& custom_spaces)
146     : cppgc::internal::HeapBase(std::make_shared<CppgcPlatformAdapter>(isolate),
147                                 custom_spaces,
148                                 cppgc::internal::HeapBase::StackSupport::
149                                     kSupportsConservativeStackScan),
150       isolate_(*reinterpret_cast<Isolate*>(isolate)) {
151   CHECK(!FLAG_incremental_marking_wrappers);
152   isolate_.heap_profiler()->AddBuildEmbedderGraphCallback(&CppGraphBuilder::Run,
153                                                           this);
154 }
155 
~CppHeap()156 CppHeap::~CppHeap() {
157   isolate_.heap_profiler()->RemoveBuildEmbedderGraphCallback(
158       &CppGraphBuilder::Run, this);
159 }
160 
RegisterV8References(const std::vector<std::pair<void *,void * >> & embedder_fields)161 void CppHeap::RegisterV8References(
162     const std::vector<std::pair<void*, void*> >& embedder_fields) {
163   DCHECK(marker_);
164   for (auto& tuple : embedder_fields) {
165     // First field points to type.
166     // Second field points to object.
167     static_cast<UnifiedHeapMarker*>(marker_.get())->AddObject(tuple.second);
168   }
169   marking_done_ = false;
170 }
171 
TracePrologue(TraceFlags flags)172 void CppHeap::TracePrologue(TraceFlags flags) {
173   // Finish sweeping in case it is still running.
174   sweeper_.FinishIfRunning();
175 
176   const UnifiedHeapMarker::MarkingConfig marking_config{
177       UnifiedHeapMarker::MarkingConfig::CollectionType::kMajor,
178       cppgc::Heap::StackState::kNoHeapPointers,
179       UnifiedHeapMarker::MarkingConfig::MarkingType::kIncrementalAndConcurrent};
180   if ((flags == TraceFlags::kReduceMemory) || (flags == TraceFlags::kForced)) {
181     // Only enable compaction when in a memory reduction garbage collection as
182     // it may significantly increase the final garbage collection pause.
183     compactor_.InitializeIfShouldCompact(marking_config.marking_type,
184                                          marking_config.stack_state);
185   }
186   marker_ =
187       cppgc::internal::MarkerFactory::CreateAndStartMarking<UnifiedHeapMarker>(
188           *isolate_.heap(), AsBase(), platform_.get(), marking_config);
189   marking_done_ = false;
190 }
191 
AdvanceTracing(double deadline_in_ms)192 bool CppHeap::AdvanceTracing(double deadline_in_ms) {
193   // TODO(chromium:1056170): Replace std::numeric_limits<size_t>::max() with a
194   // proper deadline when unified heap transitions to bytes-based deadline.
195   marking_done_ = marker_->AdvanceMarkingWithMaxDuration(
196       v8::base::TimeDelta::FromMillisecondsD(deadline_in_ms));
197   return marking_done_;
198 }
199 
IsTracingDone()200 bool CppHeap::IsTracingDone() { return marking_done_; }
201 
EnterFinalPause(EmbedderStackState stack_state)202 void CppHeap::EnterFinalPause(EmbedderStackState stack_state) {
203   marker_->EnterAtomicPause(stack_state);
204   if (compactor_.CancelIfShouldNotCompact(
205           UnifiedHeapMarker::MarkingConfig::MarkingType::kAtomic,
206           stack_state)) {
207     marker_->NotifyCompactionCancelled();
208   }
209 }
210 
TraceEpilogue(TraceSummary * trace_summary)211 void CppHeap::TraceEpilogue(TraceSummary* trace_summary) {
212   CHECK(marking_done_);
213   {
214     // Weakness callbacks and pre-finalizers are forbidden from allocating
215     // objects.
216     cppgc::internal::ObjectAllocator::NoAllocationScope no_allocation_scope_(
217         object_allocator_);
218     marker_->LeaveAtomicPause();
219     prefinalizer_handler()->InvokePreFinalizers();
220   }
221   marker_.reset();
222   // TODO(chromium:1056170): replace build flag with dedicated flag.
223 #if DEBUG
224   UnifiedHeapMarkingVerifier verifier(*this);
225   verifier.Run(cppgc::Heap::StackState::kNoHeapPointers);
226 #endif
227   cppgc::internal::Sweeper::SweepingConfig::CompactableSpaceHandling
228       compactable_space_handling = compactor_.CompactSpacesIfEnabled();
229   {
230     NoGCScope no_gc(*this);
231     const cppgc::internal::Sweeper::SweepingConfig sweeping_config{
232         cppgc::internal::Sweeper::SweepingConfig::SweepingType::
233             kIncrementalAndConcurrent,
234         compactable_space_handling};
235     sweeper().Start(sweeping_config);
236   }
237 }
238 
239 }  // namespace internal
240 }  // namespace v8
241