File: vector_traits.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (222 lines) | stat: -rw-r--r-- 10,565 bytes parent folder | download | duplicates (9)
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
/*
 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_VECTOR_TRAITS_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_VECTOR_TRAITS_H_

#include <memory>
#include <type_traits>
#include <utility>
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/type_traits.h"

namespace WTF {

// Vector traits serve two purposes:
// 1. Faster bulk operations: Instead of invoking proper constructors,
//    destructors, copy operators, and move operators on individual elements,
//    the vector implementation will just use `memcpy()` and friends where
//    possible.
// 2. Garbage collection support: HeapVector requires certain traits to be set
//    which is used to acknowledge that semantics are different from regular
//    `WTF::Vector` and `std::vector`.
template <typename T>
struct VectorTraitsBase {
  using TraitType = T;

  // When true, T will be destroyed using `~T`.
  static const bool kNeedsDestruction =
      !std::is_trivially_destructible<T>::value;

  // When true, allows initializing a value for a range with `memset()` instead
  // of invoking constructors.
  static constexpr bool kCanInitializeWithMemset =
      std::is_trivially_default_constructible<T>::value;

  // When true, allows setting a value for a range with `memset(0)` instead of
  // invoking constructors.
  static constexpr bool kCanFillWithMemset =
      std::is_default_constructible<T>::value && (sizeof(T) == sizeof(char));

  // When true, allows comparing T with `memcmp()`. instead of `std::equals()`.
  static constexpr bool kCanCompareWithMemcmp =
      std::is_scalar<T>::value;  // Types without padding.

  // When true, allows moving vector backings with memcpy instead of invoking
  // move operations on every vector slot. There's no move operator being
  // invoked.
  //
  // Garbage collection support: When true, the GC may move vector backings when
  // they are not referred to from the native stack. This prohibits keeping
  // inner pointers to vector elements and backing stores across event loop
  // turns. When elements are moved using copy, their old storage is is just
  // freed. In essence, no constructor/destructor/move operations will be
  // invoked.
  static constexpr bool kCanMoveWithMemcpy =
      std::is_trivially_move_assignable<T>::value;

  // When true, allows copying vector backings with memcpy instead of invoking
  // copy operations on every vector slot. There's no copy operator being
  // invoked.
  static constexpr bool kCanCopyWithMemcpy =
      std::is_trivially_copy_assignable<T>::value;

  // Garbage collection support: Must be true for types used in `HeapVector`.
  // The reason is that GCed vector backings are initialized to zeroed memory.
  // The GC assumes that invoking (a) `T::Trace()`, and (b) `T::~T` are no ops
  // on zeroed memory.
  static constexpr bool kCanClearUnusedSlotsWithMemset =
      std::is_trivially_destructible<T>::value &&
      (!IsTraceable<T>::value || (std::is_trivially_constructible<T>::value &&
                                  std::is_trivially_copyable<T>::value));

  // Garbage collection support: When true, the vector invokes `Trace()` methods
  // concurrently from the non-owning thread.
  static constexpr bool kCanTraceConcurrently = false;
};

template <typename T>
struct VectorTraits : VectorTraitsBase<T> {};

// Classes marked with SimpleVectorTraits will use memmov, memcpy, memcmp
// instead of constructors, copy operators, etc for initialization, move and
// comparison.
template <typename T>
struct SimpleClassVectorTraits : VectorTraitsBase<T> {
  static const bool kCanInitializeWithMemset = true;
  static const bool kCanClearUnusedSlotsWithMemset = true;
  static const bool kCanMoveWithMemcpy = true;
  static const bool kCanCompareWithMemcmp = true;
};

// We know std::unique_ptr and RefPtr are simple enough that initializing to 0
// and moving with memcpy (and then not destructing the original) will totally
// work.
template <typename P>
struct VectorTraits<scoped_refptr<P>>
    : SimpleClassVectorTraits<scoped_refptr<P>> {
  // scoped_refptr cannot be copied using memcpy as the internals (e.g. ref
  // count) depend on properly constructing the object.
  static const bool kCanCopyWithMemcpy = false;
};

template <typename P>
struct VectorTraits<std::unique_ptr<P>>
    : SimpleClassVectorTraits<std::unique_ptr<P>> {
  // std::unique_ptr -> std::unique_ptr has a very particular structure that
  // tricks the normal type traits into thinking that the class is "trivially
  // copyable".
  static const bool kCanCopyWithMemcpy = false;
};
static_assert(VectorTraits<scoped_refptr<int>>::kCanInitializeWithMemset,
              "inefficient RefPtr Vector");
static_assert(VectorTraits<scoped_refptr<int>>::kCanMoveWithMemcpy,
              "inefficient RefPtr Vector");
static_assert(VectorTraits<scoped_refptr<int>>::kCanCompareWithMemcmp,
              "inefficient RefPtr Vector");
static_assert(VectorTraits<std::unique_ptr<int>>::kCanInitializeWithMemset,
              "inefficient std::unique_ptr Vector");
static_assert(VectorTraits<std::unique_ptr<int>>::kCanMoveWithMemcpy,
              "inefficient std::unique_ptr Vector");
static_assert(VectorTraits<std::unique_ptr<int>>::kCanCompareWithMemcmp,
              "inefficient std::unique_ptr Vector");

template <typename First, typename Second>
struct VectorTraits<std::pair<First, Second>> {
  using TraitType = std::pair<First, Second>;

  typedef VectorTraits<First> FirstTraits;
  typedef VectorTraits<Second> SecondTraits;

  static_assert(!IsWeak<First>::value,
                "Weak references are not allowed in Vector");
  static_assert(!IsWeak<Second>::value,
                "Weak references are not allowed in Vector");

  static const bool kNeedsDestruction =
      FirstTraits::kNeedsDestruction || SecondTraits::kNeedsDestruction;
  static const bool kCanInitializeWithMemset =
      FirstTraits::kCanInitializeWithMemset &&
      SecondTraits::kCanInitializeWithMemset;
  static const bool kCanMoveWithMemcpy =
      FirstTraits::kCanMoveWithMemcpy && SecondTraits::kCanMoveWithMemcpy;
  static const bool kCanCopyWithMemcpy =
      FirstTraits::kCanCopyWithMemcpy && SecondTraits::kCanCopyWithMemcpy;
  static const bool kCanFillWithMemset = false;
  static const bool kCanCompareWithMemcmp =
      FirstTraits::kCanCompareWithMemcmp && SecondTraits::kCanCompareWithMemcmp;
  static const bool kCanClearUnusedSlotsWithMemset =
      FirstTraits::kCanClearUnusedSlotsWithMemset &&
      SecondTraits::kCanClearUnusedSlotsWithMemset;

  static constexpr bool kCanTraceConcurrently = false;
};

}  // namespace WTF

#define WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(ClassName)         \
  namespace WTF {                                                             \
  static_assert(!std::is_trivially_default_constructible<ClassName>::value || \
                    !std::is_trivially_move_assignable<ClassName>::value ||   \
                    !std::is_scalar<ClassName>::value,                        \
                "macro not needed");                                          \
  template <>                                                                 \
  struct VectorTraits<ClassName> : SimpleClassVectorTraits<ClassName> {};     \
  }

#define WTF_ALLOW_MOVE_AND_INIT_WITH_MEM_FUNCTIONS(ClassName)                 \
  namespace WTF {                                                             \
  static_assert(!std::is_trivially_default_constructible<ClassName>::value || \
                    !std::is_trivially_move_assignable<ClassName>::value,     \
                "macro not needed");                                          \
  template <>                                                                 \
  struct VectorTraits<ClassName> : VectorTraitsBase<ClassName> {              \
    static const bool kCanInitializeWithMemset = true;                        \
    static const bool kCanClearUnusedSlotsWithMemset = true;                  \
    static const bool kCanMoveWithMemcpy = true;                              \
  };                                                                          \
  }

#define WTF_ALLOW_INIT_WITH_MEM_FUNCTIONS(ClassName)                        \
  namespace WTF {                                                           \
  static_assert(!std::is_trivially_default_constructible<ClassName>::value, \
                "macro not needed");                                        \
  template <>                                                               \
  struct VectorTraits<ClassName> : VectorTraitsBase<ClassName> {            \
    static const bool kCanInitializeWithMemset = true;                      \
    static const bool kCanClearUnusedSlotsWithMemset = true;                \
  };                                                                        \
  }

#define WTF_ALLOW_CLEAR_UNUSED_SLOTS_WITH_MEM_FUNCTIONS(ClassName)          \
  namespace WTF {                                                           \
  static_assert(!std::is_trivially_default_constructible<ClassName>::value, \
                "macro not needed");                                        \
  template <>                                                               \
  struct VectorTraits<ClassName> : VectorTraitsBase<ClassName> {            \
    static const bool kCanClearUnusedSlotsWithMemset = true;                \
  };                                                                        \
  }

using WTF::VectorTraits;
using WTF::SimpleClassVectorTraits;

#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_VECTOR_TRAITS_H_