v8  8.4.371 (node 14.15.5)
V8 is Google's open source JavaScript engine
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 namespace internal {
18 class VisitorBase;
19 } // namespace internal
20 
21 using WeakCallback = void (*)(const LivenessBroker&, const void*);
22 
23 /**
24  * Visitor passed to trace methods. All managed pointers must have called the
25  * visitor's trace method on them.
26  */
27 class Visitor {
28  public:
29  template <typename T>
30  void Trace(const Member<T>& member) {
31  const T* value = member.GetRawAtomic();
33  Trace(value);
34  }
35 
36  template <typename T>
37  void Trace(const WeakMember<T>& weak_member) {
38  static_assert(sizeof(T), "T must be fully defined");
39  static_assert(internal::IsGarbageCollectedType<T>::value,
40  "T must be GarabgeCollected or GarbageCollectedMixin type");
41 
42  const T* value = weak_member.GetRawAtomic();
43 
44  // Bailout assumes that WeakMember emits write barrier.
45  if (!value) {
46  return;
47  }
48 
49  // TODO(chromium:1056170): DCHECK (or similar) for deleted values as they
50  // should come in at a different path.
51  VisitWeak(value, TraceTrait<T>::GetTraceDescriptor(value),
52  &HandleWeak<WeakMember<T>>, &weak_member);
53  }
54 
55  template <typename Persistent,
56  std::enable_if_t<Persistent::IsStrongPersistent::value>* = nullptr>
57  void TraceRoot(const Persistent& p, const SourceLocation& loc) {
58  using PointeeType = typename Persistent::PointeeType;
59  static_assert(sizeof(PointeeType),
60  "Persistent's pointee type must be fully defined");
61  static_assert(internal::IsGarbageCollectedType<PointeeType>::value,
62  "Persisent's pointee type must be GarabgeCollected or "
63  "GarbageCollectedMixin");
64  if (!p.Get()) {
65  return;
66  }
67  VisitRoot(p.Get(), TraceTrait<PointeeType>::GetTraceDescriptor(p.Get()));
68  }
69 
70  template <
71  typename WeakPersistent,
72  std::enable_if_t<!WeakPersistent::IsStrongPersistent::value>* = nullptr>
73  void TraceRoot(const WeakPersistent& p, const SourceLocation& loc) {
74  using PointeeType = typename WeakPersistent::PointeeType;
75  static_assert(sizeof(PointeeType),
76  "Persistent's pointee type must be fully defined");
77  static_assert(internal::IsGarbageCollectedType<PointeeType>::value,
78  "Persisent's pointee type must be GarabgeCollected or "
79  "GarbageCollectedMixin");
80  VisitWeakRoot(p.Get(), TraceTrait<PointeeType>::GetTraceDescriptor(p.Get()),
81  &HandleWeak<WeakPersistent>, &p);
82  }
83 
84  template <typename T, void (T::*method)(const LivenessBroker&)>
85  void RegisterWeakCallbackMethod(const T* obj) {
86  RegisterWeakCallback(&WeakCallbackMethodDelegate<T, method>, obj);
87  }
88 
89  virtual void RegisterWeakCallback(WeakCallback, const void*) {}
90 
91  protected:
92  virtual void Visit(const void* self, TraceDescriptor) {}
93  virtual void VisitWeak(const void* self, TraceDescriptor, WeakCallback,
94  const void* weak_member) {}
95  virtual void VisitRoot(const void*, TraceDescriptor) {}
96  virtual void VisitWeakRoot(const void* self, TraceDescriptor, WeakCallback,
97  const void* weak_root) {}
98 
99  private:
100  template <typename T, void (T::*method)(const LivenessBroker&)>
101  static void WeakCallbackMethodDelegate(const LivenessBroker& info,
102  const void* self) {
103  // Callback is registered through a potential const Trace method but needs
104  // to be able to modify fields. See HandleWeak.
105  (const_cast<T*>(static_cast<const T*>(self))->*method)(info);
106  }
107 
108  template <typename PointerType>
109  static void HandleWeak(const LivenessBroker& info, const void* object) {
110  const PointerType* weak = static_cast<const PointerType*>(object);
111  const auto* raw = weak->Get();
112  if (raw && !info.IsHeapObjectAlive(raw)) {
113  // Object is passed down through the marker as const. Alternatives are
114  // - non-const Trace method;
115  // - mutable pointer in MemberBase;
116  const_cast<PointerType*>(weak)->Clear();
117  }
118  }
119 
120  Visitor() = default;
121 
122  template <typename T>
123  void Trace(const T* t) {
124  static_assert(sizeof(T), "T must be fully defined");
125  static_assert(internal::IsGarbageCollectedType<T>::value,
126  "T must be GarabgeCollected or GarbageCollectedMixin type");
127  if (!t) {
128  return;
129  }
130  Visit(t, TraceTrait<T>::GetTraceDescriptor(t));
131  }
132 
133  friend class internal::VisitorBase;
134 };
135 
136 } // namespace cppgc
137 
138 #endif // INCLUDE_CPPGC_VISITOR_H_