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_TRACE_TRAIT_H_
6#define INCLUDE_CPPGC_TRACE_TRAIT_H_
7
8#include <type_traits>
9
10#include "cppgc/type-traits.h"
11#include "v8config.h"  // NOLINT(build/include_directory)
12
13namespace cppgc {
14
15class Visitor;
16
17namespace internal {
18
19// Implementation of the default TraceTrait handling GarbageCollected and
20// GarbageCollectedMixin.
21template <typename T,
22          bool =
23              IsGarbageCollectedMixinTypeV<typename std::remove_const<T>::type>>
24struct TraceTraitImpl;
25
26}  // namespace internal
27
28/**
29 * Callback for invoking tracing on a given object.
30 *
31 * \param visitor The visitor to dispatch to.
32 * \param object The object to invoke tracing on.
33 */
34using TraceCallback = void (*)(Visitor* visitor, const void* object);
35
36/**
37 * Describes how to trace an object, i.e., how to visit all Oilpan-relevant
38 * fields of an object.
39 */
40struct TraceDescriptor {
41  /**
42   * Adjusted base pointer, i.e., the pointer to the class inheriting directly
43   * from GarbageCollected, of the object that is being traced.
44   */
45  const void* base_object_payload;
46  /**
47   * Callback for tracing the object.
48   */
49  TraceCallback callback;
50};
51
52namespace internal {
53
54struct V8_EXPORT TraceTraitFromInnerAddressImpl {
55  static TraceDescriptor GetTraceDescriptor(const void* address);
56};
57
58/**
59 * Trait specifying how the garbage collector processes an object of type T.
60 *
61 * Advanced users may override handling by creating a specialization for their
62 * type.
63 */
64template <typename T>
65struct TraceTraitBase {
66  static_assert(internal::IsTraceableV<T>, "T must have a Trace() method");
67
68  /**
69   * Accessor for retrieving a TraceDescriptor to process an object of type T.
70   *
71   * \param self The object to be processed.
72   * \returns a TraceDescriptor to process the object.
73   */
74  static TraceDescriptor GetTraceDescriptor(const void* self) {
75    return internal::TraceTraitImpl<T>::GetTraceDescriptor(
76        static_cast<const T*>(self));
77  }
78
79  /**
80   * Function invoking the tracing for an object of type T.
81   *
82   * \param visitor The visitor to dispatch to.
83   * \param self The object to invoke tracing on.
84   */
85  static void Trace(Visitor* visitor, const void* self) {
86    static_cast<const T*>(self)->Trace(visitor);
87  }
88};
89
90}  // namespace internal
91
92template <typename T>
93struct TraceTrait : public internal::TraceTraitBase<T> {};
94
95namespace internal {
96
97template <typename T>
98struct TraceTraitImpl<T, false> {
99  static_assert(IsGarbageCollectedTypeV<T>,
100                "T must be of type GarbageCollected or GarbageCollectedMixin");
101  static TraceDescriptor GetTraceDescriptor(const void* self) {
102    return {self, TraceTrait<T>::Trace};
103  }
104};
105
106template <typename T>
107struct TraceTraitImpl<T, true> {
108  static TraceDescriptor GetTraceDescriptor(const void* self) {
109    return internal::TraceTraitFromInnerAddressImpl::GetTraceDescriptor(self);
110  }
111};
112
113}  // namespace internal
114}  // namespace cppgc
115
116#endif  // INCLUDE_CPPGC_TRACE_TRAIT_H_
117