• 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_MARKER_H_
6 #define V8_HEAP_CPPGC_MARKER_H_
7 
8 #include <memory>
9 
10 #include "include/cppgc/heap.h"
11 #include "include/cppgc/visitor.h"
12 #include "src/base/macros.h"
13 #include "src/base/platform/time.h"
14 #include "src/heap/base/worklist.h"
15 #include "src/heap/cppgc/concurrent-marker.h"
16 #include "src/heap/cppgc/globals.h"
17 #include "src/heap/cppgc/incremental-marking-schedule.h"
18 #include "src/heap/cppgc/marking-state.h"
19 #include "src/heap/cppgc/marking-visitor.h"
20 #include "src/heap/cppgc/marking-worklists.h"
21 #include "src/heap/cppgc/task-handle.h"
22 
23 namespace cppgc {
24 namespace internal {
25 
26 class HeapBase;
27 class MarkerFactory;
28 
29 // Marking algorithm. Example for a valid call sequence creating the marking
30 // phase:
31 // 1. StartMarking() [Called implicitly when creating a Marker using
32 //                    MarkerFactory]
33 // 2. AdvanceMarkingWithDeadline() [Optional, depending on environment.]
34 // 3. EnterAtomicPause()
35 // 4. AdvanceMarkingWithDeadline()
36 // 5. LeaveAtomicPause()
37 //
38 // Alternatively, FinishMarking combines steps 3.-5.
39 class V8_EXPORT_PRIVATE MarkerBase {
40  public:
41   struct MarkingConfig {
42     enum class CollectionType : uint8_t {
43       kMinor,
44       kMajor,
45     };
46     using StackState = cppgc::Heap::StackState;
47     enum MarkingType : uint8_t {
48       kAtomic,
49       kIncremental,
50       kIncrementalAndConcurrent
51     };
52 
DefaultMarkingConfig53     static constexpr MarkingConfig Default() { return {}; }
54 
55     const CollectionType collection_type = CollectionType::kMajor;
56     StackState stack_state = StackState::kMayContainHeapPointers;
57     MarkingType marking_type = MarkingType::kIncremental;
58   };
59 
60   virtual ~MarkerBase();
61 
62   MarkerBase(const MarkerBase&) = delete;
63   MarkerBase& operator=(const MarkerBase&) = delete;
64 
65   // Signals entering the atomic marking pause. The method
66   // - stops incremental/concurrent marking;
67   // - flushes back any in-construction worklists if needed;
68   // - Updates the MarkingConfig if the stack state has changed;
69   void EnterAtomicPause(MarkingConfig::StackState);
70 
71   // Makes marking progress.
72   // TODO(chromium:1056170): Remove TimeDelta argument when unified heap no
73   // longer uses it.
74   bool AdvanceMarkingWithMaxDuration(v8::base::TimeDelta);
75 
76   // Makes marking progress when allocation a new lab.
77   void AdvanceMarkingOnAllocation();
78 
79   // Signals leaving the atomic marking pause. This method expects no more
80   // objects to be marked and merely updates marking states if needed.
81   void LeaveAtomicPause();
82 
83   // Combines:
84   // - EnterAtomicPause()
85   // - AdvanceMarkingWithDeadline()
86   // - ProcessWeakness()
87   // - LeaveAtomicPause()
88   void FinishMarking(MarkingConfig::StackState);
89 
90   void ProcessWeakness();
91 
92   inline void WriteBarrierForInConstructionObject(HeapObjectHeader&);
93   inline void WriteBarrierForObject(HeapObjectHeader&);
94 
heap()95   HeapBase& heap() { return heap_; }
96 
MarkingWorklistsForTesting()97   MarkingWorklists& MarkingWorklistsForTesting() { return marking_worklists_; }
MutatorMarkingStateForTesting()98   MutatorMarkingState& MutatorMarkingStateForTesting() {
99     return mutator_marking_state_;
100   }
VisitorForTesting()101   cppgc::Visitor& VisitorForTesting() { return visitor(); }
102   void ClearAllWorklistsForTesting();
103 
104   bool IncrementalMarkingStepForTesting(MarkingConfig::StackState);
105 
106   class IncrementalMarkingTask final : public cppgc::Task {
107    public:
108     using Handle = SingleThreadedHandle;
109 
110     IncrementalMarkingTask(MarkerBase*, MarkingConfig::StackState);
111 
112     static Handle Post(cppgc::TaskRunner*, MarkerBase*);
113 
114    private:
115     void Run() final;
116 
117     MarkerBase* const marker_;
118     MarkingConfig::StackState stack_state_;
119     // TODO(chromium:1056170): Change to CancelableTask.
120     Handle handle_;
121   };
122 
123   void DisableIncrementalMarkingForTesting();
124 
125   void WaitForConcurrentMarkingForTesting();
126 
127   void NotifyCompactionCancelled();
128 
129  protected:
130   static constexpr v8::base::TimeDelta kMaximumIncrementalStepDuration =
131       v8::base::TimeDelta::FromMilliseconds(2);
132 
133   class Key {
134    private:
135     Key() = default;
136     friend class MarkerFactory;
137   };
138 
139   MarkerBase(Key, HeapBase&, cppgc::Platform*, MarkingConfig);
140 
141   // Initialize marking according to the given config. This method will
142   // trigger incremental/concurrent marking if needed.
143   void StartMarking();
144 
145   virtual cppgc::Visitor& visitor() = 0;
146   virtual ConservativeTracingVisitor& conservative_visitor() = 0;
147   virtual heap::base::StackVisitor& stack_visitor() = 0;
148 
149   // Makes marking progress.
150   // TODO(chromium:1056170): Remove TimeDelta argument when unified heap no
151   // longer uses it.
152   bool AdvanceMarkingWithDeadline(
153       v8::base::TimeDelta = kMaximumIncrementalStepDuration);
154 
155   bool ProcessWorklistsWithDeadline(size_t, v8::base::TimeTicks);
156 
157   void VisitRoots(MarkingConfig::StackState);
158 
159   void MarkNotFullyConstructedObjects();
160 
161   void ScheduleIncrementalMarkingTask();
162 
163   bool IncrementalMarkingStep(MarkingConfig::StackState);
164 
165   HeapBase& heap_;
166   MarkingConfig config_ = MarkingConfig::Default();
167 
168   cppgc::Platform* platform_;
169   std::shared_ptr<cppgc::TaskRunner> foreground_task_runner_;
170   IncrementalMarkingTask::Handle incremental_marking_handle_;
171 
172   MarkingWorklists marking_worklists_;
173   MutatorMarkingState mutator_marking_state_;
174   bool is_marking_started_{false};
175 
176   IncrementalMarkingSchedule schedule_;
177 
178   std::unique_ptr<ConcurrentMarkerBase> concurrent_marker_{nullptr};
179 
180   bool incremental_marking_disabled_for_testing_{false};
181 
182   friend class MarkerFactory;
183 };
184 
185 class V8_EXPORT_PRIVATE MarkerFactory {
186  public:
187   template <typename T, typename... Args>
CreateAndStartMarking(Args &&...args)188   static std::unique_ptr<T> CreateAndStartMarking(Args&&... args) {
189     static_assert(std::is_base_of<MarkerBase, T>::value,
190                   "MarkerFactory can only create subclasses of MarkerBase");
191     std::unique_ptr<T> marker =
192         std::make_unique<T>(MarkerBase::Key(), std::forward<Args>(args)...);
193     marker->StartMarking();
194     return marker;
195   }
196 };
197 
198 class V8_EXPORT_PRIVATE Marker final : public MarkerBase {
199  public:
200   Marker(Key, HeapBase&, cppgc::Platform*,
201          MarkingConfig = MarkingConfig::Default());
202 
203  protected:
visitor()204   cppgc::Visitor& visitor() final { return marking_visitor_; }
conservative_visitor()205   ConservativeTracingVisitor& conservative_visitor() final {
206     return conservative_marking_visitor_;
207   }
stack_visitor()208   heap::base::StackVisitor& stack_visitor() final {
209     return conservative_marking_visitor_;
210   }
211 
212  private:
213   MutatorMarkingVisitor marking_visitor_;
214   ConservativeMarkingVisitor conservative_marking_visitor_;
215 };
216 
WriteBarrierForInConstructionObject(HeapObjectHeader & header)217 void MarkerBase::WriteBarrierForInConstructionObject(HeapObjectHeader& header) {
218   mutator_marking_state_.not_fully_constructed_worklist()
219       .Push<AccessMode::kAtomic>(&header);
220 }
221 
WriteBarrierForObject(HeapObjectHeader & header)222 void MarkerBase::WriteBarrierForObject(HeapObjectHeader& header) {
223   mutator_marking_state_.write_barrier_worklist().Push(&header);
224 }
225 
226 }  // namespace internal
227 }  // namespace cppgc
228 
229 #endif  // V8_HEAP_CPPGC_MARKER_H_
230