1 // Copyright 2018 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // An open-addressing
16 // hashtable with quadratic probing.
17 //
18 // This is a low level hashtable on top of which different interfaces can be
19 // implemented, like flat_hash_set, node_hash_set, string_hash_set, etc.
20 //
21 // The table interface is similar to that of std::unordered_set. Notable
22 // differences are that most member functions support heterogeneous keys when
23 // BOTH the hash and eq functions are marked as transparent. They do so by
24 // providing a typedef called `is_transparent`.
25 //
26 // When heterogeneous lookup is enabled, functions that take key_type act as if
27 // they have an overload set like:
28 //
29 // iterator find(const key_type& key);
30 // template <class K>
31 // iterator find(const K& key);
32 //
33 // size_type erase(const key_type& key);
34 // template <class K>
35 // size_type erase(const K& key);
36 //
37 // std::pair<iterator, iterator> equal_range(const key_type& key);
38 // template <class K>
39 // std::pair<iterator, iterator> equal_range(const K& key);
40 //
41 // When heterogeneous lookup is disabled, only the explicit `key_type` overloads
42 // exist.
43 //
44 // find() also supports passing the hash explicitly:
45 //
46 // iterator find(const key_type& key, size_t hash);
47 // template <class U>
48 // iterator find(const U& key, size_t hash);
49 //
50 // In addition the pointer to element and iterator stability guarantees are
51 // weaker: all iterators and pointers are invalidated after a new element is
52 // inserted.
53 //
54 // IMPLEMENTATION DETAILS
55 //
56 // # Table Layout
57 //
58 // A raw_hash_set's backing array consists of control bytes followed by slots
59 // that may or may not contain objects.
60 //
61 // The layout of the backing array, for `capacity` slots, is thus, as a
62 // pseudo-struct:
63 //
64 // struct BackingArray {
65 // // Sampling handler. This field isn't present when the sampling is
66 // // disabled or this allocation hasn't been selected for sampling.
67 // HashtablezInfoHandle infoz_;
68 // // The number of elements we can insert before growing the capacity.
69 // size_t growth_left;
70 // // Control bytes for the "real" slots.
71 // ctrl_t ctrl[capacity];
72 // // Always `ctrl_t::kSentinel`. This is used by iterators to find when to
73 // // stop and serves no other purpose.
74 // ctrl_t sentinel;
75 // // A copy of the first `kWidth - 1` elements of `ctrl`. This is used so
76 // // that if a probe sequence picks a value near the end of `ctrl`,
77 // // `Group` will have valid control bytes to look at.
78 // ctrl_t clones[kWidth - 1];
79 // // The actual slot data.
80 // slot_type slots[capacity];
81 // };
82 //
83 // The length of this array is computed by `AllocSize()` below.
84 //
85 // Control bytes (`ctrl_t`) are bytes (collected into groups of a
86 // platform-specific size) that define the state of the corresponding slot in
87 // the slot array. Group manipulation is tightly optimized to be as efficient
88 // as possible: SSE and friends on x86, clever bit operations on other arches.
89 //
90 // Group 1 Group 2 Group 3
91 // +---------------+---------------+---------------+
92 // | | | | | | | | | | | | | | | | | | | | | | | | |
93 // +---------------+---------------+---------------+
94 //
95 // Each control byte is either a special value for empty slots, deleted slots
96 // (sometimes called *tombstones*), and a special end-of-table marker used by
97 // iterators, or, if occupied, seven bits (H2) from the hash of the value in the
98 // corresponding slot.
99 //
100 // Storing control bytes in a separate array also has beneficial cache effects,
101 // since more logical slots will fit into a cache line.
102 //
103 // # Hashing
104 //
105 // We compute two separate hashes, `H1` and `H2`, from the hash of an object.
106 // `H1(hash(x))` is an index into `slots`, and essentially the starting point
107 // for the probe sequence. `H2(hash(x))` is a 7-bit value used to filter out
108 // objects that cannot possibly be the one we are looking for.
109 //
110 // # Table operations.
111 //
112 // The key operations are `insert`, `find`, and `erase`.
113 //
114 // Since `insert` and `erase` are implemented in terms of `find`, we describe
115 // `find` first. To `find` a value `x`, we compute `hash(x)`. From
116 // `H1(hash(x))` and the capacity, we construct a `probe_seq` that visits every
117 // group of slots in some interesting order.
118 //
119 // We now walk through these indices. At each index, we select the entire group
120 // starting with that index and extract potential candidates: occupied slots
121 // with a control byte equal to `H2(hash(x))`. If we find an empty slot in the
122 // group, we stop and return an error. Each candidate slot `y` is compared with
123 // `x`; if `x == y`, we are done and return `&y`; otherwise we continue to the
124 // next probe index. Tombstones effectively behave like full slots that never
125 // match the value we're looking for.
126 //
127 // The `H2` bits ensure when we compare a slot to an object with `==`, we are
128 // likely to have actually found the object. That is, the chance is low that
129 // `==` is called and returns `false`. Thus, when we search for an object, we
130 // are unlikely to call `==` many times. This likelyhood can be analyzed as
131 // follows (assuming that H2 is a random enough hash function).
132 //
133 // Let's assume that there are `k` "wrong" objects that must be examined in a
134 // probe sequence. For example, when doing a `find` on an object that is in the
135 // table, `k` is the number of objects between the start of the probe sequence
136 // and the final found object (not including the final found object). The
137 // expected number of objects with an H2 match is then `k/128`. Measurements
138 // and analysis indicate that even at high load factors, `k` is less than 32,
139 // meaning that the number of "false positive" comparisons we must perform is
140 // less than 1/8 per `find`.
141
142 // `insert` is implemented in terms of `unchecked_insert`, which inserts a
143 // value presumed to not be in the table (violating this requirement will cause
144 // the table to behave erratically). Given `x` and its hash `hash(x)`, to insert
145 // it, we construct a `probe_seq` once again, and use it to find the first
146 // group with an unoccupied (empty *or* deleted) slot. We place `x` into the
147 // first such slot in the group and mark it as full with `x`'s H2.
148 //
149 // To `insert`, we compose `unchecked_insert` with `find`. We compute `h(x)` and
150 // perform a `find` to see if it's already present; if it is, we're done. If
151 // it's not, we may decide the table is getting overcrowded (i.e. the load
152 // factor is greater than 7/8 for big tables; `is_small()` tables use a max load
153 // factor of 1); in this case, we allocate a bigger array, `unchecked_insert`
154 // each element of the table into the new array (we know that no insertion here
155 // will insert an already-present value), and discard the old backing array. At
156 // this point, we may `unchecked_insert` the value `x`.
157 //
158 // Below, `unchecked_insert` is partly implemented by `prepare_insert`, which
159 // presents a viable, initialized slot pointee to the caller.
160 //
161 // `erase` is implemented in terms of `erase_at`, which takes an index to a
162 // slot. Given an offset, we simply create a tombstone and destroy its contents.
163 // If we can prove that the slot would not appear in a probe sequence, we can
164 // make the slot as empty, instead. We can prove this by observing that if a
165 // group has any empty slots, it has never been full (assuming we never create
166 // an empty slot in a group with no empties, which this heuristic guarantees we
167 // never do) and find would stop at this group anyways (since it does not probe
168 // beyond groups with empties).
169 //
170 // `erase` is `erase_at` composed with `find`: if we
171 // have a value `x`, we can perform a `find`, and then `erase_at` the resulting
172 // slot.
173 //
174 // To iterate, we simply traverse the array, skipping empty and deleted slots
175 // and stopping when we hit a `kSentinel`.
176
177 #ifndef ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
178 #define ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
179
180 #include <algorithm>
181 #include <cassert>
182 #include <cmath>
183 #include <cstddef>
184 #include <cstdint>
185 #include <cstring>
186 #include <initializer_list>
187 #include <iterator>
188 #include <limits>
189 #include <memory>
190 #include <tuple>
191 #include <type_traits>
192 #include <utility>
193
194 #include "absl/base/attributes.h"
195 #include "absl/base/config.h"
196 #include "absl/base/internal/endian.h"
197 #include "absl/base/internal/raw_logging.h"
198 #include "absl/base/macros.h"
199 #include "absl/base/optimization.h"
200 #include "absl/base/options.h"
201 #include "absl/base/port.h"
202 #include "absl/base/prefetch.h"
203 #include "absl/container/internal/common.h" // IWYU pragma: export // for node_handle
204 #include "absl/container/internal/compressed_tuple.h"
205 #include "absl/container/internal/container_memory.h"
206 #include "absl/container/internal/hash_policy_traits.h"
207 #include "absl/container/internal/hashtable_debug_hooks.h"
208 #include "absl/container/internal/hashtablez_sampler.h"
209 #include "absl/memory/memory.h"
210 #include "absl/meta/type_traits.h"
211 #include "absl/numeric/bits.h"
212 #include "absl/utility/utility.h"
213
214 #ifdef ABSL_INTERNAL_HAVE_SSE2
215 #include <emmintrin.h>
216 #endif
217
218 #ifdef ABSL_INTERNAL_HAVE_SSSE3
219 #include <tmmintrin.h>
220 #endif
221
222 #ifdef _MSC_VER
223 #include <intrin.h>
224 #endif
225
226 #ifdef ABSL_INTERNAL_HAVE_ARM_NEON
227 #include <arm_neon.h>
228 #endif
229
230 namespace absl {
231 ABSL_NAMESPACE_BEGIN
232 namespace container_internal {
233
234 #ifdef ABSL_SWISSTABLE_ENABLE_GENERATIONS
235 #error ABSL_SWISSTABLE_ENABLE_GENERATIONS cannot be directly set
236 #elif defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
237 defined(ABSL_HAVE_MEMORY_SANITIZER)
238 // When compiled in sanitizer mode, we add generation integers to the backing
239 // array and iterators. In the backing array, we store the generation between
240 // the control bytes and the slots. When iterators are dereferenced, we assert
241 // that the container has not been mutated in a way that could cause iterator
242 // invalidation since the iterator was initialized.
243 #define ABSL_SWISSTABLE_ENABLE_GENERATIONS
244 #endif
245
246 // We use uint8_t so we don't need to worry about padding.
247 using GenerationType = uint8_t;
248
249 // A sentinel value for empty generations. Using 0 makes it easy to constexpr
250 // initialize an array of this value.
SentinelEmptyGeneration()251 constexpr GenerationType SentinelEmptyGeneration() { return 0; }
252
NextGeneration(GenerationType generation)253 constexpr GenerationType NextGeneration(GenerationType generation) {
254 return ++generation == SentinelEmptyGeneration() ? ++generation : generation;
255 }
256
257 #ifdef ABSL_SWISSTABLE_ENABLE_GENERATIONS
SwisstableGenerationsEnabled()258 constexpr bool SwisstableGenerationsEnabled() { return true; }
NumGenerationBytes()259 constexpr size_t NumGenerationBytes() { return sizeof(GenerationType); }
260 #else
SwisstableGenerationsEnabled()261 constexpr bool SwisstableGenerationsEnabled() { return false; }
NumGenerationBytes()262 constexpr size_t NumGenerationBytes() { return 0; }
263 #endif
264
265 template <typename AllocType>
SwapAlloc(AllocType & lhs,AllocType & rhs,std::true_type)266 void SwapAlloc(AllocType& lhs, AllocType& rhs,
267 std::true_type /* propagate_on_container_swap */) {
268 using std::swap;
269 swap(lhs, rhs);
270 }
271 template <typename AllocType>
SwapAlloc(AllocType & lhs,AllocType & rhs,std::false_type)272 void SwapAlloc(AllocType& lhs, AllocType& rhs,
273 std::false_type /* propagate_on_container_swap */) {
274 (void)lhs;
275 (void)rhs;
276 assert(lhs == rhs &&
277 "It's UB to call swap with unequal non-propagating allocators.");
278 }
279
280 template <typename AllocType>
CopyAlloc(AllocType & lhs,AllocType & rhs,std::true_type)281 void CopyAlloc(AllocType& lhs, AllocType& rhs,
282 std::true_type /* propagate_alloc */) {
283 lhs = rhs;
284 }
285 template <typename AllocType>
CopyAlloc(AllocType &,AllocType &,std::false_type)286 void CopyAlloc(AllocType&, AllocType&, std::false_type /* propagate_alloc */) {}
287
288 // The state for a probe sequence.
289 //
290 // Currently, the sequence is a triangular progression of the form
291 //
292 // p(i) := Width * (i^2 + i)/2 + hash (mod mask + 1)
293 //
294 // The use of `Width` ensures that each probe step does not overlap groups;
295 // the sequence effectively outputs the addresses of *groups* (although not
296 // necessarily aligned to any boundary). The `Group` machinery allows us
297 // to check an entire group with minimal branching.
298 //
299 // Wrapping around at `mask + 1` is important, but not for the obvious reason.
300 // As described above, the first few entries of the control byte array
301 // are mirrored at the end of the array, which `Group` will find and use
302 // for selecting candidates. However, when those candidates' slots are
303 // actually inspected, there are no corresponding slots for the cloned bytes,
304 // so we need to make sure we've treated those offsets as "wrapping around".
305 //
306 // It turns out that this probe sequence visits every group exactly once if the
307 // number of groups is a power of two, since (i^2+i)/2 is a bijection in
308 // Z/(2^m). See https://en.wikipedia.org/wiki/Quadratic_probing
309 template <size_t Width>
310 class probe_seq {
311 public:
312 // Creates a new probe sequence using `hash` as the initial value of the
313 // sequence and `mask` (usually the capacity of the table) as the mask to
314 // apply to each value in the progression.
probe_seq(size_t hash,size_t mask)315 probe_seq(size_t hash, size_t mask) {
316 assert(((mask + 1) & mask) == 0 && "not a mask");
317 mask_ = mask;
318 offset_ = hash & mask_;
319 }
320
321 // The offset within the table, i.e., the value `p(i)` above.
offset()322 size_t offset() const { return offset_; }
offset(size_t i)323 size_t offset(size_t i) const { return (offset_ + i) & mask_; }
324
next()325 void next() {
326 index_ += Width;
327 offset_ += index_;
328 offset_ &= mask_;
329 }
330 // 0-based probe index, a multiple of `Width`.
index()331 size_t index() const { return index_; }
332
333 private:
334 size_t mask_;
335 size_t offset_;
336 size_t index_ = 0;
337 };
338
339 template <class ContainerKey, class Hash, class Eq>
340 struct RequireUsableKey {
341 template <class PassedKey, class... Args>
342 std::pair<
343 decltype(std::declval<const Hash&>()(std::declval<const PassedKey&>())),
344 decltype(std::declval<const Eq&>()(std::declval<const ContainerKey&>(),
345 std::declval<const PassedKey&>()))>*
346 operator()(const PassedKey&, const Args&...) const;
347 };
348
349 template <class E, class Policy, class Hash, class Eq, class... Ts>
350 struct IsDecomposable : std::false_type {};
351
352 template <class Policy, class Hash, class Eq, class... Ts>
353 struct IsDecomposable<
354 absl::void_t<decltype(Policy::apply(
355 RequireUsableKey<typename Policy::key_type, Hash, Eq>(),
356 std::declval<Ts>()...))>,
357 Policy, Hash, Eq, Ts...> : std::true_type {};
358
359 // TODO(alkis): Switch to std::is_nothrow_swappable when gcc/clang supports it.
360 template <class T>
361 constexpr bool IsNoThrowSwappable(std::true_type = {} /* is_swappable */) {
362 using std::swap;
363 return noexcept(swap(std::declval<T&>(), std::declval<T&>()));
364 }
365 template <class T>
366 constexpr bool IsNoThrowSwappable(std::false_type /* is_swappable */) {
367 return false;
368 }
369
370 template <typename T>
371 uint32_t TrailingZeros(T x) {
372 ABSL_ASSUME(x != 0);
373 return static_cast<uint32_t>(countr_zero(x));
374 }
375
376 // An abstract bitmask, such as that emitted by a SIMD instruction.
377 //
378 // Specifically, this type implements a simple bitset whose representation is
379 // controlled by `SignificantBits` and `Shift`. `SignificantBits` is the number
380 // of abstract bits in the bitset, while `Shift` is the log-base-two of the
381 // width of an abstract bit in the representation.
382 // This mask provides operations for any number of real bits set in an abstract
383 // bit. To add iteration on top of that, implementation must guarantee no more
384 // than the most significant real bit is set in a set abstract bit.
385 template <class T, int SignificantBits, int Shift = 0>
386 class NonIterableBitMask {
387 public:
388 explicit NonIterableBitMask(T mask) : mask_(mask) {}
389
390 explicit operator bool() const { return this->mask_ != 0; }
391
392 // Returns the index of the lowest *abstract* bit set in `self`.
393 uint32_t LowestBitSet() const {
394 return container_internal::TrailingZeros(mask_) >> Shift;
395 }
396
397 // Returns the index of the highest *abstract* bit set in `self`.
398 uint32_t HighestBitSet() const {
399 return static_cast<uint32_t>((bit_width(mask_) - 1) >> Shift);
400 }
401
402 // Returns the number of trailing zero *abstract* bits.
403 uint32_t TrailingZeros() const {
404 return container_internal::TrailingZeros(mask_) >> Shift;
405 }
406
407 // Returns the number of leading zero *abstract* bits.
408 uint32_t LeadingZeros() const {
409 constexpr int total_significant_bits = SignificantBits << Shift;
410 constexpr int extra_bits = sizeof(T) * 8 - total_significant_bits;
411 return static_cast<uint32_t>(
412 countl_zero(static_cast<T>(mask_ << extra_bits))) >>
413 Shift;
414 }
415
416 T mask_;
417 };
418
419 // Mask that can be iterable
420 //
421 // For example, when `SignificantBits` is 16 and `Shift` is zero, this is just
422 // an ordinary 16-bit bitset occupying the low 16 bits of `mask`. When
423 // `SignificantBits` is 8 and `Shift` is 3, abstract bits are represented as
424 // the bytes `0x00` and `0x80`, and it occupies all 64 bits of the bitmask.
425 //
426 // For example:
427 // for (int i : BitMask<uint32_t, 16>(0b101)) -> yields 0, 2
428 // for (int i : BitMask<uint64_t, 8, 3>(0x0000000080800000)) -> yields 2, 3
429 template <class T, int SignificantBits, int Shift = 0>
430 class BitMask : public NonIterableBitMask<T, SignificantBits, Shift> {
431 using Base = NonIterableBitMask<T, SignificantBits, Shift>;
432 static_assert(std::is_unsigned<T>::value, "");
433 static_assert(Shift == 0 || Shift == 3, "");
434
435 public:
436 explicit BitMask(T mask) : Base(mask) {}
437 // BitMask is an iterator over the indices of its abstract bits.
438 using value_type = int;
439 using iterator = BitMask;
440 using const_iterator = BitMask;
441
442 BitMask& operator++() {
443 if (Shift == 3) {
444 constexpr uint64_t msbs = 0x8080808080808080ULL;
445 this->mask_ &= msbs;
446 }
447 this->mask_ &= (this->mask_ - 1);
448 return *this;
449 }
450
451 uint32_t operator*() const { return Base::LowestBitSet(); }
452
453 BitMask begin() const { return *this; }
454 BitMask end() const { return BitMask(0); }
455
456 private:
457 friend bool operator==(const BitMask& a, const BitMask& b) {
458 return a.mask_ == b.mask_;
459 }
460 friend bool operator!=(const BitMask& a, const BitMask& b) {
461 return a.mask_ != b.mask_;
462 }
463 };
464
465 using h2_t = uint8_t;
466
467 // The values here are selected for maximum performance. See the static asserts
468 // below for details.
469
470 // A `ctrl_t` is a single control byte, which can have one of four
471 // states: empty, deleted, full (which has an associated seven-bit h2_t value)
472 // and the sentinel. They have the following bit patterns:
473 //
474 // empty: 1 0 0 0 0 0 0 0
475 // deleted: 1 1 1 1 1 1 1 0
476 // full: 0 h h h h h h h // h represents the hash bits.
477 // sentinel: 1 1 1 1 1 1 1 1
478 //
479 // These values are specifically tuned for SSE-flavored SIMD.
480 // The static_asserts below detail the source of these choices.
481 //
482 // We use an enum class so that when strict aliasing is enabled, the compiler
483 // knows ctrl_t doesn't alias other types.
484 enum class ctrl_t : int8_t {
485 kEmpty = -128, // 0b10000000
486 kDeleted = -2, // 0b11111110
487 kSentinel = -1, // 0b11111111
488 };
489 static_assert(
490 (static_cast<int8_t>(ctrl_t::kEmpty) &
491 static_cast<int8_t>(ctrl_t::kDeleted) &
492 static_cast<int8_t>(ctrl_t::kSentinel) & 0x80) != 0,
493 "Special markers need to have the MSB to make checking for them efficient");
494 static_assert(
495 ctrl_t::kEmpty < ctrl_t::kSentinel && ctrl_t::kDeleted < ctrl_t::kSentinel,
496 "ctrl_t::kEmpty and ctrl_t::kDeleted must be smaller than "
497 "ctrl_t::kSentinel to make the SIMD test of IsEmptyOrDeleted() efficient");
498 static_assert(
499 ctrl_t::kSentinel == static_cast<ctrl_t>(-1),
500 "ctrl_t::kSentinel must be -1 to elide loading it from memory into SIMD "
501 "registers (pcmpeqd xmm, xmm)");
502 static_assert(ctrl_t::kEmpty == static_cast<ctrl_t>(-128),
503 "ctrl_t::kEmpty must be -128 to make the SIMD check for its "
504 "existence efficient (psignb xmm, xmm)");
505 static_assert(
506 (~static_cast<int8_t>(ctrl_t::kEmpty) &
507 ~static_cast<int8_t>(ctrl_t::kDeleted) &
508 static_cast<int8_t>(ctrl_t::kSentinel) & 0x7F) != 0,
509 "ctrl_t::kEmpty and ctrl_t::kDeleted must share an unset bit that is not "
510 "shared by ctrl_t::kSentinel to make the scalar test for "
511 "MaskEmptyOrDeleted() efficient");
512 static_assert(ctrl_t::kDeleted == static_cast<ctrl_t>(-2),
513 "ctrl_t::kDeleted must be -2 to make the implementation of "
514 "ConvertSpecialToEmptyAndFullToDeleted efficient");
515
516 // See definition comment for why this is size 32.
517 ABSL_DLL extern const ctrl_t kEmptyGroup[32];
518
519 // Returns a pointer to a control byte group that can be used by empty tables.
520 inline ctrl_t* EmptyGroup() {
521 // Const must be cast away here; no uses of this function will actually write
522 // to it, because it is only used for empty tables.
523 return const_cast<ctrl_t*>(kEmptyGroup + 16);
524 }
525
526 // Returns a pointer to a generation to use for an empty hashtable.
527 GenerationType* EmptyGeneration();
528
529 // Returns whether `generation` is a generation for an empty hashtable that
530 // could be returned by EmptyGeneration().
531 inline bool IsEmptyGeneration(const GenerationType* generation) {
532 return *generation == SentinelEmptyGeneration();
533 }
534
535 // Mixes a randomly generated per-process seed with `hash` and `ctrl` to
536 // randomize insertion order within groups.
537 bool ShouldInsertBackwards(size_t hash, const ctrl_t* ctrl);
538
539 // Returns a per-table, hash salt, which changes on resize. This gets mixed into
540 // H1 to randomize iteration order per-table.
541 //
542 // The seed consists of the ctrl_ pointer, which adds enough entropy to ensure
543 // non-determinism of iteration order in most cases.
544 inline size_t PerTableSalt(const ctrl_t* ctrl) {
545 // The low bits of the pointer have little or no entropy because of
546 // alignment. We shift the pointer to try to use higher entropy bits. A
547 // good number seems to be 12 bits, because that aligns with page size.
548 return reinterpret_cast<uintptr_t>(ctrl) >> 12;
549 }
550 // Extracts the H1 portion of a hash: 57 bits mixed with a per-table salt.
551 inline size_t H1(size_t hash, const ctrl_t* ctrl) {
552 return (hash >> 7) ^ PerTableSalt(ctrl);
553 }
554
555 // Extracts the H2 portion of a hash: the 7 bits not used for H1.
556 //
557 // These are used as an occupied control byte.
558 inline h2_t H2(size_t hash) { return hash & 0x7F; }
559
560 // Helpers for checking the state of a control byte.
561 inline bool IsEmpty(ctrl_t c) { return c == ctrl_t::kEmpty; }
562 inline bool IsFull(ctrl_t c) { return c >= static_cast<ctrl_t>(0); }
563 inline bool IsDeleted(ctrl_t c) { return c == ctrl_t::kDeleted; }
564 inline bool IsEmptyOrDeleted(ctrl_t c) { return c < ctrl_t::kSentinel; }
565
566 #ifdef ABSL_INTERNAL_HAVE_SSE2
567 // Quick reference guide for intrinsics used below:
568 //
569 // * __m128i: An XMM (128-bit) word.
570 //
571 // * _mm_setzero_si128: Returns a zero vector.
572 // * _mm_set1_epi8: Returns a vector with the same i8 in each lane.
573 //
574 // * _mm_subs_epi8: Saturating-subtracts two i8 vectors.
575 // * _mm_and_si128: Ands two i128s together.
576 // * _mm_or_si128: Ors two i128s together.
577 // * _mm_andnot_si128: And-nots two i128s together.
578 //
579 // * _mm_cmpeq_epi8: Component-wise compares two i8 vectors for equality,
580 // filling each lane with 0x00 or 0xff.
581 // * _mm_cmpgt_epi8: Same as above, but using > rather than ==.
582 //
583 // * _mm_loadu_si128: Performs an unaligned load of an i128.
584 // * _mm_storeu_si128: Performs an unaligned store of an i128.
585 //
586 // * _mm_sign_epi8: Retains, negates, or zeroes each i8 lane of the first
587 // argument if the corresponding lane of the second
588 // argument is positive, negative, or zero, respectively.
589 // * _mm_movemask_epi8: Selects the sign bit out of each i8 lane and produces a
590 // bitmask consisting of those bits.
591 // * _mm_shuffle_epi8: Selects i8s from the first argument, using the low
592 // four bits of each i8 lane in the second argument as
593 // indices.
594
595 // https://github.com/abseil/abseil-cpp/issues/209
596 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87853
597 // _mm_cmpgt_epi8 is broken under GCC with -funsigned-char
598 // Work around this by using the portable implementation of Group
599 // when using -funsigned-char under GCC.
600 inline __m128i _mm_cmpgt_epi8_fixed(__m128i a, __m128i b) {
601 #if defined(__GNUC__) && !defined(__clang__)
602 if (std::is_unsigned<char>::value) {
603 const __m128i mask = _mm_set1_epi8(0x80);
604 const __m128i diff = _mm_subs_epi8(b, a);
605 return _mm_cmpeq_epi8(_mm_and_si128(diff, mask), mask);
606 }
607 #endif
608 return _mm_cmpgt_epi8(a, b);
609 }
610
611 struct GroupSse2Impl {
612 static constexpr size_t kWidth = 16; // the number of slots per group
613
614 explicit GroupSse2Impl(const ctrl_t* pos) {
615 ctrl = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pos));
616 }
617
618 // Returns a bitmask representing the positions of slots that match hash.
619 BitMask<uint16_t, kWidth> Match(h2_t hash) const {
620 auto match = _mm_set1_epi8(static_cast<char>(hash));
621 BitMask<uint16_t, kWidth> result = BitMask<uint16_t, kWidth>(0);
622 result = BitMask<uint16_t, kWidth>(
623 static_cast<uint16_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl))));
624 return result;
625 }
626
627 // Returns a bitmask representing the positions of empty slots.
628 NonIterableBitMask<uint16_t, kWidth> MaskEmpty() const {
629 #ifdef ABSL_INTERNAL_HAVE_SSSE3
630 // This only works because ctrl_t::kEmpty is -128.
631 return NonIterableBitMask<uint16_t, kWidth>(
632 static_cast<uint16_t>(_mm_movemask_epi8(_mm_sign_epi8(ctrl, ctrl))));
633 #else
634 auto match = _mm_set1_epi8(static_cast<char>(ctrl_t::kEmpty));
635 return NonIterableBitMask<uint16_t, kWidth>(
636 static_cast<uint16_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl))));
637 #endif
638 }
639
640 // Returns a bitmask representing the positions of empty or deleted slots.
641 NonIterableBitMask<uint16_t, kWidth> MaskEmptyOrDeleted() const {
642 auto special = _mm_set1_epi8(static_cast<char>(ctrl_t::kSentinel));
643 return NonIterableBitMask<uint16_t, kWidth>(static_cast<uint16_t>(
644 _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl))));
645 }
646
647 // Returns the number of trailing empty or deleted elements in the group.
648 uint32_t CountLeadingEmptyOrDeleted() const {
649 auto special = _mm_set1_epi8(static_cast<char>(ctrl_t::kSentinel));
650 return TrailingZeros(static_cast<uint32_t>(
651 _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)) + 1));
652 }
653
654 void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
655 auto msbs = _mm_set1_epi8(static_cast<char>(-128));
656 auto x126 = _mm_set1_epi8(126);
657 #ifdef ABSL_INTERNAL_HAVE_SSSE3
658 auto res = _mm_or_si128(_mm_shuffle_epi8(x126, ctrl), msbs);
659 #else
660 auto zero = _mm_setzero_si128();
661 auto special_mask = _mm_cmpgt_epi8_fixed(zero, ctrl);
662 auto res = _mm_or_si128(msbs, _mm_andnot_si128(special_mask, x126));
663 #endif
664 _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), res);
665 }
666
667 __m128i ctrl;
668 };
669 #endif // ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
670
671 #if defined(ABSL_INTERNAL_HAVE_ARM_NEON) && defined(ABSL_IS_LITTLE_ENDIAN)
672 struct GroupAArch64Impl {
673 static constexpr size_t kWidth = 8;
674
675 explicit GroupAArch64Impl(const ctrl_t* pos) {
676 ctrl = vld1_u8(reinterpret_cast<const uint8_t*>(pos));
677 }
678
679 BitMask<uint64_t, kWidth, 3> Match(h2_t hash) const {
680 uint8x8_t dup = vdup_n_u8(hash);
681 auto mask = vceq_u8(ctrl, dup);
682 return BitMask<uint64_t, kWidth, 3>(
683 vget_lane_u64(vreinterpret_u64_u8(mask), 0));
684 }
685
686 NonIterableBitMask<uint64_t, kWidth, 3> MaskEmpty() const {
687 uint64_t mask =
688 vget_lane_u64(vreinterpret_u64_u8(vceq_s8(
689 vdup_n_s8(static_cast<int8_t>(ctrl_t::kEmpty)),
690 vreinterpret_s8_u8(ctrl))),
691 0);
692 return NonIterableBitMask<uint64_t, kWidth, 3>(mask);
693 }
694
695 NonIterableBitMask<uint64_t, kWidth, 3> MaskEmptyOrDeleted() const {
696 uint64_t mask =
697 vget_lane_u64(vreinterpret_u64_u8(vcgt_s8(
698 vdup_n_s8(static_cast<int8_t>(ctrl_t::kSentinel)),
699 vreinterpret_s8_u8(ctrl))),
700 0);
701 return NonIterableBitMask<uint64_t, kWidth, 3>(mask);
702 }
703
704 uint32_t CountLeadingEmptyOrDeleted() const {
705 uint64_t mask =
706 vget_lane_u64(vreinterpret_u64_u8(vcle_s8(
707 vdup_n_s8(static_cast<int8_t>(ctrl_t::kSentinel)),
708 vreinterpret_s8_u8(ctrl))),
709 0);
710 // Similar to MaskEmptyorDeleted() but we invert the logic to invert the
711 // produced bitfield. We then count number of trailing zeros.
712 // Clang and GCC optimize countr_zero to rbit+clz without any check for 0,
713 // so we should be fine.
714 return static_cast<uint32_t>(countr_zero(mask)) >> 3;
715 }
716
717 void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
718 uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(ctrl), 0);
719 constexpr uint64_t msbs = 0x8080808080808080ULL;
720 constexpr uint64_t slsbs = 0x0202020202020202ULL;
721 constexpr uint64_t midbs = 0x7e7e7e7e7e7e7e7eULL;
722 auto x = slsbs & (mask >> 6);
723 auto res = (x + midbs) | msbs;
724 little_endian::Store64(dst, res);
725 }
726
727 uint8x8_t ctrl;
728 };
729 #endif // ABSL_INTERNAL_HAVE_ARM_NEON && ABSL_IS_LITTLE_ENDIAN
730
731 struct GroupPortableImpl {
732 static constexpr size_t kWidth = 8;
733
734 explicit GroupPortableImpl(const ctrl_t* pos)
735 : ctrl(little_endian::Load64(pos)) {}
736
737 BitMask<uint64_t, kWidth, 3> Match(h2_t hash) const {
738 // For the technique, see:
739 // http://graphics.stanford.edu/~seander/bithacks.html##ValueInWord
740 // (Determine if a word has a byte equal to n).
741 //
742 // Caveat: there are false positives but:
743 // - they only occur if there is a real match
744 // - they never occur on ctrl_t::kEmpty, ctrl_t::kDeleted, ctrl_t::kSentinel
745 // - they will be handled gracefully by subsequent checks in code
746 //
747 // Example:
748 // v = 0x1716151413121110
749 // hash = 0x12
750 // retval = (v - lsbs) & ~v & msbs = 0x0000000080800000
751 constexpr uint64_t msbs = 0x8080808080808080ULL;
752 constexpr uint64_t lsbs = 0x0101010101010101ULL;
753 auto x = ctrl ^ (lsbs * hash);
754 return BitMask<uint64_t, kWidth, 3>((x - lsbs) & ~x & msbs);
755 }
756
757 NonIterableBitMask<uint64_t, kWidth, 3> MaskEmpty() const {
758 constexpr uint64_t msbs = 0x8080808080808080ULL;
759 return NonIterableBitMask<uint64_t, kWidth, 3>((ctrl & ~(ctrl << 6)) &
760 msbs);
761 }
762
763 NonIterableBitMask<uint64_t, kWidth, 3> MaskEmptyOrDeleted() const {
764 constexpr uint64_t msbs = 0x8080808080808080ULL;
765 return NonIterableBitMask<uint64_t, kWidth, 3>((ctrl & ~(ctrl << 7)) &
766 msbs);
767 }
768
769 uint32_t CountLeadingEmptyOrDeleted() const {
770 // ctrl | ~(ctrl >> 7) will have the lowest bit set to zero for kEmpty and
771 // kDeleted. We lower all other bits and count number of trailing zeros.
772 constexpr uint64_t bits = 0x0101010101010101ULL;
773 return static_cast<uint32_t>(countr_zero((ctrl | ~(ctrl >> 7)) & bits) >>
774 3);
775 }
776
777 void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
778 constexpr uint64_t msbs = 0x8080808080808080ULL;
779 constexpr uint64_t lsbs = 0x0101010101010101ULL;
780 auto x = ctrl & msbs;
781 auto res = (~x + (x >> 7)) & ~lsbs;
782 little_endian::Store64(dst, res);
783 }
784
785 uint64_t ctrl;
786 };
787
788 #ifdef ABSL_INTERNAL_HAVE_SSE2
789 using Group = GroupSse2Impl;
790 using GroupEmptyOrDeleted = GroupSse2Impl;
791 #elif defined(ABSL_INTERNAL_HAVE_ARM_NEON) && defined(ABSL_IS_LITTLE_ENDIAN)
792 using Group = GroupAArch64Impl;
793 // For Aarch64, we use the portable implementation for counting and masking
794 // empty or deleted group elements. This is to avoid the latency of moving
795 // between data GPRs and Neon registers when it does not provide a benefit.
796 // Using Neon is profitable when we call Match(), but is not when we don't,
797 // which is the case when we do *EmptyOrDeleted operations. It is difficult to
798 // make a similar approach beneficial on other architectures such as x86 since
799 // they have much lower GPR <-> vector register transfer latency and 16-wide
800 // Groups.
801 using GroupEmptyOrDeleted = GroupPortableImpl;
802 #else
803 using Group = GroupPortableImpl;
804 using GroupEmptyOrDeleted = GroupPortableImpl;
805 #endif
806
807 // When there is an insertion with no reserved growth, we rehash with
808 // probability `min(1, RehashProbabilityConstant() / capacity())`. Using a
809 // constant divided by capacity ensures that inserting N elements is still O(N)
810 // in the average case. Using the constant 16 means that we expect to rehash ~8
811 // times more often than when generations are disabled. We are adding expected
812 // rehash_probability * #insertions/capacity_growth = 16/capacity * ((7/8 -
813 // 7/16) * capacity)/capacity_growth = ~7 extra rehashes per capacity growth.
814 inline size_t RehashProbabilityConstant() { return 16; }
815
816 class CommonFieldsGenerationInfoEnabled {
817 // A sentinel value for reserved_growth_ indicating that we just ran out of
818 // reserved growth on the last insertion. When reserve is called and then
819 // insertions take place, reserved_growth_'s state machine is N, ..., 1,
820 // kReservedGrowthJustRanOut, 0.
821 static constexpr size_t kReservedGrowthJustRanOut =
822 (std::numeric_limits<size_t>::max)();
823
824 public:
825 CommonFieldsGenerationInfoEnabled() = default;
826 CommonFieldsGenerationInfoEnabled(CommonFieldsGenerationInfoEnabled&& that)
827 : reserved_growth_(that.reserved_growth_),
828 reservation_size_(that.reservation_size_),
829 generation_(that.generation_) {
830 that.reserved_growth_ = 0;
831 that.reservation_size_ = 0;
832 that.generation_ = EmptyGeneration();
833 }
834 CommonFieldsGenerationInfoEnabled& operator=(
835 CommonFieldsGenerationInfoEnabled&&) = default;
836
837 // Whether we should rehash on insert in order to detect bugs of using invalid
838 // references. We rehash on the first insertion after reserved_growth_ reaches
839 // 0 after a call to reserve. We also do a rehash with low probability
840 // whenever reserved_growth_ is zero.
841 bool should_rehash_for_bug_detection_on_insert(const ctrl_t* ctrl,
842 size_t capacity) const;
843 // Similar to above, except that we don't depend on reserved_growth_.
844 bool should_rehash_for_bug_detection_on_move(const ctrl_t* ctrl,
845 size_t capacity) const;
846 void maybe_increment_generation_on_insert() {
847 if (reserved_growth_ == kReservedGrowthJustRanOut) reserved_growth_ = 0;
848
849 if (reserved_growth_ > 0) {
850 if (--reserved_growth_ == 0) reserved_growth_ = kReservedGrowthJustRanOut;
851 } else {
852 increment_generation();
853 }
854 }
855 void increment_generation() { *generation_ = NextGeneration(*generation_); }
856 void reset_reserved_growth(size_t reservation, size_t size) {
857 reserved_growth_ = reservation - size;
858 }
859 size_t reserved_growth() const { return reserved_growth_; }
860 void set_reserved_growth(size_t r) { reserved_growth_ = r; }
861 size_t reservation_size() const { return reservation_size_; }
862 void set_reservation_size(size_t r) { reservation_size_ = r; }
863 GenerationType generation() const { return *generation_; }
864 void set_generation(GenerationType g) { *generation_ = g; }
865 GenerationType* generation_ptr() const { return generation_; }
866 void set_generation_ptr(GenerationType* g) { generation_ = g; }
867
868 private:
869 // The number of insertions remaining that are guaranteed to not rehash due to
870 // a prior call to reserve. Note: we store reserved growth in addition to
871 // reservation size because calls to erase() decrease size_ but don't decrease
872 // reserved growth.
873 size_t reserved_growth_ = 0;
874 // The maximum argument to reserve() since the container was cleared. We need
875 // to keep track of this, in addition to reserved growth, because we reset
876 // reserved growth to this when erase(begin(), end()) is called.
877 size_t reservation_size_ = 0;
878 // Pointer to the generation counter, which is used to validate iterators and
879 // is stored in the backing array between the control bytes and the slots.
880 // Note that we can't store the generation inside the container itself and
881 // keep a pointer to the container in the iterators because iterators must
882 // remain valid when the container is moved.
883 // Note: we could derive this pointer from the control pointer, but it makes
884 // the code more complicated, and there's a benefit in having the sizes of
885 // raw_hash_set in sanitizer mode and non-sanitizer mode a bit more different,
886 // which is that tests are less likely to rely on the size remaining the same.
887 GenerationType* generation_ = EmptyGeneration();
888 };
889
890 class CommonFieldsGenerationInfoDisabled {
891 public:
892 CommonFieldsGenerationInfoDisabled() = default;
893 CommonFieldsGenerationInfoDisabled(CommonFieldsGenerationInfoDisabled&&) =
894 default;
895 CommonFieldsGenerationInfoDisabled& operator=(
896 CommonFieldsGenerationInfoDisabled&&) = default;
897
898 bool should_rehash_for_bug_detection_on_insert(const ctrl_t*, size_t) const {
899 return false;
900 }
901 bool should_rehash_for_bug_detection_on_move(const ctrl_t*, size_t) const {
902 return false;
903 }
904 void maybe_increment_generation_on_insert() {}
905 void increment_generation() {}
906 void reset_reserved_growth(size_t, size_t) {}
907 size_t reserved_growth() const { return 0; }
908 void set_reserved_growth(size_t) {}
909 size_t reservation_size() const { return 0; }
910 void set_reservation_size(size_t) {}
911 GenerationType generation() const { return 0; }
912 void set_generation(GenerationType) {}
913 GenerationType* generation_ptr() const { return nullptr; }
914 void set_generation_ptr(GenerationType*) {}
915 };
916
917 class HashSetIteratorGenerationInfoEnabled {
918 public:
919 HashSetIteratorGenerationInfoEnabled() = default;
920 explicit HashSetIteratorGenerationInfoEnabled(
921 const GenerationType* generation_ptr)
922 : generation_ptr_(generation_ptr), generation_(*generation_ptr) {}
923
924 GenerationType generation() const { return generation_; }
925 void reset_generation() { generation_ = *generation_ptr_; }
926 const GenerationType* generation_ptr() const { return generation_ptr_; }
927 void set_generation_ptr(const GenerationType* ptr) { generation_ptr_ = ptr; }
928
929 private:
930 const GenerationType* generation_ptr_ = EmptyGeneration();
931 GenerationType generation_ = *generation_ptr_;
932 };
933
934 class HashSetIteratorGenerationInfoDisabled {
935 public:
936 HashSetIteratorGenerationInfoDisabled() = default;
937 explicit HashSetIteratorGenerationInfoDisabled(const GenerationType*) {}
938
939 GenerationType generation() const { return 0; }
940 void reset_generation() {}
941 const GenerationType* generation_ptr() const { return nullptr; }
942 void set_generation_ptr(const GenerationType*) {}
943 };
944
945 #ifdef ABSL_SWISSTABLE_ENABLE_GENERATIONS
946 using CommonFieldsGenerationInfo = CommonFieldsGenerationInfoEnabled;
947 using HashSetIteratorGenerationInfo = HashSetIteratorGenerationInfoEnabled;
948 #else
949 using CommonFieldsGenerationInfo = CommonFieldsGenerationInfoDisabled;
950 using HashSetIteratorGenerationInfo = HashSetIteratorGenerationInfoDisabled;
951 #endif
952
953 // Returns whether `n` is a valid capacity (i.e., number of slots).
954 //
955 // A valid capacity is a non-zero integer `2^m - 1`.
956 inline bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n > 0; }
957
958 // Computes the offset from the start of the backing allocation of control.
959 // infoz and growth_left are stored at the beginning of the backing array.
960 inline size_t ControlOffset(bool has_infoz) {
961 return (has_infoz ? sizeof(HashtablezInfoHandle) : 0) + sizeof(size_t);
962 }
963
964 // Returns the number of "cloned control bytes".
965 //
966 // This is the number of control bytes that are present both at the beginning
967 // of the control byte array and at the end, such that we can create a
968 // `Group::kWidth`-width probe window starting from any control byte.
969 constexpr size_t NumClonedBytes() { return Group::kWidth - 1; }
970
971 // Given the capacity of a table, computes the offset (from the start of the
972 // backing allocation) of the generation counter (if it exists).
973 inline size_t GenerationOffset(size_t capacity, bool has_infoz) {
974 assert(IsValidCapacity(capacity));
975 const size_t num_control_bytes = capacity + 1 + NumClonedBytes();
976 return ControlOffset(has_infoz) + num_control_bytes;
977 }
978
979 // Given the capacity of a table, computes the offset (from the start of the
980 // backing allocation) at which the slots begin.
981 inline size_t SlotOffset(size_t capacity, size_t slot_align, bool has_infoz) {
982 assert(IsValidCapacity(capacity));
983 return (GenerationOffset(capacity, has_infoz) + NumGenerationBytes() +
984 slot_align - 1) &
985 (~slot_align + 1);
986 }
987
988 // Given the capacity of a table, computes the total size of the backing
989 // array.
990 inline size_t AllocSize(size_t capacity, size_t slot_size, size_t slot_align,
991 bool has_infoz) {
992 return SlotOffset(capacity, slot_align, has_infoz) + capacity * slot_size;
993 }
994
995 // CommonFields hold the fields in raw_hash_set that do not depend
996 // on template parameters. This allows us to conveniently pass all
997 // of this state to helper functions as a single argument.
998 class CommonFields : public CommonFieldsGenerationInfo {
999 public:
1000 CommonFields() = default;
1001
1002 // Not copyable
1003 CommonFields(const CommonFields&) = delete;
1004 CommonFields& operator=(const CommonFields&) = delete;
1005
1006 // Movable
1007 CommonFields(CommonFields&& that) = default;
1008 CommonFields& operator=(CommonFields&&) = default;
1009
1010 ctrl_t* control() const { return control_; }
1011 void set_control(ctrl_t* c) { control_ = c; }
1012 void* backing_array_start() const {
1013 // growth_left (and maybe infoz) is stored before control bytes.
1014 assert(reinterpret_cast<uintptr_t>(control()) % alignof(size_t) == 0);
1015 return control() - ControlOffset(has_infoz());
1016 }
1017
1018 // Note: we can't use slots() because Qt defines "slots" as a macro.
1019 void* slot_array() const { return slots_; }
1020 void set_slots(void* s) { slots_ = s; }
1021
1022 // The number of filled slots.
1023 size_t size() const { return size_ >> HasInfozShift(); }
1024 void set_size(size_t s) {
1025 size_ = (s << HasInfozShift()) | (size_ & HasInfozMask());
1026 }
1027 void increment_size() {
1028 assert(size() < capacity());
1029 size_ += size_t{1} << HasInfozShift();
1030 }
1031 void decrement_size() {
1032 assert(size() > 0);
1033 size_ -= size_t{1} << HasInfozShift();
1034 }
1035
1036 // The total number of available slots.
1037 size_t capacity() const { return capacity_; }
1038 void set_capacity(size_t c) {
1039 assert(c == 0 || IsValidCapacity(c));
1040 capacity_ = c;
1041 }
1042
1043 // The number of slots we can still fill without needing to rehash.
1044 // This is stored in the heap allocation before the control bytes.
1045 size_t growth_left() const {
1046 const size_t* gl_ptr = reinterpret_cast<size_t*>(control()) - 1;
1047 assert(reinterpret_cast<uintptr_t>(gl_ptr) % alignof(size_t) == 0);
1048 return *gl_ptr;
1049 }
1050 void set_growth_left(size_t gl) {
1051 size_t* gl_ptr = reinterpret_cast<size_t*>(control()) - 1;
1052 assert(reinterpret_cast<uintptr_t>(gl_ptr) % alignof(size_t) == 0);
1053 *gl_ptr = gl;
1054 }
1055
1056 bool has_infoz() const {
1057 return ABSL_PREDICT_FALSE((size_ & HasInfozMask()) != 0);
1058 }
1059 void set_has_infoz(bool has_infoz) {
1060 size_ = (size() << HasInfozShift()) | static_cast<size_t>(has_infoz);
1061 }
1062
1063 HashtablezInfoHandle infoz() {
1064 return has_infoz()
1065 ? *reinterpret_cast<HashtablezInfoHandle*>(backing_array_start())
1066 : HashtablezInfoHandle();
1067 }
1068 void set_infoz(HashtablezInfoHandle infoz) {
1069 assert(has_infoz());
1070 *reinterpret_cast<HashtablezInfoHandle*>(backing_array_start()) = infoz;
1071 }
1072
1073 bool should_rehash_for_bug_detection_on_insert() const {
1074 return CommonFieldsGenerationInfo::
1075 should_rehash_for_bug_detection_on_insert(control(), capacity());
1076 }
1077 bool should_rehash_for_bug_detection_on_move() const {
1078 return CommonFieldsGenerationInfo::
1079 should_rehash_for_bug_detection_on_move(control(), capacity());
1080 }
1081 void maybe_increment_generation_on_move() {
1082 if (capacity() == 0) return;
1083 increment_generation();
1084 }
1085 void reset_reserved_growth(size_t reservation) {
1086 CommonFieldsGenerationInfo::reset_reserved_growth(reservation, size());
1087 }
1088
1089 // The size of the backing array allocation.
1090 size_t alloc_size(size_t slot_size, size_t slot_align) const {
1091 return AllocSize(capacity(), slot_size, slot_align, has_infoz());
1092 }
1093
1094 // Returns the number of control bytes set to kDeleted. For testing only.
1095 size_t TombstonesCount() const {
1096 return static_cast<size_t>(
1097 std::count(control(), control() + capacity(), ctrl_t::kDeleted));
1098 }
1099
1100 private:
1101 // We store the has_infoz bit in the lowest bit of size_.
1102 static constexpr size_t HasInfozShift() { return 1; }
1103 static constexpr size_t HasInfozMask() {
1104 return (size_t{1} << HasInfozShift()) - 1;
1105 }
1106
1107 // TODO(b/182800944): Investigate removing some of these fields:
1108 // - control/slots can be derived from each other
1109
1110 // The control bytes (and, also, a pointer near to the base of the backing
1111 // array).
1112 //
1113 // This contains `capacity + 1 + NumClonedBytes()` entries, even
1114 // when the table is empty (hence EmptyGroup).
1115 //
1116 // Note that growth_left is stored immediately before this pointer.
1117 ctrl_t* control_ = EmptyGroup();
1118
1119 // The beginning of the slots, located at `SlotOffset()` bytes after
1120 // `control`. May be null for empty tables.
1121 void* slots_ = nullptr;
1122
1123 // The number of slots in the backing array. This is always 2^N-1 for an
1124 // integer N. NOTE: we tried experimenting with compressing the capacity and
1125 // storing it together with size_: (a) using 6 bits to store the corresponding
1126 // power (N in 2^N-1), and (b) storing 2^N as the most significant bit of
1127 // size_ and storing size in the low bits. Both of these experiments were
1128 // regressions, presumably because we need capacity to do find operations.
1129 size_t capacity_ = 0;
1130
1131 // The size and also has one bit that stores whether we have infoz.
1132 size_t size_ = 0;
1133 };
1134
1135 template <class Policy, class Hash, class Eq, class Alloc>
1136 class raw_hash_set;
1137
1138 // Returns the next valid capacity after `n`.
1139 inline size_t NextCapacity(size_t n) {
1140 assert(IsValidCapacity(n) || n == 0);
1141 return n * 2 + 1;
1142 }
1143
1144 // Applies the following mapping to every byte in the control array:
1145 // * kDeleted -> kEmpty
1146 // * kEmpty -> kEmpty
1147 // * _ -> kDeleted
1148 // PRECONDITION:
1149 // IsValidCapacity(capacity)
1150 // ctrl[capacity] == ctrl_t::kSentinel
1151 // ctrl[i] != ctrl_t::kSentinel for all i < capacity
1152 void ConvertDeletedToEmptyAndFullToDeleted(ctrl_t* ctrl, size_t capacity);
1153
1154 // Converts `n` into the next valid capacity, per `IsValidCapacity`.
1155 inline size_t NormalizeCapacity(size_t n) {
1156 return n ? ~size_t{} >> countl_zero(n) : 1;
1157 }
1158
1159 // General notes on capacity/growth methods below:
1160 // - We use 7/8th as maximum load factor. For 16-wide groups, that gives an
1161 // average of two empty slots per group.
1162 // - For (capacity+1) >= Group::kWidth, growth is 7/8*capacity.
1163 // - For (capacity+1) < Group::kWidth, growth == capacity. In this case, we
1164 // never need to probe (the whole table fits in one group) so we don't need a
1165 // load factor less than 1.
1166
1167 // Given `capacity`, applies the load factor; i.e., it returns the maximum
1168 // number of values we should put into the table before a resizing rehash.
1169 inline size_t CapacityToGrowth(size_t capacity) {
1170 assert(IsValidCapacity(capacity));
1171 // `capacity*7/8`
1172 if (Group::kWidth == 8 && capacity == 7) {
1173 // x-x/8 does not work when x==7.
1174 return 6;
1175 }
1176 return capacity - capacity / 8;
1177 }
1178
1179 // Given `growth`, "unapplies" the load factor to find how large the capacity
1180 // should be to stay within the load factor.
1181 //
1182 // This might not be a valid capacity and `NormalizeCapacity()` should be
1183 // called on this.
1184 inline size_t GrowthToLowerboundCapacity(size_t growth) {
1185 // `growth*8/7`
1186 if (Group::kWidth == 8 && growth == 7) {
1187 // x+(x-1)/7 does not work when x==7.
1188 return 8;
1189 }
1190 return growth + static_cast<size_t>((static_cast<int64_t>(growth) - 1) / 7);
1191 }
1192
1193 template <class InputIter>
1194 size_t SelectBucketCountForIterRange(InputIter first, InputIter last,
1195 size_t bucket_count) {
1196 if (bucket_count != 0) {
1197 return bucket_count;
1198 }
1199 using InputIterCategory =
1200 typename std::iterator_traits<InputIter>::iterator_category;
1201 if (std::is_base_of<std::random_access_iterator_tag,
1202 InputIterCategory>::value) {
1203 return GrowthToLowerboundCapacity(
1204 static_cast<size_t>(std::distance(first, last)));
1205 }
1206 return 0;
1207 }
1208
1209 constexpr bool SwisstableDebugEnabled() {
1210 #if defined(ABSL_SWISSTABLE_ENABLE_GENERATIONS) || \
1211 ABSL_OPTION_HARDENED == 1 || !defined(NDEBUG)
1212 return true;
1213 #else
1214 return false;
1215 #endif
1216 }
1217
1218 inline void AssertIsFull(const ctrl_t* ctrl, GenerationType generation,
1219 const GenerationType* generation_ptr,
1220 const char* operation) {
1221 if (!SwisstableDebugEnabled()) return;
1222 // `SwisstableDebugEnabled()` is also true for release builds with hardening
1223 // enabled. To minimize their impact in those builds:
1224 // - use `ABSL_PREDICT_FALSE()` to provide a compiler hint for code layout
1225 // - use `ABSL_RAW_LOG()` with a format string to reduce code size and improve
1226 // the chances that the hot paths will be inlined.
1227 if (ABSL_PREDICT_FALSE(ctrl == nullptr)) {
1228 ABSL_RAW_LOG(FATAL, "%s called on end() iterator.", operation);
1229 }
1230 if (ABSL_PREDICT_FALSE(ctrl == EmptyGroup())) {
1231 ABSL_RAW_LOG(FATAL, "%s called on default-constructed iterator.",
1232 operation);
1233 }
1234 if (SwisstableGenerationsEnabled()) {
1235 if (ABSL_PREDICT_FALSE(generation != *generation_ptr)) {
1236 ABSL_RAW_LOG(FATAL,
1237 "%s called on invalid iterator. The table could have "
1238 "rehashed or moved since this iterator was initialized.",
1239 operation);
1240 }
1241 if (ABSL_PREDICT_FALSE(!IsFull(*ctrl))) {
1242 ABSL_RAW_LOG(
1243 FATAL,
1244 "%s called on invalid iterator. The element was likely erased.",
1245 operation);
1246 }
1247 } else {
1248 if (ABSL_PREDICT_FALSE(!IsFull(*ctrl))) {
1249 ABSL_RAW_LOG(
1250 FATAL,
1251 "%s called on invalid iterator. The element might have been erased "
1252 "or the table might have rehashed. Consider running with "
1253 "--config=asan to diagnose rehashing issues.",
1254 operation);
1255 }
1256 }
1257 }
1258
1259 // Note that for comparisons, null/end iterators are valid.
1260 inline void AssertIsValidForComparison(const ctrl_t* ctrl,
1261 GenerationType generation,
1262 const GenerationType* generation_ptr) {
1263 if (!SwisstableDebugEnabled()) return;
1264 const bool ctrl_is_valid_for_comparison =
1265 ctrl == nullptr || ctrl == EmptyGroup() || IsFull(*ctrl);
1266 if (SwisstableGenerationsEnabled()) {
1267 if (ABSL_PREDICT_FALSE(generation != *generation_ptr)) {
1268 ABSL_RAW_LOG(FATAL,
1269 "Invalid iterator comparison. The table could have rehashed "
1270 "or moved since this iterator was initialized.");
1271 }
1272 if (ABSL_PREDICT_FALSE(!ctrl_is_valid_for_comparison)) {
1273 ABSL_RAW_LOG(
1274 FATAL, "Invalid iterator comparison. The element was likely erased.");
1275 }
1276 } else {
1277 ABSL_HARDENING_ASSERT(
1278 ctrl_is_valid_for_comparison &&
1279 "Invalid iterator comparison. The element might have been erased or "
1280 "the table might have rehashed. Consider running with --config=asan to "
1281 "diagnose rehashing issues.");
1282 }
1283 }
1284
1285 // If the two iterators come from the same container, then their pointers will
1286 // interleave such that ctrl_a <= ctrl_b < slot_a <= slot_b or vice/versa.
1287 // Note: we take slots by reference so that it's not UB if they're uninitialized
1288 // as long as we don't read them (when ctrl is null).
1289 inline bool AreItersFromSameContainer(const ctrl_t* ctrl_a,
1290 const ctrl_t* ctrl_b,
1291 const void* const& slot_a,
1292 const void* const& slot_b) {
1293 // If either control byte is null, then we can't tell.
1294 if (ctrl_a == nullptr || ctrl_b == nullptr) return true;
1295 const void* low_slot = slot_a;
1296 const void* hi_slot = slot_b;
1297 if (ctrl_a > ctrl_b) {
1298 std::swap(ctrl_a, ctrl_b);
1299 std::swap(low_slot, hi_slot);
1300 }
1301 return ctrl_b < low_slot && low_slot <= hi_slot;
1302 }
1303
1304 // Asserts that two iterators come from the same container.
1305 // Note: we take slots by reference so that it's not UB if they're uninitialized
1306 // as long as we don't read them (when ctrl is null).
1307 inline void AssertSameContainer(const ctrl_t* ctrl_a, const ctrl_t* ctrl_b,
1308 const void* const& slot_a,
1309 const void* const& slot_b,
1310 const GenerationType* generation_ptr_a,
1311 const GenerationType* generation_ptr_b) {
1312 if (!SwisstableDebugEnabled()) return;
1313 // `SwisstableDebugEnabled()` is also true for release builds with hardening
1314 // enabled. To minimize their impact in those builds:
1315 // - use `ABSL_PREDICT_FALSE()` to provide a compiler hint for code layout
1316 // - use `ABSL_RAW_LOG()` with a format string to reduce code size and improve
1317 // the chances that the hot paths will be inlined.
1318 const bool a_is_default = ctrl_a == EmptyGroup();
1319 const bool b_is_default = ctrl_b == EmptyGroup();
1320 if (ABSL_PREDICT_FALSE(a_is_default != b_is_default)) {
1321 ABSL_RAW_LOG(
1322 FATAL,
1323 "Invalid iterator comparison. Comparing default-constructed iterator "
1324 "with non-default-constructed iterator.");
1325 }
1326 if (a_is_default && b_is_default) return;
1327
1328 if (SwisstableGenerationsEnabled()) {
1329 if (ABSL_PREDICT_TRUE(generation_ptr_a == generation_ptr_b)) return;
1330 const bool a_is_empty = IsEmptyGeneration(generation_ptr_a);
1331 const bool b_is_empty = IsEmptyGeneration(generation_ptr_b);
1332 if (a_is_empty != b_is_empty) {
1333 ABSL_RAW_LOG(FATAL,
1334 "Invalid iterator comparison. Comparing iterator from a "
1335 "non-empty hashtable with an iterator from an empty "
1336 "hashtable.");
1337 }
1338 if (a_is_empty && b_is_empty) {
1339 ABSL_RAW_LOG(FATAL,
1340 "Invalid iterator comparison. Comparing iterators from "
1341 "different empty hashtables.");
1342 }
1343 const bool a_is_end = ctrl_a == nullptr;
1344 const bool b_is_end = ctrl_b == nullptr;
1345 if (a_is_end || b_is_end) {
1346 ABSL_RAW_LOG(FATAL,
1347 "Invalid iterator comparison. Comparing iterator with an "
1348 "end() iterator from a different hashtable.");
1349 }
1350 ABSL_RAW_LOG(FATAL,
1351 "Invalid iterator comparison. Comparing non-end() iterators "
1352 "from different hashtables.");
1353 } else {
1354 ABSL_HARDENING_ASSERT(
1355 AreItersFromSameContainer(ctrl_a, ctrl_b, slot_a, slot_b) &&
1356 "Invalid iterator comparison. The iterators may be from different "
1357 "containers or the container might have rehashed or moved. Consider "
1358 "running with --config=asan to diagnose issues.");
1359 }
1360 }
1361
1362 struct FindInfo {
1363 size_t offset;
1364 size_t probe_length;
1365 };
1366
1367 // Whether a table is "small". A small table fits entirely into a probing
1368 // group, i.e., has a capacity < `Group::kWidth`.
1369 //
1370 // In small mode we are able to use the whole capacity. The extra control
1371 // bytes give us at least one "empty" control byte to stop the iteration.
1372 // This is important to make 1 a valid capacity.
1373 //
1374 // In small mode only the first `capacity` control bytes after the sentinel
1375 // are valid. The rest contain dummy ctrl_t::kEmpty values that do not
1376 // represent a real slot. This is important to take into account on
1377 // `find_first_non_full()`, where we never try
1378 // `ShouldInsertBackwards()` for small tables.
1379 inline bool is_small(size_t capacity) { return capacity < Group::kWidth - 1; }
1380
1381 // Begins a probing operation on `common.control`, using `hash`.
1382 inline probe_seq<Group::kWidth> probe(const ctrl_t* ctrl, const size_t capacity,
1383 size_t hash) {
1384 return probe_seq<Group::kWidth>(H1(hash, ctrl), capacity);
1385 }
1386 inline probe_seq<Group::kWidth> probe(const CommonFields& common, size_t hash) {
1387 return probe(common.control(), common.capacity(), hash);
1388 }
1389
1390 // Probes an array of control bits using a probe sequence derived from `hash`,
1391 // and returns the offset corresponding to the first deleted or empty slot.
1392 //
1393 // Behavior when the entire table is full is undefined.
1394 //
1395 // NOTE: this function must work with tables having both empty and deleted
1396 // slots in the same group. Such tables appear during `erase()`.
1397 template <typename = void>
1398 inline FindInfo find_first_non_full(const CommonFields& common, size_t hash) {
1399 auto seq = probe(common, hash);
1400 const ctrl_t* ctrl = common.control();
1401 while (true) {
1402 GroupEmptyOrDeleted g{ctrl + seq.offset()};
1403 auto mask = g.MaskEmptyOrDeleted();
1404 if (mask) {
1405 #if !defined(NDEBUG)
1406 // We want to add entropy even when ASLR is not enabled.
1407 // In debug build we will randomly insert in either the front or back of
1408 // the group.
1409 // TODO(kfm,sbenza): revisit after we do unconditional mixing
1410 if (!is_small(common.capacity()) && ShouldInsertBackwards(hash, ctrl)) {
1411 return {seq.offset(mask.HighestBitSet()), seq.index()};
1412 }
1413 #endif
1414 return {seq.offset(mask.LowestBitSet()), seq.index()};
1415 }
1416 seq.next();
1417 assert(seq.index() <= common.capacity() && "full table!");
1418 }
1419 }
1420
1421 // Extern template for inline function keep possibility of inlining.
1422 // When compiler decided to not inline, no symbols will be added to the
1423 // corresponding translation unit.
1424 extern template FindInfo find_first_non_full(const CommonFields&, size_t);
1425
1426 // Non-inlined version of find_first_non_full for use in less
1427 // performance critical routines.
1428 FindInfo find_first_non_full_outofline(const CommonFields&, size_t);
1429
1430 inline void ResetGrowthLeft(CommonFields& common) {
1431 common.set_growth_left(CapacityToGrowth(common.capacity()) - common.size());
1432 }
1433
1434 // Sets `ctrl` to `{kEmpty, kSentinel, ..., kEmpty}`, marking the entire
1435 // array as marked as empty.
1436 inline void ResetCtrl(CommonFields& common, size_t slot_size) {
1437 const size_t capacity = common.capacity();
1438 ctrl_t* ctrl = common.control();
1439 std::memset(ctrl, static_cast<int8_t>(ctrl_t::kEmpty),
1440 capacity + 1 + NumClonedBytes());
1441 ctrl[capacity] = ctrl_t::kSentinel;
1442 SanitizerPoisonMemoryRegion(common.slot_array(), slot_size * capacity);
1443 ResetGrowthLeft(common);
1444 }
1445
1446 // Sets `ctrl[i]` to `h`.
1447 //
1448 // Unlike setting it directly, this function will perform bounds checks and
1449 // mirror the value to the cloned tail if necessary.
1450 inline void SetCtrl(const CommonFields& common, size_t i, ctrl_t h,
1451 size_t slot_size) {
1452 const size_t capacity = common.capacity();
1453 assert(i < capacity);
1454
1455 auto* slot_i = static_cast<const char*>(common.slot_array()) + i * slot_size;
1456 if (IsFull(h)) {
1457 SanitizerUnpoisonMemoryRegion(slot_i, slot_size);
1458 } else {
1459 SanitizerPoisonMemoryRegion(slot_i, slot_size);
1460 }
1461
1462 ctrl_t* ctrl = common.control();
1463 ctrl[i] = h;
1464 ctrl[((i - NumClonedBytes()) & capacity) + (NumClonedBytes() & capacity)] = h;
1465 }
1466
1467 // Overload for setting to an occupied `h2_t` rather than a special `ctrl_t`.
1468 inline void SetCtrl(const CommonFields& common, size_t i, h2_t h,
1469 size_t slot_size) {
1470 SetCtrl(common, i, static_cast<ctrl_t>(h), slot_size);
1471 }
1472
1473 // growth_left (which is a size_t) is stored with the backing array.
1474 constexpr size_t BackingArrayAlignment(size_t align_of_slot) {
1475 return (std::max)(align_of_slot, alignof(size_t));
1476 }
1477
1478 template <typename Alloc, size_t SizeOfSlot, size_t AlignOfSlot>
1479 ABSL_ATTRIBUTE_NOINLINE void InitializeSlots(CommonFields& c, Alloc alloc) {
1480 assert(c.capacity());
1481 // Folks with custom allocators often make unwarranted assumptions about the
1482 // behavior of their classes vis-a-vis trivial destructability and what
1483 // calls they will or won't make. Avoid sampling for people with custom
1484 // allocators to get us out of this mess. This is not a hard guarantee but
1485 // a workaround while we plan the exact guarantee we want to provide.
1486 const size_t sample_size =
1487 (std::is_same<Alloc, std::allocator<char>>::value &&
1488 c.slot_array() == nullptr)
1489 ? SizeOfSlot
1490 : 0;
1491 HashtablezInfoHandle infoz =
1492 sample_size > 0 ? Sample(sample_size) : c.infoz();
1493
1494 const bool has_infoz = infoz.IsSampled();
1495 const size_t cap = c.capacity();
1496 const size_t alloc_size = AllocSize(cap, SizeOfSlot, AlignOfSlot, has_infoz);
1497 char* mem = static_cast<char*>(
1498 Allocate<BackingArrayAlignment(AlignOfSlot)>(&alloc, alloc_size));
1499 const GenerationType old_generation = c.generation();
1500 c.set_generation_ptr(reinterpret_cast<GenerationType*>(
1501 mem + GenerationOffset(cap, has_infoz)));
1502 c.set_generation(NextGeneration(old_generation));
1503 c.set_control(reinterpret_cast<ctrl_t*>(mem + ControlOffset(has_infoz)));
1504 c.set_slots(mem + SlotOffset(cap, AlignOfSlot, has_infoz));
1505 ResetCtrl(c, SizeOfSlot);
1506 c.set_has_infoz(has_infoz);
1507 if (has_infoz) {
1508 infoz.RecordStorageChanged(c.size(), cap);
1509 c.set_infoz(infoz);
1510 }
1511 }
1512
1513 // PolicyFunctions bundles together some information for a particular
1514 // raw_hash_set<T, ...> instantiation. This information is passed to
1515 // type-erased functions that want to do small amounts of type-specific
1516 // work.
1517 struct PolicyFunctions {
1518 size_t slot_size;
1519
1520 // Returns the hash of the pointed-to slot.
1521 size_t (*hash_slot)(void* set, void* slot);
1522
1523 // Transfer the contents of src_slot to dst_slot.
1524 void (*transfer)(void* set, void* dst_slot, void* src_slot);
1525
1526 // Deallocate the backing store from common.
1527 void (*dealloc)(CommonFields& common, const PolicyFunctions& policy);
1528 };
1529
1530 // ClearBackingArray clears the backing array, either modifying it in place,
1531 // or creating a new one based on the value of "reuse".
1532 // REQUIRES: c.capacity > 0
1533 void ClearBackingArray(CommonFields& c, const PolicyFunctions& policy,
1534 bool reuse);
1535
1536 // Type-erased version of raw_hash_set::erase_meta_only.
1537 void EraseMetaOnly(CommonFields& c, ctrl_t* it, size_t slot_size);
1538
1539 // Function to place in PolicyFunctions::dealloc for raw_hash_sets
1540 // that are using std::allocator. This allows us to share the same
1541 // function body for raw_hash_set instantiations that have the
1542 // same slot alignment.
1543 template <size_t AlignOfSlot>
1544 ABSL_ATTRIBUTE_NOINLINE void DeallocateStandard(CommonFields& common,
1545 const PolicyFunctions& policy) {
1546 // Unpoison before returning the memory to the allocator.
1547 SanitizerUnpoisonMemoryRegion(common.slot_array(),
1548 policy.slot_size * common.capacity());
1549
1550 std::allocator<char> alloc;
1551 common.infoz().Unregister();
1552 Deallocate<BackingArrayAlignment(AlignOfSlot)>(
1553 &alloc, common.backing_array_start(),
1554 common.alloc_size(policy.slot_size, AlignOfSlot));
1555 }
1556
1557 // For trivially relocatable types we use memcpy directly. This allows us to
1558 // share the same function body for raw_hash_set instantiations that have the
1559 // same slot size as long as they are relocatable.
1560 template <size_t SizeOfSlot>
1561 ABSL_ATTRIBUTE_NOINLINE void TransferRelocatable(void*, void* dst, void* src) {
1562 memcpy(dst, src, SizeOfSlot);
1563 }
1564
1565 // Type-erased version of raw_hash_set::drop_deletes_without_resize.
1566 void DropDeletesWithoutResize(CommonFields& common,
1567 const PolicyFunctions& policy, void* tmp_space);
1568
1569 // A SwissTable.
1570 //
1571 // Policy: a policy defines how to perform different operations on
1572 // the slots of the hashtable (see hash_policy_traits.h for the full interface
1573 // of policy).
1574 //
1575 // Hash: a (possibly polymorphic) functor that hashes keys of the hashtable. The
1576 // functor should accept a key and return size_t as hash. For best performance
1577 // it is important that the hash function provides high entropy across all bits
1578 // of the hash.
1579 //
1580 // Eq: a (possibly polymorphic) functor that compares two keys for equality. It
1581 // should accept two (of possibly different type) keys and return a bool: true
1582 // if they are equal, false if they are not. If two keys compare equal, then
1583 // their hash values as defined by Hash MUST be equal.
1584 //
1585 // Allocator: an Allocator
1586 // [https://en.cppreference.com/w/cpp/named_req/Allocator] with which
1587 // the storage of the hashtable will be allocated and the elements will be
1588 // constructed and destroyed.
1589 template <class Policy, class Hash, class Eq, class Alloc>
1590 class raw_hash_set {
1591 using PolicyTraits = hash_policy_traits<Policy>;
1592 using KeyArgImpl =
1593 KeyArg<IsTransparent<Eq>::value && IsTransparent<Hash>::value>;
1594
1595 public:
1596 using init_type = typename PolicyTraits::init_type;
1597 using key_type = typename PolicyTraits::key_type;
1598 // TODO(sbenza): Hide slot_type as it is an implementation detail. Needs user
1599 // code fixes!
1600 using slot_type = typename PolicyTraits::slot_type;
1601 using allocator_type = Alloc;
1602 using size_type = size_t;
1603 using difference_type = ptrdiff_t;
1604 using hasher = Hash;
1605 using key_equal = Eq;
1606 using policy_type = Policy;
1607 using value_type = typename PolicyTraits::value_type;
1608 using reference = value_type&;
1609 using const_reference = const value_type&;
1610 using pointer = typename absl::allocator_traits<
1611 allocator_type>::template rebind_traits<value_type>::pointer;
1612 using const_pointer = typename absl::allocator_traits<
1613 allocator_type>::template rebind_traits<value_type>::const_pointer;
1614
1615 // Alias used for heterogeneous lookup functions.
1616 // `key_arg<K>` evaluates to `K` when the functors are transparent and to
1617 // `key_type` otherwise. It permits template argument deduction on `K` for the
1618 // transparent case.
1619 template <class K>
1620 using key_arg = typename KeyArgImpl::template type<K, key_type>;
1621
1622 private:
1623 // Give an early error when key_type is not hashable/eq.
1624 auto KeyTypeCanBeHashed(const Hash& h, const key_type& k) -> decltype(h(k));
1625 auto KeyTypeCanBeEq(const Eq& eq, const key_type& k) -> decltype(eq(k, k));
1626
1627 using AllocTraits = absl::allocator_traits<allocator_type>;
1628 using SlotAlloc = typename absl::allocator_traits<
1629 allocator_type>::template rebind_alloc<slot_type>;
1630 using SlotAllocTraits = typename absl::allocator_traits<
1631 allocator_type>::template rebind_traits<slot_type>;
1632
1633 static_assert(std::is_lvalue_reference<reference>::value,
1634 "Policy::element() must return a reference");
1635
1636 template <typename T>
1637 struct SameAsElementReference
1638 : std::is_same<typename std::remove_cv<
1639 typename std::remove_reference<reference>::type>::type,
1640 typename std::remove_cv<
1641 typename std::remove_reference<T>::type>::type> {};
1642
1643 // An enabler for insert(T&&): T must be convertible to init_type or be the
1644 // same as [cv] value_type [ref].
1645 // Note: we separate SameAsElementReference into its own type to avoid using
1646 // reference unless we need to. MSVC doesn't seem to like it in some
1647 // cases.
1648 template <class T>
1649 using RequiresInsertable = typename std::enable_if<
1650 absl::disjunction<std::is_convertible<T, init_type>,
1651 SameAsElementReference<T>>::value,
1652 int>::type;
1653
1654 // RequiresNotInit is a workaround for gcc prior to 7.1.
1655 // See https://godbolt.org/g/Y4xsUh.
1656 template <class T>
1657 using RequiresNotInit =
1658 typename std::enable_if<!std::is_same<T, init_type>::value, int>::type;
1659
1660 template <class... Ts>
1661 using IsDecomposable = IsDecomposable<void, PolicyTraits, Hash, Eq, Ts...>;
1662
1663 public:
1664 static_assert(std::is_same<pointer, value_type*>::value,
1665 "Allocators with custom pointer types are not supported");
1666 static_assert(std::is_same<const_pointer, const value_type*>::value,
1667 "Allocators with custom pointer types are not supported");
1668
1669 class iterator : private HashSetIteratorGenerationInfo {
1670 friend class raw_hash_set;
1671
1672 public:
1673 using iterator_category = std::forward_iterator_tag;
1674 using value_type = typename raw_hash_set::value_type;
1675 using reference =
1676 absl::conditional_t<PolicyTraits::constant_iterators::value,
1677 const value_type&, value_type&>;
1678 using pointer = absl::remove_reference_t<reference>*;
1679 using difference_type = typename raw_hash_set::difference_type;
1680
1681 iterator() {}
1682
1683 // PRECONDITION: not an end() iterator.
1684 reference operator*() const {
1685 AssertIsFull(ctrl_, generation(), generation_ptr(), "operator*()");
1686 return PolicyTraits::element(slot_);
1687 }
1688
1689 // PRECONDITION: not an end() iterator.
1690 pointer operator->() const {
1691 AssertIsFull(ctrl_, generation(), generation_ptr(), "operator->");
1692 return &operator*();
1693 }
1694
1695 // PRECONDITION: not an end() iterator.
1696 iterator& operator++() {
1697 AssertIsFull(ctrl_, generation(), generation_ptr(), "operator++");
1698 ++ctrl_;
1699 ++slot_;
1700 skip_empty_or_deleted();
1701 return *this;
1702 }
1703 // PRECONDITION: not an end() iterator.
1704 iterator operator++(int) {
1705 auto tmp = *this;
1706 ++*this;
1707 return tmp;
1708 }
1709
1710 friend bool operator==(const iterator& a, const iterator& b) {
1711 AssertIsValidForComparison(a.ctrl_, a.generation(), a.generation_ptr());
1712 AssertIsValidForComparison(b.ctrl_, b.generation(), b.generation_ptr());
1713 AssertSameContainer(a.ctrl_, b.ctrl_, a.slot_, b.slot_,
1714 a.generation_ptr(), b.generation_ptr());
1715 return a.ctrl_ == b.ctrl_;
1716 }
1717 friend bool operator!=(const iterator& a, const iterator& b) {
1718 return !(a == b);
1719 }
1720
1721 private:
1722 iterator(ctrl_t* ctrl, slot_type* slot,
1723 const GenerationType* generation_ptr)
1724 : HashSetIteratorGenerationInfo(generation_ptr),
1725 ctrl_(ctrl),
1726 slot_(slot) {
1727 // This assumption helps the compiler know that any non-end iterator is
1728 // not equal to any end iterator.
1729 ABSL_ASSUME(ctrl != nullptr);
1730 }
1731 // For end() iterators.
1732 explicit iterator(const GenerationType* generation_ptr)
1733 : HashSetIteratorGenerationInfo(generation_ptr), ctrl_(nullptr) {}
1734
1735 // Fixes up `ctrl_` to point to a full by advancing it and `slot_` until
1736 // they reach one.
1737 //
1738 // If a sentinel is reached, we null `ctrl_` out instead.
1739 void skip_empty_or_deleted() {
1740 while (IsEmptyOrDeleted(*ctrl_)) {
1741 uint32_t shift =
1742 GroupEmptyOrDeleted{ctrl_}.CountLeadingEmptyOrDeleted();
1743 ctrl_ += shift;
1744 slot_ += shift;
1745 }
1746 if (ABSL_PREDICT_FALSE(*ctrl_ == ctrl_t::kSentinel)) ctrl_ = nullptr;
1747 }
1748
1749 ctrl_t* control() const { return ctrl_; }
1750 slot_type* slot() const { return slot_; }
1751
1752 // We use EmptyGroup() for default-constructed iterators so that they can
1753 // be distinguished from end iterators, which have nullptr ctrl_.
1754 ctrl_t* ctrl_ = EmptyGroup();
1755 // To avoid uninitialized member warnings, put slot_ in an anonymous union.
1756 // The member is not initialized on singleton and end iterators.
1757 union {
1758 slot_type* slot_;
1759 };
1760 };
1761
1762 class const_iterator {
1763 friend class raw_hash_set;
1764 template <class Container, typename Enabler>
1765 friend struct absl::container_internal::hashtable_debug_internal::
1766 HashtableDebugAccess;
1767
1768 public:
1769 using iterator_category = typename iterator::iterator_category;
1770 using value_type = typename raw_hash_set::value_type;
1771 using reference = typename raw_hash_set::const_reference;
1772 using pointer = typename raw_hash_set::const_pointer;
1773 using difference_type = typename raw_hash_set::difference_type;
1774
1775 const_iterator() = default;
1776 // Implicit construction from iterator.
1777 const_iterator(iterator i) : inner_(std::move(i)) {} // NOLINT
1778
1779 reference operator*() const { return *inner_; }
1780 pointer operator->() const { return inner_.operator->(); }
1781
1782 const_iterator& operator++() {
1783 ++inner_;
1784 return *this;
1785 }
1786 const_iterator operator++(int) { return inner_++; }
1787
1788 friend bool operator==(const const_iterator& a, const const_iterator& b) {
1789 return a.inner_ == b.inner_;
1790 }
1791 friend bool operator!=(const const_iterator& a, const const_iterator& b) {
1792 return !(a == b);
1793 }
1794
1795 private:
1796 const_iterator(const ctrl_t* ctrl, const slot_type* slot,
1797 const GenerationType* gen)
1798 : inner_(const_cast<ctrl_t*>(ctrl), const_cast<slot_type*>(slot), gen) {
1799 }
1800 ctrl_t* control() const { return inner_.control(); }
1801 slot_type* slot() const { return inner_.slot(); }
1802
1803 iterator inner_;
1804 };
1805
1806 using node_type = node_handle<Policy, hash_policy_traits<Policy>, Alloc>;
1807 using insert_return_type = InsertReturnType<iterator, node_type>;
1808
1809 // Note: can't use `= default` due to non-default noexcept (causes
1810 // problems for some compilers). NOLINTNEXTLINE
1811 raw_hash_set() noexcept(
1812 std::is_nothrow_default_constructible<hasher>::value &&
1813 std::is_nothrow_default_constructible<key_equal>::value &&
1814 std::is_nothrow_default_constructible<allocator_type>::value) {}
1815
1816 ABSL_ATTRIBUTE_NOINLINE explicit raw_hash_set(
1817 size_t bucket_count, const hasher& hash = hasher(),
1818 const key_equal& eq = key_equal(),
1819 const allocator_type& alloc = allocator_type())
1820 : settings_(CommonFields{}, hash, eq, alloc) {
1821 if (bucket_count) {
1822 common().set_capacity(NormalizeCapacity(bucket_count));
1823 initialize_slots();
1824 }
1825 }
1826
1827 raw_hash_set(size_t bucket_count, const hasher& hash,
1828 const allocator_type& alloc)
1829 : raw_hash_set(bucket_count, hash, key_equal(), alloc) {}
1830
1831 raw_hash_set(size_t bucket_count, const allocator_type& alloc)
1832 : raw_hash_set(bucket_count, hasher(), key_equal(), alloc) {}
1833
1834 explicit raw_hash_set(const allocator_type& alloc)
1835 : raw_hash_set(0, hasher(), key_equal(), alloc) {}
1836
1837 template <class InputIter>
1838 raw_hash_set(InputIter first, InputIter last, size_t bucket_count = 0,
1839 const hasher& hash = hasher(), const key_equal& eq = key_equal(),
1840 const allocator_type& alloc = allocator_type())
1841 : raw_hash_set(SelectBucketCountForIterRange(first, last, bucket_count),
1842 hash, eq, alloc) {
1843 insert(first, last);
1844 }
1845
1846 template <class InputIter>
1847 raw_hash_set(InputIter first, InputIter last, size_t bucket_count,
1848 const hasher& hash, const allocator_type& alloc)
1849 : raw_hash_set(first, last, bucket_count, hash, key_equal(), alloc) {}
1850
1851 template <class InputIter>
1852 raw_hash_set(InputIter first, InputIter last, size_t bucket_count,
1853 const allocator_type& alloc)
1854 : raw_hash_set(first, last, bucket_count, hasher(), key_equal(), alloc) {}
1855
1856 template <class InputIter>
1857 raw_hash_set(InputIter first, InputIter last, const allocator_type& alloc)
1858 : raw_hash_set(first, last, 0, hasher(), key_equal(), alloc) {}
1859
1860 // Instead of accepting std::initializer_list<value_type> as the first
1861 // argument like std::unordered_set<value_type> does, we have two overloads
1862 // that accept std::initializer_list<T> and std::initializer_list<init_type>.
1863 // This is advantageous for performance.
1864 //
1865 // // Turns {"abc", "def"} into std::initializer_list<std::string>, then
1866 // // copies the strings into the set.
1867 // std::unordered_set<std::string> s = {"abc", "def"};
1868 //
1869 // // Turns {"abc", "def"} into std::initializer_list<const char*>, then
1870 // // copies the strings into the set.
1871 // absl::flat_hash_set<std::string> s = {"abc", "def"};
1872 //
1873 // The same trick is used in insert().
1874 //
1875 // The enabler is necessary to prevent this constructor from triggering where
1876 // the copy constructor is meant to be called.
1877 //
1878 // absl::flat_hash_set<int> a, b{a};
1879 //
1880 // RequiresNotInit<T> is a workaround for gcc prior to 7.1.
1881 template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
1882 raw_hash_set(std::initializer_list<T> init, size_t bucket_count = 0,
1883 const hasher& hash = hasher(), const key_equal& eq = key_equal(),
1884 const allocator_type& alloc = allocator_type())
1885 : raw_hash_set(init.begin(), init.end(), bucket_count, hash, eq, alloc) {}
1886
1887 raw_hash_set(std::initializer_list<init_type> init, size_t bucket_count = 0,
1888 const hasher& hash = hasher(), const key_equal& eq = key_equal(),
1889 const allocator_type& alloc = allocator_type())
1890 : raw_hash_set(init.begin(), init.end(), bucket_count, hash, eq, alloc) {}
1891
1892 template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
1893 raw_hash_set(std::initializer_list<T> init, size_t bucket_count,
1894 const hasher& hash, const allocator_type& alloc)
1895 : raw_hash_set(init, bucket_count, hash, key_equal(), alloc) {}
1896
1897 raw_hash_set(std::initializer_list<init_type> init, size_t bucket_count,
1898 const hasher& hash, const allocator_type& alloc)
1899 : raw_hash_set(init, bucket_count, hash, key_equal(), alloc) {}
1900
1901 template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
1902 raw_hash_set(std::initializer_list<T> init, size_t bucket_count,
1903 const allocator_type& alloc)
1904 : raw_hash_set(init, bucket_count, hasher(), key_equal(), alloc) {}
1905
1906 raw_hash_set(std::initializer_list<init_type> init, size_t bucket_count,
1907 const allocator_type& alloc)
1908 : raw_hash_set(init, bucket_count, hasher(), key_equal(), alloc) {}
1909
1910 template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
1911 raw_hash_set(std::initializer_list<T> init, const allocator_type& alloc)
1912 : raw_hash_set(init, 0, hasher(), key_equal(), alloc) {}
1913
1914 raw_hash_set(std::initializer_list<init_type> init,
1915 const allocator_type& alloc)
1916 : raw_hash_set(init, 0, hasher(), key_equal(), alloc) {}
1917
1918 raw_hash_set(const raw_hash_set& that)
1919 : raw_hash_set(that, AllocTraits::select_on_container_copy_construction(
1920 that.alloc_ref())) {}
1921
1922 raw_hash_set(const raw_hash_set& that, const allocator_type& a)
1923 : raw_hash_set(0, that.hash_ref(), that.eq_ref(), a) {
1924 const size_t size = that.size();
1925 if (size == 0) return;
1926 reserve(size);
1927 // Because the table is guaranteed to be empty, we can do something faster
1928 // than a full `insert`.
1929 for (const auto& v : that) {
1930 const size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, v);
1931 auto target = find_first_non_full_outofline(common(), hash);
1932 SetCtrl(common(), target.offset, H2(hash), sizeof(slot_type));
1933 emplace_at(target.offset, v);
1934 common().maybe_increment_generation_on_insert();
1935 infoz().RecordInsert(hash, target.probe_length);
1936 }
1937 common().set_size(size);
1938 set_growth_left(growth_left() - size);
1939 }
1940
1941 ABSL_ATTRIBUTE_NOINLINE raw_hash_set(raw_hash_set&& that) noexcept(
1942 std::is_nothrow_copy_constructible<hasher>::value &&
1943 std::is_nothrow_copy_constructible<key_equal>::value &&
1944 std::is_nothrow_copy_constructible<allocator_type>::value)
1945 : // Hash, equality and allocator are copied instead of moved because
1946 // `that` must be left valid. If Hash is std::function<Key>, moving it
1947 // would create a nullptr functor that cannot be called.
1948 // TODO(b/296061262): move instead of copying hash/eq/alloc.
1949 // Note: we avoid using exchange for better generated code.
1950 settings_(std::move(that.common()), that.hash_ref(), that.eq_ref(),
1951 that.alloc_ref()) {
1952 that.common() = CommonFields{};
1953 maybe_increment_generation_or_rehash_on_move();
1954 }
1955
1956 raw_hash_set(raw_hash_set&& that, const allocator_type& a)
1957 : settings_(CommonFields{}, that.hash_ref(), that.eq_ref(), a) {
1958 if (a == that.alloc_ref()) {
1959 std::swap(common(), that.common());
1960 maybe_increment_generation_or_rehash_on_move();
1961 } else {
1962 move_elements_allocs_unequal(std::move(that));
1963 }
1964 }
1965
1966 raw_hash_set& operator=(const raw_hash_set& that) {
1967 if (ABSL_PREDICT_FALSE(this == &that)) return *this;
1968 constexpr bool propagate_alloc =
1969 AllocTraits::propagate_on_container_copy_assignment::value;
1970 // TODO(ezb): maybe avoid allocating a new backing array if this->capacity()
1971 // is an exact match for that.size(). If this->capacity() is too big, then
1972 // it would make iteration very slow to reuse the allocation. Maybe we can
1973 // do the same heuristic as clear() and reuse if it's small enough.
1974 raw_hash_set tmp(that, propagate_alloc ? that.alloc_ref() : alloc_ref());
1975 // NOLINTNEXTLINE: not returning *this for performance.
1976 return assign_impl<propagate_alloc>(std::move(tmp));
1977 }
1978
1979 raw_hash_set& operator=(raw_hash_set&& that) noexcept(
1980 absl::allocator_traits<allocator_type>::is_always_equal::value &&
1981 std::is_nothrow_move_assignable<hasher>::value &&
1982 std::is_nothrow_move_assignable<key_equal>::value) {
1983 // TODO(sbenza): We should only use the operations from the noexcept clause
1984 // to make sure we actually adhere to that contract.
1985 // NOLINTNEXTLINE: not returning *this for performance.
1986 return move_assign(
1987 std::move(that),
1988 typename AllocTraits::propagate_on_container_move_assignment());
1989 }
1990
1991 ~raw_hash_set() { destructor_impl(); }
1992
1993 iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
1994 auto it = iterator_at(0);
1995 it.skip_empty_or_deleted();
1996 return it;
1997 }
1998 iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND {
1999 return iterator(common().generation_ptr());
2000 }
2001
2002 const_iterator begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
2003 return const_cast<raw_hash_set*>(this)->begin();
2004 }
2005 const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
2006 return iterator(common().generation_ptr());
2007 }
2008 const_iterator cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
2009 return begin();
2010 }
2011 const_iterator cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return end(); }
2012
2013 bool empty() const { return !size(); }
2014 size_t size() const { return common().size(); }
2015 size_t capacity() const { return common().capacity(); }
2016 size_t max_size() const { return (std::numeric_limits<size_t>::max)(); }
2017
2018 ABSL_ATTRIBUTE_REINITIALIZES void clear() {
2019 // Iterating over this container is O(bucket_count()). When bucket_count()
2020 // is much greater than size(), iteration becomes prohibitively expensive.
2021 // For clear() it is more important to reuse the allocated array when the
2022 // container is small because allocation takes comparatively long time
2023 // compared to destruction of the elements of the container. So we pick the
2024 // largest bucket_count() threshold for which iteration is still fast and
2025 // past that we simply deallocate the array.
2026 const size_t cap = capacity();
2027 if (cap == 0) {
2028 // Already guaranteed to be empty; so nothing to do.
2029 } else {
2030 destroy_slots();
2031 ClearBackingArray(common(), GetPolicyFunctions(), /*reuse=*/cap < 128);
2032 }
2033 common().set_reserved_growth(0);
2034 common().set_reservation_size(0);
2035 }
2036
2037 // This overload kicks in when the argument is an rvalue of insertable and
2038 // decomposable type other than init_type.
2039 //
2040 // flat_hash_map<std::string, int> m;
2041 // m.insert(std::make_pair("abc", 42));
2042 // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc
2043 // bug.
2044 template <class T, RequiresInsertable<T> = 0, class T2 = T,
2045 typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0,
2046 T* = nullptr>
2047 std::pair<iterator, bool> insert(T&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2048 return emplace(std::forward<T>(value));
2049 }
2050
2051 // This overload kicks in when the argument is a bitfield or an lvalue of
2052 // insertable and decomposable type.
2053 //
2054 // union { int n : 1; };
2055 // flat_hash_set<int> s;
2056 // s.insert(n);
2057 //
2058 // flat_hash_set<std::string> s;
2059 // const char* p = "hello";
2060 // s.insert(p);
2061 //
2062 template <
2063 class T, RequiresInsertable<const T&> = 0,
2064 typename std::enable_if<IsDecomposable<const T&>::value, int>::type = 0>
2065 std::pair<iterator, bool> insert(const T& value)
2066 ABSL_ATTRIBUTE_LIFETIME_BOUND {
2067 return emplace(value);
2068 }
2069
2070 // This overload kicks in when the argument is an rvalue of init_type. Its
2071 // purpose is to handle brace-init-list arguments.
2072 //
2073 // flat_hash_map<std::string, int> s;
2074 // s.insert({"abc", 42});
2075 std::pair<iterator, bool> insert(init_type&& value)
2076 ABSL_ATTRIBUTE_LIFETIME_BOUND {
2077 return emplace(std::move(value));
2078 }
2079
2080 // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc
2081 // bug.
2082 template <class T, RequiresInsertable<T> = 0, class T2 = T,
2083 typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0,
2084 T* = nullptr>
2085 iterator insert(const_iterator, T&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2086 return insert(std::forward<T>(value)).first;
2087 }
2088
2089 template <
2090 class T, RequiresInsertable<const T&> = 0,
2091 typename std::enable_if<IsDecomposable<const T&>::value, int>::type = 0>
2092 iterator insert(const_iterator,
2093 const T& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2094 return insert(value).first;
2095 }
2096
2097 iterator insert(const_iterator,
2098 init_type&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2099 return insert(std::move(value)).first;
2100 }
2101
2102 template <class InputIt>
2103 void insert(InputIt first, InputIt last) {
2104 for (; first != last; ++first) emplace(*first);
2105 }
2106
2107 template <class T, RequiresNotInit<T> = 0, RequiresInsertable<const T&> = 0>
2108 void insert(std::initializer_list<T> ilist) {
2109 insert(ilist.begin(), ilist.end());
2110 }
2111
2112 void insert(std::initializer_list<init_type> ilist) {
2113 insert(ilist.begin(), ilist.end());
2114 }
2115
2116 insert_return_type insert(node_type&& node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2117 if (!node) return {end(), false, node_type()};
2118 const auto& elem = PolicyTraits::element(CommonAccess::GetSlot(node));
2119 auto res = PolicyTraits::apply(
2120 InsertSlot<false>{*this, std::move(*CommonAccess::GetSlot(node))},
2121 elem);
2122 if (res.second) {
2123 CommonAccess::Reset(&node);
2124 return {res.first, true, node_type()};
2125 } else {
2126 return {res.first, false, std::move(node)};
2127 }
2128 }
2129
2130 iterator insert(const_iterator,
2131 node_type&& node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2132 auto res = insert(std::move(node));
2133 node = std::move(res.node);
2134 return res.position;
2135 }
2136
2137 // This overload kicks in if we can deduce the key from args. This enables us
2138 // to avoid constructing value_type if an entry with the same key already
2139 // exists.
2140 //
2141 // For example:
2142 //
2143 // flat_hash_map<std::string, std::string> m = {{"abc", "def"}};
2144 // // Creates no std::string copies and makes no heap allocations.
2145 // m.emplace("abc", "xyz");
2146 template <class... Args, typename std::enable_if<
2147 IsDecomposable<Args...>::value, int>::type = 0>
2148 std::pair<iterator, bool> emplace(Args&&... args)
2149 ABSL_ATTRIBUTE_LIFETIME_BOUND {
2150 return PolicyTraits::apply(EmplaceDecomposable{*this},
2151 std::forward<Args>(args)...);
2152 }
2153
2154 // This overload kicks in if we cannot deduce the key from args. It constructs
2155 // value_type unconditionally and then either moves it into the table or
2156 // destroys.
2157 template <class... Args, typename std::enable_if<
2158 !IsDecomposable<Args...>::value, int>::type = 0>
2159 std::pair<iterator, bool> emplace(Args&&... args)
2160 ABSL_ATTRIBUTE_LIFETIME_BOUND {
2161 alignas(slot_type) unsigned char raw[sizeof(slot_type)];
2162 slot_type* slot = reinterpret_cast<slot_type*>(&raw);
2163
2164 construct(slot, std::forward<Args>(args)...);
2165 const auto& elem = PolicyTraits::element(slot);
2166 return PolicyTraits::apply(InsertSlot<true>{*this, std::move(*slot)}, elem);
2167 }
2168
2169 template <class... Args>
2170 iterator emplace_hint(const_iterator,
2171 Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2172 return emplace(std::forward<Args>(args)...).first;
2173 }
2174
2175 // Extension API: support for lazy emplace.
2176 //
2177 // Looks up key in the table. If found, returns the iterator to the element.
2178 // Otherwise calls `f` with one argument of type `raw_hash_set::constructor`,
2179 // and returns an iterator to the new element.
2180 //
2181 // `f` must abide by several restrictions:
2182 // - it MUST call `raw_hash_set::constructor` with arguments as if a
2183 // `raw_hash_set::value_type` is constructed,
2184 // - it MUST NOT access the container before the call to
2185 // `raw_hash_set::constructor`, and
2186 // - it MUST NOT erase the lazily emplaced element.
2187 // Doing any of these is undefined behavior.
2188 //
2189 // For example:
2190 //
2191 // std::unordered_set<ArenaString> s;
2192 // // Makes ArenaStr even if "abc" is in the map.
2193 // s.insert(ArenaString(&arena, "abc"));
2194 //
2195 // flat_hash_set<ArenaStr> s;
2196 // // Makes ArenaStr only if "abc" is not in the map.
2197 // s.lazy_emplace("abc", [&](const constructor& ctor) {
2198 // ctor(&arena, "abc");
2199 // });
2200 //
2201 // WARNING: This API is currently experimental. If there is a way to implement
2202 // the same thing with the rest of the API, prefer that.
2203 class constructor {
2204 friend class raw_hash_set;
2205
2206 public:
2207 template <class... Args>
2208 void operator()(Args&&... args) const {
2209 assert(*slot_);
2210 PolicyTraits::construct(alloc_, *slot_, std::forward<Args>(args)...);
2211 *slot_ = nullptr;
2212 }
2213
2214 private:
2215 constructor(allocator_type* a, slot_type** slot) : alloc_(a), slot_(slot) {}
2216
2217 allocator_type* alloc_;
2218 slot_type** slot_;
2219 };
2220
2221 template <class K = key_type, class F>
2222 iterator lazy_emplace(const key_arg<K>& key,
2223 F&& f) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2224 auto res = find_or_prepare_insert(key);
2225 if (res.second) {
2226 slot_type* slot = slot_array() + res.first;
2227 std::forward<F>(f)(constructor(&alloc_ref(), &slot));
2228 assert(!slot);
2229 }
2230 return iterator_at(res.first);
2231 }
2232
2233 // Extension API: support for heterogeneous keys.
2234 //
2235 // std::unordered_set<std::string> s;
2236 // // Turns "abc" into std::string.
2237 // s.erase("abc");
2238 //
2239 // flat_hash_set<std::string> s;
2240 // // Uses "abc" directly without copying it into std::string.
2241 // s.erase("abc");
2242 template <class K = key_type>
2243 size_type erase(const key_arg<K>& key) {
2244 auto it = find(key);
2245 if (it == end()) return 0;
2246 erase(it);
2247 return 1;
2248 }
2249
2250 // Erases the element pointed to by `it`. Unlike `std::unordered_set::erase`,
2251 // this method returns void to reduce algorithmic complexity to O(1). The
2252 // iterator is invalidated, so any increment should be done before calling
2253 // erase. In order to erase while iterating across a map, use the following
2254 // idiom (which also works for standard containers):
2255 //
2256 // for (auto it = m.begin(), end = m.end(); it != end;) {
2257 // // `erase()` will invalidate `it`, so advance `it` first.
2258 // auto copy_it = it++;
2259 // if (<pred>) {
2260 // m.erase(copy_it);
2261 // }
2262 // }
2263 void erase(const_iterator cit) { erase(cit.inner_); }
2264
2265 // This overload is necessary because otherwise erase<K>(const K&) would be
2266 // a better match if non-const iterator is passed as an argument.
2267 void erase(iterator it) {
2268 AssertIsFull(it.control(), it.generation(), it.generation_ptr(), "erase()");
2269 destroy(it.slot());
2270 erase_meta_only(it);
2271 }
2272
2273 iterator erase(const_iterator first,
2274 const_iterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2275 // We check for empty first because ClearBackingArray requires that
2276 // capacity() > 0 as a precondition.
2277 if (empty()) return end();
2278 if (first == begin() && last == end()) {
2279 // TODO(ezb): we access control bytes in destroy_slots so it could make
2280 // sense to combine destroy_slots and ClearBackingArray to avoid cache
2281 // misses when the table is large. Note that we also do this in clear().
2282 destroy_slots();
2283 ClearBackingArray(common(), GetPolicyFunctions(), /*reuse=*/true);
2284 common().set_reserved_growth(common().reservation_size());
2285 return end();
2286 }
2287 while (first != last) {
2288 erase(first++);
2289 }
2290 return last.inner_;
2291 }
2292
2293 // Moves elements from `src` into `this`.
2294 // If the element already exists in `this`, it is left unmodified in `src`.
2295 template <typename H, typename E>
2296 void merge(raw_hash_set<Policy, H, E, Alloc>& src) { // NOLINT
2297 assert(this != &src);
2298 for (auto it = src.begin(), e = src.end(); it != e;) {
2299 auto next = std::next(it);
2300 if (PolicyTraits::apply(InsertSlot<false>{*this, std::move(*it.slot())},
2301 PolicyTraits::element(it.slot()))
2302 .second) {
2303 src.erase_meta_only(it);
2304 }
2305 it = next;
2306 }
2307 }
2308
2309 template <typename H, typename E>
2310 void merge(raw_hash_set<Policy, H, E, Alloc>&& src) {
2311 merge(src);
2312 }
2313
2314 node_type extract(const_iterator position) {
2315 AssertIsFull(position.control(), position.inner_.generation(),
2316 position.inner_.generation_ptr(), "extract()");
2317 auto node = CommonAccess::Transfer<node_type>(alloc_ref(), position.slot());
2318 erase_meta_only(position);
2319 return node;
2320 }
2321
2322 template <
2323 class K = key_type,
2324 typename std::enable_if<!std::is_same<K, iterator>::value, int>::type = 0>
2325 node_type extract(const key_arg<K>& key) {
2326 auto it = find(key);
2327 return it == end() ? node_type() : extract(const_iterator{it});
2328 }
2329
2330 void swap(raw_hash_set& that) noexcept(
2331 IsNoThrowSwappable<hasher>() && IsNoThrowSwappable<key_equal>() &&
2332 IsNoThrowSwappable<allocator_type>(
2333 typename AllocTraits::propagate_on_container_swap{})) {
2334 using std::swap;
2335 swap(common(), that.common());
2336 swap(hash_ref(), that.hash_ref());
2337 swap(eq_ref(), that.eq_ref());
2338 SwapAlloc(alloc_ref(), that.alloc_ref(),
2339 typename AllocTraits::propagate_on_container_swap{});
2340 }
2341
2342 void rehash(size_t n) {
2343 if (n == 0 && capacity() == 0) return;
2344 if (n == 0 && size() == 0) {
2345 ClearBackingArray(common(), GetPolicyFunctions(), /*reuse=*/false);
2346 return;
2347 }
2348
2349 // bitor is a faster way of doing `max` here. We will round up to the next
2350 // power-of-2-minus-1, so bitor is good enough.
2351 auto m = NormalizeCapacity(n | GrowthToLowerboundCapacity(size()));
2352 // n == 0 unconditionally rehashes as per the standard.
2353 if (n == 0 || m > capacity()) {
2354 resize(m);
2355
2356 // This is after resize, to ensure that we have completed the allocation
2357 // and have potentially sampled the hashtable.
2358 infoz().RecordReservation(n);
2359 }
2360 }
2361
2362 void reserve(size_t n) {
2363 if (n > size() + growth_left()) {
2364 size_t m = GrowthToLowerboundCapacity(n);
2365 resize(NormalizeCapacity(m));
2366
2367 // This is after resize, to ensure that we have completed the allocation
2368 // and have potentially sampled the hashtable.
2369 infoz().RecordReservation(n);
2370 }
2371 common().reset_reserved_growth(n);
2372 common().set_reservation_size(n);
2373 }
2374
2375 // Extension API: support for heterogeneous keys.
2376 //
2377 // std::unordered_set<std::string> s;
2378 // // Turns "abc" into std::string.
2379 // s.count("abc");
2380 //
2381 // ch_set<std::string> s;
2382 // // Uses "abc" directly without copying it into std::string.
2383 // s.count("abc");
2384 template <class K = key_type>
2385 size_t count(const key_arg<K>& key) const {
2386 return find(key) == end() ? 0 : 1;
2387 }
2388
2389 // Issues CPU prefetch instructions for the memory needed to find or insert
2390 // a key. Like all lookup functions, this support heterogeneous keys.
2391 //
2392 // NOTE: This is a very low level operation and should not be used without
2393 // specific benchmarks indicating its importance.
2394 template <class K = key_type>
2395 void prefetch(const key_arg<K>& key) const {
2396 (void)key;
2397 // Avoid probing if we won't be able to prefetch the addresses received.
2398 #ifdef ABSL_HAVE_PREFETCH
2399 prefetch_heap_block();
2400 auto seq = probe(common(), hash_ref()(key));
2401 PrefetchToLocalCache(control() + seq.offset());
2402 PrefetchToLocalCache(slot_array() + seq.offset());
2403 #endif // ABSL_HAVE_PREFETCH
2404 }
2405
2406 // The API of find() has two extensions.
2407 //
2408 // 1. The hash can be passed by the user. It must be equal to the hash of the
2409 // key.
2410 //
2411 // 2. The type of the key argument doesn't have to be key_type. This is so
2412 // called heterogeneous key support.
2413 template <class K = key_type>
2414 iterator find(const key_arg<K>& key,
2415 size_t hash) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2416 auto seq = probe(common(), hash);
2417 slot_type* slot_ptr = slot_array();
2418 const ctrl_t* ctrl = control();
2419 while (true) {
2420 Group g{ctrl + seq.offset()};
2421 for (uint32_t i : g.Match(H2(hash))) {
2422 if (ABSL_PREDICT_TRUE(PolicyTraits::apply(
2423 EqualElement<K>{key, eq_ref()},
2424 PolicyTraits::element(slot_ptr + seq.offset(i)))))
2425 return iterator_at(seq.offset(i));
2426 }
2427 if (ABSL_PREDICT_TRUE(g.MaskEmpty())) return end();
2428 seq.next();
2429 assert(seq.index() <= capacity() && "full table!");
2430 }
2431 }
2432 template <class K = key_type>
2433 iterator find(const key_arg<K>& key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2434 prefetch_heap_block();
2435 return find(key, hash_ref()(key));
2436 }
2437
2438 template <class K = key_type>
2439 const_iterator find(const key_arg<K>& key,
2440 size_t hash) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
2441 return const_cast<raw_hash_set*>(this)->find(key, hash);
2442 }
2443 template <class K = key_type>
2444 const_iterator find(const key_arg<K>& key) const
2445 ABSL_ATTRIBUTE_LIFETIME_BOUND {
2446 prefetch_heap_block();
2447 return find(key, hash_ref()(key));
2448 }
2449
2450 template <class K = key_type>
2451 bool contains(const key_arg<K>& key) const {
2452 return find(key) != end();
2453 }
2454
2455 template <class K = key_type>
2456 std::pair<iterator, iterator> equal_range(const key_arg<K>& key)
2457 ABSL_ATTRIBUTE_LIFETIME_BOUND {
2458 auto it = find(key);
2459 if (it != end()) return {it, std::next(it)};
2460 return {it, it};
2461 }
2462 template <class K = key_type>
2463 std::pair<const_iterator, const_iterator> equal_range(
2464 const key_arg<K>& key) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
2465 auto it = find(key);
2466 if (it != end()) return {it, std::next(it)};
2467 return {it, it};
2468 }
2469
2470 size_t bucket_count() const { return capacity(); }
2471 float load_factor() const {
2472 return capacity() ? static_cast<double>(size()) / capacity() : 0.0;
2473 }
2474 float max_load_factor() const { return 1.0f; }
2475 void max_load_factor(float) {
2476 // Does nothing.
2477 }
2478
2479 hasher hash_function() const { return hash_ref(); }
2480 key_equal key_eq() const { return eq_ref(); }
2481 allocator_type get_allocator() const { return alloc_ref(); }
2482
2483 friend bool operator==(const raw_hash_set& a, const raw_hash_set& b) {
2484 if (a.size() != b.size()) return false;
2485 const raw_hash_set* outer = &a;
2486 const raw_hash_set* inner = &b;
2487 if (outer->capacity() > inner->capacity()) std::swap(outer, inner);
2488 for (const value_type& elem : *outer) {
2489 auto it = PolicyTraits::apply(FindElement{*inner}, elem);
2490 if (it == inner->end() || !(*it == elem)) return false;
2491 }
2492 return true;
2493 }
2494
2495 friend bool operator!=(const raw_hash_set& a, const raw_hash_set& b) {
2496 return !(a == b);
2497 }
2498
2499 template <typename H>
2500 friend typename std::enable_if<H::template is_hashable<value_type>::value,
2501 H>::type
2502 AbslHashValue(H h, const raw_hash_set& s) {
2503 return H::combine(H::combine_unordered(std::move(h), s.begin(), s.end()),
2504 s.size());
2505 }
2506
2507 friend void swap(raw_hash_set& a,
2508 raw_hash_set& b) noexcept(noexcept(a.swap(b))) {
2509 a.swap(b);
2510 }
2511
2512 private:
2513 template <class Container, typename Enabler>
2514 friend struct absl::container_internal::hashtable_debug_internal::
2515 HashtableDebugAccess;
2516
2517 struct FindElement {
2518 template <class K, class... Args>
2519 const_iterator operator()(const K& key, Args&&...) const {
2520 return s.find(key);
2521 }
2522 const raw_hash_set& s;
2523 };
2524
2525 struct HashElement {
2526 template <class K, class... Args>
2527 size_t operator()(const K& key, Args&&...) const {
2528 return h(key);
2529 }
2530 const hasher& h;
2531 };
2532
2533 template <class K1>
2534 struct EqualElement {
2535 template <class K2, class... Args>
2536 bool operator()(const K2& lhs, Args&&...) const {
2537 return eq(lhs, rhs);
2538 }
2539 const K1& rhs;
2540 const key_equal& eq;
2541 };
2542
2543 struct EmplaceDecomposable {
2544 template <class K, class... Args>
2545 std::pair<iterator, bool> operator()(const K& key, Args&&... args) const {
2546 auto res = s.find_or_prepare_insert(key);
2547 if (res.second) {
2548 s.emplace_at(res.first, std::forward<Args>(args)...);
2549 }
2550 return {s.iterator_at(res.first), res.second};
2551 }
2552 raw_hash_set& s;
2553 };
2554
2555 template <bool do_destroy>
2556 struct InsertSlot {
2557 template <class K, class... Args>
2558 std::pair<iterator, bool> operator()(const K& key, Args&&...) && {
2559 auto res = s.find_or_prepare_insert(key);
2560 if (res.second) {
2561 s.transfer(s.slot_array() + res.first, &slot);
2562 } else if (do_destroy) {
2563 s.destroy(&slot);
2564 }
2565 return {s.iterator_at(res.first), res.second};
2566 }
2567 raw_hash_set& s;
2568 // Constructed slot. Either moved into place or destroyed.
2569 slot_type&& slot;
2570 };
2571
2572 // TODO(b/303305702): re-enable reentrant validation.
2573 template <typename... Args>
2574 inline void construct(slot_type* slot, Args&&... args) {
2575 PolicyTraits::construct(&alloc_ref(), slot, std::forward<Args>(args)...);
2576 }
2577 inline void destroy(slot_type* slot) {
2578 PolicyTraits::destroy(&alloc_ref(), slot);
2579 }
2580 inline void transfer(slot_type* to, slot_type* from) {
2581 PolicyTraits::transfer(&alloc_ref(), to, from);
2582 }
2583
2584 inline void destroy_slots() {
2585 const size_t cap = capacity();
2586 const ctrl_t* ctrl = control();
2587 slot_type* slot = slot_array();
2588 for (size_t i = 0; i != cap; ++i) {
2589 if (IsFull(ctrl[i])) {
2590 destroy(slot + i);
2591 }
2592 }
2593 }
2594
2595 inline void dealloc() {
2596 assert(capacity() != 0);
2597 // Unpoison before returning the memory to the allocator.
2598 SanitizerUnpoisonMemoryRegion(slot_array(), sizeof(slot_type) * capacity());
2599 infoz().Unregister();
2600 Deallocate<BackingArrayAlignment(alignof(slot_type))>(
2601 &alloc_ref(), common().backing_array_start(),
2602 common().alloc_size(sizeof(slot_type), alignof(slot_type)));
2603 }
2604
2605 inline void destructor_impl() {
2606 if (capacity() == 0) return;
2607 destroy_slots();
2608 dealloc();
2609 }
2610
2611 // Erases, but does not destroy, the value pointed to by `it`.
2612 //
2613 // This merely updates the pertinent control byte. This can be used in
2614 // conjunction with Policy::transfer to move the object to another place.
2615 void erase_meta_only(const_iterator it) {
2616 EraseMetaOnly(common(), it.control(), sizeof(slot_type));
2617 }
2618
2619 // Allocates a backing array for `self` and initializes its control bytes.
2620 // This reads `capacity` and updates all other fields based on the result of
2621 // the allocation.
2622 //
2623 // This does not free the currently held array; `capacity` must be nonzero.
2624 inline void initialize_slots() {
2625 // People are often sloppy with the exact type of their allocator (sometimes
2626 // it has an extra const or is missing the pair, but rebinds made it work
2627 // anyway).
2628 using CharAlloc =
2629 typename absl::allocator_traits<Alloc>::template rebind_alloc<char>;
2630 InitializeSlots<CharAlloc, sizeof(slot_type), alignof(slot_type)>(
2631 common(), CharAlloc(alloc_ref()));
2632 }
2633
2634 ABSL_ATTRIBUTE_NOINLINE void resize(size_t new_capacity) {
2635 assert(IsValidCapacity(new_capacity));
2636 auto* old_ctrl = control();
2637 auto* old_slots = slot_array();
2638 const bool had_infoz = common().has_infoz();
2639 const size_t old_capacity = common().capacity();
2640 common().set_capacity(new_capacity);
2641 initialize_slots();
2642
2643 auto* new_slots = slot_array();
2644 size_t total_probe_length = 0;
2645 for (size_t i = 0; i != old_capacity; ++i) {
2646 if (IsFull(old_ctrl[i])) {
2647 size_t hash = PolicyTraits::apply(HashElement{hash_ref()},
2648 PolicyTraits::element(old_slots + i));
2649 auto target = find_first_non_full(common(), hash);
2650 size_t new_i = target.offset;
2651 total_probe_length += target.probe_length;
2652 SetCtrl(common(), new_i, H2(hash), sizeof(slot_type));
2653 transfer(new_slots + new_i, old_slots + i);
2654 }
2655 }
2656 if (old_capacity) {
2657 SanitizerUnpoisonMemoryRegion(old_slots,
2658 sizeof(slot_type) * old_capacity);
2659 Deallocate<BackingArrayAlignment(alignof(slot_type))>(
2660 &alloc_ref(), old_ctrl - ControlOffset(had_infoz),
2661 AllocSize(old_capacity, sizeof(slot_type), alignof(slot_type),
2662 had_infoz));
2663 }
2664 infoz().RecordRehash(total_probe_length);
2665 }
2666
2667 // Prunes control bytes to remove as many tombstones as possible.
2668 //
2669 // See the comment on `rehash_and_grow_if_necessary()`.
2670 inline void drop_deletes_without_resize() {
2671 // Stack-allocate space for swapping elements.
2672 alignas(slot_type) unsigned char tmp[sizeof(slot_type)];
2673 DropDeletesWithoutResize(common(), GetPolicyFunctions(), tmp);
2674 }
2675
2676 // Called whenever the table *might* need to conditionally grow.
2677 //
2678 // This function is an optimization opportunity to perform a rehash even when
2679 // growth is unnecessary, because vacating tombstones is beneficial for
2680 // performance in the long-run.
2681 void rehash_and_grow_if_necessary() {
2682 const size_t cap = capacity();
2683 if (cap > Group::kWidth &&
2684 // Do these calculations in 64-bit to avoid overflow.
2685 size() * uint64_t{32} <= cap * uint64_t{25}) {
2686 // Squash DELETED without growing if there is enough capacity.
2687 //
2688 // Rehash in place if the current size is <= 25/32 of capacity.
2689 // Rationale for such a high factor: 1) drop_deletes_without_resize() is
2690 // faster than resize, and 2) it takes quite a bit of work to add
2691 // tombstones. In the worst case, seems to take approximately 4
2692 // insert/erase pairs to create a single tombstone and so if we are
2693 // rehashing because of tombstones, we can afford to rehash-in-place as
2694 // long as we are reclaiming at least 1/8 the capacity without doing more
2695 // than 2X the work. (Where "work" is defined to be size() for rehashing
2696 // or rehashing in place, and 1 for an insert or erase.) But rehashing in
2697 // place is faster per operation than inserting or even doubling the size
2698 // of the table, so we actually afford to reclaim even less space from a
2699 // resize-in-place. The decision is to rehash in place if we can reclaim
2700 // at about 1/8th of the usable capacity (specifically 3/28 of the
2701 // capacity) which means that the total cost of rehashing will be a small
2702 // fraction of the total work.
2703 //
2704 // Here is output of an experiment using the BM_CacheInSteadyState
2705 // benchmark running the old case (where we rehash-in-place only if we can
2706 // reclaim at least 7/16*capacity) vs. this code (which rehashes in place
2707 // if we can recover 3/32*capacity).
2708 //
2709 // Note that although in the worst-case number of rehashes jumped up from
2710 // 15 to 190, but the number of operations per second is almost the same.
2711 //
2712 // Abridged output of running BM_CacheInSteadyState benchmark from
2713 // raw_hash_set_benchmark. N is the number of insert/erase operations.
2714 //
2715 // | OLD (recover >= 7/16 | NEW (recover >= 3/32)
2716 // size | N/s LoadFactor NRehashes | N/s LoadFactor NRehashes
2717 // 448 | 145284 0.44 18 | 140118 0.44 19
2718 // 493 | 152546 0.24 11 | 151417 0.48 28
2719 // 538 | 151439 0.26 11 | 151152 0.53 38
2720 // 583 | 151765 0.28 11 | 150572 0.57 50
2721 // 628 | 150241 0.31 11 | 150853 0.61 66
2722 // 672 | 149602 0.33 12 | 150110 0.66 90
2723 // 717 | 149998 0.35 12 | 149531 0.70 129
2724 // 762 | 149836 0.37 13 | 148559 0.74 190
2725 // 807 | 149736 0.39 14 | 151107 0.39 14
2726 // 852 | 150204 0.42 15 | 151019 0.42 15
2727 drop_deletes_without_resize();
2728 } else {
2729 // Otherwise grow the container.
2730 resize(NextCapacity(cap));
2731 }
2732 }
2733
2734 void maybe_increment_generation_or_rehash_on_move() {
2735 common().maybe_increment_generation_on_move();
2736 if (!empty() && common().should_rehash_for_bug_detection_on_move()) {
2737 resize(capacity());
2738 }
2739 }
2740
2741 template<bool propagate_alloc>
2742 raw_hash_set& assign_impl(raw_hash_set&& that) {
2743 // We don't bother checking for this/that aliasing. We just need to avoid
2744 // breaking the invariants in that case.
2745 destructor_impl();
2746 common() = std::move(that.common());
2747 // TODO(b/296061262): move instead of copying hash/eq/alloc.
2748 hash_ref() = that.hash_ref();
2749 eq_ref() = that.eq_ref();
2750 CopyAlloc(alloc_ref(), that.alloc_ref(),
2751 std::integral_constant<bool, propagate_alloc>());
2752 that.common() = CommonFields{};
2753 maybe_increment_generation_or_rehash_on_move();
2754 return *this;
2755 }
2756
2757 raw_hash_set& move_elements_allocs_unequal(raw_hash_set&& that) {
2758 const size_t size = that.size();
2759 if (size == 0) return *this;
2760 reserve(size);
2761 for (iterator it = that.begin(); it != that.end(); ++it) {
2762 insert(std::move(PolicyTraits::element(it.slot())));
2763 that.destroy(it.slot());
2764 }
2765 that.dealloc();
2766 that.common() = CommonFields{};
2767 maybe_increment_generation_or_rehash_on_move();
2768 return *this;
2769 }
2770
2771 raw_hash_set& move_assign(raw_hash_set&& that,
2772 std::true_type /*propagate_alloc*/) {
2773 return assign_impl<true>(std::move(that));
2774 }
2775 raw_hash_set& move_assign(raw_hash_set&& that,
2776 std::false_type /*propagate_alloc*/) {
2777 if (alloc_ref() == that.alloc_ref()) {
2778 return assign_impl<false>(std::move(that));
2779 }
2780 // Aliasing can't happen here because allocs would compare equal above.
2781 assert(this != &that);
2782 destructor_impl();
2783 // We can't take over that's memory so we need to move each element.
2784 // While moving elements, this should have that's hash/eq so copy hash/eq
2785 // before moving elements.
2786 // TODO(b/296061262): move instead of copying hash/eq.
2787 hash_ref() = that.hash_ref();
2788 eq_ref() = that.eq_ref();
2789 return move_elements_allocs_unequal(std::move(that));
2790 }
2791
2792 protected:
2793 // Attempts to find `key` in the table; if it isn't found, returns a slot that
2794 // the value can be inserted into, with the control byte already set to
2795 // `key`'s H2.
2796 template <class K>
2797 std::pair<size_t, bool> find_or_prepare_insert(const K& key) {
2798 prefetch_heap_block();
2799 auto hash = hash_ref()(key);
2800 auto seq = probe(common(), hash);
2801 const ctrl_t* ctrl = control();
2802 while (true) {
2803 Group g{ctrl + seq.offset()};
2804 for (uint32_t i : g.Match(H2(hash))) {
2805 if (ABSL_PREDICT_TRUE(PolicyTraits::apply(
2806 EqualElement<K>{key, eq_ref()},
2807 PolicyTraits::element(slot_array() + seq.offset(i)))))
2808 return {seq.offset(i), false};
2809 }
2810 if (ABSL_PREDICT_TRUE(g.MaskEmpty())) break;
2811 seq.next();
2812 assert(seq.index() <= capacity() && "full table!");
2813 }
2814 return {prepare_insert(hash), true};
2815 }
2816
2817 // Given the hash of a value not currently in the table, finds the next
2818 // viable slot index to insert it at.
2819 //
2820 // REQUIRES: At least one non-full slot available.
2821 size_t prepare_insert(size_t hash) ABSL_ATTRIBUTE_NOINLINE {
2822 const bool rehash_for_bug_detection =
2823 common().should_rehash_for_bug_detection_on_insert();
2824 if (rehash_for_bug_detection) {
2825 // Move to a different heap allocation in order to detect bugs.
2826 const size_t cap = capacity();
2827 resize(growth_left() > 0 ? cap : NextCapacity(cap));
2828 }
2829 auto target = find_first_non_full(common(), hash);
2830 if (!rehash_for_bug_detection &&
2831 ABSL_PREDICT_FALSE(growth_left() == 0 &&
2832 !IsDeleted(control()[target.offset]))) {
2833 rehash_and_grow_if_necessary();
2834 target = find_first_non_full(common(), hash);
2835 }
2836 common().increment_size();
2837 set_growth_left(growth_left() - IsEmpty(control()[target.offset]));
2838 SetCtrl(common(), target.offset, H2(hash), sizeof(slot_type));
2839 common().maybe_increment_generation_on_insert();
2840 infoz().RecordInsert(hash, target.probe_length);
2841 return target.offset;
2842 }
2843
2844 // Constructs the value in the space pointed by the iterator. This only works
2845 // after an unsuccessful find_or_prepare_insert() and before any other
2846 // modifications happen in the raw_hash_set.
2847 //
2848 // PRECONDITION: i is an index returned from find_or_prepare_insert(k), where
2849 // k is the key decomposed from `forward<Args>(args)...`, and the bool
2850 // returned by find_or_prepare_insert(k) was true.
2851 // POSTCONDITION: *m.iterator_at(i) == value_type(forward<Args>(args)...).
2852 template <class... Args>
2853 void emplace_at(size_t i, Args&&... args) {
2854 construct(slot_array() + i, std::forward<Args>(args)...);
2855
2856 assert(PolicyTraits::apply(FindElement{*this}, *iterator_at(i)) ==
2857 iterator_at(i) &&
2858 "constructed value does not match the lookup key");
2859 }
2860
2861 iterator iterator_at(size_t i) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2862 return {control() + i, slot_array() + i, common().generation_ptr()};
2863 }
2864 const_iterator iterator_at(size_t i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
2865 return {control() + i, slot_array() + i, common().generation_ptr()};
2866 }
2867
2868 private:
2869 friend struct RawHashSetTestOnlyAccess;
2870
2871 // The number of slots we can still fill without needing to rehash.
2872 //
2873 // This is stored separately due to tombstones: we do not include tombstones
2874 // in the growth capacity, because we'd like to rehash when the table is
2875 // otherwise filled with tombstones: otherwise, probe sequences might get
2876 // unacceptably long without triggering a rehash. Callers can also force a
2877 // rehash via the standard `rehash(0)`, which will recompute this value as a
2878 // side-effect.
2879 //
2880 // See `CapacityToGrowth()`.
2881 size_t growth_left() const { return common().growth_left(); }
2882 void set_growth_left(size_t gl) { return common().set_growth_left(gl); }
2883
2884 // Prefetch the heap-allocated memory region to resolve potential TLB and
2885 // cache misses. This is intended to overlap with execution of calculating the
2886 // hash for a key.
2887 void prefetch_heap_block() const {
2888 #if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__)
2889 __builtin_prefetch(control(), 0, 1);
2890 #endif
2891 }
2892
2893 CommonFields& common() { return settings_.template get<0>(); }
2894 const CommonFields& common() const { return settings_.template get<0>(); }
2895
2896 ctrl_t* control() const { return common().control(); }
2897 slot_type* slot_array() const {
2898 return static_cast<slot_type*>(common().slot_array());
2899 }
2900 HashtablezInfoHandle infoz() { return common().infoz(); }
2901
2902 hasher& hash_ref() { return settings_.template get<1>(); }
2903 const hasher& hash_ref() const { return settings_.template get<1>(); }
2904 key_equal& eq_ref() { return settings_.template get<2>(); }
2905 const key_equal& eq_ref() const { return settings_.template get<2>(); }
2906 allocator_type& alloc_ref() { return settings_.template get<3>(); }
2907 const allocator_type& alloc_ref() const {
2908 return settings_.template get<3>();
2909 }
2910
2911 // Make type-specific functions for this type's PolicyFunctions struct.
2912 static size_t hash_slot_fn(void* set, void* slot) {
2913 auto* h = static_cast<raw_hash_set*>(set);
2914 return PolicyTraits::apply(
2915 HashElement{h->hash_ref()},
2916 PolicyTraits::element(static_cast<slot_type*>(slot)));
2917 }
2918 static void transfer_slot_fn(void* set, void* dst, void* src) {
2919 auto* h = static_cast<raw_hash_set*>(set);
2920 h->transfer(static_cast<slot_type*>(dst), static_cast<slot_type*>(src));
2921 }
2922 // Note: dealloc_fn will only be used if we have a non-standard allocator.
2923 static void dealloc_fn(CommonFields& common, const PolicyFunctions&) {
2924 auto* set = reinterpret_cast<raw_hash_set*>(&common);
2925
2926 // Unpoison before returning the memory to the allocator.
2927 SanitizerUnpoisonMemoryRegion(common.slot_array(),
2928 sizeof(slot_type) * common.capacity());
2929
2930 common.infoz().Unregister();
2931 Deallocate<BackingArrayAlignment(alignof(slot_type))>(
2932 &set->alloc_ref(), common.backing_array_start(),
2933 common.alloc_size(sizeof(slot_type), alignof(slot_type)));
2934 }
2935
2936 static const PolicyFunctions& GetPolicyFunctions() {
2937 static constexpr PolicyFunctions value = {
2938 sizeof(slot_type),
2939 &raw_hash_set::hash_slot_fn,
2940 PolicyTraits::transfer_uses_memcpy()
2941 ? TransferRelocatable<sizeof(slot_type)>
2942 : &raw_hash_set::transfer_slot_fn,
2943 (std::is_same<SlotAlloc, std::allocator<slot_type>>::value
2944 ? &DeallocateStandard<alignof(slot_type)>
2945 : &raw_hash_set::dealloc_fn),
2946 };
2947 return value;
2948 }
2949
2950 // Bundle together CommonFields plus other objects which might be empty.
2951 // CompressedTuple will ensure that sizeof is not affected by any of the empty
2952 // fields that occur after CommonFields.
2953 absl::container_internal::CompressedTuple<CommonFields, hasher, key_equal,
2954 allocator_type>
2955 settings_{CommonFields{}, hasher{}, key_equal{}, allocator_type{}};
2956 };
2957
2958 // Erases all elements that satisfy the predicate `pred` from the container `c`.
2959 template <typename P, typename H, typename E, typename A, typename Predicate>
2960 typename raw_hash_set<P, H, E, A>::size_type EraseIf(
2961 Predicate& pred, raw_hash_set<P, H, E, A>* c) {
2962 const auto initial_size = c->size();
2963 for (auto it = c->begin(), last = c->end(); it != last;) {
2964 if (pred(*it)) {
2965 c->erase(it++);
2966 } else {
2967 ++it;
2968 }
2969 }
2970 return initial_size - c->size();
2971 }
2972
2973 namespace hashtable_debug_internal {
2974 template <typename Set>
2975 struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> {
2976 using Traits = typename Set::PolicyTraits;
2977 using Slot = typename Traits::slot_type;
2978
2979 static size_t GetNumProbes(const Set& set,
2980 const typename Set::key_type& key) {
2981 size_t num_probes = 0;
2982 size_t hash = set.hash_ref()(key);
2983 auto seq = probe(set.common(), hash);
2984 const ctrl_t* ctrl = set.control();
2985 while (true) {
2986 container_internal::Group g{ctrl + seq.offset()};
2987 for (uint32_t i : g.Match(container_internal::H2(hash))) {
2988 if (Traits::apply(
2989 typename Set::template EqualElement<typename Set::key_type>{
2990 key, set.eq_ref()},
2991 Traits::element(set.slot_array() + seq.offset(i))))
2992 return num_probes;
2993 ++num_probes;
2994 }
2995 if (g.MaskEmpty()) return num_probes;
2996 seq.next();
2997 ++num_probes;
2998 }
2999 }
3000
3001 static size_t AllocatedByteSize(const Set& c) {
3002 size_t capacity = c.capacity();
3003 if (capacity == 0) return 0;
3004 size_t m = c.common().alloc_size(sizeof(Slot), alignof(Slot));
3005
3006 size_t per_slot = Traits::space_used(static_cast<const Slot*>(nullptr));
3007 if (per_slot != ~size_t{}) {
3008 m += per_slot * c.size();
3009 } else {
3010 for (auto it = c.begin(); it != c.end(); ++it) {
3011 m += Traits::space_used(it.slot());
3012 }
3013 }
3014 return m;
3015 }
3016 };
3017
3018 } // namespace hashtable_debug_internal
3019 } // namespace container_internal
3020 ABSL_NAMESPACE_END
3021 } // namespace absl
3022
3023 #undef ABSL_SWISSTABLE_ENABLE_GENERATIONS
3024
3025 #endif // ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
3026