summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/heap/visitor.h
blob: 159e40106f992928151c67c5cb623df3fd961a77 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
/*
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_VISITOR_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_VISITOR_H_

#include <memory>
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "third_party/blink/renderer/platform/wtf/forward.h"
#include "third_party/blink/renderer/platform/wtf/hash_traits.h"
#include "third_party/blink/renderer/platform/wtf/type_traits.h"

namespace blink {

template <typename T>
class GarbageCollected;
template <typename T>
class TraceTrait;
class ThreadState;
class Visitor;
template <typename T>
class SameThreadCheckedMember;
template <typename T>
class TraceWrapperMember;

// The TraceMethodDelegate is used to convert a trace method for type T to a
// TraceCallback.  This allows us to pass a type's trace method as a parameter
// to the PersistentNode constructor. The PersistentNode constructor needs the
// specific trace method due an issue with the Windows compiler which
// instantiates even unused variables. This causes problems
// in header files where we have only forward declarations of classes.
template <typename T, void (T::*method)(Visitor*)>
struct TraceMethodDelegate {
  STATIC_ONLY(TraceMethodDelegate);
  static void Trampoline(Visitor* visitor, void* self) {
    (reinterpret_cast<T*>(self)->*method)(visitor);
  }
};

// Visitor is used to traverse Oilpan's object graph.
class PLATFORM_EXPORT Visitor {
 public:
  explicit Visitor(ThreadState* state) : state_(state) {}
  virtual ~Visitor() = default;

  inline ThreadState* State() const { return state_; }
  inline ThreadHeap& Heap() const { return state_->Heap(); }

  // Static visitor implementation forwarding to dynamic interface.

  // Member version of the one-argument templated trace method.
  template <typename T>
  void Trace(const Member<T>& t) {
    DCHECK(!t.IsHashTableDeletedValue());
    Trace(t.Get());
  }

  template <typename T>
  void Trace(const TraceWrapperMember<T>& t) {
    Trace(*(static_cast<const Member<T>*>(&t)));
  }

  template <typename T>
  void Trace(const SameThreadCheckedMember<T>& t) {
    Trace(*(static_cast<const Member<T>*>(&t)));
  }

  // Fallback methods used only when we need to trace raw pointers of T. This is
  // the case when a member is a union where we do not support members.
  template <typename T>
  void Trace(const T* t) {
    Trace(const_cast<T*>(t));
  }

  template <typename T>
  void Trace(T* t) {
    static_assert(sizeof(T), "T must be fully defined");
    static_assert(IsGarbageCollectedType<T>::value,
                  "T needs to be a garbage collected object");
    if (!t)
      return;
    Visit(const_cast<void*>(reinterpret_cast<const void*>(t)),
          TraceTrait<T>::GetTraceDescriptor(
              const_cast<void*>(reinterpret_cast<const void*>(t))));
  }

  template <typename T>
  void TraceBackingStoreStrongly(T* backing_store, T** backing_store_slot) {
    static_assert(sizeof(T), "T must be fully defined");
    static_assert(IsGarbageCollectedType<T>::value,
                  "T needs to be a garbage collected object");

    if (!backing_store)
      return;
    VisitBackingStoreStrongly(reinterpret_cast<void*>(backing_store),
                              reinterpret_cast<void**>(backing_store_slot),
                              TraceTrait<T>::GetTraceDescriptor(
                                  reinterpret_cast<void*>(backing_store)));
  }

  template <typename T>
  void TraceBackingStoreWeakly(T* backing_store,
                               T** backing_store_slot,
                               WeakCallback callback,
                               void* parameter) {
    static_assert(sizeof(T), "T must be fully defined");
    static_assert(IsGarbageCollectedType<T>::value,
                  "T needs to be a garbage collected object");

    if (!backing_store)
      return;
    VisitBackingStoreWeakly(reinterpret_cast<void*>(backing_store),
                            reinterpret_cast<void**>(backing_store_slot),
                            TraceTrait<T>::GetTraceDescriptor(
                                reinterpret_cast<void*>(backing_store)),
                            callback, parameter);
  }

  template <typename T>
  void TraceBackingStoreOnly(T* backing_store, T** backing_store_slot) {
    static_assert(sizeof(T), "T must be fully defined");
    static_assert(IsGarbageCollectedType<T>::value,
                  "T needs to be a garbage collected object");

    if (!backing_store)
      return;
    VisitBackingStoreOnly(reinterpret_cast<void*>(backing_store),
                          reinterpret_cast<void**>(backing_store_slot));
  }

  // WeakMember version of the templated trace method. It doesn't keep
  // the traced thing alive, but will write null to the WeakMember later
  // if the pointed-to object is dead. It's lying for this to be const,
  // but the overloading resolver prioritizes constness too high when
  // picking the correct overload, so all these trace methods have to have
  // the same constness on their argument to allow the type to decide.
  template <typename T>
  void Trace(const WeakMember<T>& t) {
    static_assert(sizeof(T), "T must be fully defined");
    static_assert(IsGarbageCollectedType<T>::value,
                  "T needs to be a garbage collected object");

    if (!t.Get())
      return;

    DCHECK(!t.IsHashTableDeletedValue());
    VisitWeak(const_cast<void*>(reinterpret_cast<const void*>(t.Get())),
              reinterpret_cast<void**>(
                  const_cast<typename std::remove_const<T>::type**>(t.Cell())),
              TraceTrait<T>::GetTraceDescriptor(
                  const_cast<void*>(reinterpret_cast<const void*>(t.Get()))),
              &HandleWeakCell<T>);
  }

  // Fallback trace method for part objects to allow individual trace methods
  // to trace through a part object with visitor->trace(m_partObject). This
  // takes a const argument, because otherwise it will match too eagerly: a
  // non-const argument would match a non-const Vector<T>& argument better
  // than the specialization that takes const Vector<T>&. For a similar reason,
  // the other specializations take a const argument even though they are
  // usually used with non-const arguments, otherwise this function would match
  // too well.
  template <typename T>
  void Trace(const T& t) {
    static_assert(sizeof(T), "T must be fully defined");
    if (std::is_polymorphic<T>::value) {
      intptr_t vtable = *reinterpret_cast<const intptr_t*>(&t);
      if (!vtable)
        return;
    }
    TraceTrait<T>::Trace(this, &const_cast<T&>(t));
  }

  // Registers a callback for custom weakness.
  template <typename T, void (T::*method)(Visitor*)>
  void RegisterWeakMembers(const T* obj) {
    RegisterWeakCallback(const_cast<T*>(obj),
                         &TraceMethodDelegate<T, method>::Trampoline);
  }

  // Dynamic visitor interface.

  // Visits an object through a strong reference.
  virtual void Visit(void*, TraceDescriptor) = 0;

  // Visits an object through a weak reference.
  virtual void VisitWeak(void*, void**, TraceDescriptor, WeakCallback) = 0;

  // Visitors for collection backing stores.
  virtual void VisitBackingStoreStrongly(void*, void**, TraceDescriptor) = 0;
  virtual void VisitBackingStoreWeakly(void*,
                                       void**,
                                       TraceDescriptor,
                                       WeakCallback,
                                       void*) = 0;
  virtual void VisitBackingStoreOnly(void*, void**) = 0;

  // Registers backing store pointers so that they can be moved and properly
  // updated.
  virtual void RegisterBackingStoreCallback(void* backing_store,
                                            MovingObjectCallback,
                                            void* callback_data) = 0;

  // Used to register ephemeron callbacks.
  virtual bool RegisterWeakTable(const void* closure,
                                 EphemeronCallback iteration_callback) {
    return false;
  }

  // |WeakCallback| will usually use |ObjectAliveTrait| to figure out liveness
  // of any children of |closure|. Upon return from the callback all references
  // to dead objects must have been purged. Any operation that extends the
  // object graph, including allocation or reviving objects, is prohibited.
  // Clearing out additional pointers is allowed. Note that removing elements
  // from heap collections such as HeapHashSet can cause an allocation if the
  // backing store requires resizing. These collections know how to deal with
  // WeakMember elements though.
  virtual void RegisterWeakCallback(void* closure, WeakCallback) = 0;

 private:
  template <typename T>
  static void HandleWeakCell(Visitor* self, void*);

  ThreadState* const state_;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_VISITOR_H_