• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 `RawHashSetLayout::alloc_size` 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 // # Small Object Optimization (SOO)
104 //
105 // When the size/alignment of the value_type and the capacity of the table are
106 // small, we enable small object optimization and store the values inline in
107 // the raw_hash_set object. This optimization allows us to avoid
108 // allocation/deallocation as well as cache/dTLB misses.
109 //
110 // # Hashing
111 //
112 // We compute two separate hashes, `H1` and `H2`, from the hash of an object.
113 // `H1(hash(x))` is an index into `slots`, and essentially the starting point
114 // for the probe sequence. `H2(hash(x))` is a 7-bit value used to filter out
115 // objects that cannot possibly be the one we are looking for.
116 //
117 // # Table operations.
118 //
119 // The key operations are `insert`, `find`, and `erase`.
120 //
121 // Since `insert` and `erase` are implemented in terms of `find`, we describe
122 // `find` first. To `find` a value `x`, we compute `hash(x)`. From
123 // `H1(hash(x))` and the capacity, we construct a `probe_seq` that visits every
124 // group of slots in some interesting order.
125 //
126 // We now walk through these indices. At each index, we select the entire group
127 // starting with that index and extract potential candidates: occupied slots
128 // with a control byte equal to `H2(hash(x))`. If we find an empty slot in the
129 // group, we stop and return an error. Each candidate slot `y` is compared with
130 // `x`; if `x == y`, we are done and return `&y`; otherwise we continue to the
131 // next probe index. Tombstones effectively behave like full slots that never
132 // match the value we're looking for.
133 //
134 // The `H2` bits ensure when we compare a slot to an object with `==`, we are
135 // likely to have actually found the object.  That is, the chance is low that
136 // `==` is called and returns `false`.  Thus, when we search for an object, we
137 // are unlikely to call `==` many times.  This likelyhood can be analyzed as
138 // follows (assuming that H2 is a random enough hash function).
139 //
140 // Let's assume that there are `k` "wrong" objects that must be examined in a
141 // probe sequence.  For example, when doing a `find` on an object that is in the
142 // table, `k` is the number of objects between the start of the probe sequence
143 // and the final found object (not including the final found object).  The
144 // expected number of objects with an H2 match is then `k/128`.  Measurements
145 // and analysis indicate that even at high load factors, `k` is less than 32,
146 // meaning that the number of "false positive" comparisons we must perform is
147 // less than 1/8 per `find`.
148 
149 // `insert` is implemented in terms of `unchecked_insert`, which inserts a
150 // value presumed to not be in the table (violating this requirement will cause
151 // the table to behave erratically). Given `x` and its hash `hash(x)`, to insert
152 // it, we construct a `probe_seq` once again, and use it to find the first
153 // group with an unoccupied (empty *or* deleted) slot. We place `x` into the
154 // first such slot in the group and mark it as full with `x`'s H2.
155 //
156 // To `insert`, we compose `unchecked_insert` with `find`. We compute `h(x)` and
157 // perform a `find` to see if it's already present; if it is, we're done. If
158 // it's not, we may decide the table is getting overcrowded (i.e. the load
159 // factor is greater than 7/8 for big tables; `is_small()` tables use a max load
160 // factor of 1); in this case, we allocate a bigger array, `unchecked_insert`
161 // each element of the table into the new array (we know that no insertion here
162 // will insert an already-present value), and discard the old backing array. At
163 // this point, we may `unchecked_insert` the value `x`.
164 //
165 // Below, `unchecked_insert` is partly implemented by `prepare_insert`, which
166 // presents a viable, initialized slot pointee to the caller.
167 //
168 // `erase` is implemented in terms of `erase_at`, which takes an index to a
169 // slot. Given an offset, we simply create a tombstone and destroy its contents.
170 // If we can prove that the slot would not appear in a probe sequence, we can
171 // make the slot as empty, instead. We can prove this by observing that if a
172 // group has any empty slots, it has never been full (assuming we never create
173 // an empty slot in a group with no empties, which this heuristic guarantees we
174 // never do) and find would stop at this group anyways (since it does not probe
175 // beyond groups with empties).
176 //
177 // `erase` is `erase_at` composed with `find`: if we
178 // have a value `x`, we can perform a `find`, and then `erase_at` the resulting
179 // slot.
180 //
181 // To iterate, we simply traverse the array, skipping empty and deleted slots
182 // and stopping when we hit a `kSentinel`.
183 
184 #ifndef ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
185 #define ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
186 
187 #include <algorithm>
188 #include <cassert>
189 #include <cmath>
190 #include <cstddef>
191 #include <cstdint>
192 #include <cstring>
193 #include <initializer_list>
194 #include <iterator>
195 #include <limits>
196 #include <memory>
197 #include <tuple>
198 #include <type_traits>
199 #include <utility>
200 
201 #include "absl/base/attributes.h"
202 #include "absl/base/config.h"
203 #include "absl/base/internal/endian.h"
204 #include "absl/base/internal/raw_logging.h"
205 #include "absl/base/macros.h"
206 #include "absl/base/optimization.h"
207 #include "absl/base/options.h"
208 #include "absl/base/port.h"
209 #include "absl/base/prefetch.h"
210 #include "absl/container/internal/common.h"  // IWYU pragma: export // for node_handle
211 #include "absl/container/internal/compressed_tuple.h"
212 #include "absl/container/internal/container_memory.h"
213 #include "absl/container/internal/hash_policy_traits.h"
214 #include "absl/container/internal/hashtable_debug_hooks.h"
215 #include "absl/container/internal/hashtablez_sampler.h"
216 #include "absl/memory/memory.h"
217 #include "absl/meta/type_traits.h"
218 #include "absl/numeric/bits.h"
219 #include "absl/utility/utility.h"
220 
221 #ifdef ABSL_INTERNAL_HAVE_SSE2
222 #include <emmintrin.h>
223 #endif
224 
225 #ifdef ABSL_INTERNAL_HAVE_SSSE3
226 #include <tmmintrin.h>
227 #endif
228 
229 #ifdef _MSC_VER
230 #include <intrin.h>
231 #endif
232 
233 #ifdef ABSL_INTERNAL_HAVE_ARM_NEON
234 #include <arm_neon.h>
235 #endif
236 
237 namespace absl {
238 ABSL_NAMESPACE_BEGIN
239 namespace container_internal {
240 
241 #ifdef ABSL_SWISSTABLE_ENABLE_GENERATIONS
242 #error ABSL_SWISSTABLE_ENABLE_GENERATIONS cannot be directly set
243 #elif (defined(ABSL_HAVE_ADDRESS_SANITIZER) ||   \
244        defined(ABSL_HAVE_HWADDRESS_SANITIZER) || \
245        defined(ABSL_HAVE_MEMORY_SANITIZER)) &&   \
246     !defined(NDEBUG_SANITIZER)  // If defined, performance is important.
247 // When compiled in sanitizer mode, we add generation integers to the backing
248 // array and iterators. In the backing array, we store the generation between
249 // the control bytes and the slots. When iterators are dereferenced, we assert
250 // that the container has not been mutated in a way that could cause iterator
251 // invalidation since the iterator was initialized.
252 #define ABSL_SWISSTABLE_ENABLE_GENERATIONS
253 #endif
254 
255 // We use uint8_t so we don't need to worry about padding.
256 using GenerationType = uint8_t;
257 
258 // A sentinel value for empty generations. Using 0 makes it easy to constexpr
259 // initialize an array of this value.
SentinelEmptyGeneration()260 constexpr GenerationType SentinelEmptyGeneration() { return 0; }
261 
NextGeneration(GenerationType generation)262 constexpr GenerationType NextGeneration(GenerationType generation) {
263   return ++generation == SentinelEmptyGeneration() ? ++generation : generation;
264 }
265 
266 #ifdef ABSL_SWISSTABLE_ENABLE_GENERATIONS
SwisstableGenerationsEnabled()267 constexpr bool SwisstableGenerationsEnabled() { return true; }
NumGenerationBytes()268 constexpr size_t NumGenerationBytes() { return sizeof(GenerationType); }
269 #else
SwisstableGenerationsEnabled()270 constexpr bool SwisstableGenerationsEnabled() { return false; }
NumGenerationBytes()271 constexpr size_t NumGenerationBytes() { return 0; }
272 #endif
273 
274 template <typename AllocType>
SwapAlloc(AllocType & lhs,AllocType & rhs,std::true_type)275 void SwapAlloc(AllocType& lhs, AllocType& rhs,
276                std::true_type /* propagate_on_container_swap */) {
277   using std::swap;
278   swap(lhs, rhs);
279 }
280 template <typename AllocType>
SwapAlloc(AllocType & lhs,AllocType & rhs,std::false_type)281 void SwapAlloc(AllocType& lhs, AllocType& rhs,
282                std::false_type /* propagate_on_container_swap */) {
283   (void)lhs;
284   (void)rhs;
285   assert(lhs == rhs &&
286          "It's UB to call swap with unequal non-propagating allocators.");
287 }
288 
289 template <typename AllocType>
CopyAlloc(AllocType & lhs,AllocType & rhs,std::true_type)290 void CopyAlloc(AllocType& lhs, AllocType& rhs,
291                std::true_type /* propagate_alloc */) {
292   lhs = rhs;
293 }
294 template <typename AllocType>
CopyAlloc(AllocType &,AllocType &,std::false_type)295 void CopyAlloc(AllocType&, AllocType&, std::false_type /* propagate_alloc */) {}
296 
297 // The state for a probe sequence.
298 //
299 // Currently, the sequence is a triangular progression of the form
300 //
301 //   p(i) := Width * (i^2 + i)/2 + hash (mod mask + 1)
302 //
303 // The use of `Width` ensures that each probe step does not overlap groups;
304 // the sequence effectively outputs the addresses of *groups* (although not
305 // necessarily aligned to any boundary). The `Group` machinery allows us
306 // to check an entire group with minimal branching.
307 //
308 // Wrapping around at `mask + 1` is important, but not for the obvious reason.
309 // As described above, the first few entries of the control byte array
310 // are mirrored at the end of the array, which `Group` will find and use
311 // for selecting candidates. However, when those candidates' slots are
312 // actually inspected, there are no corresponding slots for the cloned bytes,
313 // so we need to make sure we've treated those offsets as "wrapping around".
314 //
315 // It turns out that this probe sequence visits every group exactly once if the
316 // number of groups is a power of two, since (i^2+i)/2 is a bijection in
317 // Z/(2^m). See https://en.wikipedia.org/wiki/Quadratic_probing
318 template <size_t Width>
319 class probe_seq {
320  public:
321   // Creates a new probe sequence using `hash` as the initial value of the
322   // sequence and `mask` (usually the capacity of the table) as the mask to
323   // apply to each value in the progression.
probe_seq(size_t hash,size_t mask)324   probe_seq(size_t hash, size_t mask) {
325     assert(((mask + 1) & mask) == 0 && "not a mask");
326     mask_ = mask;
327     offset_ = hash & mask_;
328   }
329 
330   // The offset within the table, i.e., the value `p(i)` above.
offset()331   size_t offset() const { return offset_; }
offset(size_t i)332   size_t offset(size_t i) const { return (offset_ + i) & mask_; }
333 
next()334   void next() {
335     index_ += Width;
336     offset_ += index_;
337     offset_ &= mask_;
338   }
339   // 0-based probe index, a multiple of `Width`.
index()340   size_t index() const { return index_; }
341 
342  private:
343   size_t mask_;
344   size_t offset_;
345   size_t index_ = 0;
346 };
347 
348 template <class ContainerKey, class Hash, class Eq>
349 struct RequireUsableKey {
350   template <class PassedKey, class... Args>
351   std::pair<
352       decltype(std::declval<const Hash&>()(std::declval<const PassedKey&>())),
353       decltype(std::declval<const Eq&>()(std::declval<const ContainerKey&>(),
354                                          std::declval<const PassedKey&>()))>*
355   operator()(const PassedKey&, const Args&...) const;
356 };
357 
358 template <class E, class Policy, class Hash, class Eq, class... Ts>
359 struct IsDecomposable : std::false_type {};
360 
361 template <class Policy, class Hash, class Eq, class... Ts>
362 struct IsDecomposable<
363     absl::void_t<decltype(Policy::apply(
364         RequireUsableKey<typename Policy::key_type, Hash, Eq>(),
365         std::declval<Ts>()...))>,
366     Policy, Hash, Eq, Ts...> : std::true_type {};
367 
368 // TODO(alkis): Switch to std::is_nothrow_swappable when gcc/clang supports it.
369 template <class T>
370 constexpr bool IsNoThrowSwappable(std::true_type = {} /* is_swappable */) {
371   using std::swap;
372   return noexcept(swap(std::declval<T&>(), std::declval<T&>()));
373 }
374 template <class T>
375 constexpr bool IsNoThrowSwappable(std::false_type /* is_swappable */) {
376   return false;
377 }
378 
379 template <typename T>
380 uint32_t TrailingZeros(T x) {
381   ABSL_ASSUME(x != 0);
382   return static_cast<uint32_t>(countr_zero(x));
383 }
384 
385 // 8 bytes bitmask with most significant bit set for every byte.
386 constexpr uint64_t kMsbs8Bytes = 0x8080808080808080ULL;
387 
388 // An abstract bitmask, such as that emitted by a SIMD instruction.
389 //
390 // Specifically, this type implements a simple bitset whose representation is
391 // controlled by `SignificantBits` and `Shift`. `SignificantBits` is the number
392 // of abstract bits in the bitset, while `Shift` is the log-base-two of the
393 // width of an abstract bit in the representation.
394 // This mask provides operations for any number of real bits set in an abstract
395 // bit. To add iteration on top of that, implementation must guarantee no more
396 // than the most significant real bit is set in a set abstract bit.
397 template <class T, int SignificantBits, int Shift = 0>
398 class NonIterableBitMask {
399  public:
400   explicit NonIterableBitMask(T mask) : mask_(mask) {}
401 
402   explicit operator bool() const { return this->mask_ != 0; }
403 
404   // Returns the index of the lowest *abstract* bit set in `self`.
405   uint32_t LowestBitSet() const {
406     return container_internal::TrailingZeros(mask_) >> Shift;
407   }
408 
409   // Returns the index of the highest *abstract* bit set in `self`.
410   uint32_t HighestBitSet() const {
411     return static_cast<uint32_t>((bit_width(mask_) - 1) >> Shift);
412   }
413 
414   // Returns the number of trailing zero *abstract* bits.
415   uint32_t TrailingZeros() const {
416     return container_internal::TrailingZeros(mask_) >> Shift;
417   }
418 
419   // Returns the number of leading zero *abstract* bits.
420   uint32_t LeadingZeros() const {
421     constexpr int total_significant_bits = SignificantBits << Shift;
422     constexpr int extra_bits = sizeof(T) * 8 - total_significant_bits;
423     return static_cast<uint32_t>(
424                countl_zero(static_cast<T>(mask_ << extra_bits))) >>
425            Shift;
426   }
427 
428   T mask_;
429 };
430 
431 // Mask that can be iterable
432 //
433 // For example, when `SignificantBits` is 16 and `Shift` is zero, this is just
434 // an ordinary 16-bit bitset occupying the low 16 bits of `mask`. When
435 // `SignificantBits` is 8 and `Shift` is 3, abstract bits are represented as
436 // the bytes `0x00` and `0x80`, and it occupies all 64 bits of the bitmask.
437 // If NullifyBitsOnIteration is true (only allowed for Shift == 3),
438 // non zero abstract bit is allowed to have additional bits
439 // (e.g., `0xff`, `0x83` and `0x9c` are ok, but `0x6f` is not).
440 //
441 // For example:
442 //   for (int i : BitMask<uint32_t, 16>(0b101)) -> yields 0, 2
443 //   for (int i : BitMask<uint64_t, 8, 3>(0x0000000080800000)) -> yields 2, 3
444 template <class T, int SignificantBits, int Shift = 0,
445           bool NullifyBitsOnIteration = false>
446 class BitMask : public NonIterableBitMask<T, SignificantBits, Shift> {
447   using Base = NonIterableBitMask<T, SignificantBits, Shift>;
448   static_assert(std::is_unsigned<T>::value, "");
449   static_assert(Shift == 0 || Shift == 3, "");
450   static_assert(!NullifyBitsOnIteration || Shift == 3, "");
451 
452  public:
453   explicit BitMask(T mask) : Base(mask) {
454     if (Shift == 3 && !NullifyBitsOnIteration) {
455       assert(this->mask_ == (this->mask_ & kMsbs8Bytes));
456     }
457   }
458   // BitMask is an iterator over the indices of its abstract bits.
459   using value_type = int;
460   using iterator = BitMask;
461   using const_iterator = BitMask;
462 
463   BitMask& operator++() {
464     if (Shift == 3 && NullifyBitsOnIteration) {
465       this->mask_ &= kMsbs8Bytes;
466     }
467     this->mask_ &= (this->mask_ - 1);
468     return *this;
469   }
470 
471   uint32_t operator*() const { return Base::LowestBitSet(); }
472 
473   BitMask begin() const { return *this; }
474   BitMask end() const { return BitMask(0); }
475 
476  private:
477   friend bool operator==(const BitMask& a, const BitMask& b) {
478     return a.mask_ == b.mask_;
479   }
480   friend bool operator!=(const BitMask& a, const BitMask& b) {
481     return a.mask_ != b.mask_;
482   }
483 };
484 
485 using h2_t = uint8_t;
486 
487 // The values here are selected for maximum performance. See the static asserts
488 // below for details.
489 
490 // A `ctrl_t` is a single control byte, which can have one of four
491 // states: empty, deleted, full (which has an associated seven-bit h2_t value)
492 // and the sentinel. They have the following bit patterns:
493 //
494 //      empty: 1 0 0 0 0 0 0 0
495 //    deleted: 1 1 1 1 1 1 1 0
496 //       full: 0 h h h h h h h  // h represents the hash bits.
497 //   sentinel: 1 1 1 1 1 1 1 1
498 //
499 // These values are specifically tuned for SSE-flavored SIMD.
500 // The static_asserts below detail the source of these choices.
501 //
502 // We use an enum class so that when strict aliasing is enabled, the compiler
503 // knows ctrl_t doesn't alias other types.
504 enum class ctrl_t : int8_t {
505   kEmpty = -128,   // 0b10000000
506   kDeleted = -2,   // 0b11111110
507   kSentinel = -1,  // 0b11111111
508 };
509 static_assert(
510     (static_cast<int8_t>(ctrl_t::kEmpty) &
511      static_cast<int8_t>(ctrl_t::kDeleted) &
512      static_cast<int8_t>(ctrl_t::kSentinel) & 0x80) != 0,
513     "Special markers need to have the MSB to make checking for them efficient");
514 static_assert(
515     ctrl_t::kEmpty < ctrl_t::kSentinel && ctrl_t::kDeleted < ctrl_t::kSentinel,
516     "ctrl_t::kEmpty and ctrl_t::kDeleted must be smaller than "
517     "ctrl_t::kSentinel to make the SIMD test of IsEmptyOrDeleted() efficient");
518 static_assert(
519     ctrl_t::kSentinel == static_cast<ctrl_t>(-1),
520     "ctrl_t::kSentinel must be -1 to elide loading it from memory into SIMD "
521     "registers (pcmpeqd xmm, xmm)");
522 static_assert(ctrl_t::kEmpty == static_cast<ctrl_t>(-128),
523               "ctrl_t::kEmpty must be -128 to make the SIMD check for its "
524               "existence efficient (psignb xmm, xmm)");
525 static_assert(
526     (~static_cast<int8_t>(ctrl_t::kEmpty) &
527      ~static_cast<int8_t>(ctrl_t::kDeleted) &
528      static_cast<int8_t>(ctrl_t::kSentinel) & 0x7F) != 0,
529     "ctrl_t::kEmpty and ctrl_t::kDeleted must share an unset bit that is not "
530     "shared by ctrl_t::kSentinel to make the scalar test for "
531     "MaskEmptyOrDeleted() efficient");
532 static_assert(ctrl_t::kDeleted == static_cast<ctrl_t>(-2),
533               "ctrl_t::kDeleted must be -2 to make the implementation of "
534               "ConvertSpecialToEmptyAndFullToDeleted efficient");
535 
536 // See definition comment for why this is size 32.
537 ABSL_DLL extern const ctrl_t kEmptyGroup[32];
538 
539 // Returns a pointer to a control byte group that can be used by empty tables.
540 inline ctrl_t* EmptyGroup() {
541   // Const must be cast away here; no uses of this function will actually write
542   // to it because it is only used for empty tables.
543   return const_cast<ctrl_t*>(kEmptyGroup + 16);
544 }
545 
546 // For use in SOO iterators.
547 // TODO(b/289225379): we could potentially get rid of this by adding an is_soo
548 // bit in iterators. This would add branches but reduce cache misses.
549 ABSL_DLL extern const ctrl_t kSooControl[17];
550 
551 // Returns a pointer to a full byte followed by a sentinel byte.
552 inline ctrl_t* SooControl() {
553   // Const must be cast away here; no uses of this function will actually write
554   // to it because it is only used for SOO iterators.
555   return const_cast<ctrl_t*>(kSooControl);
556 }
557 // Whether ctrl is from the SooControl array.
558 inline bool IsSooControl(const ctrl_t* ctrl) { return ctrl == SooControl(); }
559 
560 // Returns a pointer to a generation to use for an empty hashtable.
561 GenerationType* EmptyGeneration();
562 
563 // Returns whether `generation` is a generation for an empty hashtable that
564 // could be returned by EmptyGeneration().
565 inline bool IsEmptyGeneration(const GenerationType* generation) {
566   return *generation == SentinelEmptyGeneration();
567 }
568 
569 // Mixes a randomly generated per-process seed with `hash` and `ctrl` to
570 // randomize insertion order within groups.
571 bool ShouldInsertBackwardsForDebug(size_t capacity, size_t hash,
572                                    const ctrl_t* ctrl);
573 
574 ABSL_ATTRIBUTE_ALWAYS_INLINE inline bool ShouldInsertBackwards(
575     ABSL_ATTRIBUTE_UNUSED size_t capacity, ABSL_ATTRIBUTE_UNUSED size_t hash,
576     ABSL_ATTRIBUTE_UNUSED const ctrl_t* ctrl) {
577 #if defined(NDEBUG)
578   return false;
579 #else
580   return ShouldInsertBackwardsForDebug(capacity, hash, ctrl);
581 #endif
582 }
583 
584 // Returns insert position for the given mask.
585 // We want to add entropy even when ASLR is not enabled.
586 // In debug build we will randomly insert in either the front or back of
587 // the group.
588 // TODO(kfm,sbenza): revisit after we do unconditional mixing
589 template <class Mask>
590 ABSL_ATTRIBUTE_ALWAYS_INLINE inline auto GetInsertionOffset(
591     Mask mask, ABSL_ATTRIBUTE_UNUSED size_t capacity,
592     ABSL_ATTRIBUTE_UNUSED size_t hash,
593     ABSL_ATTRIBUTE_UNUSED const ctrl_t* ctrl) {
594 #if defined(NDEBUG)
595   return mask.LowestBitSet();
596 #else
597   return ShouldInsertBackwardsForDebug(capacity, hash, ctrl)
598              ? mask.HighestBitSet()
599              : mask.LowestBitSet();
600 #endif
601 }
602 
603 // Returns a per-table, hash salt, which changes on resize. This gets mixed into
604 // H1 to randomize iteration order per-table.
605 //
606 // The seed consists of the ctrl_ pointer, which adds enough entropy to ensure
607 // non-determinism of iteration order in most cases.
608 inline size_t PerTableSalt(const ctrl_t* ctrl) {
609   // The low bits of the pointer have little or no entropy because of
610   // alignment. We shift the pointer to try to use higher entropy bits. A
611   // good number seems to be 12 bits, because that aligns with page size.
612   return reinterpret_cast<uintptr_t>(ctrl) >> 12;
613 }
614 // Extracts the H1 portion of a hash: 57 bits mixed with a per-table salt.
615 inline size_t H1(size_t hash, const ctrl_t* ctrl) {
616   return (hash >> 7) ^ PerTableSalt(ctrl);
617 }
618 
619 // Extracts the H2 portion of a hash: the 7 bits not used for H1.
620 //
621 // These are used as an occupied control byte.
622 inline h2_t H2(size_t hash) { return hash & 0x7F; }
623 
624 // Helpers for checking the state of a control byte.
625 inline bool IsEmpty(ctrl_t c) { return c == ctrl_t::kEmpty; }
626 inline bool IsFull(ctrl_t c) {
627   // Cast `c` to the underlying type instead of casting `0` to `ctrl_t` as `0`
628   // is not a value in the enum. Both ways are equivalent, but this way makes
629   // linters happier.
630   return static_cast<std::underlying_type_t<ctrl_t>>(c) >= 0;
631 }
632 inline bool IsDeleted(ctrl_t c) { return c == ctrl_t::kDeleted; }
633 inline bool IsEmptyOrDeleted(ctrl_t c) { return c < ctrl_t::kSentinel; }
634 
635 #ifdef ABSL_INTERNAL_HAVE_SSE2
636 // Quick reference guide for intrinsics used below:
637 //
638 // * __m128i: An XMM (128-bit) word.
639 //
640 // * _mm_setzero_si128: Returns a zero vector.
641 // * _mm_set1_epi8:     Returns a vector with the same i8 in each lane.
642 //
643 // * _mm_subs_epi8:    Saturating-subtracts two i8 vectors.
644 // * _mm_and_si128:    Ands two i128s together.
645 // * _mm_or_si128:     Ors two i128s together.
646 // * _mm_andnot_si128: And-nots two i128s together.
647 //
648 // * _mm_cmpeq_epi8: Component-wise compares two i8 vectors for equality,
649 //                   filling each lane with 0x00 or 0xff.
650 // * _mm_cmpgt_epi8: Same as above, but using > rather than ==.
651 //
652 // * _mm_loadu_si128:  Performs an unaligned load of an i128.
653 // * _mm_storeu_si128: Performs an unaligned store of an i128.
654 //
655 // * _mm_sign_epi8:     Retains, negates, or zeroes each i8 lane of the first
656 //                      argument if the corresponding lane of the second
657 //                      argument is positive, negative, or zero, respectively.
658 // * _mm_movemask_epi8: Selects the sign bit out of each i8 lane and produces a
659 //                      bitmask consisting of those bits.
660 // * _mm_shuffle_epi8:  Selects i8s from the first argument, using the low
661 //                      four bits of each i8 lane in the second argument as
662 //                      indices.
663 
664 // https://github.com/abseil/abseil-cpp/issues/209
665 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87853
666 // _mm_cmpgt_epi8 is broken under GCC with -funsigned-char
667 // Work around this by using the portable implementation of Group
668 // when using -funsigned-char under GCC.
669 inline __m128i _mm_cmpgt_epi8_fixed(__m128i a, __m128i b) {
670 #if defined(__GNUC__) && !defined(__clang__)
671   if (std::is_unsigned<char>::value) {
672     const __m128i mask = _mm_set1_epi8(0x80);
673     const __m128i diff = _mm_subs_epi8(b, a);
674     return _mm_cmpeq_epi8(_mm_and_si128(diff, mask), mask);
675   }
676 #endif
677   return _mm_cmpgt_epi8(a, b);
678 }
679 
680 struct GroupSse2Impl {
681   static constexpr size_t kWidth = 16;  // the number of slots per group
682 
683   explicit GroupSse2Impl(const ctrl_t* pos) {
684     ctrl = _mm_loadu_si128(reinterpret_cast<const __m128i*>(pos));
685   }
686 
687   // Returns a bitmask representing the positions of slots that match hash.
688   BitMask<uint16_t, kWidth> Match(h2_t hash) const {
689     auto match = _mm_set1_epi8(static_cast<char>(hash));
690     BitMask<uint16_t, kWidth> result = BitMask<uint16_t, kWidth>(0);
691     result = BitMask<uint16_t, kWidth>(
692         static_cast<uint16_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl))));
693     return result;
694   }
695 
696   // Returns a bitmask representing the positions of empty slots.
697   NonIterableBitMask<uint16_t, kWidth> MaskEmpty() const {
698 #ifdef ABSL_INTERNAL_HAVE_SSSE3
699     // This only works because ctrl_t::kEmpty is -128.
700     return NonIterableBitMask<uint16_t, kWidth>(
701         static_cast<uint16_t>(_mm_movemask_epi8(_mm_sign_epi8(ctrl, ctrl))));
702 #else
703     auto match = _mm_set1_epi8(static_cast<char>(ctrl_t::kEmpty));
704     return NonIterableBitMask<uint16_t, kWidth>(
705         static_cast<uint16_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl))));
706 #endif
707   }
708 
709   // Returns a bitmask representing the positions of full slots.
710   // Note: for `is_small()` tables group may contain the "same" slot twice:
711   // original and mirrored.
712   BitMask<uint16_t, kWidth> MaskFull() const {
713     return BitMask<uint16_t, kWidth>(
714         static_cast<uint16_t>(_mm_movemask_epi8(ctrl) ^ 0xffff));
715   }
716 
717   // Returns a bitmask representing the positions of non full slots.
718   // Note: this includes: kEmpty, kDeleted, kSentinel.
719   // It is useful in contexts when kSentinel is not present.
720   auto MaskNonFull() const {
721     return BitMask<uint16_t, kWidth>(
722         static_cast<uint16_t>(_mm_movemask_epi8(ctrl)));
723   }
724 
725   // Returns a bitmask representing the positions of empty or deleted slots.
726   NonIterableBitMask<uint16_t, kWidth> MaskEmptyOrDeleted() const {
727     auto special = _mm_set1_epi8(static_cast<char>(ctrl_t::kSentinel));
728     return NonIterableBitMask<uint16_t, kWidth>(static_cast<uint16_t>(
729         _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl))));
730   }
731 
732   // Returns the number of trailing empty or deleted elements in the group.
733   uint32_t CountLeadingEmptyOrDeleted() const {
734     auto special = _mm_set1_epi8(static_cast<char>(ctrl_t::kSentinel));
735     return TrailingZeros(static_cast<uint32_t>(
736         _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)) + 1));
737   }
738 
739   void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
740     auto msbs = _mm_set1_epi8(static_cast<char>(-128));
741     auto x126 = _mm_set1_epi8(126);
742 #ifdef ABSL_INTERNAL_HAVE_SSSE3
743     auto res = _mm_or_si128(_mm_shuffle_epi8(x126, ctrl), msbs);
744 #else
745     auto zero = _mm_setzero_si128();
746     auto special_mask = _mm_cmpgt_epi8_fixed(zero, ctrl);
747     auto res = _mm_or_si128(msbs, _mm_andnot_si128(special_mask, x126));
748 #endif
749     _mm_storeu_si128(reinterpret_cast<__m128i*>(dst), res);
750   }
751 
752   __m128i ctrl;
753 };
754 #endif  // ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
755 
756 #if defined(ABSL_INTERNAL_HAVE_ARM_NEON) && defined(ABSL_IS_LITTLE_ENDIAN)
757 struct GroupAArch64Impl {
758   static constexpr size_t kWidth = 8;
759 
760   explicit GroupAArch64Impl(const ctrl_t* pos) {
761     ctrl = vld1_u8(reinterpret_cast<const uint8_t*>(pos));
762   }
763 
764   auto Match(h2_t hash) const {
765     uint8x8_t dup = vdup_n_u8(hash);
766     auto mask = vceq_u8(ctrl, dup);
767     return BitMask<uint64_t, kWidth, /*Shift=*/3,
768                    /*NullifyBitsOnIteration=*/true>(
769         vget_lane_u64(vreinterpret_u64_u8(mask), 0));
770   }
771 
772   NonIterableBitMask<uint64_t, kWidth, 3> MaskEmpty() const {
773     uint64_t mask =
774         vget_lane_u64(vreinterpret_u64_u8(vceq_s8(
775                           vdup_n_s8(static_cast<int8_t>(ctrl_t::kEmpty)),
776                           vreinterpret_s8_u8(ctrl))),
777                       0);
778     return NonIterableBitMask<uint64_t, kWidth, 3>(mask);
779   }
780 
781   // Returns a bitmask representing the positions of full slots.
782   // Note: for `is_small()` tables group may contain the "same" slot twice:
783   // original and mirrored.
784   auto MaskFull() const {
785     uint64_t mask = vget_lane_u64(
786         vreinterpret_u64_u8(vcge_s8(vreinterpret_s8_u8(ctrl),
787                                     vdup_n_s8(static_cast<int8_t>(0)))),
788         0);
789     return BitMask<uint64_t, kWidth, /*Shift=*/3,
790                    /*NullifyBitsOnIteration=*/true>(mask);
791   }
792 
793   // Returns a bitmask representing the positions of non full slots.
794   // Note: this includes: kEmpty, kDeleted, kSentinel.
795   // It is useful in contexts when kSentinel is not present.
796   auto MaskNonFull() const {
797     uint64_t mask = vget_lane_u64(
798         vreinterpret_u64_u8(vclt_s8(vreinterpret_s8_u8(ctrl),
799                                     vdup_n_s8(static_cast<int8_t>(0)))),
800         0);
801     return BitMask<uint64_t, kWidth, /*Shift=*/3,
802                    /*NullifyBitsOnIteration=*/true>(mask);
803   }
804 
805   NonIterableBitMask<uint64_t, kWidth, 3> MaskEmptyOrDeleted() const {
806     uint64_t mask =
807         vget_lane_u64(vreinterpret_u64_u8(vcgt_s8(
808                           vdup_n_s8(static_cast<int8_t>(ctrl_t::kSentinel)),
809                           vreinterpret_s8_u8(ctrl))),
810                       0);
811     return NonIterableBitMask<uint64_t, kWidth, 3>(mask);
812   }
813 
814   uint32_t CountLeadingEmptyOrDeleted() const {
815     uint64_t mask =
816         vget_lane_u64(vreinterpret_u64_u8(vcle_s8(
817                           vdup_n_s8(static_cast<int8_t>(ctrl_t::kSentinel)),
818                           vreinterpret_s8_u8(ctrl))),
819                       0);
820     // Similar to MaskEmptyorDeleted() but we invert the logic to invert the
821     // produced bitfield. We then count number of trailing zeros.
822     // Clang and GCC optimize countr_zero to rbit+clz without any check for 0,
823     // so we should be fine.
824     return static_cast<uint32_t>(countr_zero(mask)) >> 3;
825   }
826 
827   void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
828     uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(ctrl), 0);
829     constexpr uint64_t slsbs = 0x0202020202020202ULL;
830     constexpr uint64_t midbs = 0x7e7e7e7e7e7e7e7eULL;
831     auto x = slsbs & (mask >> 6);
832     auto res = (x + midbs) | kMsbs8Bytes;
833     little_endian::Store64(dst, res);
834   }
835 
836   uint8x8_t ctrl;
837 };
838 #endif  // ABSL_INTERNAL_HAVE_ARM_NEON && ABSL_IS_LITTLE_ENDIAN
839 
840 struct GroupPortableImpl {
841   static constexpr size_t kWidth = 8;
842 
843   explicit GroupPortableImpl(const ctrl_t* pos)
844       : ctrl(little_endian::Load64(pos)) {}
845 
846   BitMask<uint64_t, kWidth, 3> Match(h2_t hash) const {
847     // For the technique, see:
848     // http://graphics.stanford.edu/~seander/bithacks.html##ValueInWord
849     // (Determine if a word has a byte equal to n).
850     //
851     // Caveat: there are false positives but:
852     // - they only occur if there is a real match
853     // - they never occur on ctrl_t::kEmpty, ctrl_t::kDeleted, ctrl_t::kSentinel
854     // - they will be handled gracefully by subsequent checks in code
855     //
856     // Example:
857     //   v = 0x1716151413121110
858     //   hash = 0x12
859     //   retval = (v - lsbs) & ~v & msbs = 0x0000000080800000
860     constexpr uint64_t lsbs = 0x0101010101010101ULL;
861     auto x = ctrl ^ (lsbs * hash);
862     return BitMask<uint64_t, kWidth, 3>((x - lsbs) & ~x & kMsbs8Bytes);
863   }
864 
865   NonIterableBitMask<uint64_t, kWidth, 3> MaskEmpty() const {
866     return NonIterableBitMask<uint64_t, kWidth, 3>((ctrl & ~(ctrl << 6)) &
867                                                    kMsbs8Bytes);
868   }
869 
870   // Returns a bitmask representing the positions of full slots.
871   // Note: for `is_small()` tables group may contain the "same" slot twice:
872   // original and mirrored.
873   BitMask<uint64_t, kWidth, 3> MaskFull() const {
874     return BitMask<uint64_t, kWidth, 3>((ctrl ^ kMsbs8Bytes) & kMsbs8Bytes);
875   }
876 
877   // Returns a bitmask representing the positions of non full slots.
878   // Note: this includes: kEmpty, kDeleted, kSentinel.
879   // It is useful in contexts when kSentinel is not present.
880   auto MaskNonFull() const {
881     return BitMask<uint64_t, kWidth, 3>(ctrl  & kMsbs8Bytes);
882   }
883 
884   NonIterableBitMask<uint64_t, kWidth, 3> MaskEmptyOrDeleted() const {
885     return NonIterableBitMask<uint64_t, kWidth, 3>((ctrl & ~(ctrl << 7)) &
886                                                    kMsbs8Bytes);
887   }
888 
889   uint32_t CountLeadingEmptyOrDeleted() const {
890     // ctrl | ~(ctrl >> 7) will have the lowest bit set to zero for kEmpty and
891     // kDeleted. We lower all other bits and count number of trailing zeros.
892     constexpr uint64_t bits = 0x0101010101010101ULL;
893     return static_cast<uint32_t>(countr_zero((ctrl | ~(ctrl >> 7)) & bits) >>
894                                  3);
895   }
896 
897   void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
898     constexpr uint64_t lsbs = 0x0101010101010101ULL;
899     auto x = ctrl & kMsbs8Bytes;
900     auto res = (~x + (x >> 7)) & ~lsbs;
901     little_endian::Store64(dst, res);
902   }
903 
904   uint64_t ctrl;
905 };
906 
907 #ifdef ABSL_INTERNAL_HAVE_SSE2
908 using Group = GroupSse2Impl;
909 using GroupFullEmptyOrDeleted = GroupSse2Impl;
910 #elif defined(ABSL_INTERNAL_HAVE_ARM_NEON) && defined(ABSL_IS_LITTLE_ENDIAN)
911 using Group = GroupAArch64Impl;
912 // For Aarch64, we use the portable implementation for counting and masking
913 // full, empty or deleted group elements. This is to avoid the latency of moving
914 // between data GPRs and Neon registers when it does not provide a benefit.
915 // Using Neon is profitable when we call Match(), but is not when we don't,
916 // which is the case when we do *EmptyOrDeleted and MaskFull operations.
917 // It is difficult to make a similar approach beneficial on other architectures
918 // such as x86 since they have much lower GPR <-> vector register transfer
919 // latency and 16-wide Groups.
920 using GroupFullEmptyOrDeleted = GroupPortableImpl;
921 #else
922 using Group = GroupPortableImpl;
923 using GroupFullEmptyOrDeleted = GroupPortableImpl;
924 #endif
925 
926 // When there is an insertion with no reserved growth, we rehash with
927 // probability `min(1, RehashProbabilityConstant() / capacity())`. Using a
928 // constant divided by capacity ensures that inserting N elements is still O(N)
929 // in the average case. Using the constant 16 means that we expect to rehash ~8
930 // times more often than when generations are disabled. We are adding expected
931 // rehash_probability * #insertions/capacity_growth = 16/capacity * ((7/8 -
932 // 7/16) * capacity)/capacity_growth = ~7 extra rehashes per capacity growth.
933 inline size_t RehashProbabilityConstant() { return 16; }
934 
935 class CommonFieldsGenerationInfoEnabled {
936   // A sentinel value for reserved_growth_ indicating that we just ran out of
937   // reserved growth on the last insertion. When reserve is called and then
938   // insertions take place, reserved_growth_'s state machine is N, ..., 1,
939   // kReservedGrowthJustRanOut, 0.
940   static constexpr size_t kReservedGrowthJustRanOut =
941       (std::numeric_limits<size_t>::max)();
942 
943  public:
944   CommonFieldsGenerationInfoEnabled() = default;
945   CommonFieldsGenerationInfoEnabled(CommonFieldsGenerationInfoEnabled&& that)
946       : reserved_growth_(that.reserved_growth_),
947         reservation_size_(that.reservation_size_),
948         generation_(that.generation_) {
949     that.reserved_growth_ = 0;
950     that.reservation_size_ = 0;
951     that.generation_ = EmptyGeneration();
952   }
953   CommonFieldsGenerationInfoEnabled& operator=(
954       CommonFieldsGenerationInfoEnabled&&) = default;
955 
956   // Whether we should rehash on insert in order to detect bugs of using invalid
957   // references. We rehash on the first insertion after reserved_growth_ reaches
958   // 0 after a call to reserve. We also do a rehash with low probability
959   // whenever reserved_growth_ is zero.
960   bool should_rehash_for_bug_detection_on_insert(const ctrl_t* ctrl,
961                                                  size_t capacity) const;
962   // Similar to above, except that we don't depend on reserved_growth_.
963   bool should_rehash_for_bug_detection_on_move(const ctrl_t* ctrl,
964                                                size_t capacity) const;
965   void maybe_increment_generation_on_insert() {
966     if (reserved_growth_ == kReservedGrowthJustRanOut) reserved_growth_ = 0;
967 
968     if (reserved_growth_ > 0) {
969       if (--reserved_growth_ == 0) reserved_growth_ = kReservedGrowthJustRanOut;
970     } else {
971       increment_generation();
972     }
973   }
974   void increment_generation() { *generation_ = NextGeneration(*generation_); }
975   void reset_reserved_growth(size_t reservation, size_t size) {
976     reserved_growth_ = reservation - size;
977   }
978   size_t reserved_growth() const { return reserved_growth_; }
979   void set_reserved_growth(size_t r) { reserved_growth_ = r; }
980   size_t reservation_size() const { return reservation_size_; }
981   void set_reservation_size(size_t r) { reservation_size_ = r; }
982   GenerationType generation() const { return *generation_; }
983   void set_generation(GenerationType g) { *generation_ = g; }
984   GenerationType* generation_ptr() const { return generation_; }
985   void set_generation_ptr(GenerationType* g) { generation_ = g; }
986 
987  private:
988   // The number of insertions remaining that are guaranteed to not rehash due to
989   // a prior call to reserve. Note: we store reserved growth in addition to
990   // reservation size because calls to erase() decrease size_ but don't decrease
991   // reserved growth.
992   size_t reserved_growth_ = 0;
993   // The maximum argument to reserve() since the container was cleared. We need
994   // to keep track of this, in addition to reserved growth, because we reset
995   // reserved growth to this when erase(begin(), end()) is called.
996   size_t reservation_size_ = 0;
997   // Pointer to the generation counter, which is used to validate iterators and
998   // is stored in the backing array between the control bytes and the slots.
999   // Note that we can't store the generation inside the container itself and
1000   // keep a pointer to the container in the iterators because iterators must
1001   // remain valid when the container is moved.
1002   // Note: we could derive this pointer from the control pointer, but it makes
1003   // the code more complicated, and there's a benefit in having the sizes of
1004   // raw_hash_set in sanitizer mode and non-sanitizer mode a bit more different,
1005   // which is that tests are less likely to rely on the size remaining the same.
1006   GenerationType* generation_ = EmptyGeneration();
1007 };
1008 
1009 class CommonFieldsGenerationInfoDisabled {
1010  public:
1011   CommonFieldsGenerationInfoDisabled() = default;
1012   CommonFieldsGenerationInfoDisabled(CommonFieldsGenerationInfoDisabled&&) =
1013       default;
1014   CommonFieldsGenerationInfoDisabled& operator=(
1015       CommonFieldsGenerationInfoDisabled&&) = default;
1016 
1017   bool should_rehash_for_bug_detection_on_insert(const ctrl_t*, size_t) const {
1018     return false;
1019   }
1020   bool should_rehash_for_bug_detection_on_move(const ctrl_t*, size_t) const {
1021     return false;
1022   }
1023   void maybe_increment_generation_on_insert() {}
1024   void increment_generation() {}
1025   void reset_reserved_growth(size_t, size_t) {}
1026   size_t reserved_growth() const { return 0; }
1027   void set_reserved_growth(size_t) {}
1028   size_t reservation_size() const { return 0; }
1029   void set_reservation_size(size_t) {}
1030   GenerationType generation() const { return 0; }
1031   void set_generation(GenerationType) {}
1032   GenerationType* generation_ptr() const { return nullptr; }
1033   void set_generation_ptr(GenerationType*) {}
1034 };
1035 
1036 class HashSetIteratorGenerationInfoEnabled {
1037  public:
1038   HashSetIteratorGenerationInfoEnabled() = default;
1039   explicit HashSetIteratorGenerationInfoEnabled(
1040       const GenerationType* generation_ptr)
1041       : generation_ptr_(generation_ptr), generation_(*generation_ptr) {}
1042 
1043   GenerationType generation() const { return generation_; }
1044   void reset_generation() { generation_ = *generation_ptr_; }
1045   const GenerationType* generation_ptr() const { return generation_ptr_; }
1046   void set_generation_ptr(const GenerationType* ptr) { generation_ptr_ = ptr; }
1047 
1048  private:
1049   const GenerationType* generation_ptr_ = EmptyGeneration();
1050   GenerationType generation_ = *generation_ptr_;
1051 };
1052 
1053 class HashSetIteratorGenerationInfoDisabled {
1054  public:
1055   HashSetIteratorGenerationInfoDisabled() = default;
1056   explicit HashSetIteratorGenerationInfoDisabled(const GenerationType*) {}
1057 
1058   GenerationType generation() const { return 0; }
1059   void reset_generation() {}
1060   const GenerationType* generation_ptr() const { return nullptr; }
1061   void set_generation_ptr(const GenerationType*) {}
1062 };
1063 
1064 #ifdef ABSL_SWISSTABLE_ENABLE_GENERATIONS
1065 using CommonFieldsGenerationInfo = CommonFieldsGenerationInfoEnabled;
1066 using HashSetIteratorGenerationInfo = HashSetIteratorGenerationInfoEnabled;
1067 #else
1068 using CommonFieldsGenerationInfo = CommonFieldsGenerationInfoDisabled;
1069 using HashSetIteratorGenerationInfo = HashSetIteratorGenerationInfoDisabled;
1070 #endif
1071 
1072 // Stored the information regarding number of slots we can still fill
1073 // without needing to rehash.
1074 //
1075 // We want to ensure sufficient number of empty slots in the table in order
1076 // to keep probe sequences relatively short. Empty slot in the probe group
1077 // is required to stop probing.
1078 //
1079 // Tombstones (kDeleted slots) are not included in the growth capacity,
1080 // because we'd like to rehash when the table is filled with tombstones and/or
1081 // full slots.
1082 //
1083 // GrowthInfo also stores a bit that encodes whether table may have any
1084 // deleted slots.
1085 // Most of the tables (>95%) have no deleted slots, so some functions can
1086 // be more efficient with this information.
1087 //
1088 // Callers can also force a rehash via the standard `rehash(0)`,
1089 // which will recompute this value as a side-effect.
1090 //
1091 // See also `CapacityToGrowth()`.
1092 class GrowthInfo {
1093  public:
1094   // Leaves data member uninitialized.
1095   GrowthInfo() = default;
1096 
1097   // Initializes the GrowthInfo assuming we can grow `growth_left` elements
1098   // and there are no kDeleted slots in the table.
1099   void InitGrowthLeftNoDeleted(size_t growth_left) {
1100     growth_left_info_ = growth_left;
1101   }
1102 
1103   // Overwrites single full slot with an empty slot.
1104   void OverwriteFullAsEmpty() { ++growth_left_info_; }
1105 
1106   // Overwrites single empty slot with a full slot.
1107   void OverwriteEmptyAsFull() {
1108     assert(GetGrowthLeft() > 0);
1109     --growth_left_info_;
1110   }
1111 
1112   // Overwrites several empty slots with full slots.
1113   void OverwriteManyEmptyAsFull(size_t cnt) {
1114     assert(GetGrowthLeft() >= cnt);
1115     growth_left_info_ -= cnt;
1116   }
1117 
1118   // Overwrites specified control element with full slot.
1119   void OverwriteControlAsFull(ctrl_t ctrl) {
1120     assert(GetGrowthLeft() >= static_cast<size_t>(IsEmpty(ctrl)));
1121     growth_left_info_ -= static_cast<size_t>(IsEmpty(ctrl));
1122   }
1123 
1124   // Overwrites single full slot with a deleted slot.
1125   void OverwriteFullAsDeleted() { growth_left_info_ |= kDeletedBit; }
1126 
1127   // Returns true if table satisfies two properties:
1128   // 1. Guaranteed to have no kDeleted slots.
1129   // 2. There is a place for at least one element to grow.
1130   bool HasNoDeletedAndGrowthLeft() const {
1131     return static_cast<std::make_signed_t<size_t>>(growth_left_info_) > 0;
1132   }
1133 
1134   // Returns true if the table satisfies two properties:
1135   // 1. Guaranteed to have no kDeleted slots.
1136   // 2. There is no growth left.
1137   bool HasNoGrowthLeftAndNoDeleted() const {
1138     return growth_left_info_ == 0;
1139   }
1140 
1141   // Returns true if table guaranteed to have no k
1142   bool HasNoDeleted() const {
1143     return static_cast<std::make_signed_t<size_t>>(growth_left_info_) >= 0;
1144   }
1145 
1146   // Returns the number of elements left to grow.
1147   size_t GetGrowthLeft() const {
1148     return growth_left_info_ & kGrowthLeftMask;
1149   }
1150 
1151  private:
1152   static constexpr size_t kGrowthLeftMask = ((~size_t{}) >> 1);
1153   static constexpr size_t kDeletedBit = ~kGrowthLeftMask;
1154   // Topmost bit signal whenever there are deleted slots.
1155   size_t growth_left_info_;
1156 };
1157 
1158 static_assert(sizeof(GrowthInfo) == sizeof(size_t), "");
1159 static_assert(alignof(GrowthInfo) == alignof(size_t), "");
1160 
1161 // Returns whether `n` is a valid capacity (i.e., number of slots).
1162 //
1163 // A valid capacity is a non-zero integer `2^m - 1`.
1164 inline bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n > 0; }
1165 
1166 // Returns the number of "cloned control bytes".
1167 //
1168 // This is the number of control bytes that are present both at the beginning
1169 // of the control byte array and at the end, such that we can create a
1170 // `Group::kWidth`-width probe window starting from any control byte.
1171 constexpr size_t NumClonedBytes() { return Group::kWidth - 1; }
1172 
1173 // Returns the number of control bytes including cloned.
1174 constexpr size_t NumControlBytes(size_t capacity) {
1175   return capacity + 1 + NumClonedBytes();
1176 }
1177 
1178 // Computes the offset from the start of the backing allocation of control.
1179 // infoz and growth_info are stored at the beginning of the backing array.
1180 inline static size_t ControlOffset(bool has_infoz) {
1181   return (has_infoz ? sizeof(HashtablezInfoHandle) : 0) + sizeof(GrowthInfo);
1182 }
1183 
1184 // Helper class for computing offsets and allocation size of hash set fields.
1185 class RawHashSetLayout {
1186  public:
1187   explicit RawHashSetLayout(size_t capacity, size_t slot_align, bool has_infoz)
1188       : capacity_(capacity),
1189         control_offset_(ControlOffset(has_infoz)),
1190         generation_offset_(control_offset_ + NumControlBytes(capacity)),
1191         slot_offset_(
1192             (generation_offset_ + NumGenerationBytes() + slot_align - 1) &
1193             (~slot_align + 1)) {
1194     assert(IsValidCapacity(capacity));
1195   }
1196 
1197   // Returns the capacity of a table.
1198   size_t capacity() const { return capacity_; }
1199 
1200   // Returns precomputed offset from the start of the backing allocation of
1201   // control.
1202   size_t control_offset() const { return control_offset_; }
1203 
1204   // Given the capacity of a table, computes the offset (from the start of the
1205   // backing allocation) of the generation counter (if it exists).
1206   size_t generation_offset() const { return generation_offset_; }
1207 
1208   // Given the capacity of a table, computes the offset (from the start of the
1209   // backing allocation) at which the slots begin.
1210   size_t slot_offset() const { return slot_offset_; }
1211 
1212   // Given the capacity of a table, computes the total size of the backing
1213   // array.
1214   size_t alloc_size(size_t slot_size) const {
1215     return slot_offset_ + capacity_ * slot_size;
1216   }
1217 
1218  private:
1219   size_t capacity_;
1220   size_t control_offset_;
1221   size_t generation_offset_;
1222   size_t slot_offset_;
1223 };
1224 
1225 // We only allow a maximum of 1 SOO element, which makes the implementation
1226 // much simpler. Complications with multiple SOO elements include:
1227 // - Satisfying the guarantee that erasing one element doesn't invalidate
1228 //   iterators to other elements means we would probably need actual SOO
1229 //   control bytes.
1230 // - In order to prevent user code from depending on iteration order for small
1231 //   tables, we would need to randomize the iteration order somehow.
1232 constexpr size_t SooCapacity() { return 1; }
1233 // Sentinel type to indicate SOO CommonFields construction.
1234 struct soo_tag_t {};
1235 // Sentinel type to indicate SOO CommonFields construction with full size.
1236 struct full_soo_tag_t {};
1237 
1238 // Suppress erroneous uninitialized memory errors on GCC. For example, GCC
1239 // thinks that the call to slot_array() in find_or_prepare_insert() is reading
1240 // uninitialized memory, but slot_array is only called there when the table is
1241 // non-empty and this memory is initialized when the table is non-empty.
1242 #if !defined(__clang__) && defined(__GNUC__)
1243 #define ABSL_SWISSTABLE_IGNORE_UNINITIALIZED(x)                    \
1244   _Pragma("GCC diagnostic push")                                   \
1245       _Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")  \
1246           _Pragma("GCC diagnostic ignored \"-Wuninitialized\"") x; \
1247   _Pragma("GCC diagnostic pop")
1248 #define ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(x) \
1249   ABSL_SWISSTABLE_IGNORE_UNINITIALIZED(return x)
1250 #else
1251 #define ABSL_SWISSTABLE_IGNORE_UNINITIALIZED(x) x
1252 #define ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(x) return x
1253 #endif
1254 
1255 // This allows us to work around an uninitialized memory warning when
1256 // constructing begin() iterators in empty hashtables.
1257 union MaybeInitializedPtr {
1258   void* get() const { ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(p); }
1259   void set(void* ptr) { p = ptr; }
1260 
1261   void* p;
1262 };
1263 
1264 struct HeapPtrs {
1265   HeapPtrs() = default;
1266   explicit HeapPtrs(ctrl_t* c) : control(c) {}
1267 
1268   // The control bytes (and, also, a pointer near to the base of the backing
1269   // array).
1270   //
1271   // This contains `capacity + 1 + NumClonedBytes()` entries, even
1272   // when the table is empty (hence EmptyGroup).
1273   //
1274   // Note that growth_info is stored immediately before this pointer.
1275   // May be uninitialized for SOO tables.
1276   ctrl_t* control;
1277 
1278   // The beginning of the slots, located at `SlotOffset()` bytes after
1279   // `control`. May be uninitialized for empty tables.
1280   // Note: we can't use `slots` because Qt defines "slots" as a macro.
1281   MaybeInitializedPtr slot_array;
1282 };
1283 
1284 // Manages the backing array pointers or the SOO slot. When raw_hash_set::is_soo
1285 // is true, the SOO slot is stored in `soo_data`. Otherwise, we use `heap`.
1286 union HeapOrSoo {
1287   HeapOrSoo() = default;
1288   explicit HeapOrSoo(ctrl_t* c) : heap(c) {}
1289 
1290   ctrl_t*& control() {
1291     ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(heap.control);
1292   }
1293   ctrl_t* control() const {
1294     ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(heap.control);
1295   }
1296   MaybeInitializedPtr& slot_array() {
1297     ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(heap.slot_array);
1298   }
1299   MaybeInitializedPtr slot_array() const {
1300     ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(heap.slot_array);
1301   }
1302   void* get_soo_data() {
1303     ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(soo_data);
1304   }
1305   const void* get_soo_data() const {
1306     ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN(soo_data);
1307   }
1308 
1309   HeapPtrs heap;
1310   unsigned char soo_data[sizeof(HeapPtrs)];
1311 };
1312 
1313 // CommonFields hold the fields in raw_hash_set that do not depend
1314 // on template parameters. This allows us to conveniently pass all
1315 // of this state to helper functions as a single argument.
1316 class CommonFields : public CommonFieldsGenerationInfo {
1317  public:
1318   CommonFields() : capacity_(0), size_(0), heap_or_soo_(EmptyGroup()) {}
1319   explicit CommonFields(soo_tag_t) : capacity_(SooCapacity()), size_(0) {}
1320   explicit CommonFields(full_soo_tag_t)
1321       : capacity_(SooCapacity()), size_(size_t{1} << HasInfozShift()) {}
1322 
1323   // Not copyable
1324   CommonFields(const CommonFields&) = delete;
1325   CommonFields& operator=(const CommonFields&) = delete;
1326 
1327   // Movable
1328   CommonFields(CommonFields&& that) = default;
1329   CommonFields& operator=(CommonFields&&) = default;
1330 
1331   template <bool kSooEnabled>
1332   static CommonFields CreateDefault() {
1333     return kSooEnabled ? CommonFields{soo_tag_t{}} : CommonFields{};
1334   }
1335 
1336   // The inline data for SOO is written on top of control_/slots_.
1337   const void* soo_data() const { return heap_or_soo_.get_soo_data(); }
1338   void* soo_data() { return heap_or_soo_.get_soo_data(); }
1339 
1340   HeapOrSoo heap_or_soo() const { return heap_or_soo_; }
1341   const HeapOrSoo& heap_or_soo_ref() const { return heap_or_soo_; }
1342 
1343   ctrl_t* control() const { return heap_or_soo_.control(); }
1344   void set_control(ctrl_t* c) { heap_or_soo_.control() = c; }
1345   void* backing_array_start() const {
1346     // growth_info (and maybe infoz) is stored before control bytes.
1347     assert(reinterpret_cast<uintptr_t>(control()) % alignof(size_t) == 0);
1348     return control() - ControlOffset(has_infoz());
1349   }
1350 
1351   // Note: we can't use slots() because Qt defines "slots" as a macro.
1352   void* slot_array() const { return heap_or_soo_.slot_array().get(); }
1353   MaybeInitializedPtr slots_union() const { return heap_or_soo_.slot_array(); }
1354   void set_slots(void* s) { heap_or_soo_.slot_array().set(s); }
1355 
1356   // The number of filled slots.
1357   size_t size() const { return size_ >> HasInfozShift(); }
1358   void set_size(size_t s) {
1359     size_ = (s << HasInfozShift()) | (size_ & HasInfozMask());
1360   }
1361   void set_empty_soo() {
1362     AssertInSooMode();
1363     size_ = 0;
1364   }
1365   void set_full_soo() {
1366     AssertInSooMode();
1367     size_ = size_t{1} << HasInfozShift();
1368   }
1369   void increment_size() {
1370     assert(size() < capacity());
1371     size_ += size_t{1} << HasInfozShift();
1372   }
1373   void decrement_size() {
1374     assert(size() > 0);
1375     size_ -= size_t{1} << HasInfozShift();
1376   }
1377 
1378   // The total number of available slots.
1379   size_t capacity() const { return capacity_; }
1380   void set_capacity(size_t c) {
1381     assert(c == 0 || IsValidCapacity(c));
1382     capacity_ = c;
1383   }
1384 
1385   // The number of slots we can still fill without needing to rehash.
1386   // This is stored in the heap allocation before the control bytes.
1387   // TODO(b/289225379): experiment with moving growth_info back inline to
1388   // increase room for SOO.
1389   size_t growth_left() const { return growth_info().GetGrowthLeft(); }
1390 
1391   GrowthInfo& growth_info() {
1392     auto* gl_ptr = reinterpret_cast<GrowthInfo*>(control()) - 1;
1393     assert(reinterpret_cast<uintptr_t>(gl_ptr) % alignof(GrowthInfo) == 0);
1394     return *gl_ptr;
1395   }
1396   GrowthInfo growth_info() const {
1397     return const_cast<CommonFields*>(this)->growth_info();
1398   }
1399 
1400   bool has_infoz() const {
1401     return ABSL_PREDICT_FALSE((size_ & HasInfozMask()) != 0);
1402   }
1403   void set_has_infoz(bool has_infoz) {
1404     size_ = (size() << HasInfozShift()) | static_cast<size_t>(has_infoz);
1405   }
1406 
1407   HashtablezInfoHandle infoz() {
1408     return has_infoz()
1409                ? *reinterpret_cast<HashtablezInfoHandle*>(backing_array_start())
1410                : HashtablezInfoHandle();
1411   }
1412   void set_infoz(HashtablezInfoHandle infoz) {
1413     assert(has_infoz());
1414     *reinterpret_cast<HashtablezInfoHandle*>(backing_array_start()) = infoz;
1415   }
1416 
1417   bool should_rehash_for_bug_detection_on_insert() const {
1418     return CommonFieldsGenerationInfo::
1419         should_rehash_for_bug_detection_on_insert(control(), capacity());
1420   }
1421   bool should_rehash_for_bug_detection_on_move() const {
1422     return CommonFieldsGenerationInfo::
1423         should_rehash_for_bug_detection_on_move(control(), capacity());
1424   }
1425   void reset_reserved_growth(size_t reservation) {
1426     CommonFieldsGenerationInfo::reset_reserved_growth(reservation, size());
1427   }
1428 
1429   // The size of the backing array allocation.
1430   size_t alloc_size(size_t slot_size, size_t slot_align) const {
1431     return RawHashSetLayout(capacity(), slot_align, has_infoz())
1432         .alloc_size(slot_size);
1433   }
1434 
1435   // Move fields other than heap_or_soo_.
1436   void move_non_heap_or_soo_fields(CommonFields& that) {
1437     static_cast<CommonFieldsGenerationInfo&>(*this) =
1438         std::move(static_cast<CommonFieldsGenerationInfo&>(that));
1439     capacity_ = that.capacity_;
1440     size_ = that.size_;
1441   }
1442 
1443   // Returns the number of control bytes set to kDeleted. For testing only.
1444   size_t TombstonesCount() const {
1445     return static_cast<size_t>(
1446         std::count(control(), control() + capacity(), ctrl_t::kDeleted));
1447   }
1448 
1449  private:
1450   // We store the has_infoz bit in the lowest bit of size_.
1451   static constexpr size_t HasInfozShift() { return 1; }
1452   static constexpr size_t HasInfozMask() {
1453     return (size_t{1} << HasInfozShift()) - 1;
1454   }
1455 
1456   // We can't assert that SOO is enabled because we don't have SooEnabled(), but
1457   // we assert what we can.
1458   void AssertInSooMode() const {
1459     assert(capacity() == SooCapacity());
1460     assert(!has_infoz());
1461   }
1462 
1463   // The number of slots in the backing array. This is always 2^N-1 for an
1464   // integer N. NOTE: we tried experimenting with compressing the capacity and
1465   // storing it together with size_: (a) using 6 bits to store the corresponding
1466   // power (N in 2^N-1), and (b) storing 2^N as the most significant bit of
1467   // size_ and storing size in the low bits. Both of these experiments were
1468   // regressions, presumably because we need capacity to do find operations.
1469   size_t capacity_;
1470 
1471   // The size and also has one bit that stores whether we have infoz.
1472   // TODO(b/289225379): we could put size_ into HeapOrSoo and make capacity_
1473   // encode the size in SOO case. We would be making size()/capacity() more
1474   // expensive in order to have more SOO space.
1475   size_t size_;
1476 
1477   // Either the control/slots pointers or the SOO slot.
1478   HeapOrSoo heap_or_soo_;
1479 };
1480 
1481 template <class Policy, class Hash, class Eq, class Alloc>
1482 class raw_hash_set;
1483 
1484 // Returns the next valid capacity after `n`.
1485 inline size_t NextCapacity(size_t n) {
1486   assert(IsValidCapacity(n) || n == 0);
1487   return n * 2 + 1;
1488 }
1489 
1490 // Applies the following mapping to every byte in the control array:
1491 //   * kDeleted -> kEmpty
1492 //   * kEmpty -> kEmpty
1493 //   * _ -> kDeleted
1494 // PRECONDITION:
1495 //   IsValidCapacity(capacity)
1496 //   ctrl[capacity] == ctrl_t::kSentinel
1497 //   ctrl[i] != ctrl_t::kSentinel for all i < capacity
1498 void ConvertDeletedToEmptyAndFullToDeleted(ctrl_t* ctrl, size_t capacity);
1499 
1500 // Converts `n` into the next valid capacity, per `IsValidCapacity`.
1501 inline size_t NormalizeCapacity(size_t n) {
1502   return n ? ~size_t{} >> countl_zero(n) : 1;
1503 }
1504 
1505 // General notes on capacity/growth methods below:
1506 // - We use 7/8th as maximum load factor. For 16-wide groups, that gives an
1507 //   average of two empty slots per group.
1508 // - For (capacity+1) >= Group::kWidth, growth is 7/8*capacity.
1509 // - For (capacity+1) < Group::kWidth, growth == capacity. In this case, we
1510 //   never need to probe (the whole table fits in one group) so we don't need a
1511 //   load factor less than 1.
1512 
1513 // Given `capacity`, applies the load factor; i.e., it returns the maximum
1514 // number of values we should put into the table before a resizing rehash.
1515 inline size_t CapacityToGrowth(size_t capacity) {
1516   assert(IsValidCapacity(capacity));
1517   // `capacity*7/8`
1518   if (Group::kWidth == 8 && capacity == 7) {
1519     // x-x/8 does not work when x==7.
1520     return 6;
1521   }
1522   return capacity - capacity / 8;
1523 }
1524 
1525 // Given `growth`, "unapplies" the load factor to find how large the capacity
1526 // should be to stay within the load factor.
1527 //
1528 // This might not be a valid capacity and `NormalizeCapacity()` should be
1529 // called on this.
1530 inline size_t GrowthToLowerboundCapacity(size_t growth) {
1531   // `growth*8/7`
1532   if (Group::kWidth == 8 && growth == 7) {
1533     // x+(x-1)/7 does not work when x==7.
1534     return 8;
1535   }
1536   return growth + static_cast<size_t>((static_cast<int64_t>(growth) - 1) / 7);
1537 }
1538 
1539 template <class InputIter>
1540 size_t SelectBucketCountForIterRange(InputIter first, InputIter last,
1541                                      size_t bucket_count) {
1542   if (bucket_count != 0) {
1543     return bucket_count;
1544   }
1545   using InputIterCategory =
1546       typename std::iterator_traits<InputIter>::iterator_category;
1547   if (std::is_base_of<std::random_access_iterator_tag,
1548                       InputIterCategory>::value) {
1549     return GrowthToLowerboundCapacity(
1550         static_cast<size_t>(std::distance(first, last)));
1551   }
1552   return 0;
1553 }
1554 
1555 constexpr bool SwisstableDebugEnabled() {
1556 #if defined(ABSL_SWISSTABLE_ENABLE_GENERATIONS) || \
1557     ABSL_OPTION_HARDENED == 1 || !defined(NDEBUG)
1558   return true;
1559 #else
1560   return false;
1561 #endif
1562 }
1563 
1564 inline void AssertIsFull(const ctrl_t* ctrl, GenerationType generation,
1565                          const GenerationType* generation_ptr,
1566                          const char* operation) {
1567   if (!SwisstableDebugEnabled()) return;
1568   // `SwisstableDebugEnabled()` is also true for release builds with hardening
1569   // enabled. To minimize their impact in those builds:
1570   // - use `ABSL_PREDICT_FALSE()` to provide a compiler hint for code layout
1571   // - use `ABSL_RAW_LOG()` with a format string to reduce code size and improve
1572   //   the chances that the hot paths will be inlined.
1573   if (ABSL_PREDICT_FALSE(ctrl == nullptr)) {
1574     ABSL_RAW_LOG(FATAL, "%s called on end() iterator.", operation);
1575   }
1576   if (ABSL_PREDICT_FALSE(ctrl == EmptyGroup())) {
1577     ABSL_RAW_LOG(FATAL, "%s called on default-constructed iterator.",
1578                  operation);
1579   }
1580   if (SwisstableGenerationsEnabled()) {
1581     if (ABSL_PREDICT_FALSE(generation != *generation_ptr)) {
1582       ABSL_RAW_LOG(FATAL,
1583                    "%s called on invalid iterator. The table could have "
1584                    "rehashed or moved since this iterator was initialized.",
1585                    operation);
1586     }
1587     if (ABSL_PREDICT_FALSE(!IsFull(*ctrl))) {
1588       ABSL_RAW_LOG(
1589           FATAL,
1590           "%s called on invalid iterator. The element was likely erased.",
1591           operation);
1592     }
1593   } else {
1594     if (ABSL_PREDICT_FALSE(!IsFull(*ctrl))) {
1595       ABSL_RAW_LOG(
1596           FATAL,
1597           "%s called on invalid iterator. The element might have been erased "
1598           "or the table might have rehashed. Consider running with "
1599           "--config=asan to diagnose rehashing issues.",
1600           operation);
1601     }
1602   }
1603 }
1604 
1605 // Note that for comparisons, null/end iterators are valid.
1606 inline void AssertIsValidForComparison(const ctrl_t* ctrl,
1607                                        GenerationType generation,
1608                                        const GenerationType* generation_ptr) {
1609   if (!SwisstableDebugEnabled()) return;
1610   const bool ctrl_is_valid_for_comparison =
1611       ctrl == nullptr || ctrl == EmptyGroup() || IsFull(*ctrl);
1612   if (SwisstableGenerationsEnabled()) {
1613     if (ABSL_PREDICT_FALSE(generation != *generation_ptr)) {
1614       ABSL_RAW_LOG(FATAL,
1615                    "Invalid iterator comparison. The table could have rehashed "
1616                    "or moved since this iterator was initialized.");
1617     }
1618     if (ABSL_PREDICT_FALSE(!ctrl_is_valid_for_comparison)) {
1619       ABSL_RAW_LOG(
1620           FATAL, "Invalid iterator comparison. The element was likely erased.");
1621     }
1622   } else {
1623     ABSL_HARDENING_ASSERT(
1624         ctrl_is_valid_for_comparison &&
1625         "Invalid iterator comparison. The element might have been erased or "
1626         "the table might have rehashed. Consider running with --config=asan to "
1627         "diagnose rehashing issues.");
1628   }
1629 }
1630 
1631 // If the two iterators come from the same container, then their pointers will
1632 // interleave such that ctrl_a <= ctrl_b < slot_a <= slot_b or vice/versa.
1633 // Note: we take slots by reference so that it's not UB if they're uninitialized
1634 // as long as we don't read them (when ctrl is null).
1635 inline bool AreItersFromSameContainer(const ctrl_t* ctrl_a,
1636                                       const ctrl_t* ctrl_b,
1637                                       const void* const& slot_a,
1638                                       const void* const& slot_b) {
1639   // If either control byte is null, then we can't tell.
1640   if (ctrl_a == nullptr || ctrl_b == nullptr) return true;
1641   const bool a_is_soo = IsSooControl(ctrl_a);
1642   if (a_is_soo != IsSooControl(ctrl_b)) return false;
1643   if (a_is_soo) return slot_a == slot_b;
1644 
1645   const void* low_slot = slot_a;
1646   const void* hi_slot = slot_b;
1647   if (ctrl_a > ctrl_b) {
1648     std::swap(ctrl_a, ctrl_b);
1649     std::swap(low_slot, hi_slot);
1650   }
1651   return ctrl_b < low_slot && low_slot <= hi_slot;
1652 }
1653 
1654 // Asserts that two iterators come from the same container.
1655 // Note: we take slots by reference so that it's not UB if they're uninitialized
1656 // as long as we don't read them (when ctrl is null).
1657 inline void AssertSameContainer(const ctrl_t* ctrl_a, const ctrl_t* ctrl_b,
1658                                 const void* const& slot_a,
1659                                 const void* const& slot_b,
1660                                 const GenerationType* generation_ptr_a,
1661                                 const GenerationType* generation_ptr_b) {
1662   if (!SwisstableDebugEnabled()) return;
1663   // `SwisstableDebugEnabled()` is also true for release builds with hardening
1664   // enabled. To minimize their impact in those builds:
1665   // - use `ABSL_PREDICT_FALSE()` to provide a compiler hint for code layout
1666   // - use `ABSL_RAW_LOG()` with a format string to reduce code size and improve
1667   //   the chances that the hot paths will be inlined.
1668 
1669   // fail_if(is_invalid, message) crashes when is_invalid is true and provides
1670   // an error message based on `message`.
1671   const auto fail_if = [](bool is_invalid, const char* message) {
1672     if (ABSL_PREDICT_FALSE(is_invalid)) {
1673       ABSL_RAW_LOG(FATAL, "Invalid iterator comparison. %s", message);
1674     }
1675   };
1676 
1677   const bool a_is_default = ctrl_a == EmptyGroup();
1678   const bool b_is_default = ctrl_b == EmptyGroup();
1679   if (a_is_default && b_is_default) return;
1680   fail_if(a_is_default != b_is_default,
1681           "Comparing default-constructed hashtable iterator with a "
1682           "non-default-constructed hashtable iterator.");
1683 
1684   if (SwisstableGenerationsEnabled()) {
1685     if (ABSL_PREDICT_TRUE(generation_ptr_a == generation_ptr_b)) return;
1686     // Users don't need to know whether the tables are SOO so don't mention SOO
1687     // in the debug message.
1688     const bool a_is_soo = IsSooControl(ctrl_a);
1689     const bool b_is_soo = IsSooControl(ctrl_b);
1690     fail_if(a_is_soo != b_is_soo || (a_is_soo && b_is_soo),
1691             "Comparing iterators from different hashtables.");
1692 
1693     const bool a_is_empty = IsEmptyGeneration(generation_ptr_a);
1694     const bool b_is_empty = IsEmptyGeneration(generation_ptr_b);
1695     fail_if(a_is_empty != b_is_empty,
1696             "Comparing an iterator from an empty hashtable with an iterator "
1697             "from a non-empty hashtable.");
1698     fail_if(a_is_empty && b_is_empty,
1699             "Comparing iterators from different empty hashtables.");
1700 
1701     const bool a_is_end = ctrl_a == nullptr;
1702     const bool b_is_end = ctrl_b == nullptr;
1703     fail_if(a_is_end || b_is_end,
1704             "Comparing iterator with an end() iterator from a different "
1705             "hashtable.");
1706     fail_if(true, "Comparing non-end() iterators from different hashtables.");
1707   } else {
1708     ABSL_HARDENING_ASSERT(
1709         AreItersFromSameContainer(ctrl_a, ctrl_b, slot_a, slot_b) &&
1710         "Invalid iterator comparison. The iterators may be from different "
1711         "containers or the container might have rehashed or moved. Consider "
1712         "running with --config=asan to diagnose issues.");
1713   }
1714 }
1715 
1716 struct FindInfo {
1717   size_t offset;
1718   size_t probe_length;
1719 };
1720 
1721 // Whether a table is "small". A small table fits entirely into a probing
1722 // group, i.e., has a capacity < `Group::kWidth`.
1723 //
1724 // In small mode we are able to use the whole capacity. The extra control
1725 // bytes give us at least one "empty" control byte to stop the iteration.
1726 // This is important to make 1 a valid capacity.
1727 //
1728 // In small mode only the first `capacity` control bytes after the sentinel
1729 // are valid. The rest contain dummy ctrl_t::kEmpty values that do not
1730 // represent a real slot. This is important to take into account on
1731 // `find_first_non_full()`, where we never try
1732 // `ShouldInsertBackwards()` for small tables.
1733 inline bool is_small(size_t capacity) { return capacity < Group::kWidth - 1; }
1734 
1735 // Whether a table fits entirely into a probing group.
1736 // Arbitrary order of elements in such tables is correct.
1737 inline bool is_single_group(size_t capacity) {
1738   return capacity <= Group::kWidth;
1739 }
1740 
1741 // Begins a probing operation on `common.control`, using `hash`.
1742 inline probe_seq<Group::kWidth> probe(const ctrl_t* ctrl, const size_t capacity,
1743                                       size_t hash) {
1744   return probe_seq<Group::kWidth>(H1(hash, ctrl), capacity);
1745 }
1746 inline probe_seq<Group::kWidth> probe(const CommonFields& common, size_t hash) {
1747   return probe(common.control(), common.capacity(), hash);
1748 }
1749 
1750 // Probes an array of control bits using a probe sequence derived from `hash`,
1751 // and returns the offset corresponding to the first deleted or empty slot.
1752 //
1753 // Behavior when the entire table is full is undefined.
1754 //
1755 // NOTE: this function must work with tables having both empty and deleted
1756 // slots in the same group. Such tables appear during `erase()`.
1757 template <typename = void>
1758 inline FindInfo find_first_non_full(const CommonFields& common, size_t hash) {
1759   auto seq = probe(common, hash);
1760   const ctrl_t* ctrl = common.control();
1761   if (IsEmptyOrDeleted(ctrl[seq.offset()]) &&
1762       !ShouldInsertBackwards(common.capacity(), hash, ctrl)) {
1763     return {seq.offset(), /*probe_length=*/0};
1764   }
1765   while (true) {
1766     GroupFullEmptyOrDeleted g{ctrl + seq.offset()};
1767     auto mask = g.MaskEmptyOrDeleted();
1768     if (mask) {
1769       return {
1770           seq.offset(GetInsertionOffset(mask, common.capacity(), hash, ctrl)),
1771           seq.index()};
1772     }
1773     seq.next();
1774     assert(seq.index() <= common.capacity() && "full table!");
1775   }
1776 }
1777 
1778 // Extern template for inline function keep possibility of inlining.
1779 // When compiler decided to not inline, no symbols will be added to the
1780 // corresponding translation unit.
1781 extern template FindInfo find_first_non_full(const CommonFields&, size_t);
1782 
1783 // Non-inlined version of find_first_non_full for use in less
1784 // performance critical routines.
1785 FindInfo find_first_non_full_outofline(const CommonFields&, size_t);
1786 
1787 inline void ResetGrowthLeft(CommonFields& common) {
1788   common.growth_info().InitGrowthLeftNoDeleted(
1789       CapacityToGrowth(common.capacity()) - common.size());
1790 }
1791 
1792 // Sets `ctrl` to `{kEmpty, kSentinel, ..., kEmpty}`, marking the entire
1793 // array as marked as empty.
1794 inline void ResetCtrl(CommonFields& common, size_t slot_size) {
1795   const size_t capacity = common.capacity();
1796   ctrl_t* ctrl = common.control();
1797   std::memset(ctrl, static_cast<int8_t>(ctrl_t::kEmpty),
1798               capacity + 1 + NumClonedBytes());
1799   ctrl[capacity] = ctrl_t::kSentinel;
1800   SanitizerPoisonMemoryRegion(common.slot_array(), slot_size * capacity);
1801 }
1802 
1803 // Sets sanitizer poisoning for slot corresponding to control byte being set.
1804 inline void DoSanitizeOnSetCtrl(const CommonFields& c, size_t i, ctrl_t h,
1805                                 size_t slot_size) {
1806   assert(i < c.capacity());
1807   auto* slot_i = static_cast<const char*>(c.slot_array()) + i * slot_size;
1808   if (IsFull(h)) {
1809     SanitizerUnpoisonMemoryRegion(slot_i, slot_size);
1810   } else {
1811     SanitizerPoisonMemoryRegion(slot_i, slot_size);
1812   }
1813 }
1814 
1815 // Sets `ctrl[i]` to `h`.
1816 //
1817 // Unlike setting it directly, this function will perform bounds checks and
1818 // mirror the value to the cloned tail if necessary.
1819 inline void SetCtrl(const CommonFields& c, size_t i, ctrl_t h,
1820                     size_t slot_size) {
1821   DoSanitizeOnSetCtrl(c, i, h, slot_size);
1822   ctrl_t* ctrl = c.control();
1823   ctrl[i] = h;
1824   ctrl[((i - NumClonedBytes()) & c.capacity()) +
1825        (NumClonedBytes() & c.capacity())] = h;
1826 }
1827 // Overload for setting to an occupied `h2_t` rather than a special `ctrl_t`.
1828 inline void SetCtrl(const CommonFields& c, size_t i, h2_t h, size_t slot_size) {
1829   SetCtrl(c, i, static_cast<ctrl_t>(h), slot_size);
1830 }
1831 
1832 // Like SetCtrl, but in a single group table, we can save some operations when
1833 // setting the cloned control byte.
1834 inline void SetCtrlInSingleGroupTable(const CommonFields& c, size_t i, ctrl_t h,
1835                                       size_t slot_size) {
1836   assert(is_single_group(c.capacity()));
1837   DoSanitizeOnSetCtrl(c, i, h, slot_size);
1838   ctrl_t* ctrl = c.control();
1839   ctrl[i] = h;
1840   ctrl[i + c.capacity() + 1] = h;
1841 }
1842 // Overload for setting to an occupied `h2_t` rather than a special `ctrl_t`.
1843 inline void SetCtrlInSingleGroupTable(const CommonFields& c, size_t i, h2_t h,
1844                                       size_t slot_size) {
1845   SetCtrlInSingleGroupTable(c, i, static_cast<ctrl_t>(h), slot_size);
1846 }
1847 
1848 // growth_info (which is a size_t) is stored with the backing array.
1849 constexpr size_t BackingArrayAlignment(size_t align_of_slot) {
1850   return (std::max)(align_of_slot, alignof(GrowthInfo));
1851 }
1852 
1853 // Returns the address of the ith slot in slots where each slot occupies
1854 // slot_size.
1855 inline void* SlotAddress(void* slot_array, size_t slot, size_t slot_size) {
1856   return reinterpret_cast<void*>(reinterpret_cast<char*>(slot_array) +
1857                                  (slot * slot_size));
1858 }
1859 
1860 // Iterates over all full slots and calls `cb(const ctrl_t*, SlotType*)`.
1861 // NOTE: no erasure from this table allowed during Callback call.
1862 template <class SlotType, class Callback>
1863 ABSL_ATTRIBUTE_ALWAYS_INLINE inline void IterateOverFullSlots(
1864     const CommonFields& c, SlotType* slot, Callback cb) {
1865   const size_t cap = c.capacity();
1866   const ctrl_t* ctrl = c.control();
1867   if (is_small(cap)) {
1868     // Mirrored/cloned control bytes in small table are also located in the
1869     // first group (starting from position 0). We are taking group from position
1870     // `capacity` in order to avoid duplicates.
1871 
1872     // Small tables capacity fits into portable group, where
1873     // GroupPortableImpl::MaskFull is more efficient for the
1874     // capacity <= GroupPortableImpl::kWidth.
1875     assert(cap <= GroupPortableImpl::kWidth &&
1876            "unexpectedly large small capacity");
1877     static_assert(Group::kWidth >= GroupPortableImpl::kWidth,
1878                   "unexpected group width");
1879     // Group starts from kSentinel slot, so indices in the mask will
1880     // be increased by 1.
1881     const auto mask = GroupPortableImpl(ctrl + cap).MaskFull();
1882     --ctrl;
1883     --slot;
1884     for (uint32_t i : mask) {
1885       cb(ctrl + i, slot + i);
1886     }
1887     return;
1888   }
1889   size_t remaining = c.size();
1890   while (remaining != 0) {
1891     for (uint32_t i : GroupFullEmptyOrDeleted(ctrl).MaskFull()) {
1892       cb(ctrl + i, slot + i);
1893       --remaining;
1894     }
1895     slot += Group::kWidth;
1896     ctrl += Group::kWidth;
1897   }
1898 }
1899 
1900 template <typename CharAlloc>
1901 constexpr bool ShouldSampleHashtablezInfo() {
1902   // Folks with custom allocators often make unwarranted assumptions about the
1903   // behavior of their classes vis-a-vis trivial destructability and what
1904   // calls they will or won't make.  Avoid sampling for people with custom
1905   // allocators to get us out of this mess.  This is not a hard guarantee but
1906   // a workaround while we plan the exact guarantee we want to provide.
1907   return std::is_same<CharAlloc, std::allocator<char>>::value;
1908 }
1909 
1910 template <bool kSooEnabled>
1911 HashtablezInfoHandle SampleHashtablezInfo(size_t sizeof_slot, size_t sizeof_key,
1912                                           size_t sizeof_value,
1913                                           size_t old_capacity, bool was_soo,
1914                                           HashtablezInfoHandle forced_infoz,
1915                                           CommonFields& c) {
1916   if (forced_infoz.IsSampled()) return forced_infoz;
1917   // In SOO, we sample on the first insertion so if this is an empty SOO case
1918   // (e.g. when reserve is called), then we still need to sample.
1919   if (kSooEnabled && was_soo && c.size() == 0) {
1920     return Sample(sizeof_slot, sizeof_key, sizeof_value, SooCapacity());
1921   }
1922   // For non-SOO cases, we sample whenever the capacity is increasing from zero
1923   // to non-zero.
1924   if (!kSooEnabled && old_capacity == 0) {
1925     return Sample(sizeof_slot, sizeof_key, sizeof_value, 0);
1926   }
1927   return c.infoz();
1928 }
1929 
1930 // Helper class to perform resize of the hash set.
1931 //
1932 // It contains special optimizations for small group resizes.
1933 // See GrowIntoSingleGroupShuffleControlBytes for details.
1934 class HashSetResizeHelper {
1935  public:
1936   explicit HashSetResizeHelper(CommonFields& c, bool was_soo, bool had_soo_slot,
1937                                HashtablezInfoHandle forced_infoz)
1938       : old_capacity_(c.capacity()),
1939         had_infoz_(c.has_infoz()),
1940         was_soo_(was_soo),
1941         had_soo_slot_(had_soo_slot),
1942         forced_infoz_(forced_infoz) {}
1943 
1944   // Optimized for small groups version of `find_first_non_full`.
1945   // Beneficial only right after calling `raw_hash_set::resize`.
1946   // It is safe to call in case capacity is big or was not changed, but there
1947   // will be no performance benefit.
1948   // It has implicit assumption that `resize` will call
1949   // `GrowSizeIntoSingleGroup*` in case `IsGrowingIntoSingleGroupApplicable`.
1950   // Falls back to `find_first_non_full` in case of big groups.
1951   static FindInfo FindFirstNonFullAfterResize(const CommonFields& c,
1952                                               size_t old_capacity,
1953                                               size_t hash) {
1954     if (!IsGrowingIntoSingleGroupApplicable(old_capacity, c.capacity())) {
1955       return find_first_non_full(c, hash);
1956     }
1957     // Find a location for the new element non-deterministically.
1958     // Note that any position is correct.
1959     // It will located at `half_old_capacity` or one of the other
1960     // empty slots with approximately 50% probability each.
1961     size_t offset = probe(c, hash).offset();
1962 
1963     // Note that we intentionally use unsigned int underflow.
1964     if (offset - (old_capacity + 1) >= old_capacity) {
1965       // Offset fall on kSentinel or into the mostly occupied first half.
1966       offset = old_capacity / 2;
1967     }
1968     assert(IsEmpty(c.control()[offset]));
1969     return FindInfo{offset, 0};
1970   }
1971 
1972   HeapOrSoo& old_heap_or_soo() { return old_heap_or_soo_; }
1973   void* old_soo_data() { return old_heap_or_soo_.get_soo_data(); }
1974   ctrl_t* old_ctrl() const {
1975     assert(!was_soo_);
1976     return old_heap_or_soo_.control();
1977   }
1978   void* old_slots() const {
1979     assert(!was_soo_);
1980     return old_heap_or_soo_.slot_array().get();
1981   }
1982   size_t old_capacity() const { return old_capacity_; }
1983 
1984   // Returns the index of the SOO slot when growing from SOO to non-SOO in a
1985   // single group. See also InitControlBytesAfterSoo(). It's important to use
1986   // index 1 so that when resizing from capacity 1 to 3, we can still have
1987   // random iteration order between the first two inserted elements.
1988   // I.e. it allows inserting the second element at either index 0 or 2.
1989   static size_t SooSlotIndex() { return 1; }
1990 
1991   // Allocates a backing array for the hashtable.
1992   // Reads `capacity` and updates all other fields based on the result of
1993   // the allocation.
1994   //
1995   // It also may do the following actions:
1996   // 1. initialize control bytes
1997   // 2. initialize slots
1998   // 3. deallocate old slots.
1999   //
2000   // We are bundling a lot of functionality
2001   // in one ABSL_ATTRIBUTE_NOINLINE function in order to minimize binary code
2002   // duplication in raw_hash_set<>::resize.
2003   //
2004   // `c.capacity()` must be nonzero.
2005   // POSTCONDITIONS:
2006   //  1. CommonFields is initialized.
2007   //
2008   //  if IsGrowingIntoSingleGroupApplicable && TransferUsesMemcpy
2009   //    Both control bytes and slots are fully initialized.
2010   //    old_slots are deallocated.
2011   //    infoz.RecordRehash is called.
2012   //
2013   //  if IsGrowingIntoSingleGroupApplicable && !TransferUsesMemcpy
2014   //    Control bytes are fully initialized.
2015   //    infoz.RecordRehash is called.
2016   //    GrowSizeIntoSingleGroup must be called to finish slots initialization.
2017   //
2018   //  if !IsGrowingIntoSingleGroupApplicable
2019   //    Control bytes are initialized to empty table via ResetCtrl.
2020   //    raw_hash_set<>::resize must insert elements regularly.
2021   //    infoz.RecordRehash is called if old_capacity == 0.
2022   //
2023   //  Returns IsGrowingIntoSingleGroupApplicable result to avoid recomputation.
2024   template <typename Alloc, size_t SizeOfSlot, bool TransferUsesMemcpy,
2025             bool SooEnabled, size_t AlignOfSlot>
2026   ABSL_ATTRIBUTE_NOINLINE bool InitializeSlots(CommonFields& c, Alloc alloc,
2027                                                ctrl_t soo_slot_h2,
2028                                                size_t key_size,
2029                                                size_t value_size) {
2030     assert(c.capacity());
2031     HashtablezInfoHandle infoz =
2032         ShouldSampleHashtablezInfo<Alloc>()
2033             ? SampleHashtablezInfo<SooEnabled>(SizeOfSlot, key_size, value_size,
2034                                                old_capacity_, was_soo_,
2035                                                forced_infoz_, c)
2036             : HashtablezInfoHandle{};
2037 
2038     const bool has_infoz = infoz.IsSampled();
2039     RawHashSetLayout layout(c.capacity(), AlignOfSlot, has_infoz);
2040     char* mem = static_cast<char*>(Allocate<BackingArrayAlignment(AlignOfSlot)>(
2041         &alloc, layout.alloc_size(SizeOfSlot)));
2042     const GenerationType old_generation = c.generation();
2043     c.set_generation_ptr(
2044         reinterpret_cast<GenerationType*>(mem + layout.generation_offset()));
2045     c.set_generation(NextGeneration(old_generation));
2046     c.set_control(reinterpret_cast<ctrl_t*>(mem + layout.control_offset()));
2047     c.set_slots(mem + layout.slot_offset());
2048     ResetGrowthLeft(c);
2049 
2050     const bool grow_single_group =
2051         IsGrowingIntoSingleGroupApplicable(old_capacity_, layout.capacity());
2052     if (SooEnabled && was_soo_ && grow_single_group) {
2053       InitControlBytesAfterSoo(c.control(), soo_slot_h2, layout.capacity());
2054       if (TransferUsesMemcpy && had_soo_slot_) {
2055         TransferSlotAfterSoo(c, SizeOfSlot);
2056       }
2057       // SooEnabled implies that old_capacity_ != 0.
2058     } else if ((SooEnabled || old_capacity_ != 0) && grow_single_group) {
2059       if (TransferUsesMemcpy) {
2060         GrowSizeIntoSingleGroupTransferable(c, SizeOfSlot);
2061         DeallocateOld<AlignOfSlot>(alloc, SizeOfSlot);
2062       } else {
2063         GrowIntoSingleGroupShuffleControlBytes(c.control(), layout.capacity());
2064       }
2065     } else {
2066       ResetCtrl(c, SizeOfSlot);
2067     }
2068 
2069     c.set_has_infoz(has_infoz);
2070     if (has_infoz) {
2071       infoz.RecordStorageChanged(c.size(), layout.capacity());
2072       if ((SooEnabled && was_soo_) || grow_single_group || old_capacity_ == 0) {
2073         infoz.RecordRehash(0);
2074       }
2075       c.set_infoz(infoz);
2076     }
2077     return grow_single_group;
2078   }
2079 
2080   // Relocates slots into new single group consistent with
2081   // GrowIntoSingleGroupShuffleControlBytes.
2082   //
2083   // PRECONDITIONS:
2084   // 1. GrowIntoSingleGroupShuffleControlBytes was already called.
2085   template <class PolicyTraits, class Alloc>
2086   void GrowSizeIntoSingleGroup(CommonFields& c, Alloc& alloc_ref) {
2087     assert(old_capacity_ < Group::kWidth / 2);
2088     assert(IsGrowingIntoSingleGroupApplicable(old_capacity_, c.capacity()));
2089     using slot_type = typename PolicyTraits::slot_type;
2090     assert(is_single_group(c.capacity()));
2091 
2092     auto* new_slots = reinterpret_cast<slot_type*>(c.slot_array());
2093     auto* old_slots_ptr = reinterpret_cast<slot_type*>(old_slots());
2094 
2095     size_t shuffle_bit = old_capacity_ / 2 + 1;
2096     for (size_t i = 0; i < old_capacity_; ++i) {
2097       if (IsFull(old_ctrl()[i])) {
2098         size_t new_i = i ^ shuffle_bit;
2099         SanitizerUnpoisonMemoryRegion(new_slots + new_i, sizeof(slot_type));
2100         PolicyTraits::transfer(&alloc_ref, new_slots + new_i,
2101                                old_slots_ptr + i);
2102       }
2103     }
2104     PoisonSingleGroupEmptySlots(c, sizeof(slot_type));
2105   }
2106 
2107   // Deallocates old backing array.
2108   template <size_t AlignOfSlot, class CharAlloc>
2109   void DeallocateOld(CharAlloc alloc_ref, size_t slot_size) {
2110     SanitizerUnpoisonMemoryRegion(old_slots(), slot_size * old_capacity_);
2111     auto layout = RawHashSetLayout(old_capacity_, AlignOfSlot, had_infoz_);
2112     Deallocate<BackingArrayAlignment(AlignOfSlot)>(
2113         &alloc_ref, old_ctrl() - layout.control_offset(),
2114         layout.alloc_size(slot_size));
2115   }
2116 
2117  private:
2118   // Returns true if `GrowSizeIntoSingleGroup` can be used for resizing.
2119   static bool IsGrowingIntoSingleGroupApplicable(size_t old_capacity,
2120                                                  size_t new_capacity) {
2121     // NOTE that `old_capacity < new_capacity` in order to have
2122     // `old_capacity < Group::kWidth / 2` to make faster copies of 8 bytes.
2123     return is_single_group(new_capacity) && old_capacity < new_capacity;
2124   }
2125 
2126   // Relocates control bytes and slots into new single group for
2127   // transferable objects.
2128   // Must be called only if IsGrowingIntoSingleGroupApplicable returned true.
2129   void GrowSizeIntoSingleGroupTransferable(CommonFields& c, size_t slot_size);
2130 
2131   // If there was an SOO slot and slots are transferable, transfers the SOO slot
2132   // into the new heap allocation. Must be called only if
2133   // IsGrowingIntoSingleGroupApplicable returned true.
2134   void TransferSlotAfterSoo(CommonFields& c, size_t slot_size);
2135 
2136   // Shuffle control bits deterministically to the next capacity.
2137   // Returns offset for newly added element with given hash.
2138   //
2139   // PRECONDITIONs:
2140   // 1. new_ctrl is allocated for new_capacity,
2141   //    but not initialized.
2142   // 2. new_capacity is a single group.
2143   //
2144   // All elements are transferred into the first `old_capacity + 1` positions
2145   // of the new_ctrl. Elements are rotated by `old_capacity_ / 2 + 1` positions
2146   // in order to change an order and keep it non deterministic.
2147   // Although rotation itself deterministic, position of the new added element
2148   // will be based on `H1` and is not deterministic.
2149   //
2150   // Examples:
2151   // S = kSentinel, E = kEmpty
2152   //
2153   // old_ctrl = SEEEEEEEE...
2154   // new_ctrl = ESEEEEEEE...
2155   //
2156   // old_ctrl = 0SEEEEEEE...
2157   // new_ctrl = E0ESE0EEE...
2158   //
2159   // old_ctrl = 012S012EEEEEEEEE...
2160   // new_ctrl = 2E01EEES2E01EEE...
2161   //
2162   // old_ctrl = 0123456S0123456EEEEEEEEEEE...
2163   // new_ctrl = 456E0123EEEEEES456E0123EEE...
2164   void GrowIntoSingleGroupShuffleControlBytes(ctrl_t* new_ctrl,
2165                                               size_t new_capacity) const;
2166 
2167   // If the table was SOO, initializes new control bytes. `h2` is the control
2168   // byte corresponding to the full slot. Must be called only if
2169   // IsGrowingIntoSingleGroupApplicable returned true.
2170   // Requires: `had_soo_slot_ || h2 == ctrl_t::kEmpty`.
2171   void InitControlBytesAfterSoo(ctrl_t* new_ctrl, ctrl_t h2,
2172                                 size_t new_capacity);
2173 
2174   // Shuffle trivially transferable slots in the way consistent with
2175   // GrowIntoSingleGroupShuffleControlBytes.
2176   //
2177   // PRECONDITIONs:
2178   // 1. old_capacity must be non-zero.
2179   // 2. new_ctrl is fully initialized using
2180   //    GrowIntoSingleGroupShuffleControlBytes.
2181   // 3. new_slots is allocated and *not* poisoned.
2182   //
2183   // POSTCONDITIONS:
2184   // 1. new_slots are transferred from old_slots_ consistent with
2185   //    GrowIntoSingleGroupShuffleControlBytes.
2186   // 2. Empty new_slots are *not* poisoned.
2187   void GrowIntoSingleGroupShuffleTransferableSlots(void* new_slots,
2188                                                    size_t slot_size) const;
2189 
2190   // Poison empty slots that were transferred using the deterministic algorithm
2191   // described above.
2192   // PRECONDITIONs:
2193   // 1. new_ctrl is fully initialized using
2194   //    GrowIntoSingleGroupShuffleControlBytes.
2195   // 2. new_slots is fully initialized consistent with
2196   //    GrowIntoSingleGroupShuffleControlBytes.
2197   void PoisonSingleGroupEmptySlots(CommonFields& c, size_t slot_size) const {
2198     // poison non full items
2199     for (size_t i = 0; i < c.capacity(); ++i) {
2200       if (!IsFull(c.control()[i])) {
2201         SanitizerPoisonMemoryRegion(SlotAddress(c.slot_array(), i, slot_size),
2202                                     slot_size);
2203       }
2204     }
2205   }
2206 
2207   HeapOrSoo old_heap_or_soo_;
2208   size_t old_capacity_;
2209   bool had_infoz_;
2210   bool was_soo_;
2211   bool had_soo_slot_;
2212   // Either null infoz or a pre-sampled forced infoz for SOO tables.
2213   HashtablezInfoHandle forced_infoz_;
2214 };
2215 
2216 inline void PrepareInsertCommon(CommonFields& common) {
2217   common.increment_size();
2218   common.maybe_increment_generation_on_insert();
2219 }
2220 
2221 // Like prepare_insert, but for the case of inserting into a full SOO table.
2222 size_t PrepareInsertAfterSoo(size_t hash, size_t slot_size,
2223                              CommonFields& common);
2224 
2225 // PolicyFunctions bundles together some information for a particular
2226 // raw_hash_set<T, ...> instantiation. This information is passed to
2227 // type-erased functions that want to do small amounts of type-specific
2228 // work.
2229 struct PolicyFunctions {
2230   size_t slot_size;
2231 
2232   // Returns the pointer to the hash function stored in the set.
2233   const void* (*hash_fn)(const CommonFields& common);
2234 
2235   // Returns the hash of the pointed-to slot.
2236   size_t (*hash_slot)(const void* hash_fn, void* slot);
2237 
2238   // Transfers the contents of src_slot to dst_slot.
2239   void (*transfer)(void* set, void* dst_slot, void* src_slot);
2240 
2241   // Deallocates the backing store from common.
2242   void (*dealloc)(CommonFields& common, const PolicyFunctions& policy);
2243 
2244   // Resizes set to the new capacity.
2245   // Arguments are used as in raw_hash_set::resize_impl.
2246   void (*resize)(CommonFields& common, size_t new_capacity,
2247                  HashtablezInfoHandle forced_infoz);
2248 };
2249 
2250 // ClearBackingArray clears the backing array, either modifying it in place,
2251 // or creating a new one based on the value of "reuse".
2252 // REQUIRES: c.capacity > 0
2253 void ClearBackingArray(CommonFields& c, const PolicyFunctions& policy,
2254                        bool reuse, bool soo_enabled);
2255 
2256 // Type-erased version of raw_hash_set::erase_meta_only.
2257 void EraseMetaOnly(CommonFields& c, size_t index, size_t slot_size);
2258 
2259 // Function to place in PolicyFunctions::dealloc for raw_hash_sets
2260 // that are using std::allocator. This allows us to share the same
2261 // function body for raw_hash_set instantiations that have the
2262 // same slot alignment.
2263 template <size_t AlignOfSlot>
2264 ABSL_ATTRIBUTE_NOINLINE void DeallocateStandard(CommonFields& common,
2265                                                 const PolicyFunctions& policy) {
2266   // Unpoison before returning the memory to the allocator.
2267   SanitizerUnpoisonMemoryRegion(common.slot_array(),
2268                                 policy.slot_size * common.capacity());
2269 
2270   std::allocator<char> alloc;
2271   common.infoz().Unregister();
2272   Deallocate<BackingArrayAlignment(AlignOfSlot)>(
2273       &alloc, common.backing_array_start(),
2274       common.alloc_size(policy.slot_size, AlignOfSlot));
2275 }
2276 
2277 // For trivially relocatable types we use memcpy directly. This allows us to
2278 // share the same function body for raw_hash_set instantiations that have the
2279 // same slot size as long as they are relocatable.
2280 template <size_t SizeOfSlot>
2281 ABSL_ATTRIBUTE_NOINLINE void TransferRelocatable(void*, void* dst, void* src) {
2282   memcpy(dst, src, SizeOfSlot);
2283 }
2284 
2285 // Type erased raw_hash_set::get_hash_ref_fn for the empty hash function case.
2286 const void* GetHashRefForEmptyHasher(const CommonFields& common);
2287 
2288 // Given the hash of a value not currently in the table and the first empty
2289 // slot in the probe sequence, finds a viable slot index to insert it at.
2290 //
2291 // In case there's no space left, the table can be resized or rehashed
2292 // (for tables with deleted slots, see FindInsertPositionWithGrowthOrRehash).
2293 //
2294 // In the case of absence of deleted slots and positive growth_left, the element
2295 // can be inserted in the provided `target` position.
2296 //
2297 // When the table has deleted slots (according to GrowthInfo), the target
2298 // position will be searched one more time using `find_first_non_full`.
2299 //
2300 // REQUIRES: Table is not SOO.
2301 // REQUIRES: At least one non-full slot available.
2302 // REQUIRES: `target` is a valid empty position to insert.
2303 size_t PrepareInsertNonSoo(CommonFields& common, size_t hash, FindInfo target,
2304                            const PolicyFunctions& policy);
2305 
2306 // A SwissTable.
2307 //
2308 // Policy: a policy defines how to perform different operations on
2309 // the slots of the hashtable (see hash_policy_traits.h for the full interface
2310 // of policy).
2311 //
2312 // Hash: a (possibly polymorphic) functor that hashes keys of the hashtable. The
2313 // functor should accept a key and return size_t as hash. For best performance
2314 // it is important that the hash function provides high entropy across all bits
2315 // of the hash.
2316 //
2317 // Eq: a (possibly polymorphic) functor that compares two keys for equality. It
2318 // should accept two (of possibly different type) keys and return a bool: true
2319 // if they are equal, false if they are not. If two keys compare equal, then
2320 // their hash values as defined by Hash MUST be equal.
2321 //
2322 // Allocator: an Allocator
2323 // [https://en.cppreference.com/w/cpp/named_req/Allocator] with which
2324 // the storage of the hashtable will be allocated and the elements will be
2325 // constructed and destroyed.
2326 template <class Policy, class Hash, class Eq, class Alloc>
2327 class raw_hash_set {
2328   using PolicyTraits = hash_policy_traits<Policy>;
2329   using KeyArgImpl =
2330       KeyArg<IsTransparent<Eq>::value && IsTransparent<Hash>::value>;
2331 
2332  public:
2333   using init_type = typename PolicyTraits::init_type;
2334   using key_type = typename PolicyTraits::key_type;
2335   // TODO(sbenza): Hide slot_type as it is an implementation detail. Needs user
2336   // code fixes!
2337   using slot_type = typename PolicyTraits::slot_type;
2338   using allocator_type = Alloc;
2339   using size_type = size_t;
2340   using difference_type = ptrdiff_t;
2341   using hasher = Hash;
2342   using key_equal = Eq;
2343   using policy_type = Policy;
2344   using value_type = typename PolicyTraits::value_type;
2345   using reference = value_type&;
2346   using const_reference = const value_type&;
2347   using pointer = typename absl::allocator_traits<
2348       allocator_type>::template rebind_traits<value_type>::pointer;
2349   using const_pointer = typename absl::allocator_traits<
2350       allocator_type>::template rebind_traits<value_type>::const_pointer;
2351 
2352   // Alias used for heterogeneous lookup functions.
2353   // `key_arg<K>` evaluates to `K` when the functors are transparent and to
2354   // `key_type` otherwise. It permits template argument deduction on `K` for the
2355   // transparent case.
2356   template <class K>
2357   using key_arg = typename KeyArgImpl::template type<K, key_type>;
2358 
2359  private:
2360   // TODO(b/289225379): we could add extra SOO space inside raw_hash_set
2361   // after CommonFields to allow inlining larger slot_types (e.g. std::string),
2362   // but it's a bit complicated if we want to support incomplete mapped_type in
2363   // flat_hash_map. We could potentially do this for flat_hash_set and for an
2364   // allowlist of `mapped_type`s of flat_hash_map that includes e.g. arithmetic
2365   // types, strings, cords, and pairs/tuples of allowlisted types.
2366   constexpr static bool SooEnabled() {
2367     return PolicyTraits::soo_enabled() &&
2368            sizeof(slot_type) <= sizeof(HeapOrSoo) &&
2369            alignof(slot_type) <= alignof(HeapOrSoo);
2370   }
2371 
2372   // Whether `size` fits in the SOO capacity of this table.
2373   bool fits_in_soo(size_t size) const {
2374     return SooEnabled() && size <= SooCapacity();
2375   }
2376   // Whether this table is in SOO mode or non-SOO mode.
2377   bool is_soo() const { return fits_in_soo(capacity()); }
2378   bool is_full_soo() const { return is_soo() && !empty(); }
2379 
2380   // Give an early error when key_type is not hashable/eq.
2381   auto KeyTypeCanBeHashed(const Hash& h, const key_type& k) -> decltype(h(k));
2382   auto KeyTypeCanBeEq(const Eq& eq, const key_type& k) -> decltype(eq(k, k));
2383 
2384   using AllocTraits = absl::allocator_traits<allocator_type>;
2385   using SlotAlloc = typename absl::allocator_traits<
2386       allocator_type>::template rebind_alloc<slot_type>;
2387   // People are often sloppy with the exact type of their allocator (sometimes
2388   // it has an extra const or is missing the pair, but rebinds made it work
2389   // anyway).
2390   using CharAlloc =
2391       typename absl::allocator_traits<Alloc>::template rebind_alloc<char>;
2392   using SlotAllocTraits = typename absl::allocator_traits<
2393       allocator_type>::template rebind_traits<slot_type>;
2394 
2395   static_assert(std::is_lvalue_reference<reference>::value,
2396                 "Policy::element() must return a reference");
2397 
2398   template <typename T>
2399   struct SameAsElementReference
2400       : std::is_same<typename std::remove_cv<
2401                          typename std::remove_reference<reference>::type>::type,
2402                      typename std::remove_cv<
2403                          typename std::remove_reference<T>::type>::type> {};
2404 
2405   // An enabler for insert(T&&): T must be convertible to init_type or be the
2406   // same as [cv] value_type [ref].
2407   // Note: we separate SameAsElementReference into its own type to avoid using
2408   // reference unless we need to. MSVC doesn't seem to like it in some
2409   // cases.
2410   template <class T>
2411   using RequiresInsertable = typename std::enable_if<
2412       absl::disjunction<std::is_convertible<T, init_type>,
2413                         SameAsElementReference<T>>::value,
2414       int>::type;
2415 
2416   // RequiresNotInit is a workaround for gcc prior to 7.1.
2417   // See https://godbolt.org/g/Y4xsUh.
2418   template <class T>
2419   using RequiresNotInit =
2420       typename std::enable_if<!std::is_same<T, init_type>::value, int>::type;
2421 
2422   template <class... Ts>
2423   using IsDecomposable = IsDecomposable<void, PolicyTraits, Hash, Eq, Ts...>;
2424 
2425  public:
2426   static_assert(std::is_same<pointer, value_type*>::value,
2427                 "Allocators with custom pointer types are not supported");
2428   static_assert(std::is_same<const_pointer, const value_type*>::value,
2429                 "Allocators with custom pointer types are not supported");
2430 
2431   class iterator : private HashSetIteratorGenerationInfo {
2432     friend class raw_hash_set;
2433 
2434    public:
2435     using iterator_category = std::forward_iterator_tag;
2436     using value_type = typename raw_hash_set::value_type;
2437     using reference =
2438         absl::conditional_t<PolicyTraits::constant_iterators::value,
2439                             const value_type&, value_type&>;
2440     using pointer = absl::remove_reference_t<reference>*;
2441     using difference_type = typename raw_hash_set::difference_type;
2442 
2443     iterator() {}
2444 
2445     // PRECONDITION: not an end() iterator.
2446     reference operator*() const {
2447       AssertIsFull(ctrl_, generation(), generation_ptr(), "operator*()");
2448       return unchecked_deref();
2449     }
2450 
2451     // PRECONDITION: not an end() iterator.
2452     pointer operator->() const {
2453       AssertIsFull(ctrl_, generation(), generation_ptr(), "operator->");
2454       return &operator*();
2455     }
2456 
2457     // PRECONDITION: not an end() iterator.
2458     iterator& operator++() {
2459       AssertIsFull(ctrl_, generation(), generation_ptr(), "operator++");
2460       ++ctrl_;
2461       ++slot_;
2462       skip_empty_or_deleted();
2463       if (ABSL_PREDICT_FALSE(*ctrl_ == ctrl_t::kSentinel)) ctrl_ = nullptr;
2464       return *this;
2465     }
2466     // PRECONDITION: not an end() iterator.
2467     iterator operator++(int) {
2468       auto tmp = *this;
2469       ++*this;
2470       return tmp;
2471     }
2472 
2473     friend bool operator==(const iterator& a, const iterator& b) {
2474       AssertIsValidForComparison(a.ctrl_, a.generation(), a.generation_ptr());
2475       AssertIsValidForComparison(b.ctrl_, b.generation(), b.generation_ptr());
2476       AssertSameContainer(a.ctrl_, b.ctrl_, a.slot_, b.slot_,
2477                           a.generation_ptr(), b.generation_ptr());
2478       return a.ctrl_ == b.ctrl_;
2479     }
2480     friend bool operator!=(const iterator& a, const iterator& b) {
2481       return !(a == b);
2482     }
2483 
2484    private:
2485     iterator(ctrl_t* ctrl, slot_type* slot,
2486              const GenerationType* generation_ptr)
2487         : HashSetIteratorGenerationInfo(generation_ptr),
2488           ctrl_(ctrl),
2489           slot_(slot) {
2490       // This assumption helps the compiler know that any non-end iterator is
2491       // not equal to any end iterator.
2492       ABSL_ASSUME(ctrl != nullptr);
2493     }
2494     // This constructor is used in begin() to avoid an MSan
2495     // use-of-uninitialized-value error. Delegating from this constructor to
2496     // the previous one doesn't avoid the error.
2497     iterator(ctrl_t* ctrl, MaybeInitializedPtr slot,
2498              const GenerationType* generation_ptr)
2499         : HashSetIteratorGenerationInfo(generation_ptr),
2500           ctrl_(ctrl),
2501           slot_(to_slot(slot.get())) {
2502       // This assumption helps the compiler know that any non-end iterator is
2503       // not equal to any end iterator.
2504       ABSL_ASSUME(ctrl != nullptr);
2505     }
2506     // For end() iterators.
2507     explicit iterator(const GenerationType* generation_ptr)
2508         : HashSetIteratorGenerationInfo(generation_ptr), ctrl_(nullptr) {}
2509 
2510     // Fixes up `ctrl_` to point to a full or sentinel by advancing `ctrl_` and
2511     // `slot_` until they reach one.
2512     void skip_empty_or_deleted() {
2513       while (IsEmptyOrDeleted(*ctrl_)) {
2514         uint32_t shift =
2515             GroupFullEmptyOrDeleted{ctrl_}.CountLeadingEmptyOrDeleted();
2516         ctrl_ += shift;
2517         slot_ += shift;
2518       }
2519     }
2520 
2521     ctrl_t* control() const { return ctrl_; }
2522     slot_type* slot() const { return slot_; }
2523 
2524     // We use EmptyGroup() for default-constructed iterators so that they can
2525     // be distinguished from end iterators, which have nullptr ctrl_.
2526     ctrl_t* ctrl_ = EmptyGroup();
2527     // To avoid uninitialized member warnings, put slot_ in an anonymous union.
2528     // The member is not initialized on singleton and end iterators.
2529     union {
2530       slot_type* slot_;
2531     };
2532 
2533     // An equality check which skips ABSL Hardening iterator invalidation
2534     // checks.
2535     // Should be used when the lifetimes of the iterators are well-enough
2536     // understood to prove that they cannot be invalid.
2537     bool unchecked_equals(const iterator& b) { return ctrl_ == b.control(); }
2538 
2539     // Dereferences the iterator without ABSL Hardening iterator invalidation
2540     // checks.
2541     reference unchecked_deref() const { return PolicyTraits::element(slot_); }
2542   };
2543 
2544   class const_iterator {
2545     friend class raw_hash_set;
2546     template <class Container, typename Enabler>
2547     friend struct absl::container_internal::hashtable_debug_internal::
2548         HashtableDebugAccess;
2549 
2550    public:
2551     using iterator_category = typename iterator::iterator_category;
2552     using value_type = typename raw_hash_set::value_type;
2553     using reference = typename raw_hash_set::const_reference;
2554     using pointer = typename raw_hash_set::const_pointer;
2555     using difference_type = typename raw_hash_set::difference_type;
2556 
2557     const_iterator() = default;
2558     // Implicit construction from iterator.
2559     const_iterator(iterator i) : inner_(std::move(i)) {}  // NOLINT
2560 
2561     reference operator*() const { return *inner_; }
2562     pointer operator->() const { return inner_.operator->(); }
2563 
2564     const_iterator& operator++() {
2565       ++inner_;
2566       return *this;
2567     }
2568     const_iterator operator++(int) { return inner_++; }
2569 
2570     friend bool operator==(const const_iterator& a, const const_iterator& b) {
2571       return a.inner_ == b.inner_;
2572     }
2573     friend bool operator!=(const const_iterator& a, const const_iterator& b) {
2574       return !(a == b);
2575     }
2576 
2577    private:
2578     const_iterator(const ctrl_t* ctrl, const slot_type* slot,
2579                    const GenerationType* gen)
2580         : inner_(const_cast<ctrl_t*>(ctrl), const_cast<slot_type*>(slot), gen) {
2581     }
2582     ctrl_t* control() const { return inner_.control(); }
2583     slot_type* slot() const { return inner_.slot(); }
2584 
2585     iterator inner_;
2586 
2587     bool unchecked_equals(const const_iterator& b) {
2588       return inner_.unchecked_equals(b.inner_);
2589     }
2590   };
2591 
2592   using node_type = node_handle<Policy, hash_policy_traits<Policy>, Alloc>;
2593   using insert_return_type = InsertReturnType<iterator, node_type>;
2594 
2595   // Note: can't use `= default` due to non-default noexcept (causes
2596   // problems for some compilers). NOLINTNEXTLINE
2597   raw_hash_set() noexcept(
2598       std::is_nothrow_default_constructible<hasher>::value &&
2599       std::is_nothrow_default_constructible<key_equal>::value &&
2600       std::is_nothrow_default_constructible<allocator_type>::value) {}
2601 
2602   ABSL_ATTRIBUTE_NOINLINE explicit raw_hash_set(
2603       size_t bucket_count, const hasher& hash = hasher(),
2604       const key_equal& eq = key_equal(),
2605       const allocator_type& alloc = allocator_type())
2606       : settings_(CommonFields::CreateDefault<SooEnabled()>(), hash, eq,
2607                   alloc) {
2608     if (bucket_count > (SooEnabled() ? SooCapacity() : 0)) {
2609       resize(NormalizeCapacity(bucket_count));
2610     }
2611   }
2612 
2613   raw_hash_set(size_t bucket_count, const hasher& hash,
2614                const allocator_type& alloc)
2615       : raw_hash_set(bucket_count, hash, key_equal(), alloc) {}
2616 
2617   raw_hash_set(size_t bucket_count, const allocator_type& alloc)
2618       : raw_hash_set(bucket_count, hasher(), key_equal(), alloc) {}
2619 
2620   explicit raw_hash_set(const allocator_type& alloc)
2621       : raw_hash_set(0, hasher(), key_equal(), alloc) {}
2622 
2623   template <class InputIter>
2624   raw_hash_set(InputIter first, InputIter last, size_t bucket_count = 0,
2625                const hasher& hash = hasher(), const key_equal& eq = key_equal(),
2626                const allocator_type& alloc = allocator_type())
2627       : raw_hash_set(SelectBucketCountForIterRange(first, last, bucket_count),
2628                      hash, eq, alloc) {
2629     insert(first, last);
2630   }
2631 
2632   template <class InputIter>
2633   raw_hash_set(InputIter first, InputIter last, size_t bucket_count,
2634                const hasher& hash, const allocator_type& alloc)
2635       : raw_hash_set(first, last, bucket_count, hash, key_equal(), alloc) {}
2636 
2637   template <class InputIter>
2638   raw_hash_set(InputIter first, InputIter last, size_t bucket_count,
2639                const allocator_type& alloc)
2640       : raw_hash_set(first, last, bucket_count, hasher(), key_equal(), alloc) {}
2641 
2642   template <class InputIter>
2643   raw_hash_set(InputIter first, InputIter last, const allocator_type& alloc)
2644       : raw_hash_set(first, last, 0, hasher(), key_equal(), alloc) {}
2645 
2646   // Instead of accepting std::initializer_list<value_type> as the first
2647   // argument like std::unordered_set<value_type> does, we have two overloads
2648   // that accept std::initializer_list<T> and std::initializer_list<init_type>.
2649   // This is advantageous for performance.
2650   //
2651   //   // Turns {"abc", "def"} into std::initializer_list<std::string>, then
2652   //   // copies the strings into the set.
2653   //   std::unordered_set<std::string> s = {"abc", "def"};
2654   //
2655   //   // Turns {"abc", "def"} into std::initializer_list<const char*>, then
2656   //   // copies the strings into the set.
2657   //   absl::flat_hash_set<std::string> s = {"abc", "def"};
2658   //
2659   // The same trick is used in insert().
2660   //
2661   // The enabler is necessary to prevent this constructor from triggering where
2662   // the copy constructor is meant to be called.
2663   //
2664   //   absl::flat_hash_set<int> a, b{a};
2665   //
2666   // RequiresNotInit<T> is a workaround for gcc prior to 7.1.
2667   template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
2668   raw_hash_set(std::initializer_list<T> init, size_t bucket_count = 0,
2669                const hasher& hash = hasher(), const key_equal& eq = key_equal(),
2670                const allocator_type& alloc = allocator_type())
2671       : raw_hash_set(init.begin(), init.end(), bucket_count, hash, eq, alloc) {}
2672 
2673   raw_hash_set(std::initializer_list<init_type> init, size_t bucket_count = 0,
2674                const hasher& hash = hasher(), const key_equal& eq = key_equal(),
2675                const allocator_type& alloc = allocator_type())
2676       : raw_hash_set(init.begin(), init.end(), bucket_count, hash, eq, alloc) {}
2677 
2678   template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
2679   raw_hash_set(std::initializer_list<T> init, size_t bucket_count,
2680                const hasher& hash, const allocator_type& alloc)
2681       : raw_hash_set(init, bucket_count, hash, key_equal(), alloc) {}
2682 
2683   raw_hash_set(std::initializer_list<init_type> init, size_t bucket_count,
2684                const hasher& hash, const allocator_type& alloc)
2685       : raw_hash_set(init, bucket_count, hash, key_equal(), alloc) {}
2686 
2687   template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
2688   raw_hash_set(std::initializer_list<T> init, size_t bucket_count,
2689                const allocator_type& alloc)
2690       : raw_hash_set(init, bucket_count, hasher(), key_equal(), alloc) {}
2691 
2692   raw_hash_set(std::initializer_list<init_type> init, size_t bucket_count,
2693                const allocator_type& alloc)
2694       : raw_hash_set(init, bucket_count, hasher(), key_equal(), alloc) {}
2695 
2696   template <class T, RequiresNotInit<T> = 0, RequiresInsertable<T> = 0>
2697   raw_hash_set(std::initializer_list<T> init, const allocator_type& alloc)
2698       : raw_hash_set(init, 0, hasher(), key_equal(), alloc) {}
2699 
2700   raw_hash_set(std::initializer_list<init_type> init,
2701                const allocator_type& alloc)
2702       : raw_hash_set(init, 0, hasher(), key_equal(), alloc) {}
2703 
2704   raw_hash_set(const raw_hash_set& that)
2705       : raw_hash_set(that, AllocTraits::select_on_container_copy_construction(
2706                                that.alloc_ref())) {}
2707 
2708   raw_hash_set(const raw_hash_set& that, const allocator_type& a)
2709       : raw_hash_set(GrowthToLowerboundCapacity(that.size()), that.hash_ref(),
2710                      that.eq_ref(), a) {
2711     const size_t size = that.size();
2712     if (size == 0) {
2713       return;
2714     }
2715     // We don't use `that.is_soo()` here because `that` can have non-SOO
2716     // capacity but have a size that fits into SOO capacity.
2717     if (fits_in_soo(size)) {
2718       assert(size == 1);
2719       common().set_full_soo();
2720       emplace_at(soo_iterator(), *that.begin());
2721       const HashtablezInfoHandle infoz = try_sample_soo();
2722       if (infoz.IsSampled()) resize_with_soo_infoz(infoz);
2723       return;
2724     }
2725     assert(!that.is_soo());
2726     const size_t cap = capacity();
2727     // Note about single group tables:
2728     // 1. It is correct to have any order of elements.
2729     // 2. Order has to be non deterministic.
2730     // 3. We are assigning elements with arbitrary `shift` starting from
2731     //    `capacity + shift` position.
2732     // 4. `shift` must be coprime with `capacity + 1` in order to be able to use
2733     //     modular arithmetic to traverse all positions, instead if cycling
2734     //     through a subset of positions. Odd numbers are coprime with any
2735     //     `capacity + 1` (2^N).
2736     size_t offset = cap;
2737     const size_t shift =
2738         is_single_group(cap) ? (PerTableSalt(control()) | 1) : 0;
2739     IterateOverFullSlots(
2740         that.common(), that.slot_array(),
2741         [&](const ctrl_t* that_ctrl,
2742             slot_type* that_slot) ABSL_ATTRIBUTE_ALWAYS_INLINE {
2743           if (shift == 0) {
2744             // Big tables case. Position must be searched via probing.
2745             // The table is guaranteed to be empty, so we can do faster than
2746             // a full `insert`.
2747             const size_t hash = PolicyTraits::apply(
2748                 HashElement{hash_ref()}, PolicyTraits::element(that_slot));
2749             FindInfo target = find_first_non_full_outofline(common(), hash);
2750             infoz().RecordInsert(hash, target.probe_length);
2751             offset = target.offset;
2752           } else {
2753             // Small tables case. Next position is computed via shift.
2754             offset = (offset + shift) & cap;
2755           }
2756           const h2_t h2 = static_cast<h2_t>(*that_ctrl);
2757           assert(  // We rely that hash is not changed for small tables.
2758               H2(PolicyTraits::apply(HashElement{hash_ref()},
2759                                      PolicyTraits::element(that_slot))) == h2 &&
2760               "hash function value changed unexpectedly during the copy");
2761           SetCtrl(common(), offset, h2, sizeof(slot_type));
2762           emplace_at(iterator_at(offset), PolicyTraits::element(that_slot));
2763           common().maybe_increment_generation_on_insert();
2764         });
2765     if (shift != 0) {
2766       // On small table copy we do not record individual inserts.
2767       // RecordInsert requires hash, but it is unknown for small tables.
2768       infoz().RecordStorageChanged(size, cap);
2769     }
2770     common().set_size(size);
2771     growth_info().OverwriteManyEmptyAsFull(size);
2772   }
2773 
2774   ABSL_ATTRIBUTE_NOINLINE raw_hash_set(raw_hash_set&& that) noexcept(
2775       std::is_nothrow_copy_constructible<hasher>::value &&
2776       std::is_nothrow_copy_constructible<key_equal>::value &&
2777       std::is_nothrow_copy_constructible<allocator_type>::value)
2778       :  // Hash, equality and allocator are copied instead of moved because
2779          // `that` must be left valid. If Hash is std::function<Key>, moving it
2780          // would create a nullptr functor that cannot be called.
2781          // TODO(b/296061262): move instead of copying hash/eq/alloc.
2782          // Note: we avoid using exchange for better generated code.
2783         settings_(PolicyTraits::transfer_uses_memcpy() || !that.is_full_soo()
2784                       ? std::move(that.common())
2785                       : CommonFields{full_soo_tag_t{}},
2786                   that.hash_ref(), that.eq_ref(), that.alloc_ref()) {
2787     if (!PolicyTraits::transfer_uses_memcpy() && that.is_full_soo()) {
2788       transfer(soo_slot(), that.soo_slot());
2789     }
2790     that.common() = CommonFields::CreateDefault<SooEnabled()>();
2791     maybe_increment_generation_or_rehash_on_move();
2792   }
2793 
2794   raw_hash_set(raw_hash_set&& that, const allocator_type& a)
2795       : settings_(CommonFields::CreateDefault<SooEnabled()>(), that.hash_ref(),
2796                   that.eq_ref(), a) {
2797     if (a == that.alloc_ref()) {
2798       swap_common(that);
2799       maybe_increment_generation_or_rehash_on_move();
2800     } else {
2801       move_elements_allocs_unequal(std::move(that));
2802     }
2803   }
2804 
2805   raw_hash_set& operator=(const raw_hash_set& that) {
2806     if (ABSL_PREDICT_FALSE(this == &that)) return *this;
2807     constexpr bool propagate_alloc =
2808         AllocTraits::propagate_on_container_copy_assignment::value;
2809     // TODO(ezb): maybe avoid allocating a new backing array if this->capacity()
2810     // is an exact match for that.size(). If this->capacity() is too big, then
2811     // it would make iteration very slow to reuse the allocation. Maybe we can
2812     // do the same heuristic as clear() and reuse if it's small enough.
2813     raw_hash_set tmp(that, propagate_alloc ? that.alloc_ref() : alloc_ref());
2814     // NOLINTNEXTLINE: not returning *this for performance.
2815     return assign_impl<propagate_alloc>(std::move(tmp));
2816   }
2817 
2818   raw_hash_set& operator=(raw_hash_set&& that) noexcept(
2819       absl::allocator_traits<allocator_type>::is_always_equal::value &&
2820       std::is_nothrow_move_assignable<hasher>::value &&
2821       std::is_nothrow_move_assignable<key_equal>::value) {
2822     // TODO(sbenza): We should only use the operations from the noexcept clause
2823     // to make sure we actually adhere to that contract.
2824     // NOLINTNEXTLINE: not returning *this for performance.
2825     return move_assign(
2826         std::move(that),
2827         typename AllocTraits::propagate_on_container_move_assignment());
2828   }
2829 
2830   ~raw_hash_set() { destructor_impl(); }
2831 
2832   iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
2833     if (ABSL_PREDICT_FALSE(empty())) return end();
2834     if (is_soo()) return soo_iterator();
2835     iterator it = {control(), common().slots_union(),
2836                    common().generation_ptr()};
2837     it.skip_empty_or_deleted();
2838     assert(IsFull(*it.control()));
2839     return it;
2840   }
2841   iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND {
2842     return iterator(common().generation_ptr());
2843   }
2844 
2845   const_iterator begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
2846     return const_cast<raw_hash_set*>(this)->begin();
2847   }
2848   const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
2849     return iterator(common().generation_ptr());
2850   }
2851   const_iterator cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
2852     return begin();
2853   }
2854   const_iterator cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND { return end(); }
2855 
2856   bool empty() const { return !size(); }
2857   size_t size() const { return common().size(); }
2858   size_t capacity() const {
2859     const size_t cap = common().capacity();
2860     // Compiler complains when using functions in assume so use local variables.
2861     ABSL_ATTRIBUTE_UNUSED static constexpr bool kEnabled = SooEnabled();
2862     ABSL_ATTRIBUTE_UNUSED static constexpr size_t kCapacity = SooCapacity();
2863     ABSL_ASSUME(!kEnabled || cap >= kCapacity);
2864     return cap;
2865   }
2866   size_t max_size() const { return (std::numeric_limits<size_t>::max)(); }
2867 
2868   ABSL_ATTRIBUTE_REINITIALIZES void clear() {
2869     // Iterating over this container is O(bucket_count()). When bucket_count()
2870     // is much greater than size(), iteration becomes prohibitively expensive.
2871     // For clear() it is more important to reuse the allocated array when the
2872     // container is small because allocation takes comparatively long time
2873     // compared to destruction of the elements of the container. So we pick the
2874     // largest bucket_count() threshold for which iteration is still fast and
2875     // past that we simply deallocate the array.
2876     const size_t cap = capacity();
2877     if (cap == 0) {
2878       // Already guaranteed to be empty; so nothing to do.
2879     } else if (is_soo()) {
2880       if (!empty()) destroy(soo_slot());
2881       common().set_empty_soo();
2882     } else {
2883       destroy_slots();
2884       ClearBackingArray(common(), GetPolicyFunctions(), /*reuse=*/cap < 128,
2885                         SooEnabled());
2886     }
2887     common().set_reserved_growth(0);
2888     common().set_reservation_size(0);
2889   }
2890 
2891   // This overload kicks in when the argument is an rvalue of insertable and
2892   // decomposable type other than init_type.
2893   //
2894   //   flat_hash_map<std::string, int> m;
2895   //   m.insert(std::make_pair("abc", 42));
2896   // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc
2897   // bug.
2898   template <class T, RequiresInsertable<T> = 0, class T2 = T,
2899             typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0,
2900             T* = nullptr>
2901   std::pair<iterator, bool> insert(T&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2902     return emplace(std::forward<T>(value));
2903   }
2904 
2905   // This overload kicks in when the argument is a bitfield or an lvalue of
2906   // insertable and decomposable type.
2907   //
2908   //   union { int n : 1; };
2909   //   flat_hash_set<int> s;
2910   //   s.insert(n);
2911   //
2912   //   flat_hash_set<std::string> s;
2913   //   const char* p = "hello";
2914   //   s.insert(p);
2915   //
2916   template <
2917       class T, RequiresInsertable<const T&> = 0,
2918       typename std::enable_if<IsDecomposable<const T&>::value, int>::type = 0>
2919   std::pair<iterator, bool> insert(const T& value)
2920       ABSL_ATTRIBUTE_LIFETIME_BOUND {
2921     return emplace(value);
2922   }
2923 
2924   // This overload kicks in when the argument is an rvalue of init_type. Its
2925   // purpose is to handle brace-init-list arguments.
2926   //
2927   //   flat_hash_map<std::string, int> s;
2928   //   s.insert({"abc", 42});
2929   std::pair<iterator, bool> insert(init_type&& value)
2930       ABSL_ATTRIBUTE_LIFETIME_BOUND {
2931     return emplace(std::move(value));
2932   }
2933 
2934   // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc
2935   // bug.
2936   template <class T, RequiresInsertable<T> = 0, class T2 = T,
2937             typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0,
2938             T* = nullptr>
2939   iterator insert(const_iterator, T&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2940     return insert(std::forward<T>(value)).first;
2941   }
2942 
2943   template <
2944       class T, RequiresInsertable<const T&> = 0,
2945       typename std::enable_if<IsDecomposable<const T&>::value, int>::type = 0>
2946   iterator insert(const_iterator,
2947                   const T& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2948     return insert(value).first;
2949   }
2950 
2951   iterator insert(const_iterator,
2952                   init_type&& value) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2953     return insert(std::move(value)).first;
2954   }
2955 
2956   template <class InputIt>
2957   void insert(InputIt first, InputIt last) {
2958     for (; first != last; ++first) emplace(*first);
2959   }
2960 
2961   template <class T, RequiresNotInit<T> = 0, RequiresInsertable<const T&> = 0>
2962   void insert(std::initializer_list<T> ilist) {
2963     insert(ilist.begin(), ilist.end());
2964   }
2965 
2966   void insert(std::initializer_list<init_type> ilist) {
2967     insert(ilist.begin(), ilist.end());
2968   }
2969 
2970   insert_return_type insert(node_type&& node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2971     if (!node) return {end(), false, node_type()};
2972     const auto& elem = PolicyTraits::element(CommonAccess::GetSlot(node));
2973     auto res = PolicyTraits::apply(
2974         InsertSlot<false>{*this, std::move(*CommonAccess::GetSlot(node))},
2975         elem);
2976     if (res.second) {
2977       CommonAccess::Reset(&node);
2978       return {res.first, true, node_type()};
2979     } else {
2980       return {res.first, false, std::move(node)};
2981     }
2982   }
2983 
2984   iterator insert(const_iterator,
2985                   node_type&& node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
2986     auto res = insert(std::move(node));
2987     node = std::move(res.node);
2988     return res.position;
2989   }
2990 
2991   // This overload kicks in if we can deduce the key from args. This enables us
2992   // to avoid constructing value_type if an entry with the same key already
2993   // exists.
2994   //
2995   // For example:
2996   //
2997   //   flat_hash_map<std::string, std::string> m = {{"abc", "def"}};
2998   //   // Creates no std::string copies and makes no heap allocations.
2999   //   m.emplace("abc", "xyz");
3000   template <class... Args, typename std::enable_if<
3001                                IsDecomposable<Args...>::value, int>::type = 0>
3002   std::pair<iterator, bool> emplace(Args&&... args)
3003       ABSL_ATTRIBUTE_LIFETIME_BOUND {
3004     return PolicyTraits::apply(EmplaceDecomposable{*this},
3005                                std::forward<Args>(args)...);
3006   }
3007 
3008   // This overload kicks in if we cannot deduce the key from args. It constructs
3009   // value_type unconditionally and then either moves it into the table or
3010   // destroys.
3011   template <class... Args, typename std::enable_if<
3012                                !IsDecomposable<Args...>::value, int>::type = 0>
3013   std::pair<iterator, bool> emplace(Args&&... args)
3014       ABSL_ATTRIBUTE_LIFETIME_BOUND {
3015     alignas(slot_type) unsigned char raw[sizeof(slot_type)];
3016     slot_type* slot = to_slot(&raw);
3017 
3018     construct(slot, std::forward<Args>(args)...);
3019     const auto& elem = PolicyTraits::element(slot);
3020     return PolicyTraits::apply(InsertSlot<true>{*this, std::move(*slot)}, elem);
3021   }
3022 
3023   template <class... Args>
3024   iterator emplace_hint(const_iterator,
3025                         Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
3026     return emplace(std::forward<Args>(args)...).first;
3027   }
3028 
3029   // Extension API: support for lazy emplace.
3030   //
3031   // Looks up key in the table. If found, returns the iterator to the element.
3032   // Otherwise calls `f` with one argument of type `raw_hash_set::constructor`,
3033   // and returns an iterator to the new element.
3034   //
3035   // `f` must abide by several restrictions:
3036   //  - it MUST call `raw_hash_set::constructor` with arguments as if a
3037   //    `raw_hash_set::value_type` is constructed,
3038   //  - it MUST NOT access the container before the call to
3039   //    `raw_hash_set::constructor`, and
3040   //  - it MUST NOT erase the lazily emplaced element.
3041   // Doing any of these is undefined behavior.
3042   //
3043   // For example:
3044   //
3045   //   std::unordered_set<ArenaString> s;
3046   //   // Makes ArenaStr even if "abc" is in the map.
3047   //   s.insert(ArenaString(&arena, "abc"));
3048   //
3049   //   flat_hash_set<ArenaStr> s;
3050   //   // Makes ArenaStr only if "abc" is not in the map.
3051   //   s.lazy_emplace("abc", [&](const constructor& ctor) {
3052   //     ctor(&arena, "abc");
3053   //   });
3054   //
3055   // WARNING: This API is currently experimental. If there is a way to implement
3056   // the same thing with the rest of the API, prefer that.
3057   class constructor {
3058     friend class raw_hash_set;
3059 
3060    public:
3061     template <class... Args>
3062     void operator()(Args&&... args) const {
3063       assert(*slot_);
3064       PolicyTraits::construct(alloc_, *slot_, std::forward<Args>(args)...);
3065       *slot_ = nullptr;
3066     }
3067 
3068    private:
3069     constructor(allocator_type* a, slot_type** slot) : alloc_(a), slot_(slot) {}
3070 
3071     allocator_type* alloc_;
3072     slot_type** slot_;
3073   };
3074 
3075   template <class K = key_type, class F>
3076   iterator lazy_emplace(const key_arg<K>& key,
3077                         F&& f) ABSL_ATTRIBUTE_LIFETIME_BOUND {
3078     auto res = find_or_prepare_insert(key);
3079     if (res.second) {
3080       slot_type* slot = res.first.slot();
3081       std::forward<F>(f)(constructor(&alloc_ref(), &slot));
3082       assert(!slot);
3083     }
3084     return res.first;
3085   }
3086 
3087   // Extension API: support for heterogeneous keys.
3088   //
3089   //   std::unordered_set<std::string> s;
3090   //   // Turns "abc" into std::string.
3091   //   s.erase("abc");
3092   //
3093   //   flat_hash_set<std::string> s;
3094   //   // Uses "abc" directly without copying it into std::string.
3095   //   s.erase("abc");
3096   template <class K = key_type>
3097   size_type erase(const key_arg<K>& key) {
3098     auto it = find(key);
3099     if (it == end()) return 0;
3100     erase(it);
3101     return 1;
3102   }
3103 
3104   // Erases the element pointed to by `it`.  Unlike `std::unordered_set::erase`,
3105   // this method returns void to reduce algorithmic complexity to O(1).  The
3106   // iterator is invalidated, so any increment should be done before calling
3107   // erase.  In order to erase while iterating across a map, use the following
3108   // idiom (which also works for some standard containers):
3109   //
3110   // for (auto it = m.begin(), end = m.end(); it != end;) {
3111   //   // `erase()` will invalidate `it`, so advance `it` first.
3112   //   auto copy_it = it++;
3113   //   if (<pred>) {
3114   //     m.erase(copy_it);
3115   //   }
3116   // }
3117   void erase(const_iterator cit) { erase(cit.inner_); }
3118 
3119   // This overload is necessary because otherwise erase<K>(const K&) would be
3120   // a better match if non-const iterator is passed as an argument.
3121   void erase(iterator it) {
3122     AssertIsFull(it.control(), it.generation(), it.generation_ptr(), "erase()");
3123     destroy(it.slot());
3124     if (is_soo()) {
3125       common().set_empty_soo();
3126     } else {
3127       erase_meta_only(it);
3128     }
3129   }
3130 
3131   iterator erase(const_iterator first,
3132                  const_iterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {
3133     // We check for empty first because ClearBackingArray requires that
3134     // capacity() > 0 as a precondition.
3135     if (empty()) return end();
3136     if (first == last) return last.inner_;
3137     if (is_soo()) {
3138       destroy(soo_slot());
3139       common().set_empty_soo();
3140       return end();
3141     }
3142     if (first == begin() && last == end()) {
3143       // TODO(ezb): we access control bytes in destroy_slots so it could make
3144       // sense to combine destroy_slots and ClearBackingArray to avoid cache
3145       // misses when the table is large. Note that we also do this in clear().
3146       destroy_slots();
3147       ClearBackingArray(common(), GetPolicyFunctions(), /*reuse=*/true,
3148                         SooEnabled());
3149       common().set_reserved_growth(common().reservation_size());
3150       return end();
3151     }
3152     while (first != last) {
3153       erase(first++);
3154     }
3155     return last.inner_;
3156   }
3157 
3158   // Moves elements from `src` into `this`.
3159   // If the element already exists in `this`, it is left unmodified in `src`.
3160   template <typename H, typename E>
3161   void merge(raw_hash_set<Policy, H, E, Alloc>& src) {  // NOLINT
3162     assert(this != &src);
3163     // Returns whether insertion took place.
3164     const auto insert_slot = [this](slot_type* src_slot) {
3165       return PolicyTraits::apply(InsertSlot<false>{*this, std::move(*src_slot)},
3166                                  PolicyTraits::element(src_slot))
3167           .second;
3168     };
3169 
3170     if (src.is_soo()) {
3171       if (src.empty()) return;
3172       if (insert_slot(src.soo_slot())) src.common().set_empty_soo();
3173       return;
3174     }
3175     for (auto it = src.begin(), e = src.end(); it != e;) {
3176       auto next = std::next(it);
3177       if (insert_slot(it.slot())) src.erase_meta_only(it);
3178       it = next;
3179     }
3180   }
3181 
3182   template <typename H, typename E>
3183   void merge(raw_hash_set<Policy, H, E, Alloc>&& src) {
3184     merge(src);
3185   }
3186 
3187   node_type extract(const_iterator position) {
3188     AssertIsFull(position.control(), position.inner_.generation(),
3189                  position.inner_.generation_ptr(), "extract()");
3190     auto node = CommonAccess::Transfer<node_type>(alloc_ref(), position.slot());
3191     if (is_soo()) {
3192       common().set_empty_soo();
3193     } else {
3194       erase_meta_only(position);
3195     }
3196     return node;
3197   }
3198 
3199   template <
3200       class K = key_type,
3201       typename std::enable_if<!std::is_same<K, iterator>::value, int>::type = 0>
3202   node_type extract(const key_arg<K>& key) {
3203     auto it = find(key);
3204     return it == end() ? node_type() : extract(const_iterator{it});
3205   }
3206 
3207   void swap(raw_hash_set& that) noexcept(
3208       IsNoThrowSwappable<hasher>() && IsNoThrowSwappable<key_equal>() &&
3209       IsNoThrowSwappable<allocator_type>(
3210           typename AllocTraits::propagate_on_container_swap{})) {
3211     using std::swap;
3212     swap_common(that);
3213     swap(hash_ref(), that.hash_ref());
3214     swap(eq_ref(), that.eq_ref());
3215     SwapAlloc(alloc_ref(), that.alloc_ref(),
3216               typename AllocTraits::propagate_on_container_swap{});
3217   }
3218 
3219   void rehash(size_t n) {
3220     const size_t cap = capacity();
3221     if (n == 0) {
3222       if (cap == 0 || is_soo()) return;
3223       if (empty()) {
3224         ClearBackingArray(common(), GetPolicyFunctions(), /*reuse=*/false,
3225                           SooEnabled());
3226         return;
3227       }
3228       if (fits_in_soo(size())) {
3229         // When the table is already sampled, we keep it sampled.
3230         if (infoz().IsSampled()) {
3231           const size_t kInitialSampledCapacity = NextCapacity(SooCapacity());
3232           if (capacity() > kInitialSampledCapacity) {
3233             resize(kInitialSampledCapacity);
3234           }
3235           // This asserts that we didn't lose sampling coverage in `resize`.
3236           assert(infoz().IsSampled());
3237           return;
3238         }
3239         alignas(slot_type) unsigned char slot_space[sizeof(slot_type)];
3240         slot_type* tmp_slot = to_slot(slot_space);
3241         transfer(tmp_slot, begin().slot());
3242         ClearBackingArray(common(), GetPolicyFunctions(), /*reuse=*/false,
3243                           SooEnabled());
3244         transfer(soo_slot(), tmp_slot);
3245         common().set_full_soo();
3246         return;
3247       }
3248     }
3249 
3250     // bitor is a faster way of doing `max` here. We will round up to the next
3251     // power-of-2-minus-1, so bitor is good enough.
3252     auto m = NormalizeCapacity(n | GrowthToLowerboundCapacity(size()));
3253     // n == 0 unconditionally rehashes as per the standard.
3254     if (n == 0 || m > cap) {
3255       resize(m);
3256 
3257       // This is after resize, to ensure that we have completed the allocation
3258       // and have potentially sampled the hashtable.
3259       infoz().RecordReservation(n);
3260     }
3261   }
3262 
3263   void reserve(size_t n) {
3264     const size_t max_size_before_growth =
3265         is_soo() ? SooCapacity() : size() + growth_left();
3266     if (n > max_size_before_growth) {
3267       size_t m = GrowthToLowerboundCapacity(n);
3268       resize(NormalizeCapacity(m));
3269 
3270       // This is after resize, to ensure that we have completed the allocation
3271       // and have potentially sampled the hashtable.
3272       infoz().RecordReservation(n);
3273     }
3274     common().reset_reserved_growth(n);
3275     common().set_reservation_size(n);
3276   }
3277 
3278   // Extension API: support for heterogeneous keys.
3279   //
3280   //   std::unordered_set<std::string> s;
3281   //   // Turns "abc" into std::string.
3282   //   s.count("abc");
3283   //
3284   //   ch_set<std::string> s;
3285   //   // Uses "abc" directly without copying it into std::string.
3286   //   s.count("abc");
3287   template <class K = key_type>
3288   size_t count(const key_arg<K>& key) const {
3289     return find(key) == end() ? 0 : 1;
3290   }
3291 
3292   // Issues CPU prefetch instructions for the memory needed to find or insert
3293   // a key.  Like all lookup functions, this support heterogeneous keys.
3294   //
3295   // NOTE: This is a very low level operation and should not be used without
3296   // specific benchmarks indicating its importance.
3297   template <class K = key_type>
3298   void prefetch(const key_arg<K>& key) const {
3299     if (SooEnabled() ? is_soo() : capacity() == 0) return;
3300     (void)key;
3301     // Avoid probing if we won't be able to prefetch the addresses received.
3302 #ifdef ABSL_HAVE_PREFETCH
3303     prefetch_heap_block();
3304     auto seq = probe(common(), hash_ref()(key));
3305     PrefetchToLocalCache(control() + seq.offset());
3306     PrefetchToLocalCache(slot_array() + seq.offset());
3307 #endif  // ABSL_HAVE_PREFETCH
3308   }
3309 
3310   // The API of find() has two extensions.
3311   //
3312   // 1. The hash can be passed by the user. It must be equal to the hash of the
3313   // key.
3314   //
3315   // 2. The type of the key argument doesn't have to be key_type. This is so
3316   // called heterogeneous key support.
3317   template <class K = key_type>
3318   iterator find(const key_arg<K>& key,
3319                 size_t hash) ABSL_ATTRIBUTE_LIFETIME_BOUND {
3320     if (is_soo()) return find_soo(key);
3321     return find_non_soo(key, hash);
3322   }
3323   template <class K = key_type>
3324   iterator find(const key_arg<K>& key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
3325     if (is_soo()) return find_soo(key);
3326     prefetch_heap_block();
3327     return find_non_soo(key, hash_ref()(key));
3328   }
3329 
3330   template <class K = key_type>
3331   const_iterator find(const key_arg<K>& key,
3332                       size_t hash) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
3333     return const_cast<raw_hash_set*>(this)->find(key, hash);
3334   }
3335   template <class K = key_type>
3336   const_iterator find(const key_arg<K>& key) const
3337       ABSL_ATTRIBUTE_LIFETIME_BOUND {
3338     return const_cast<raw_hash_set*>(this)->find(key);
3339   }
3340 
3341   template <class K = key_type>
3342   bool contains(const key_arg<K>& key) const {
3343     // Here neither the iterator returned by `find()` nor `end()` can be invalid
3344     // outside of potential thread-safety issues.
3345     // `find()`'s return value is constructed, used, and then destructed
3346     // all in this context.
3347     return !find(key).unchecked_equals(end());
3348   }
3349 
3350   template <class K = key_type>
3351   std::pair<iterator, iterator> equal_range(const key_arg<K>& key)
3352       ABSL_ATTRIBUTE_LIFETIME_BOUND {
3353     auto it = find(key);
3354     if (it != end()) return {it, std::next(it)};
3355     return {it, it};
3356   }
3357   template <class K = key_type>
3358   std::pair<const_iterator, const_iterator> equal_range(
3359       const key_arg<K>& key) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
3360     auto it = find(key);
3361     if (it != end()) return {it, std::next(it)};
3362     return {it, it};
3363   }
3364 
3365   size_t bucket_count() const { return capacity(); }
3366   float load_factor() const {
3367     return capacity() ? static_cast<double>(size()) / capacity() : 0.0;
3368   }
3369   float max_load_factor() const { return 1.0f; }
3370   void max_load_factor(float) {
3371     // Does nothing.
3372   }
3373 
3374   hasher hash_function() const { return hash_ref(); }
3375   key_equal key_eq() const { return eq_ref(); }
3376   allocator_type get_allocator() const { return alloc_ref(); }
3377 
3378   friend bool operator==(const raw_hash_set& a, const raw_hash_set& b) {
3379     if (a.size() != b.size()) return false;
3380     const raw_hash_set* outer = &a;
3381     const raw_hash_set* inner = &b;
3382     if (outer->capacity() > inner->capacity()) std::swap(outer, inner);
3383     for (const value_type& elem : *outer) {
3384       auto it = PolicyTraits::apply(FindElement{*inner}, elem);
3385       if (it == inner->end() || !(*it == elem)) return false;
3386     }
3387     return true;
3388   }
3389 
3390   friend bool operator!=(const raw_hash_set& a, const raw_hash_set& b) {
3391     return !(a == b);
3392   }
3393 
3394   template <typename H>
3395   friend typename std::enable_if<H::template is_hashable<value_type>::value,
3396                                  H>::type
3397   AbslHashValue(H h, const raw_hash_set& s) {
3398     return H::combine(H::combine_unordered(std::move(h), s.begin(), s.end()),
3399                       s.size());
3400   }
3401 
3402   friend void swap(raw_hash_set& a,
3403                    raw_hash_set& b) noexcept(noexcept(a.swap(b))) {
3404     a.swap(b);
3405   }
3406 
3407  private:
3408   template <class Container, typename Enabler>
3409   friend struct absl::container_internal::hashtable_debug_internal::
3410       HashtableDebugAccess;
3411 
3412   struct FindElement {
3413     template <class K, class... Args>
3414     const_iterator operator()(const K& key, Args&&...) const {
3415       return s.find(key);
3416     }
3417     const raw_hash_set& s;
3418   };
3419 
3420   struct HashElement {
3421     template <class K, class... Args>
3422     size_t operator()(const K& key, Args&&...) const {
3423       return h(key);
3424     }
3425     const hasher& h;
3426   };
3427 
3428   template <class K1>
3429   struct EqualElement {
3430     template <class K2, class... Args>
3431     bool operator()(const K2& lhs, Args&&...) const {
3432       return eq(lhs, rhs);
3433     }
3434     const K1& rhs;
3435     const key_equal& eq;
3436   };
3437 
3438   struct EmplaceDecomposable {
3439     template <class K, class... Args>
3440     std::pair<iterator, bool> operator()(const K& key, Args&&... args) const {
3441       auto res = s.find_or_prepare_insert(key);
3442       if (res.second) {
3443         s.emplace_at(res.first, std::forward<Args>(args)...);
3444       }
3445       return res;
3446     }
3447     raw_hash_set& s;
3448   };
3449 
3450   template <bool do_destroy>
3451   struct InsertSlot {
3452     template <class K, class... Args>
3453     std::pair<iterator, bool> operator()(const K& key, Args&&...) && {
3454       auto res = s.find_or_prepare_insert(key);
3455       if (res.second) {
3456         s.transfer(res.first.slot(), &slot);
3457       } else if (do_destroy) {
3458         s.destroy(&slot);
3459       }
3460       return res;
3461     }
3462     raw_hash_set& s;
3463     // Constructed slot. Either moved into place or destroyed.
3464     slot_type&& slot;
3465   };
3466 
3467   // TODO(b/303305702): re-enable reentrant validation.
3468   template <typename... Args>
3469   inline void construct(slot_type* slot, Args&&... args) {
3470     PolicyTraits::construct(&alloc_ref(), slot, std::forward<Args>(args)...);
3471   }
3472   inline void destroy(slot_type* slot) {
3473     PolicyTraits::destroy(&alloc_ref(), slot);
3474   }
3475   inline void transfer(slot_type* to, slot_type* from) {
3476     PolicyTraits::transfer(&alloc_ref(), to, from);
3477   }
3478 
3479   // TODO(b/289225379): consider having a helper class that has the impls for
3480   // SOO functionality.
3481   template <class K = key_type>
3482   iterator find_soo(const key_arg<K>& key) {
3483     assert(is_soo());
3484     return empty() || !PolicyTraits::apply(EqualElement<K>{key, eq_ref()},
3485                                            PolicyTraits::element(soo_slot()))
3486                ? end()
3487                : soo_iterator();
3488   }
3489 
3490   template <class K = key_type>
3491   iterator find_non_soo(const key_arg<K>& key, size_t hash) {
3492     assert(!is_soo());
3493     auto seq = probe(common(), hash);
3494     const ctrl_t* ctrl = control();
3495     while (true) {
3496       Group g{ctrl + seq.offset()};
3497       for (uint32_t i : g.Match(H2(hash))) {
3498         if (ABSL_PREDICT_TRUE(PolicyTraits::apply(
3499                 EqualElement<K>{key, eq_ref()},
3500                 PolicyTraits::element(slot_array() + seq.offset(i)))))
3501           return iterator_at(seq.offset(i));
3502       }
3503       if (ABSL_PREDICT_TRUE(g.MaskEmpty())) return end();
3504       seq.next();
3505       assert(seq.index() <= capacity() && "full table!");
3506     }
3507   }
3508 
3509   // Conditionally samples hashtablez for SOO tables. This should be called on
3510   // insertion into an empty SOO table and in copy construction when the size
3511   // can fit in SOO capacity.
3512   inline HashtablezInfoHandle try_sample_soo() {
3513     assert(is_soo());
3514     if (!ShouldSampleHashtablezInfo<CharAlloc>()) return HashtablezInfoHandle{};
3515     return Sample(sizeof(slot_type), sizeof(key_type), sizeof(value_type),
3516                   SooCapacity());
3517   }
3518 
3519   inline void destroy_slots() {
3520     assert(!is_soo());
3521     if (PolicyTraits::template destroy_is_trivial<Alloc>()) return;
3522     IterateOverFullSlots(
3523         common(), slot_array(),
3524         [&](const ctrl_t*, slot_type* slot)
3525             ABSL_ATTRIBUTE_ALWAYS_INLINE { this->destroy(slot); });
3526   }
3527 
3528   inline void dealloc() {
3529     assert(capacity() != 0);
3530     // Unpoison before returning the memory to the allocator.
3531     SanitizerUnpoisonMemoryRegion(slot_array(), sizeof(slot_type) * capacity());
3532     infoz().Unregister();
3533     Deallocate<BackingArrayAlignment(alignof(slot_type))>(
3534         &alloc_ref(), common().backing_array_start(),
3535         common().alloc_size(sizeof(slot_type), alignof(slot_type)));
3536   }
3537 
3538   inline void destructor_impl() {
3539     if (capacity() == 0) return;
3540     if (is_soo()) {
3541       if (!empty()) {
3542         ABSL_SWISSTABLE_IGNORE_UNINITIALIZED(destroy(soo_slot()));
3543       }
3544       return;
3545     }
3546     destroy_slots();
3547     dealloc();
3548   }
3549 
3550   // Erases, but does not destroy, the value pointed to by `it`.
3551   //
3552   // This merely updates the pertinent control byte. This can be used in
3553   // conjunction with Policy::transfer to move the object to another place.
3554   void erase_meta_only(const_iterator it) {
3555     assert(!is_soo());
3556     EraseMetaOnly(common(), static_cast<size_t>(it.control() - control()),
3557                   sizeof(slot_type));
3558   }
3559 
3560   size_t hash_of(slot_type* slot) const {
3561     return PolicyTraits::apply(HashElement{hash_ref()},
3562                                PolicyTraits::element(slot));
3563   }
3564 
3565   // Resizes table to the new capacity and move all elements to the new
3566   // positions accordingly.
3567   //
3568   // Note that for better performance instead of
3569   // find_first_non_full(common(), hash),
3570   // HashSetResizeHelper::FindFirstNonFullAfterResize(
3571   //    common(), old_capacity, hash)
3572   // can be called right after `resize`.
3573   void resize(size_t new_capacity) {
3574     raw_hash_set::resize_impl(common(), new_capacity, HashtablezInfoHandle{});
3575   }
3576 
3577   // As above, except that we also accept a pre-sampled, forced infoz for
3578   // SOO tables, since they need to switch from SOO to heap in order to
3579   // store the infoz.
3580   void resize_with_soo_infoz(HashtablezInfoHandle forced_infoz) {
3581     assert(forced_infoz.IsSampled());
3582     raw_hash_set::resize_impl(common(), NextCapacity(SooCapacity()),
3583                               forced_infoz);
3584   }
3585 
3586   // Resizes set to the new capacity.
3587   // It is a static function in order to use its pointer in GetPolicyFunctions.
3588   ABSL_ATTRIBUTE_NOINLINE static void resize_impl(
3589       CommonFields& common, size_t new_capacity,
3590       HashtablezInfoHandle forced_infoz) {
3591     raw_hash_set* set = reinterpret_cast<raw_hash_set*>(&common);
3592     assert(IsValidCapacity(new_capacity));
3593     assert(!set->fits_in_soo(new_capacity));
3594     const bool was_soo = set->is_soo();
3595     const bool had_soo_slot = was_soo && !set->empty();
3596     const ctrl_t soo_slot_h2 =
3597         had_soo_slot ? static_cast<ctrl_t>(H2(set->hash_of(set->soo_slot())))
3598                      : ctrl_t::kEmpty;
3599     HashSetResizeHelper resize_helper(common, was_soo, had_soo_slot,
3600                                       forced_infoz);
3601     // Initialize HashSetResizeHelper::old_heap_or_soo_. We can't do this in
3602     // HashSetResizeHelper constructor because it can't transfer slots when
3603     // transfer_uses_memcpy is false.
3604     // TODO(b/289225379): try to handle more of the SOO cases inside
3605     // InitializeSlots. See comment on cl/555990034 snapshot #63.
3606     if (PolicyTraits::transfer_uses_memcpy() || !had_soo_slot) {
3607       resize_helper.old_heap_or_soo() = common.heap_or_soo();
3608     } else {
3609       set->transfer(set->to_slot(resize_helper.old_soo_data()),
3610                     set->soo_slot());
3611     }
3612     common.set_capacity(new_capacity);
3613     // Note that `InitializeSlots` does different number initialization steps
3614     // depending on the values of `transfer_uses_memcpy` and capacities.
3615     // Refer to the comment in `InitializeSlots` for more details.
3616     const bool grow_single_group =
3617         resize_helper.InitializeSlots<CharAlloc, sizeof(slot_type),
3618                                       PolicyTraits::transfer_uses_memcpy(),
3619                                       SooEnabled(), alignof(slot_type)>(
3620             common, CharAlloc(set->alloc_ref()), soo_slot_h2, sizeof(key_type),
3621             sizeof(value_type));
3622 
3623     // In the SooEnabled() case, capacity is never 0 so we don't check.
3624     if (!SooEnabled() && resize_helper.old_capacity() == 0) {
3625       // InitializeSlots did all the work including infoz().RecordRehash().
3626       return;
3627     }
3628     assert(resize_helper.old_capacity() > 0);
3629     // Nothing more to do in this case.
3630     if (was_soo && !had_soo_slot) return;
3631 
3632     slot_type* new_slots = set->slot_array();
3633     if (grow_single_group) {
3634       if (PolicyTraits::transfer_uses_memcpy()) {
3635         // InitializeSlots did all the work.
3636         return;
3637       }
3638       if (was_soo) {
3639         set->transfer(new_slots + resize_helper.SooSlotIndex(),
3640                       to_slot(resize_helper.old_soo_data()));
3641         return;
3642       } else {
3643         // We want GrowSizeIntoSingleGroup to be called here in order to make
3644         // InitializeSlots not depend on PolicyTraits.
3645         resize_helper.GrowSizeIntoSingleGroup<PolicyTraits>(common,
3646                                                             set->alloc_ref());
3647       }
3648     } else {
3649       // InitializeSlots prepares control bytes to correspond to empty table.
3650       const auto insert_slot = [&](slot_type* slot) {
3651         size_t hash = PolicyTraits::apply(HashElement{set->hash_ref()},
3652                                           PolicyTraits::element(slot));
3653         auto target = find_first_non_full(common, hash);
3654         SetCtrl(common, target.offset, H2(hash), sizeof(slot_type));
3655         set->transfer(new_slots + target.offset, slot);
3656         return target.probe_length;
3657       };
3658       if (was_soo) {
3659         insert_slot(to_slot(resize_helper.old_soo_data()));
3660         return;
3661       } else {
3662         auto* old_slots =
3663             reinterpret_cast<slot_type*>(resize_helper.old_slots());
3664         size_t total_probe_length = 0;
3665         for (size_t i = 0; i != resize_helper.old_capacity(); ++i) {
3666           if (IsFull(resize_helper.old_ctrl()[i])) {
3667             total_probe_length += insert_slot(old_slots + i);
3668           }
3669         }
3670         common.infoz().RecordRehash(total_probe_length);
3671       }
3672     }
3673     resize_helper.DeallocateOld<alignof(slot_type)>(CharAlloc(set->alloc_ref()),
3674                                                     sizeof(slot_type));
3675   }
3676 
3677   // Casting directly from e.g. char* to slot_type* can cause compilation errors
3678   // on objective-C. This function converts to void* first, avoiding the issue.
3679   static slot_type* to_slot(void* buf) {
3680     return reinterpret_cast<slot_type*>(buf);
3681   }
3682 
3683   // Requires that lhs does not have a full SOO slot.
3684   static void move_common(bool that_is_full_soo, allocator_type& rhs_alloc,
3685                           CommonFields& lhs, CommonFields&& rhs) {
3686     if (PolicyTraits::transfer_uses_memcpy() || !that_is_full_soo) {
3687       lhs = std::move(rhs);
3688     } else {
3689       lhs.move_non_heap_or_soo_fields(rhs);
3690       // TODO(b/303305702): add reentrancy guard.
3691       PolicyTraits::transfer(&rhs_alloc, to_slot(lhs.soo_data()),
3692                              to_slot(rhs.soo_data()));
3693     }
3694   }
3695 
3696   // Swaps common fields making sure to avoid memcpy'ing a full SOO slot if we
3697   // aren't allowed to do so.
3698   void swap_common(raw_hash_set& that) {
3699     using std::swap;
3700     if (PolicyTraits::transfer_uses_memcpy()) {
3701       swap(common(), that.common());
3702       return;
3703     }
3704     CommonFields tmp = CommonFields::CreateDefault<SooEnabled()>();
3705     const bool that_is_full_soo = that.is_full_soo();
3706     move_common(that_is_full_soo, that.alloc_ref(), tmp,
3707                 std::move(that.common()));
3708     move_common(is_full_soo(), alloc_ref(), that.common(), std::move(common()));
3709     move_common(that_is_full_soo, that.alloc_ref(), common(), std::move(tmp));
3710   }
3711 
3712   void maybe_increment_generation_or_rehash_on_move() {
3713     if (!SwisstableGenerationsEnabled() || capacity() == 0 || is_soo()) {
3714       return;
3715     }
3716     common().increment_generation();
3717     if (!empty() && common().should_rehash_for_bug_detection_on_move()) {
3718       resize(capacity());
3719     }
3720   }
3721 
3722   template<bool propagate_alloc>
3723   raw_hash_set& assign_impl(raw_hash_set&& that) {
3724     // We don't bother checking for this/that aliasing. We just need to avoid
3725     // breaking the invariants in that case.
3726     destructor_impl();
3727     move_common(that.is_full_soo(), that.alloc_ref(), common(),
3728                 std::move(that.common()));
3729     // TODO(b/296061262): move instead of copying hash/eq/alloc.
3730     hash_ref() = that.hash_ref();
3731     eq_ref() = that.eq_ref();
3732     CopyAlloc(alloc_ref(), that.alloc_ref(),
3733               std::integral_constant<bool, propagate_alloc>());
3734     that.common() = CommonFields::CreateDefault<SooEnabled()>();
3735     maybe_increment_generation_or_rehash_on_move();
3736     return *this;
3737   }
3738 
3739   raw_hash_set& move_elements_allocs_unequal(raw_hash_set&& that) {
3740     const size_t size = that.size();
3741     if (size == 0) return *this;
3742     reserve(size);
3743     for (iterator it = that.begin(); it != that.end(); ++it) {
3744       insert(std::move(PolicyTraits::element(it.slot())));
3745       that.destroy(it.slot());
3746     }
3747     if (!that.is_soo()) that.dealloc();
3748     that.common() = CommonFields::CreateDefault<SooEnabled()>();
3749     maybe_increment_generation_or_rehash_on_move();
3750     return *this;
3751   }
3752 
3753   raw_hash_set& move_assign(raw_hash_set&& that,
3754                             std::true_type /*propagate_alloc*/) {
3755     return assign_impl<true>(std::move(that));
3756   }
3757   raw_hash_set& move_assign(raw_hash_set&& that,
3758                             std::false_type /*propagate_alloc*/) {
3759     if (alloc_ref() == that.alloc_ref()) {
3760       return assign_impl<false>(std::move(that));
3761     }
3762     // Aliasing can't happen here because allocs would compare equal above.
3763     assert(this != &that);
3764     destructor_impl();
3765     // We can't take over that's memory so we need to move each element.
3766     // While moving elements, this should have that's hash/eq so copy hash/eq
3767     // before moving elements.
3768     // TODO(b/296061262): move instead of copying hash/eq.
3769     hash_ref() = that.hash_ref();
3770     eq_ref() = that.eq_ref();
3771     return move_elements_allocs_unequal(std::move(that));
3772   }
3773 
3774   template <class K>
3775   std::pair<iterator, bool> find_or_prepare_insert_soo(const K& key) {
3776     if (empty()) {
3777       const HashtablezInfoHandle infoz = try_sample_soo();
3778       if (infoz.IsSampled()) {
3779         resize_with_soo_infoz(infoz);
3780       } else {
3781         common().set_full_soo();
3782         return {soo_iterator(), true};
3783       }
3784     } else if (PolicyTraits::apply(EqualElement<K>{key, eq_ref()},
3785                                    PolicyTraits::element(soo_slot()))) {
3786       return {soo_iterator(), false};
3787     } else {
3788       resize(NextCapacity(SooCapacity()));
3789     }
3790     const size_t index =
3791         PrepareInsertAfterSoo(hash_ref()(key), sizeof(slot_type), common());
3792     return {iterator_at(index), true};
3793   }
3794 
3795   template <class K>
3796   std::pair<iterator, bool> find_or_prepare_insert_non_soo(const K& key) {
3797     assert(!is_soo());
3798     prefetch_heap_block();
3799     auto hash = hash_ref()(key);
3800     auto seq = probe(common(), hash);
3801     const ctrl_t* ctrl = control();
3802     while (true) {
3803       Group g{ctrl + seq.offset()};
3804       for (uint32_t i : g.Match(H2(hash))) {
3805         if (ABSL_PREDICT_TRUE(PolicyTraits::apply(
3806                 EqualElement<K>{key, eq_ref()},
3807                 PolicyTraits::element(slot_array() + seq.offset(i)))))
3808           return {iterator_at(seq.offset(i)), false};
3809       }
3810       auto mask_empty = g.MaskEmpty();
3811       if (ABSL_PREDICT_TRUE(mask_empty)) {
3812         size_t target = seq.offset(
3813             GetInsertionOffset(mask_empty, capacity(), hash, control()));
3814         return {iterator_at(PrepareInsertNonSoo(common(), hash,
3815                                                 FindInfo{target, seq.index()},
3816                                                 GetPolicyFunctions())),
3817                 true};
3818       }
3819       seq.next();
3820       assert(seq.index() <= capacity() && "full table!");
3821     }
3822   }
3823 
3824  protected:
3825   // Attempts to find `key` in the table; if it isn't found, returns an iterator
3826   // where the value can be inserted into, with the control byte already set to
3827   // `key`'s H2. Returns a bool indicating whether an insertion can take place.
3828   template <class K>
3829   std::pair<iterator, bool> find_or_prepare_insert(const K& key) {
3830     if (is_soo()) return find_or_prepare_insert_soo(key);
3831     return find_or_prepare_insert_non_soo(key);
3832   }
3833 
3834   // Constructs the value in the space pointed by the iterator. This only works
3835   // after an unsuccessful find_or_prepare_insert() and before any other
3836   // modifications happen in the raw_hash_set.
3837   //
3838   // PRECONDITION: iter was returned from find_or_prepare_insert(k), where k is
3839   // the key decomposed from `forward<Args>(args)...`, and the bool returned by
3840   // find_or_prepare_insert(k) was true.
3841   // POSTCONDITION: *m.iterator_at(i) == value_type(forward<Args>(args)...).
3842   template <class... Args>
3843   void emplace_at(iterator iter, Args&&... args) {
3844     construct(iter.slot(), std::forward<Args>(args)...);
3845 
3846     assert(PolicyTraits::apply(FindElement{*this}, *iter) == iter &&
3847            "constructed value does not match the lookup key");
3848   }
3849 
3850   iterator iterator_at(size_t i) ABSL_ATTRIBUTE_LIFETIME_BOUND {
3851     return {control() + i, slot_array() + i, common().generation_ptr()};
3852   }
3853   const_iterator iterator_at(size_t i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
3854     return const_cast<raw_hash_set*>(this)->iterator_at(i);
3855   }
3856 
3857   reference unchecked_deref(iterator it) { return it.unchecked_deref(); }
3858 
3859  private:
3860   friend struct RawHashSetTestOnlyAccess;
3861 
3862   // The number of slots we can still fill without needing to rehash.
3863   //
3864   // This is stored separately due to tombstones: we do not include tombstones
3865   // in the growth capacity, because we'd like to rehash when the table is
3866   // otherwise filled with tombstones: otherwise, probe sequences might get
3867   // unacceptably long without triggering a rehash. Callers can also force a
3868   // rehash via the standard `rehash(0)`, which will recompute this value as a
3869   // side-effect.
3870   //
3871   // See `CapacityToGrowth()`.
3872   size_t growth_left() const {
3873     assert(!is_soo());
3874     return common().growth_left();
3875   }
3876 
3877   GrowthInfo& growth_info() {
3878     assert(!is_soo());
3879     return common().growth_info();
3880   }
3881   GrowthInfo growth_info() const {
3882     assert(!is_soo());
3883     return common().growth_info();
3884   }
3885 
3886   // Prefetch the heap-allocated memory region to resolve potential TLB and
3887   // cache misses. This is intended to overlap with execution of calculating the
3888   // hash for a key.
3889   void prefetch_heap_block() const {
3890     if (is_soo()) return;
3891 #if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__)
3892     __builtin_prefetch(control(), 0, 1);
3893 #endif
3894   }
3895 
3896   CommonFields& common() { return settings_.template get<0>(); }
3897   const CommonFields& common() const { return settings_.template get<0>(); }
3898 
3899   ctrl_t* control() const {
3900     assert(!is_soo());
3901     return common().control();
3902   }
3903   slot_type* slot_array() const {
3904     assert(!is_soo());
3905     return static_cast<slot_type*>(common().slot_array());
3906   }
3907   slot_type* soo_slot() {
3908     assert(is_soo());
3909     return static_cast<slot_type*>(common().soo_data());
3910   }
3911   const slot_type* soo_slot() const {
3912     return const_cast<raw_hash_set*>(this)->soo_slot();
3913   }
3914   iterator soo_iterator() {
3915     return {SooControl(), soo_slot(), common().generation_ptr()};
3916   }
3917   const_iterator soo_iterator() const {
3918     return const_cast<raw_hash_set*>(this)->soo_iterator();
3919   }
3920   HashtablezInfoHandle infoz() {
3921     assert(!is_soo());
3922     return common().infoz();
3923   }
3924 
3925   hasher& hash_ref() { return settings_.template get<1>(); }
3926   const hasher& hash_ref() const { return settings_.template get<1>(); }
3927   key_equal& eq_ref() { return settings_.template get<2>(); }
3928   const key_equal& eq_ref() const { return settings_.template get<2>(); }
3929   allocator_type& alloc_ref() { return settings_.template get<3>(); }
3930   const allocator_type& alloc_ref() const {
3931     return settings_.template get<3>();
3932   }
3933 
3934   static const void* get_hash_ref_fn(const CommonFields& common) {
3935     auto* h = reinterpret_cast<const raw_hash_set*>(&common);
3936     return &h->hash_ref();
3937   }
3938   static void transfer_slot_fn(void* set, void* dst, void* src) {
3939     auto* h = static_cast<raw_hash_set*>(set);
3940     h->transfer(static_cast<slot_type*>(dst), static_cast<slot_type*>(src));
3941   }
3942   // Note: dealloc_fn will only be used if we have a non-standard allocator.
3943   static void dealloc_fn(CommonFields& common, const PolicyFunctions&) {
3944     auto* set = reinterpret_cast<raw_hash_set*>(&common);
3945 
3946     // Unpoison before returning the memory to the allocator.
3947     SanitizerUnpoisonMemoryRegion(common.slot_array(),
3948                                   sizeof(slot_type) * common.capacity());
3949 
3950     common.infoz().Unregister();
3951     Deallocate<BackingArrayAlignment(alignof(slot_type))>(
3952         &set->alloc_ref(), common.backing_array_start(),
3953         common.alloc_size(sizeof(slot_type), alignof(slot_type)));
3954   }
3955 
3956   static const PolicyFunctions& GetPolicyFunctions() {
3957     static constexpr PolicyFunctions value = {
3958         sizeof(slot_type),
3959         // TODO(b/328722020): try to type erase
3960         // for standard layout and alignof(Hash) <= alignof(CommonFields).
3961         std::is_empty<hasher>::value ? &GetHashRefForEmptyHasher
3962                                      : &raw_hash_set::get_hash_ref_fn,
3963         PolicyTraits::template get_hash_slot_fn<hasher>(),
3964         PolicyTraits::transfer_uses_memcpy()
3965             ? TransferRelocatable<sizeof(slot_type)>
3966             : &raw_hash_set::transfer_slot_fn,
3967         (std::is_same<SlotAlloc, std::allocator<slot_type>>::value
3968              ? &DeallocateStandard<alignof(slot_type)>
3969              : &raw_hash_set::dealloc_fn),
3970         &raw_hash_set::resize_impl,
3971     };
3972     return value;
3973   }
3974 
3975   // Bundle together CommonFields plus other objects which might be empty.
3976   // CompressedTuple will ensure that sizeof is not affected by any of the empty
3977   // fields that occur after CommonFields.
3978   absl::container_internal::CompressedTuple<CommonFields, hasher, key_equal,
3979                                             allocator_type>
3980       settings_{CommonFields::CreateDefault<SooEnabled()>(), hasher{},
3981                 key_equal{}, allocator_type{}};
3982 };
3983 
3984 // Erases all elements that satisfy the predicate `pred` from the container `c`.
3985 template <typename P, typename H, typename E, typename A, typename Predicate>
3986 typename raw_hash_set<P, H, E, A>::size_type EraseIf(
3987     Predicate& pred, raw_hash_set<P, H, E, A>* c) {
3988   const auto initial_size = c->size();
3989   for (auto it = c->begin(), last = c->end(); it != last;) {
3990     if (pred(*it)) {
3991       c->erase(it++);
3992     } else {
3993       ++it;
3994     }
3995   }
3996   return initial_size - c->size();
3997 }
3998 
3999 namespace hashtable_debug_internal {
4000 template <typename Set>
4001 struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> {
4002   using Traits = typename Set::PolicyTraits;
4003   using Slot = typename Traits::slot_type;
4004 
4005   static size_t GetNumProbes(const Set& set,
4006                              const typename Set::key_type& key) {
4007     if (set.is_soo()) return 0;
4008     size_t num_probes = 0;
4009     size_t hash = set.hash_ref()(key);
4010     auto seq = probe(set.common(), hash);
4011     const ctrl_t* ctrl = set.control();
4012     while (true) {
4013       container_internal::Group g{ctrl + seq.offset()};
4014       for (uint32_t i : g.Match(container_internal::H2(hash))) {
4015         if (Traits::apply(
4016                 typename Set::template EqualElement<typename Set::key_type>{
4017                     key, set.eq_ref()},
4018                 Traits::element(set.slot_array() + seq.offset(i))))
4019           return num_probes;
4020         ++num_probes;
4021       }
4022       if (g.MaskEmpty()) return num_probes;
4023       seq.next();
4024       ++num_probes;
4025     }
4026   }
4027 
4028   static size_t AllocatedByteSize(const Set& c) {
4029     size_t capacity = c.capacity();
4030     if (capacity == 0) return 0;
4031     size_t m =
4032         c.is_soo() ? 0 : c.common().alloc_size(sizeof(Slot), alignof(Slot));
4033 
4034     size_t per_slot = Traits::space_used(static_cast<const Slot*>(nullptr));
4035     if (per_slot != ~size_t{}) {
4036       m += per_slot * c.size();
4037     } else {
4038       for (auto it = c.begin(); it != c.end(); ++it) {
4039         m += Traits::space_used(it.slot());
4040       }
4041     }
4042     return m;
4043   }
4044 };
4045 
4046 }  // namespace hashtable_debug_internal
4047 }  // namespace container_internal
4048 ABSL_NAMESPACE_END
4049 }  // namespace absl
4050 
4051 #undef ABSL_SWISSTABLE_ENABLE_GENERATIONS
4052 #undef ABSL_SWISSTABLE_IGNORE_UNINITIALIZED
4053 #undef ABSL_SWISSTABLE_IGNORE_UNINITIALIZED_RETURN
4054 
4055 #endif  // ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
4056