v8  8.4.371 (node 14.15.5)
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 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_