v8  8.6.395 (node 15.0.1)
V8 is Google's open source JavaScript engine
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
visitor.h
Go to the documentation of this file.
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 INCLUDE_CPPGC_VISITOR_H_
6 #define INCLUDE_CPPGC_VISITOR_H_
7 
8 #include "cppgc/garbage-collected.h"
9 #include "cppgc/internal/logging.h"
10 #include "cppgc/internal/pointer-policies.h"
11 #include "cppgc/liveness-broker.h"
12 #include "cppgc/member.h"
13 #include "cppgc/source-location.h"
14 #include "cppgc/trace-trait.h"
15 
16 namespace cppgc {
17 
18 namespace internal {
19 template <typename T, typename WeaknessPolicy, typename LocationPolicy,
20  typename CheckingPolicy>
21 class BasicPersistent;
22 class ConservativeTracingVisitor;
23 class VisitorBase;
24 class VisitorFactory;
25 
26 } // namespace internal
27 
28 using WeakCallback = void (*)(const LivenessBroker&, const void*);
29 
30 /**
31  * Visitor passed to trace methods. All managed pointers must have called the
32  * Visitor's trace method on them.
33  *
34  * \code
35  * class Foo final : public GarbageCollected<Foo> {
36  * public:
37  * void Trace(Visitor* visitor) const {
38  * visitor->Trace(foo_);
39  * visitor->Trace(weak_foo_);
40  * }
41  * private:
42  * Member<Foo> foo_;
43  * WeakMember<Foo> weak_foo_;
44  * };
45  * \endcode
46  */
47 class Visitor {
48  public:
49  class Key {
50  private:
51  Key() = default;
52  friend class internal::VisitorFactory;
53  };
54 
55  explicit Visitor(Key) {}
56 
57  virtual ~Visitor() = default;
58 
59  /**
60  * Trace method for Member.
61  *
62  * \param member Member reference retaining an object.
63  */
64  template <typename T>
65  void Trace(const Member<T>& member) {
66  const T* value = member.GetRawAtomic();
68  Trace(value);
69  }
70 
71  /**
72  * Trace method for WeakMember.
73  *
74  * \param weak_member WeakMember reference weakly retaining an object.
75  */
76  template <typename T>
77  void Trace(const WeakMember<T>& weak_member) {
78  static_assert(sizeof(T), "Pointee type must be fully defined.");
79  static_assert(internal::IsGarbageCollectedType<T>::value,
80  "T must be GarbageCollected or GarbageCollectedMixin type");
81 
82  const T* value = weak_member.GetRawAtomic();
83 
84  // Bailout assumes that WeakMember emits write barrier.
85  if (!value) {
86  return;
87  }
88 
89  // TODO(chromium:1056170): DCHECK (or similar) for deleted values as they
90  // should come in at a different path.
91  VisitWeak(value, TraceTrait<T>::GetTraceDescriptor(value),
92  &HandleWeak<WeakMember<T>>, &weak_member);
93  }
94 
95  /**
96  * Trace method for inlined objects that are not allocated themselves but
97  * otherwise follow managed heap layout and have a Trace() method.
98  *
99  * \param object reference of the inlined object.
100  */
101  template <typename T>
102  void Trace(const T& object) {
103 #if V8_ENABLE_CHECKS
104  // This object is embedded in potentially multiple nested objects. The
105  // outermost object must not be in construction as such objects are (a) not
106  // processed immediately, and (b) only processed conservatively if not
107  // otherwise possible.
108  CheckObjectNotInConstruction(&object);
109 #endif // V8_ENABLE_CHECKS
110  TraceTrait<T>::Trace(this, &object);
111  }
112 
113  /**
114  * Registers a weak callback method on the object of type T. See
115  * LivenessBroker for an usage example.
116  *
117  * \param object of type T specifying a weak callback method.
118  */
119  template <typename T, void (T::*method)(const LivenessBroker&)>
120  void RegisterWeakCallbackMethod(const T* object) {
121  RegisterWeakCallback(&WeakCallbackMethodDelegate<T, method>, object);
122  }
123 
124  /**
125  * Registers a weak callback that is invoked during garbage collection.
126  *
127  * \param callback to be invoked.
128  * \param data custom data that is passed to the callback.
129  */
130  virtual void RegisterWeakCallback(WeakCallback callback, const void* data) {}
131 
132  protected:
133  virtual void Visit(const void* self, TraceDescriptor) {}
134  virtual void VisitWeak(const void* self, TraceDescriptor, WeakCallback,
135  const void* weak_member) {}
136  virtual void VisitRoot(const void*, TraceDescriptor) {}
137  virtual void VisitWeakRoot(const void* self, TraceDescriptor, WeakCallback,
138  const void* weak_root) {}
139 
140  private:
141  template <typename T, void (T::*method)(const LivenessBroker&)>
142  static void WeakCallbackMethodDelegate(const LivenessBroker& info,
143  const void* self) {
144  // Callback is registered through a potential const Trace method but needs
145  // to be able to modify fields. See HandleWeak.
146  (const_cast<T*>(static_cast<const T*>(self))->*method)(info);
147  }
148 
149  template <typename PointerType>
150  static void HandleWeak(const LivenessBroker& info, const void* object) {
151  const PointerType* weak = static_cast<const PointerType*>(object);
152  // Sentinel values are preserved for weak pointers.
153  if (*weak == kSentinelPointer) return;
154  const auto* raw = weak->Get();
155  if (!info.IsHeapObjectAlive(raw)) {
156  weak->ClearFromGC();
157  }
158  }
159 
160  template <typename Persistent,
161  std::enable_if_t<Persistent::IsStrongPersistent::value>* = nullptr>
162  void TraceRoot(const Persistent& p, const SourceLocation& loc) {
163  using PointeeType = typename Persistent::PointeeType;
164  static_assert(sizeof(PointeeType),
165  "Persistent's pointee type must be fully defined");
166  static_assert(internal::IsGarbageCollectedType<PointeeType>::value,
167  "Persistent's pointee type must be GarbageCollected or "
168  "GarbageCollectedMixin");
169  if (!p.Get()) {
170  return;
171  }
172  VisitRoot(p.Get(), TraceTrait<PointeeType>::GetTraceDescriptor(p.Get()));
173  }
174 
175  template <
176  typename WeakPersistent,
177  std::enable_if_t<!WeakPersistent::IsStrongPersistent::value>* = nullptr>
178  void TraceRoot(const WeakPersistent& p, const SourceLocation& loc) {
179  using PointeeType = typename WeakPersistent::PointeeType;
180  static_assert(sizeof(PointeeType),
181  "Persistent's pointee type must be fully defined");
182  static_assert(internal::IsGarbageCollectedType<PointeeType>::value,
183  "Persistent's pointee type must be GarbageCollected or "
184  "GarbageCollectedMixin");
185  VisitWeakRoot(p.Get(), TraceTrait<PointeeType>::GetTraceDescriptor(p.Get()),
186  &HandleWeak<WeakPersistent>, &p);
187  }
188 
189  template <typename T>
190  void Trace(const T* t) {
191  static_assert(sizeof(T), "Pointee type must be fully defined.");
192  static_assert(internal::IsGarbageCollectedType<T>::value,
193  "T must be GarbageCollected or GarbageCollectedMixin type");
194  if (!t) {
195  return;
196  }
197  Visit(t, TraceTrait<T>::GetTraceDescriptor(t));
198  }
199 
200 #if V8_ENABLE_CHECKS
202 #endif // V8_ENABLE_CHECKS
203 
204  template <typename T, typename WeaknessPolicy, typename LocationPolicy,
205  typename CheckingPolicy>
206  friend class internal::BasicPersistent;
207  friend class internal::ConservativeTracingVisitor;
208  friend class internal::VisitorBase;
209 };
210 
211 } // namespace cppgc
212 
213 #endif // INCLUDE_CPPGC_VISITOR_H_