// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "absl/container/internal/raw_hash_set.h"

#include <algorithm>
#include <atomic>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <memory>
#include <tuple>
#include <utility>

#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/dynamic_annotations.h"
#include "absl/base/internal/endian.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/optimization.h"
#include "absl/container/internal/container_memory.h"
#include "absl/container/internal/hashtable_control_bytes.h"
#include "absl/container/internal/hashtablez_sampler.h"
#include "absl/container/internal/raw_hash_set_resize_impl.h"
#include "absl/functional/function_ref.h"
#include "absl/hash/hash.h"

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {

// Represents a control byte corresponding to a full slot with arbitrary hash.
constexpr ctrl_t ZeroCtrlT() { return static_cast<ctrl_t>(0); }

// A single byte for default-constructed iterators. We leave it uninitialized
// because reading this memory is a bug.
ABSL_DLL char kDefaultIterSlot;

// We need one full byte followed by a sentinel byte for iterator::operator++.
ABSL_CONST_INIT ABSL_DLL const ctrl_t kSooControl[2] = {ZeroCtrlT(),
                                                        ctrl_t::kSentinel};
// We need one full byte followed by a sentinel byte for iterator::operator++.
ABSL_CONST_INIT ABSL_DLL const ctrl_t kInsertIteratorControl[2] = {
    ZeroCtrlT(), ctrl_t::kSentinel};

namespace {

#ifdef ABSL_SWISSTABLE_ASSERT
#error ABSL_SWISSTABLE_ASSERT cannot be directly set
#else
// We use this macro for assertions that users may see when the table is in an
// invalid state that sanitizers may help diagnose.
#define ABSL_SWISSTABLE_ASSERT(CONDITION) \
  assert((CONDITION) && "Try enabling sanitizers.")
#endif

void ValidateMaxSize([[maybe_unused]] size_t size,
                     [[maybe_unused]] size_t key_size,
                     [[maybe_unused]] size_t slot_size) {
  ABSL_SWISSTABLE_ASSERT(size <= MaxValidSize(key_size, slot_size));
}
void ValidateMaxCapacity(size_t capacity, size_t key_size, size_t slot_size) {
  if (capacity <= 1) return;
  ValidateMaxSize(CapacityToGrowth(PreviousCapacity(capacity)), key_size,
                  slot_size);
}

// Returns "random" seed.
inline size_t RandomSeed() {
  constexpr size_t kIncrement = 0xad53;
#ifdef ABSL_HAVE_THREAD_LOCAL
  static thread_local size_t counter = 0;
  counter += kIncrement;
  size_t value = counter;
#else   // ABSL_HAVE_THREAD_LOCAL
  static std::atomic<size_t> counter(0);
  size_t value = counter.fetch_add(kIncrement, std::memory_order_relaxed);
#endif  // ABSL_HAVE_THREAD_LOCAL
  return value ^ static_cast<size_t>(reinterpret_cast<uintptr_t>(&counter));
}

bool ShouldRehashForBugDetection(size_t capacity) {
  // Note: we can't use the abseil-random library because abseil-random
  // depends on swisstable. We want to return true with probability
  // `min(1, RehashProbabilityConstant() / capacity())`. In order to do this,
  // we probe based on a random hash and see if the offset is less than
  // RehashProbabilityConstant().
  return probe(ProbeCapacity{capacity}, absl::HashOf(RandomSeed()))
             .offset() < RehashProbabilityConstant();
}

// Find a non-deterministic hash for single group table.
// Last two bits are used to find a position for a newly inserted element after
// resize.
// This function basically using H2 last bits to save on shift operation.
size_t SingleGroupTableH1(size_t hash, PerTableSeed seed) {
  return hash ^ seed.seed();
}

// Returns the offset of the new element after resize from capacity 1 to 3.
size_t Resize1To3NewOffset(size_t hash, PerTableSeed seed) {
  // After resize from capacity 1 to 3, we always have exactly the slot with
  // index 1 occupied, so we need to insert either at index 0 or index 2.
  static_assert(SooSlotIndex() == 1);
  return SingleGroupTableH1(hash, seed) & 2;
}

// Returns the address of the ith slot in slots where each slot occupies
// slot_size.
inline void* SlotAddress(void* slot_array, size_t slot, size_t slot_size) {
  return static_cast<void*>(static_cast<char*>(slot_array) +
                            (slot * slot_size));
}

// Returns the address of the slot `i` iterations after `slot` assuming each
// slot has the specified size.
inline void* NextSlot(void* slot, size_t slot_size, size_t i = 1) {
  return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(slot) +
                                 slot_size * i);
}

// Returns the address of the slot just before `slot` assuming each slot has the
// specified size.
inline void* PrevSlot(void* slot, size_t slot_size) {
  return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(slot) - slot_size);
}

}  // namespace

// Must be defined out-of-line to avoid MSVC error C2482 on some platforms,
// which is caused by non-constexpr initialization.
uint16_t NextHashTableSeed() {
  static_assert(PerTableSeed::kBitCount <= 16);
  return static_cast<uint16_t>(RandomSeed());
}

GenerationType* EmptyGeneration() {
  if (SwisstableGenerationsEnabled()) {
    constexpr size_t kNumEmptyGenerations = 1024;
    static constexpr GenerationType kEmptyGenerations[kNumEmptyGenerations]{};
    return const_cast<GenerationType*>(
        &kEmptyGenerations[RandomSeed() % kNumEmptyGenerations]);
  }
  return nullptr;
}

bool CommonFieldsGenerationInfoEnabled::
    should_rehash_for_bug_detection_on_insert(size_t capacity) const {
  if (reserved_growth_ == kReservedGrowthJustRanOut) return true;
  if (reserved_growth_ > 0) return false;
  return ShouldRehashForBugDetection(capacity);
}

bool CommonFieldsGenerationInfoEnabled::should_rehash_for_bug_detection_on_move(
    size_t capacity) const {
  return ShouldRehashForBugDetection(capacity);
}

namespace {

// Probes an array of control bits using a probe sequence,
// and returns the mask corresponding to the first group with a deleted or empty
// slot.
inline Group::NonIterableBitMaskType probe_till_first_non_full_group(
    const ctrl_t* ctrl, probe_seq<Group::kWidth>& seq,
    [[maybe_unused]] size_t capacity) {
  while (true) {
    GroupFullEmptyOrDeleted g{ctrl + seq.offset()};
    auto mask = g.MaskEmptyOrDeleted();
    if (mask) {
      return mask;
    }
    seq.next();
    ABSL_SWISSTABLE_ASSERT(seq.index() <= capacity && "full table!");
  }
}

FindInfo find_first_non_full_from_h1(const ctrl_t* ctrl, size_t h1,
                                     HashtableCapacity capacity) {
  const size_t cap = capacity.capacity();
  auto seq = probe_h1(ProbeCapacity{cap}, h1);
  if (IsEmptyOrDeleted(ctrl[seq.offset()])) {
    return {seq.offset(), /*probe_length=*/0};
  }
  auto mask = probe_till_first_non_full_group(ctrl, seq, cap);
  return {seq.offset(mask.LowestBitSet()), seq.index()};
}

// Probes an array of control bits using a probe sequence derived from `hash`,
// and returns the offset corresponding to the first deleted or empty slot.
//
// Behavior when the entire table is full is undefined.
//
// NOTE: this function must work with tables having both empty and deleted
// slots in the same group. Such tables appear during `erase()`.
FindInfo find_first_non_full(const CommonFields& common, size_t hash) {
  return find_first_non_full_from_h1(common.control(), H1(hash),
                                     common.capacity_impl());
}

// Same as `find_first_non_full`, but returns the mask corresponding to the
// first group with a deleted or empty slot.
std::pair<FindInfo, Group::NonIterableBitMaskType> find_first_non_full_group(
    const CommonFields& common, size_t hash) {
  auto seq = probe(common, hash);
  auto mask =
      probe_till_first_non_full_group(common.control(), seq, common.capacity());
  return {{seq.offset(), seq.index()}, mask};
}

// Whether a table fits in half a group. A half-group table fits entirely into a
// probing group, i.e., has a capacity < `Group::kWidth`.
//
// In half-group mode we are able to use the whole capacity. The extra control
// bytes give us at least one "empty" control byte to stop the iteration.
// This is important to make 1 a valid capacity.
//
// In half-group mode only the first `capacity` control bytes after the sentinel
// are valid. The rest contain dummy ctrl_t::kEmpty values that do not
// represent a real slot.
constexpr bool is_half_group(size_t capacity) {
  return capacity < Group::kWidth - 1;
}

template <class Fn>
void IterateOverFullSlotsImpl(const CommonFields& c, size_t slot_size, Fn cb) {
  const size_t cap = c.capacity();
  ABSL_ASSUME(cap > kMaxSmallCapacity);
  const ctrl_t* ctrl = c.control();
  void* slot = c.slot_array(cap);
  if (is_half_group(cap)) {
    // Mirrored/cloned control bytes in half-group table are also located in the
    // first group (starting from position 0). We are taking group from position
    // `capacity` in order to avoid duplicates.

    // Half-group tables capacity fits into portable group, where
    // GroupPortableImpl::MaskFull is more efficient for the
    // capacity <= GroupPortableImpl::kWidth.
    ABSL_SWISSTABLE_ASSERT(cap <= GroupPortableImpl::kWidth &&
                           "unexpectedly large half-group capacity");
    static_assert(Group::kWidth >= GroupPortableImpl::kWidth,
                  "unexpected group width");
    // Group starts from kSentinel slot, so indices in the mask will
    // be increased by 1.
    const auto mask = GroupPortableImpl(ctrl + cap).MaskFull();
    --ctrl;
    slot = PrevSlot(slot, slot_size);
    for (uint32_t i : mask) {
      cb(ctrl + i, SlotAddress(slot, i, slot_size));
    }
    return;
  }
  size_t remaining = c.size();
  ABSL_ATTRIBUTE_UNUSED const size_t original_size_for_assert = remaining;
  while (remaining != 0) {
    for (uint32_t i : GroupFullEmptyOrDeleted(ctrl).MaskFull()) {
      ABSL_SWISSTABLE_ASSERT(IsFull(ctrl[i]) &&
                             "hash table was modified unexpectedly");
      cb(ctrl + i, SlotAddress(slot, i, slot_size));
      --remaining;
    }
    ctrl += Group::kWidth;
    slot = NextSlot(slot, slot_size, Group::kWidth);
    ABSL_SWISSTABLE_ASSERT(
        (remaining == 0 || *(ctrl - 1) != ctrl_t::kSentinel) &&
        "hash table was modified unexpectedly");
  }
  // NOTE: erasure of the current element is allowed in callback for
  // absl::erase_if specialization. So we use `>=`.
  ABSL_SWISSTABLE_ASSERT(original_size_for_assert >= c.size() &&
                         "hash table was modified unexpectedly");
}

// NOTE: we don't use structure with bit fields for GrowthInfo because for
// correctness we rely on the lower bound being the most significant byte.

// Returns the increment that needs to be added to the packed full growth info
// in order to increase lower bound by lower_bound_increment and increase
// overflow growth left by overflow_increment.
constexpr uint64_t GetPackedIncrement(uint64_t lower_bound_increment,
                                      uint64_t overflow_increment) {
  return (lower_bound_increment << GrowthInfoAccessor::kLowerBoundShift) +
         overflow_increment;
}

// Returns the increment that needs to be added to the packed full growth info
// in order to increase lower bound by overflow_to_lower_bound_size and
// decrease overflow growth left by overflow_to_lower_bound_size.
constexpr uint64_t GetRebalanceIncrement(
    uint64_t overflow_to_lower_bound_size) {
  return GetPackedIncrement(overflow_to_lower_bound_size,
                            0u - overflow_to_lower_bound_size);
}

// Returns the number of elements left to grow in the full growth info.
constexpr uint64_t GetOverflowGrowthLeftFromPacked(
    uint64_t packed_full_growth_info) {
  constexpr uint64_t kFullGrowthMask =
      (uint64_t{1} << GrowthInfoAccessor::kLowerBoundShift) - 1;
  return packed_full_growth_info & kFullGrowthMask;
}

// Returns the GrowthInfoLowerBound object containing the information
// about minimum growth left.
constexpr GrowthInfoLowerBound GetGrowthInfoLowerBoundFromPacked(
    uint64_t packed_full_growth_info) {
  return GrowthInfoLowerBound(packed_full_growth_info >>
                              GrowthInfoAccessor::kLowerBoundShift);
}

// Returns the number of elements left to grow in the lower bound.
constexpr uint64_t GetGrowthLeftLowerBoundFromPacked(
    uint64_t packed_full_growth_info) {
  return GetGrowthInfoLowerBoundFromPacked(packed_full_growth_info)
      .GetGrowthLeft();
}

// Returns the total number of elements left to grow in the full growth info.
// Assumes that the table has capacity > kMaxGrowthLeftLowerBound.
uint64_t GetGrowthLeftTotalBigCapacity(void* full_growth_info) {
  uint64_t packed_full_growth_left = little_endian::Load64(full_growth_info);
  return GetOverflowGrowthLeftFromPacked(packed_full_growth_left) +
         GetGrowthLeftLowerBoundFromPacked(packed_full_growth_left);
}

}  // namespace

void CommonFields::AssertNotDebugCapacityImpl() const {
  const HashtableCapacity cap = maybe_invalid_capacity();
  if (ABSL_PREDICT_TRUE(cap.IsValid())) {
    return;
  }
  assert(!cap.IsReentrance() &&
         "Reentrant container access during element construction/destruction "
         "is not allowed.");
  if (cap.IsDestroyed()) {
    ABSL_RAW_LOG(FATAL, "Use of destroyed hash table.");
  }
  if (SwisstableGenerationsEnabled() && ABSL_PREDICT_FALSE(cap.IsMovedFrom())) {
    if (cap.IsSelfMovedFrom()) {
      // If this log triggers, then a hash table was move-assigned to itself
      // and then used again later without being reinitialized.
      ABSL_RAW_LOG(FATAL, "Use of self-move-assigned hash table.");
    }
    ABSL_RAW_LOG(FATAL, "Use of moved-from hash table.");
  }
}

void GrowthInfoAccessor::InitGrowthLeftNoDeleted(size_t growth_left,
                                                 size_t capacity) {
  if (capacity <= GrowthInfoLowerBound::kMaxGrowthLeftLowerBound) {
    *growth_info_lower_bound_ = static_cast<uint8_t>(growth_left);
  } else {
    uint64_t lower_bound =
        (std::min)(uint64_t{growth_left},
                   GrowthInfoLowerBound::kMaxGrowthLeftLowerBound);
    little_endian::Store64(
        full_growth_info_ptr(),
        GetPackedIncrement(lower_bound, growth_left - lower_bound));
  }
}

GrowthInfoLowerBound GrowthInfoAccessor::RebalanceGrowthLeftLowerBound(
    size_t capacity) {
  auto growth_left_lower_bound = GetGrowthInfoLowerBound();
  if (capacity <= GrowthInfoLowerBound::kMaxGrowthLeftLowerBound ||
      // For tables with deleted slots, we often call rebalance even if
      // we have growth left in the lower bound.
      growth_left_lower_bound.HasDeletedAndGrowthLeft()) {
    return growth_left_lower_bound;
  } else {
    return RebalanceGrowthLeftLowerBoundLargeCapacity();
  }
}

size_t GrowthInfoAccessor::GetGrowthLeftTotalSlow(size_t capacity) const {
  if (capacity <= GrowthInfoLowerBound::kMaxGrowthLeftLowerBound) {
    return GetGrowthLeftLowerBound();
  } else {
    return static_cast<size_t>(
        GetGrowthLeftTotalBigCapacity(full_growth_info_ptr()));
  }
}

ABSL_ATTRIBUTE_NOINLINE GrowthInfoLowerBound
GrowthInfoAccessor::RebalanceGrowthLeftLowerBoundLargeCapacity() {
  void* full_growth_info = full_growth_info_ptr();
  uint64_t packed_full_growth_info = little_endian::Load64(full_growth_info);
  uint64_t overflow_growth_left =
      GetOverflowGrowthLeftFromPacked(packed_full_growth_info);
  uint64_t lower_bound_growth_left =
      GetGrowthLeftLowerBoundFromPacked(packed_full_growth_info);
  uint64_t overflow_to_lower_bound_size =
      (std::min)(overflow_growth_left,
                 GrowthInfoLowerBound::kMaxGrowthLeftLowerBound -
                     lower_bound_growth_left);
  packed_full_growth_info +=
      GetRebalanceIncrement(overflow_to_lower_bound_size);
  little_endian::Store64(full_growth_info, packed_full_growth_info);
  auto result = GetGrowthInfoLowerBoundFromPacked(packed_full_growth_info);
  ABSL_SWISSTABLE_ASSERT(result.HasNoDeleted() ==
                         GetGrowthInfoLowerBound().HasNoDeleted());
  ABSL_SWISSTABLE_ASSERT(
      (result.GetGrowthLeft() > 0 ||
       GetGrowthLeftTotalBigCapacity(full_growth_info_ptr()) == 0) &&
      "rebalance may return 0 only if we have absolutely no growth left");
  return result;
}

void GrowthInfoAccessor::OverwriteFullAsEmpty() {
  if (GetGrowthLeftLowerBound() <
      GrowthInfoLowerBound::kMaxGrowthLeftLowerBound) {
    ++(*growth_info_lower_bound_);
  } else {
    constexpr uint64_t kIncrement = GetPackedIncrement(
        /*lower_bound_increment=*/0, /*overflow_increment=*/1);
    void* const full_growth_info = full_growth_info_ptr();
    little_endian::Store64(
        full_growth_info, little_endian::Load64(full_growth_info) + kIncrement);
  }
}

void ConvertDeletedToEmptyAndFullToDeleted(ctrl_t* ctrl, size_t capacity) {
  ABSL_SWISSTABLE_ASSERT(ctrl[capacity] == ctrl_t::kSentinel);
  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(capacity));
  for (ctrl_t* pos = ctrl; pos < ctrl + capacity; pos += Group::kWidth) {
    Group{pos}.ConvertSpecialToEmptyAndFullToDeleted(pos);
  }
  // Copy the cloned ctrl bytes.
  std::memcpy(ctrl + capacity + 1, ctrl, NumClonedBytes());
  ctrl[capacity] = ctrl_t::kSentinel;
}

void IterateOverFullSlots(const CommonFields& c, size_t slot_size,
                          absl::FunctionRef<void(const ctrl_t*, void*)> cb) {
  IterateOverFullSlotsImpl(c, slot_size, cb);
}

HashtablezInfoHandle CommonFields::infoz_ptr() const {
  // growth_info is stored before control bytes.
  ABSL_SWISSTABLE_ASSERT(has_infoz());
  HashtablezInfoHandle res;
  void* src = reinterpret_cast<char*>(control()) -
              MetadataBeforeControlSize(/*has_infoz=*/true, capacity());
  std::memcpy(&res, src, sizeof(HashtablezInfoHandle));
  return res;
}

void CommonFields::set_infoz(HashtablezInfoHandle infoz) {
  ABSL_SWISSTABLE_ASSERT(has_infoz());
  void* dst = reinterpret_cast<char*>(control()) -
              MetadataBeforeControlSize(/*has_infoz=*/true, capacity());
  std::memcpy(dst, &infoz, sizeof(HashtablezInfoHandle));
}

namespace {

void ResetGrowthLeft(GrowthInfoAccessor growth_info, size_t capacity,
                     size_t occupied_elements) {
  growth_info.InitGrowthLeftNoDeleted(
      CapacityToGrowth(capacity) - occupied_elements, capacity);
}

// Finds guaranteed to exists empty slot from the given position.
// NOTE: this function is almost never triggered inside of the
// DropDeletesWithoutResize, so we keep it simple.
// The table is rather sparse, so empty slot will be found very quickly.
size_t FindEmptySlot(size_t start, size_t end, const ctrl_t* ctrl) {
  for (size_t i = start; i < end; ++i) {
    if (IsEmpty(ctrl[i])) {
      return i;
    }
  }
  ABSL_UNREACHABLE();
}

// Finds guaranteed to exist full slot starting from the given position.
// NOTE: this function is only triggered for rehash(0), when we need to
// go back to SOO state, so we keep it simple.
size_t FindFirstFullSlot(size_t start, size_t end, const ctrl_t* ctrl) {
  for (size_t i = start; i < end; ++i) {
    if (IsFull(ctrl[i])) {
      return i;
    }
  }
  ABSL_UNREACHABLE();
}

void PrepareInsertCommon(CommonFields& common) {
  common.increment_size();
  common.maybe_increment_generation_on_insert();
}

// Sets sanitizer poisoning for slot corresponding to control byte being set.
inline void DoSanitizeOnSetCtrl(const CommonFields& c, size_t i, ctrl_t h,
                                size_t slot_size) {
  const size_t cap = c.capacity();
  ABSL_ASSUME(cap > kMaxSmallCapacity);
  ABSL_SWISSTABLE_ASSERT(i < cap);
  auto* slot_i = static_cast<const char*>(c.slot_array(cap)) + i * slot_size;
  if (IsFull(h)) {
    SanitizerUnpoisonMemoryRegion(slot_i, slot_size);
  } else {
    SanitizerPoisonMemoryRegion(slot_i, slot_size);
  }
}

// Sets `ctrl[i]` to `h`.
//
// Unlike setting it directly, this function will perform bounds checks and
// mirror the value to the cloned tail if necessary.
inline void SetCtrlNoSanitizeImpl(const CommonFields& c, size_t i, ctrl_t h) {
  ABSL_SWISSTABLE_ASSERT(i < c.capacity());
  ctrl_t* ctrl = c.control();
  const size_t cap = c.capacity();
  ctrl[i] = h;
  ctrl[((i - NumClonedBytes()) & cap) + (NumClonedBytes() & cap)] = h;
}

inline void SetCtrl(const CommonFields& c, size_t i, ctrl_t h,
                    size_t slot_size) {
  ABSL_SWISSTABLE_ASSERT(!c.is_small());
  DoSanitizeOnSetCtrl(c, i, h, slot_size);
  SetCtrlNoSanitizeImpl(c, i, h);
}
// Overload for setting to an occupied `h2_t` rather than a special `ctrl_t`.
inline void SetCtrl(const CommonFields& c, size_t i, h2_t h, size_t slot_size) {
  SetCtrl(c, i, static_cast<ctrl_t>(h), slot_size);
}

// Sets `ctrl[i]` to `ctrl_t::kSentinel`.
//
// Unlike setting it directly, this function will perform bounds checks and
// mirror the value to the cloned tail if necessary.
inline void BlockCtrl(const CommonFields& c, size_t i) {
  ABSL_SWISSTABLE_ASSERT(!c.is_small());
  SetCtrlNoSanitizeImpl(c, i, ctrl_t::kSentinel);
}

// Like SetCtrl, but in a single group table, we can save some operations when
// setting the cloned control byte.
inline void SetCtrlInSingleGroupTable(const CommonFields& c, size_t i, ctrl_t h,
                                      size_t slot_size) {
  const size_t cap = c.capacity();
  ABSL_SWISSTABLE_ASSERT(!c.is_small());
  ABSL_SWISSTABLE_ASSERT(is_single_group(cap));
  DoSanitizeOnSetCtrl(c, i, h, slot_size);
  ctrl_t* ctrl = c.control();
  ctrl[i] = h;
  ctrl[i + cap + 1] = h;
}
// Overload for setting to an occupied `h2_t` rather than a special `ctrl_t`.
inline void SetCtrlInSingleGroupTable(const CommonFields& c, size_t i, h2_t h,
                                      size_t slot_size) {
  SetCtrlInSingleGroupTable(c, i, static_cast<ctrl_t>(h), slot_size);
}

// Like SetCtrl, but in a table with capacity >= Group::kWidth - 1,
// we can save some operations when setting the cloned control byte.
inline void SetCtrlInLargeTable(const CommonFields& c, size_t i, ctrl_t h,
                                size_t slot_size) {
  ABSL_SWISSTABLE_ASSERT(c.capacity() >= Group::kWidth - 1);
  DoSanitizeOnSetCtrl(c, i, h, slot_size);
  ctrl_t* ctrl = c.control();
  ctrl[i] = h;
  ctrl[((i - NumClonedBytes()) & c.capacity()) + NumClonedBytes()] = h;
}
// Overload for setting to an occupied `h2_t` rather than a special `ctrl_t`.
inline void SetCtrlInLargeTable(const CommonFields& c, size_t i, h2_t h,
                                size_t slot_size) {
  SetCtrlInLargeTable(c, i, static_cast<ctrl_t>(h), slot_size);
}

void BlockControlBytes(CommonFields& common, size_t blocked_element_count) {
  const size_t capacity = common.capacity();
  while (blocked_element_count > 0) {
    BlockCtrl(common, capacity - blocked_element_count);
    --blocked_element_count;
  }
}

void* DropDeletesWithoutResizeAndPrepareInsert(
    CommonFields& common, const PolicyFunctions& __restrict policy,
    size_t new_hash) {
  void* set = &common;
  const size_t capacity = common.capacity();
  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(capacity));
  ABSL_SWISSTABLE_ASSERT(!is_single_group(capacity));
  ABSL_ASSUME(capacity > kMaxSmallCapacity);

  ctrl_t* ctrl = common.control();
  void* slot_array = common.slot_array(capacity);
  // Algorithm:
  // - mark all DELETED slots as EMPTY
  // - mark all FULL slots as DELETED
  // - for each slot marked as DELETED
  //     hash = Hash(element)
  //     target = find_first_non_full(hash)
  //     if target is in the same group
  //       mark slot as FULL
  //     else if target is EMPTY
  //       transfer element to target
  //       mark slot as EMPTY
  //       mark target as FULL
  //     else if target is DELETED
  //       swap current element with target element
  //       mark target as FULL
  //       repeat procedure for current slot with moved from element (target)
  const size_t blocked_element_count = common.blocked_element_count();
  ConvertDeletedToEmptyAndFullToDeleted(ctrl, capacity);
  BlockControlBytes(common, blocked_element_count);
  const void* hash_fn = policy.hash_fn(common);
  auto hasher = policy.hash_slot;
  auto transfer_n = policy.transfer_n;
  const size_t slot_size = policy.slot_size;

  size_t total_probe_length = 0;
  void* slot_ptr = SlotAddress(slot_array, 0, slot_size);

  // The index of an empty slot that can be used as temporary memory for
  // the swap operation.
  constexpr size_t kUnknownId = ~size_t{};
  size_t tmp_space_id = kUnknownId;

  for (size_t i = 0; i != capacity;
       ++i, slot_ptr = NextSlot(slot_ptr, slot_size)) {
    ABSL_SWISSTABLE_ASSERT(slot_ptr == SlotAddress(slot_array, i, slot_size));
    if (IsEmpty(ctrl[i])) {
      tmp_space_id = i;
      continue;
    }
    if (!IsDeleted(ctrl[i])) continue;
    const size_t hash = (*hasher)(hash_fn, slot_ptr, common.seed().seed());
    const FindInfo target = find_first_non_full(common, hash);
    const size_t new_i = target.offset;
    total_probe_length += target.probe_length;

    // Verify if the old and new i fall within the same group wrt the hash.
    // If they do, we don't need to move the object as it falls already in the
    // best probe we can.
    const size_t probe_offset = probe(common, hash).offset();
    const h2_t h2 = H2(hash);
    const auto probe_index = [probe_offset, capacity](size_t pos) {
      return ((pos - probe_offset) & capacity) / Group::kWidth;
    };

    // Element doesn't move.
    if (ABSL_PREDICT_TRUE(probe_index(new_i) == probe_index(i))) {
      SetCtrlInLargeTable(common, i, h2, slot_size);
      continue;
    }

    void* new_slot_ptr = SlotAddress(slot_array, new_i, slot_size);
    if (IsEmpty(ctrl[new_i])) {
      // Transfer element to the empty spot.
      // SetCtrl poisons/unpoisons the slots so we have to call it at the
      // right time.
      SetCtrlInLargeTable(common, new_i, h2, slot_size);
      (*transfer_n)(set, new_slot_ptr, slot_ptr, 1);
      SetCtrlInLargeTable(common, i, ctrl_t::kEmpty, slot_size);
      // Initialize or change empty space id.
      tmp_space_id = i;
    } else {
      ABSL_SWISSTABLE_ASSERT(IsDeleted(ctrl[new_i]));
      SetCtrlInLargeTable(common, new_i, h2, slot_size);
      // Until we are done rehashing, DELETED marks previously FULL slots.

      if (tmp_space_id == kUnknownId) {
        tmp_space_id = FindEmptySlot(i + 1, capacity, ctrl);
      }
      void* tmp_space = SlotAddress(slot_array, tmp_space_id, slot_size);
      SanitizerUnpoisonMemoryRegion(tmp_space, slot_size);

      // Swap i and new_i elements.
      (*transfer_n)(set, tmp_space, new_slot_ptr, 1);
      (*transfer_n)(set, new_slot_ptr, slot_ptr, 1);
      (*transfer_n)(set, slot_ptr, tmp_space, 1);

      SanitizerPoisonMemoryRegion(tmp_space, slot_size);

      // repeat the processing of the ith slot
      --i;
      slot_ptr = PrevSlot(slot_ptr, slot_size);
    }
  }
  // Prepare insert for the new element.
  PrepareInsertCommon(common);
  ResetGrowthLeft(common.growth_info(), capacity,
                  common.size() + blocked_element_count);
  FindInfo find_info = find_first_non_full(common, new_hash);
  SetCtrlInLargeTable(common, find_info.offset, H2(new_hash), slot_size);
  common.infoz().RecordInsertMiss(new_hash, find_info.probe_length);
  common.infoz().RecordRehash(total_probe_length);
  return SlotAddress(slot_array, find_info.offset, slot_size);
}

bool WasNeverFull(CommonFields& c, size_t index) {
  if (is_single_group(c.capacity())) {
    return true;
  }
  const size_t index_before = (index - Group::kWidth) & c.capacity();
  const auto empty_after = Group(c.control() + index).MaskEmpty();
  const auto empty_before = Group(c.control() + index_before).MaskEmpty();

  // We count how many consecutive non empties we have to the right and to the
  // left of `it`. If the sum is >= kWidth then there is at least one probe
  // window that might have seen a full group.
  return empty_before && empty_after &&
         static_cast<size_t>(empty_after.TrailingZeros()) +
                 empty_before.LeadingZeros() <
             Group::kWidth;
}

// Updates the control bytes to indicate a completely empty table such that all
// control bytes are kEmpty except for the kSentinel bytes.
// If the table has blocked elements, last `blocked_element_count` are set to
// kSentinel.
void ResetCtrl(CommonFields& common, size_t slot_size,
               size_t blocked_element_count) {
  ABSL_SWISSTABLE_ASSERT(IsCapacityValidForBlockedElements(common.capacity()) ||
                         blocked_element_count == 0);
  const size_t capacity = common.capacity();
  ctrl_t* ctrl = common.control();
  static constexpr size_t kTwoGroupCapacity = 2 * Group::kWidth - 1;
  if (ABSL_PREDICT_TRUE(capacity <= kTwoGroupCapacity)) {
    if (IsSmallCapacity(capacity)) return;
    std::memset(ctrl, static_cast<int8_t>(ctrl_t::kEmpty), Group::kWidth);
    std::memset(ctrl + capacity, static_cast<int8_t>(ctrl_t::kEmpty),
                Group::kWidth);
    if (capacity == kTwoGroupCapacity) {
      std::memset(ctrl + Group::kWidth, static_cast<int8_t>(ctrl_t::kEmpty),
                  Group::kWidth);
    }
  } else {
    std::memset(ctrl, static_cast<int8_t>(ctrl_t::kEmpty),
                capacity + 1 + NumClonedBytes());
  }
  ctrl[capacity] = ctrl_t::kSentinel;
  SanitizerPoisonMemoryRegion(common.slot_array(capacity),
                              slot_size * (capacity - blocked_element_count));
  BlockControlBytes(common, blocked_element_count);
}

// Initializes control bytes for growing from capacity 1 to 3.
// `orig_h2` is placed in the position `SooSlotIndex()`.
// `new_h2` is placed in the position `new_offset`.
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void InitializeThreeElementsControlBytes(
    h2_t orig_h2, h2_t new_h2, size_t new_offset, ctrl_t* new_ctrl) {
  static constexpr size_t kNewCapacity = NextCapacity(SooCapacity());
  static_assert(kNewCapacity == 3);
  static_assert(is_single_group(kNewCapacity));
  static_assert(SooSlotIndex() == 1);
  ABSL_SWISSTABLE_ASSERT(new_offset == 0 || new_offset == 2);

  static constexpr uint64_t kEmptyXorSentinel =
      static_cast<uint8_t>(ctrl_t::kEmpty) ^
      static_cast<uint8_t>(ctrl_t::kSentinel);
  static constexpr uint64_t kEmpty64 = static_cast<uint8_t>(ctrl_t::kEmpty);
  static constexpr size_t kMirroredSooSlotIndex =
      SooSlotIndex() + kNewCapacity + 1;
  // The first 8 bytes, where SOO slot original and mirrored positions are
  // replaced with 0.
  // Result will look like: E0ESE0EE
  static constexpr uint64_t kFirstCtrlBytesWithZeroes =
      k8EmptyBytes ^ (kEmpty64 << (8 * SooSlotIndex())) ^
      (kEmptyXorSentinel << (8 * kNewCapacity)) ^
      (kEmpty64 << (8 * kMirroredSooSlotIndex));

  const uint64_t soo_h2 = static_cast<uint64_t>(orig_h2);
  const uint64_t new_h2_xor_empty =
      static_cast<uint64_t>(new_h2 ^ static_cast<uint8_t>(ctrl_t::kEmpty));
  // Fill the original and mirrored bytes for SOO slot.
  // Result will look like:
  // EHESEHEE
  // Where H = soo_h2, E = kEmpty, S = kSentinel.
  uint64_t first_ctrl_bytes =
      ((soo_h2 << (8 * SooSlotIndex())) | kFirstCtrlBytesWithZeroes) |
      (soo_h2 << (8 * kMirroredSooSlotIndex));
  // Replace original and mirrored empty bytes for the new position.
  // Result for new_offset 0 will look like:
  // NHESNHEE
  // Where H = soo_h2, N = H2(new_hash), E = kEmpty, S = kSentinel.
  // Result for new_offset 2 will look like:
  // EHNSEHNE
  first_ctrl_bytes ^= (new_h2_xor_empty << (8 * new_offset));
  size_t new_mirrored_offset = new_offset + kNewCapacity + 1;
  first_ctrl_bytes ^= (new_h2_xor_empty << (8 * new_mirrored_offset));

  // Fill last bytes with kEmpty.
  std::memset(new_ctrl + kNewCapacity, static_cast<int8_t>(ctrl_t::kEmpty),
              Group::kWidth);
  // Overwrite the first 8 bytes with first_ctrl_bytes.
  absl::little_endian::Store64(new_ctrl, first_ctrl_bytes);

  // Example for group size 16:
  // new_ctrl after 1st memset =      ???EEEEEEEEEEEEEEEE
  // new_offset 0:
  // new_ctrl after 2nd store  =      NHESNHEEEEEEEEEEEEE
  // new_offset 2:
  // new_ctrl after 2nd store  =      EHNSEHNEEEEEEEEEEEE

  // Example for group size 8:
  // new_ctrl after 1st memset =      ???EEEEEEEE
  // new_offset 0:
  // new_ctrl after 2nd store  =      NHESNHEEEEE
  // new_offset 2:
  // new_ctrl after 2nd store  =      EHNSEHNEEEE
}

// ClearBackingArrayNoReuse clears the backing array and sets the common
// fields to the default values for empty non-allocated tables.
// REQUIRES: c.capacity > policy.soo_capacity.
void ClearBackingArrayNoReuse(CommonFields& c,
                              const PolicyFunctions& __restrict policy,
                              void* alloc) {
  ABSL_SWISSTABLE_ASSERT(c.capacity() > policy.soo_capacity());
  // We need to record infoz before calling dealloc, which will unregister
  // infoz.
  c.infoz().RecordClearedReservation();
  c.infoz().RecordStorageChanged(0, policy.soo_capacity());
  c.infoz().Unregister();
  (*policy.dealloc)(alloc, c.capacity(), c.control(), policy.slot_size,
                    policy.slot_align, c.has_infoz(),
                    c.blocked_element_count());
  c = policy.soo_enabled ? CommonFields{soo_tag_t{}}
                         : CommonFields{non_soo_tag_t{}};
}

template <bool kSooEnabled>
void* SingleSlotAddress(CommonFields& c) {
  return kSooEnabled ? c.soo_data() : c.slot_array(/*capacity=*/1);
}

template <bool kSooEnabled>
void DecrementSmallSize(CommonFields& c) {
  if constexpr (kSooEnabled) {
    c.set_empty_soo();
  } else {
    c.decrement_size();
  }
}

}  // namespace

void EraseMetaOnlySmall(CommonFields& c, bool soo_enabled, size_t slot_size) {
  ABSL_SWISSTABLE_ASSERT(c.is_small());
  if (soo_enabled) {
    c.set_empty_soo();
    return;
  }
  c.decrement_size();
  c.infoz().RecordErase();
  SanitizerPoisonMemoryRegion(SingleSlotAddress</*kSooEnabled=*/false>(c),
                              slot_size);
}

void EraseMetaOnlyLarge(CommonFields& c, size_t index, size_t slot_size) {
  ABSL_SWISSTABLE_ASSERT(!c.is_small());
  ABSL_SWISSTABLE_ASSERT(IsFull(c.control()[index]) &&
                         "erasing a dangling iterator");
  c.decrement_size();
  c.infoz().RecordErase();

  if (WasNeverFull(c, index)) {
    SetCtrl(c, index, ctrl_t::kEmpty, slot_size);
    c.growth_info().OverwriteFullAsEmpty();
    return;
  }

  c.growth_info().OverwriteFullAsDeleted();
  SetCtrlInLargeTable(c, index, ctrl_t::kDeleted, slot_size);
}

void ClearBackingArray(CommonFields& c,
                       const PolicyFunctions& __restrict policy, void* alloc,
                       bool reuse) {
  ABSL_SWISSTABLE_ASSERT(c.capacity() > kMaxSmallCapacity);
  if (reuse) {
    const size_t blocked_element_count = c.blocked_element_count();
    c.set_size_to_zero();
    ABSL_SWISSTABLE_ASSERT(c.capacity() > policy.soo_capacity());
    ResetCtrl(c, policy.slot_size, blocked_element_count);
    ResetGrowthLeft(c.growth_info(), c.capacity(), blocked_element_count);
    ABSL_SWISSTABLE_ASSERT(c.blocked_element_count() == blocked_element_count);
    c.infoz().RecordStorageChanged(0, c.capacity());
  } else {
    ClearBackingArrayNoReuse(c, policy, alloc);
  }
}

void DestroySlots(CommonFields& c, size_t slot_size,
                  DestroySlotFn destroy_slot) {
  ABSL_SWISSTABLE_ASSERT(!c.is_small());
  ABSL_SWISSTABLE_ASSERT(destroy_slot != nullptr);
  auto destroy_slot_wrapper = [&](const ctrl_t*, void* slot) {
    destroy_slot(&c, slot);
  };
  if constexpr (SwisstableGenerationsOrDebugEnabled()) {
    CommonFields common_copy(non_soo_tag_t{}, c);
    c.set_capacity(HashtableCapacity::CreateDestroyed());
    IterateOverFullSlotsImpl(common_copy, slot_size, destroy_slot_wrapper);
    c.set_capacity(common_copy.capacity());
  } else {
    IterateOverFullSlotsImpl(c, slot_size, destroy_slot_wrapper);
  }
}

void DeallocBackingArray(CommonFields& c, size_t slot_size, size_t slot_align,
                         DeallocBackingArrayFn dealloc, void* alloc) {
  const size_t cap = c.capacity();
  c.infoz().Unregister();
  dealloc(alloc, cap, c.control(), slot_size, slot_align, c.has_infoz(),
          c.blocked_element_count());
}

template <bool kSooEnabled>
void Clear(CommonFields& c, const PolicyFunctions& __restrict policy,
           DestroySlotFn destroy_slot, void* alloc) {
  if (SwisstableGenerationsEnabled() &&
      c.maybe_invalid_capacity().IsMovedFrom()) {
    c.set_capacity(policy.soo_capacity());
  }
  c.AssertNotDebugCapacity();
  const size_t cap = c.capacity();
  if constexpr (kSooEnabled) {
    ABSL_ASSUME(cap > 0);
  }
  if (c.is_small()) {
    if (!c.empty()) {
      if (destroy_slot != nullptr) {
        destroy_slot(&c, SingleSlotAddress<kSooEnabled>(c));
      }
      DecrementSmallSize<kSooEnabled>(c);
    }
  } else {
    if (destroy_slot != nullptr) {
      DestroySlots(c, policy.slot_size, destroy_slot);
    }
    // Iterating over this container is O(bucket_count()). When bucket_count()
    // is much greater than size(), iteration becomes prohibitively expensive.
    // For clear() it is more important to reuse the allocated array when the
    // container is small because allocation takes comparatively long time
    // compared to destruction of the elements of the container. So we pick the
    // largest bucket_count() threshold for which iteration is still fast and
    // past that we simply deallocate the array.
    ClearBackingArray(c, policy, alloc, /*reuse=*/cap < 128);
  }
  c.set_reserved_growth(0);
  c.set_reservation_size(0);
}

void DestructSoo(CommonFields& c, size_t slot_size, size_t slot_align,
                 DestroySlotFn destroy_slot, DeallocBackingArrayFn dealloc,
                 void* alloc) {
  ABSL_SWISSTABLE_ASSERT(!c.is_small() || !c.empty());
  if (c.is_small()) {
    ABSL_SWISSTABLE_ASSERT(destroy_slot != nullptr);
    destroy_slot(&c, c.soo_data());
    return;
  }
  if (destroy_slot != nullptr) {
    DestroySlots(c, slot_size, destroy_slot);
  }
  DeallocBackingArray(c, slot_size, slot_align, dealloc, alloc);
}

void DestructNonSoo(CommonFields& c, size_t slot_size, size_t slot_align,
                    DestroySlotFn destroy_slot, DeallocBackingArrayFn dealloc,
                    void* alloc) {
  ABSL_SWISSTABLE_ASSERT(c.capacity() > 0);
  if (destroy_slot != nullptr) {
    if (c.is_small()) {
      if (!c.empty()) {
        static_assert(kMaxSmallCapacity == 1);
        destroy_slot(&c, c.slot_array(/*capacity=*/1));
      }
    } else {
      DestroySlots(c, slot_size, destroy_slot);
    }
  }
  DeallocBackingArray(c, slot_size, slot_align, dealloc, alloc);
}

namespace {

// Iterates over full slots in old table, finds new positions for them and
// transfers the slots.
// This function is used for reserving or rehashing non-empty tables.
// This use case is rare so the function is type erased.
// Returns the total probe length.
size_t FindNewPositionsAndTransferSlots(
    CommonFields& common, const PolicyFunctions& __restrict policy,
    ctrl_t* old_ctrl, void* old_slots, size_t old_capacity) {
  void* new_slots = common.slot_array(common.capacity());
  const void* hash_fn = policy.hash_fn(common);
  const size_t slot_size = policy.slot_size;
  const size_t seed = common.seed().seed();

  const auto insert_slot = [&](void* slot) {
    size_t hash = policy.hash_slot(hash_fn, slot, seed);
    FindInfo target;
    if (common.is_small()) {
      target = FindInfo{0, 0};
    } else {
      target = find_first_non_full(common, hash);
      SetCtrl(common, target.offset, H2(hash), slot_size);
    }
    policy.transfer_n(&common, SlotAddress(new_slots, target.offset, slot_size),
                      slot, 1);
    return target.probe_length;
  };
  if (IsSmallCapacity(old_capacity)) {
    if (common.size() == 1) insert_slot(old_slots);
    return 0;
  }
  size_t total_probe_length = 0;
  for (size_t i = 0; i < old_capacity; ++i) {
    if (IsFull(old_ctrl[i])) {
      total_probe_length += insert_slot(old_slots);
    }
    old_slots = NextSlot(old_slots, slot_size);
  }
  return total_probe_length;
}

void ReportGrowthToInfozImpl(CommonFields& common, HashtablezInfoHandle infoz,
                             size_t hash, size_t total_probe_length,
                             size_t distance_from_desired) {
  ABSL_SWISSTABLE_ASSERT(infoz.IsSampled());
  infoz.RecordStorageChanged(common.size() - 1, common.capacity());
  infoz.RecordRehash(total_probe_length);
  infoz.RecordInsertMiss(hash, distance_from_desired);
  common.set_has_infoz();
  // TODO(b/413062340): we could potentially store infoz in place of the
  // control pointer for the capacity 1 case.
  common.set_infoz(infoz);
}

// Specialization to avoid passing two 0s from hot function.
ABSL_ATTRIBUTE_NOINLINE void ReportSingleGroupTableGrowthToInfoz(
    CommonFields& common, HashtablezInfoHandle infoz, size_t hash) {
  ReportGrowthToInfozImpl(common, infoz, hash, /*total_probe_length=*/0,
                          /*distance_from_desired=*/0);
}

ABSL_ATTRIBUTE_NOINLINE void ReportGrowthToInfoz(CommonFields& common,
                                                 HashtablezInfoHandle infoz,
                                                 size_t hash,
                                                 size_t total_probe_length,
                                                 size_t distance_from_desired) {
  ReportGrowthToInfozImpl(common, infoz, hash, total_probe_length,
                          distance_from_desired);
}

ABSL_ATTRIBUTE_NOINLINE void ReportResizeToInfoz(CommonFields& common,
                                                 HashtablezInfoHandle infoz,
                                                 size_t total_probe_length) {
  ABSL_SWISSTABLE_ASSERT(infoz.IsSampled());
  infoz.RecordStorageChanged(common.size(), common.capacity());
  infoz.RecordRehash(total_probe_length);
  common.set_has_infoz();
  common.set_infoz(infoz);
}

struct BackingArrayPtrs {
  ctrl_t* ctrl;
  void* slots;
};

BackingArrayPtrs AllocBackingArray(CommonFields& common,
                                   const PolicyFunctions& __restrict policy,
                                   size_t new_capacity, bool has_infoz,
                                   void* alloc, size_t blocked_element_count) {
  RawHashSetLayout layout(new_capacity, policy.slot_size, policy.slot_align,
                          has_infoz, blocked_element_count);
  // Perform a direct call in the common case to allow for profile-guided
  // heap optimization (PGHO) to understand which allocation function is used.
  constexpr size_t kDefaultAlignment = BackingArrayAlignment(alignof(size_t));
  char* mem = static_cast<char*>(
      ABSL_PREDICT_TRUE(
          policy.alloc ==
          (&AllocateBackingArray<kDefaultAlignment, std::allocator<char>>))
          ? AllocateBackingArray<kDefaultAlignment, std::allocator<char>>(
                alloc, layout.alloc_size())
          : policy.alloc(alloc, layout.alloc_size()));
  const GenerationType old_generation = common.generation();
  common.set_generation_ptr(
      reinterpret_cast<GenerationType*>(mem + layout.generation_offset()));
  common.set_generation(NextGeneration(old_generation));

  return {reinterpret_cast<ctrl_t*>(mem + layout.control_offset()),
          mem + layout.slot_offset()};
}

void ResizeEmptyNonAllocatedTableImpl(CommonFields& common,
                                      const PolicyFunctions& __restrict policy,
                                      size_t new_capacity,
                                      size_t blocked_element_count,
                                      bool force_infoz) {
  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(new_capacity));
  ABSL_SWISSTABLE_ASSERT(new_capacity > policy.soo_capacity());
  ABSL_SWISSTABLE_ASSERT(!force_infoz || policy.soo_enabled);
  ABSL_SWISSTABLE_ASSERT(common.capacity() == policy.soo_capacity());
  ABSL_SWISSTABLE_ASSERT(common.empty());
  const size_t slot_size = policy.slot_size;
  HashtablezInfoHandle infoz;
  const bool should_sample =
      policy.is_hashtablez_eligible && (force_infoz || ShouldSampleNextTable());
  if (ABSL_PREDICT_FALSE(should_sample)) {
    infoz = ForcedTrySample(slot_size, policy.key_size, policy.value_size,
                            policy.soo_capacity());
  }
  const bool has_infoz = infoz.IsSampled();
  void* alloc = policy.get_char_alloc(common);

  common.set_capacity(new_capacity);
  common.init_blocked_element_count(blocked_element_count);
  const auto [new_ctrl, new_slots] = AllocBackingArray(
      common, policy, new_capacity, has_infoz, alloc, blocked_element_count);
  common.set_control(new_ctrl);
  common.generate_new_seed(has_infoz);

  ResetCtrl(common, slot_size, blocked_element_count);
  if (GrowthInfoSizeForCapacity(new_capacity) > 0) {
    ResetGrowthLeft(GetGrowthInfoFromControl(new_ctrl), new_capacity,
                    blocked_element_count);
  }

  if (ABSL_PREDICT_FALSE(has_infoz)) {
    ReportResizeToInfoz(common, infoz, 0);
  }
}

// If the table was SOO, initializes new control bytes and transfers slot.
// After transferring the slot, sets control and slots in CommonFields.
// It is rare to resize an SOO table with one element to a large size.
// Requires: `c` contains SOO data.
void InsertOldSooSlotAndInitializeControlBytes(
    CommonFields& c, const PolicyFunctions& __restrict policy, ctrl_t* new_ctrl,
    void* new_slots, bool has_infoz) {
  ABSL_SWISSTABLE_ASSERT(c.size() == policy.soo_capacity());
  ABSL_SWISSTABLE_ASSERT(policy.soo_enabled);
  const size_t new_capacity = c.capacity();

  c.generate_new_seed(has_infoz);

  const size_t soo_slot_hash =
      policy.hash_slot(policy.hash_fn(c), c.soo_data(), c.seed().seed());
  size_t offset = probe(ProbeCapacity{new_capacity}, soo_slot_hash).offset();
  offset = offset == new_capacity ? 0 : offset;
  SanitizerPoisonMemoryRegion(new_slots, policy.slot_size * new_capacity);
  void* target_slot = SlotAddress(new_slots, offset, policy.slot_size);
  SanitizerUnpoisonMemoryRegion(target_slot, policy.slot_size);
  policy.transfer_n(&c, target_slot, c.soo_data(), 1);
  c.set_control(new_ctrl);
  ResetCtrl(c, policy.slot_size, /*blocked_element_count=*/0);
  SetCtrl(c, offset, H2(soo_slot_hash), policy.slot_size);
}

enum class ResizeFullSooTableSamplingMode {
  kNoSampling,
  // Force sampling. If the table was still not sampled, do not resize.
  kForceSampleNoResizeIfUnsampled,
};

void AssertSoo([[maybe_unused]] CommonFields& common,
               [[maybe_unused]] const PolicyFunctions& __restrict policy) {
  ABSL_SWISSTABLE_ASSERT(policy.soo_enabled);
  ABSL_SWISSTABLE_ASSERT(common.capacity() == policy.soo_capacity());
}
void AssertFullSoo([[maybe_unused]] CommonFields& common,
                   [[maybe_unused]] const PolicyFunctions& __restrict policy) {
  AssertSoo(common, policy);
  ABSL_SWISSTABLE_ASSERT(common.size() == policy.soo_capacity());
}

void ResizeFullSooTable(CommonFields& common,
                        const PolicyFunctions& __restrict policy,
                        size_t new_capacity,
                        ResizeFullSooTableSamplingMode sampling_mode) {
  AssertFullSoo(common, policy);
  const size_t slot_size = policy.slot_size;
  void* alloc = policy.get_char_alloc(common);
  constexpr size_t kTableSize = 1;

  HashtablezInfoHandle infoz;
  bool has_infoz = false;
  if (sampling_mode ==
      ResizeFullSooTableSamplingMode::kForceSampleNoResizeIfUnsampled) {
    if (ABSL_PREDICT_FALSE(policy.is_hashtablez_eligible)) {
      infoz = ForcedTrySample(slot_size, policy.key_size, policy.value_size,
                              policy.soo_capacity());
    }

    if (!infoz.IsSampled()) return;
    has_infoz = true;
  }

  common.set_capacity(new_capacity);

  // We do not set control and slots in CommonFields yet to avoid overriding
  // SOO data.
  const auto [new_ctrl, new_slots] =
      AllocBackingArray(common, policy, new_capacity, has_infoz, alloc,
                        /*blocked_element_count=*/0);

  InsertOldSooSlotAndInitializeControlBytes(common, policy, new_ctrl, new_slots,
                                            has_infoz);
  ResetGrowthLeft(common.growth_info(), new_capacity, kTableSize);
  if (has_infoz) {
    common.set_has_infoz();
    common.set_infoz(infoz);
    infoz.RecordStorageChanged(kTableSize, new_capacity);
  }
}

void GrowIntoSingleGroupShuffleControlBytes(ctrl_t* __restrict old_ctrl,
                                            size_t old_capacity,
                                            size_t old_blocked_element_count,
                                            ctrl_t* __restrict new_ctrl,
                                            size_t new_capacity) {
  ABSL_SWISSTABLE_ASSERT(is_single_group(new_capacity));
  constexpr size_t kHalfWidth = Group::kWidth / 2;
  ABSL_ASSUME(old_capacity < kHalfWidth);
  ABSL_ASSUME(old_capacity > 0);
  static_assert(Group::kWidth == 8 || Group::kWidth == 16,
                "Group size is not supported.");

  // NOTE: operations are done with compile time known size = 8.
  // Compiler optimizes that into single ASM operation.

  // Load the bytes from old_capacity. This contains
  // - the sentinel byte
  // - all the old control bytes
  // - the rest is filled with kEmpty bytes
  // Example:
  // old_ctrl =     012S012EEEEEEEEE...
  // copied_bytes = S012EEEE
  // Example with blocked elements:
  // old_ctrl =     01SS01SEEEEEEEEE...
  // copied_bytes = S01SEEEE
  uint64_t copied_bytes = absl::little_endian::Load64(old_ctrl + old_capacity);

  // We change the sentinel byte to kEmpty before storing to both the start of
  // the new_ctrl, and past the end of the new_ctrl later for the new cloned
  // bytes. Note that this is faster than setting the sentinel byte to kEmpty
  // after the copy directly in new_ctrl because we are limited on store
  // bandwidth.
  static constexpr uint64_t kEmptyXorSentinel =
      static_cast<uint8_t>(ctrl_t::kEmpty) ^
      static_cast<uint8_t>(ctrl_t::kSentinel);

  // Replace the first byte kSentinel with kEmpty.
  // Resulting bytes will be shifted by one byte old control blocks.
  // Example:
  // old_ctrl = 012S012EEEEEEEEE...
  // before =   S012EEEE
  // after  =   E012EEEE
  copied_bytes ^= kEmptyXorSentinel;

  if (ABSL_PREDICT_FALSE(old_blocked_element_count > 0)) {
    // Replacing blocked sentinel elements with kEmpty.
    static constexpr uint64_t kAllBytesEmptyXorSentinel =
        kEmptyXorSentinel * uint64_t{0x0101010101010101};
    uint64_t blocked_mask = kAllBytesEmptyXorSentinel;
    // Keep old_blocked_element_count bytes in the mask.
    blocked_mask >>= 64 - old_blocked_element_count * 8;
    // Shift the mask to the start of the blocked elements bytes.
    blocked_mask <<= (old_capacity - old_blocked_element_count + 1) * 8;
    // Example with blocked elements:
    // old_ctrl = 0SSS0SSEEEEEEEEE...
    // before =   E0SSEEEE
    // after  =   E0EEEEEE
    copied_bytes ^= blocked_mask;
  }

  if (Group::kWidth == 8) {
    // With group size 8, we can grow with two write operations.
    ABSL_SWISSTABLE_ASSERT(old_capacity < 8 &&
                           "old_capacity is too large for group size 8");
    absl::little_endian::Store64(new_ctrl, copied_bytes);

    static constexpr uint64_t kSentinal64 =
        static_cast<uint8_t>(ctrl_t::kSentinel);

    // Prepend kSentinel byte to the beginning of copied_bytes.
    // We have maximum 3 non-empty bytes at the beginning of copied_bytes for
    // group size 8.
    // Example:
    // old_ctrl = 012S012EEEE
    // before =   E012EEEE
    // after  =   SE012EEE
    copied_bytes = (copied_bytes << 8) ^ kSentinal64;
    absl::little_endian::Store64(new_ctrl + new_capacity, copied_bytes);
    // Example for capacity 3:
    // old_ctrl = 012S012EEEE
    // After the first store:
    //           >!
    // new_ctrl = E012EEEE???????
    // After the second store:
    //                  >!
    // new_ctrl = E012EEESE012EEE
    return;
  }

  ABSL_SWISSTABLE_ASSERT(Group::kWidth == 16);  // NOLINT(misc-static-assert)

  // Fill the second half of the main control bytes with kEmpty.
  // For small capacity that may write into mirrored control bytes.
  // It is fine as we will overwrite all the bytes later.
  std::memset(new_ctrl + kHalfWidth, static_cast<int8_t>(ctrl_t::kEmpty),
              kHalfWidth);
  // Fill the second half of the mirrored control bytes with kEmpty.
  std::memset(new_ctrl + new_capacity + kHalfWidth,
              static_cast<int8_t>(ctrl_t::kEmpty), kHalfWidth);
  // Copy the first half of the non-mirrored control bytes.
  absl::little_endian::Store64(new_ctrl, copied_bytes);
  new_ctrl[new_capacity] = ctrl_t::kSentinel;
  // Copy the first half of the mirrored control bytes.
  absl::little_endian::Store64(new_ctrl + new_capacity + 1, copied_bytes);

  // Example for growth capacity 1->3:
  // old_ctrl =                  0S0EEEEEEEEEEEEEE
  // new_ctrl at the end =       E0ESE0EEEEEEEEEEEEE
  //                                    >!
  // new_ctrl after 1st memset = ????????EEEEEEEE???
  //                                       >!
  // new_ctrl after 2nd memset = ????????EEEEEEEEEEE
  //                            >!
  // new_ctrl after 1st store =  E0EEEEEEEEEEEEEEEEE
  // new_ctrl after kSentinel =  E0ESEEEEEEEEEEEEEEE
  //                                >!
  // new_ctrl after 2nd store =  E0ESE0EEEEEEEEEEEEE

  // Example for growth capacity 3->7:
  // old_ctrl =                  012S012EEEEEEEEEEEE
  // new_ctrl at the end =       E012EEESE012EEEEEEEEEEE
  //                                    >!
  // new_ctrl after 1st memset = ????????EEEEEEEE???????
  //                                           >!
  // new_ctrl after 2nd memset = ????????EEEEEEEEEEEEEEE
  //                            >!
  // new_ctrl after 1st store =  E012EEEEEEEEEEEEEEEEEEE
  // new_ctrl after kSentinel =  E012EEESEEEEEEEEEEEEEEE
  //                                >!
  // new_ctrl after 2nd store =  E012EEESE012EEEEEEEEEEE

  // Example for growth capacity 7->15:
  // old_ctrl =                  0123456S0123456EEEEEEEE
  // new_ctrl at the end =       E0123456EEEEEEESE0123456EEEEEEE
  //                                    >!
  // new_ctrl after 1st memset = ????????EEEEEEEE???????????????
  //                                                   >!
  // new_ctrl after 2nd memset = ????????EEEEEEEE???????EEEEEEEE
  //                            >!
  // new_ctrl after 1st store =  E0123456EEEEEEEE???????EEEEEEEE
  // new_ctrl after kSentinel =  E0123456EEEEEEES???????EEEEEEEE
  //                                            >!
  // new_ctrl after 2nd store =  E0123456EEEEEEESE0123456EEEEEEE
}

// Size of the buffer we allocate on stack for storing probed elements in
// GrowToNextCapacity algorithm.
constexpr size_t kProbedElementsBufferSize = 512;

// Decodes information about probed elements from contiguous memory.
// Finds new position for each element and transfers it to the new slots.
// Returns the total probe length.
template <typename ProbedItem>
ABSL_ATTRIBUTE_NOINLINE size_t DecodeAndInsertImpl(
    CommonFields& c, const PolicyFunctions& __restrict policy,
    const ProbedItem* start, const ProbedItem* end, void* old_slots) {
  const HashtableCapacity new_capacity = c.capacity_impl();

  void* new_slots = c.slot_array(new_capacity.capacity());
  ctrl_t* new_ctrl = c.control();
  size_t total_probe_length = 0;

  const size_t slot_size = policy.slot_size;
  auto transfer_n = policy.transfer_n;

  for (; start < end; ++start) {
    const FindInfo target = find_first_non_full_from_h1(
        new_ctrl, static_cast<size_t>(start->h1), new_capacity);
    total_probe_length += target.probe_length;
    const size_t old_index = static_cast<size_t>(start->source_offset);
    const size_t new_i = target.offset;
    ABSL_SWISSTABLE_ASSERT(old_index < new_capacity.capacity() / 2);
    ABSL_SWISSTABLE_ASSERT(new_i < new_capacity.capacity());
    ABSL_SWISSTABLE_ASSERT(IsEmpty(new_ctrl[new_i]));
    void* src_slot = SlotAddress(old_slots, old_index, slot_size);
    void* dst_slot = SlotAddress(new_slots, new_i, slot_size);
    SanitizerUnpoisonMemoryRegion(dst_slot, slot_size);
    transfer_n(&c, dst_slot, src_slot, 1);
    SetCtrlInLargeTable(c, new_i, static_cast<h2_t>(start->h2), slot_size);
  }
  return total_probe_length;
}

// Sentinel value for the start of marked elements.
// Signals that there are no marked elements.
constexpr size_t kNoMarkedElementsSentinel = ~size_t{};

// Process probed elements that did not fit into available buffers.
// We marked them in control bytes as kMarkedForSlowTransfer.
// Hash recomputation and full probing is done here.
// This use case should be extremely rare.
ABSL_ATTRIBUTE_NOINLINE size_t ProcessProbedMarkedElements(
    CommonFields& c, const PolicyFunctions& __restrict policy, ctrl_t* old_ctrl,
    void* old_slots, size_t start) {
  size_t old_capacity = PreviousCapacity(c.capacity());
  const size_t slot_size = policy.slot_size;
  void* new_slots = c.slot_array(c.capacity());
  size_t total_probe_length = 0;
  const void* hash_fn = policy.hash_fn(c);
  auto hash_slot = policy.hash_slot;
  auto transfer_n = policy.transfer_n;
  const size_t seed = c.seed().seed();
  for (size_t old_index = start; old_index < old_capacity; ++old_index) {
    if (old_ctrl[old_index] != ctrl_t::kMarkedForSlowTransfer) {
      continue;
    }
    void* src_slot = SlotAddress(old_slots, old_index, slot_size);
    const size_t hash = hash_slot(hash_fn, src_slot, seed);
    const FindInfo target = find_first_non_full(c, hash);
    total_probe_length += target.probe_length;
    const size_t new_i = target.offset;
    void* dst_slot = SlotAddress(new_slots, new_i, slot_size);
    SetCtrlInLargeTable(c, new_i, H2(hash), slot_size);
    transfer_n(&c, dst_slot, src_slot, 1);
  }
  return total_probe_length;
}

// The largest old capacity for which it is guaranteed that all probed elements
// fit in ProbedItemEncoder's local buffer.
// For such tables, `encode_probed_element` is trivial.
constexpr size_t kMaxLocalBufferOldCapacity =
    kProbedElementsBufferSize / sizeof(ProbedItem4Bytes) - 1;
static_assert(IsValidCapacity(kMaxLocalBufferOldCapacity));
constexpr size_t kMaxLocalBufferNewCapacity =
    NextCapacity(kMaxLocalBufferOldCapacity);
static_assert(kMaxLocalBufferNewCapacity <= ProbedItem4Bytes::kMaxNewCapacity);
static_assert(NextCapacity(kMaxLocalBufferNewCapacity) <=
              ProbedItem4Bytes::kMaxNewCapacity);

// Initializes mirrored control bytes after
// transfer_unprobed_elements_to_next_capacity.
void InitializeMirroredControlBytes(ctrl_t* new_ctrl, size_t new_capacity) {
  std::memcpy(new_ctrl + new_capacity,
              // We own GrowthInfo just before control bytes. So it is ok
              // to read one byte from it.
              new_ctrl - 1, Group::kWidth);
  new_ctrl[new_capacity] = ctrl_t::kSentinel;
}

// Encodes probed elements into available memory.
// At first, a local (on stack) buffer is used. The size of the buffer is
// kProbedElementsBufferSize bytes.
// When the local buffer is full, we switch to `control_` buffer. We are allowed
// to overwrite `control_` buffer till the `source_offset` byte. In case we have
// no space in `control_` buffer, we fallback to a naive algorithm for all the
// rest of the probed elements. We mark elements as kSentinel in control bytes
// and later process them fully. See ProcessMarkedElements for details. It
// should be extremely rare.
template <typename ProbedItemType,
          // If true, we only use the local buffer and never switch to the
          // control buffer.
          bool kGuaranteedFitToBuffer = false>
class ProbedItemEncoder {
 public:
  using ProbedItem = ProbedItemType;
  explicit ProbedItemEncoder(ctrl_t* control) : control_(control) {}

  // Encode item into the best available location.
  void EncodeItem(ProbedItem item) {
    if (ABSL_PREDICT_FALSE(!kGuaranteedFitToBuffer && pos_ >= end_)) {
      return ProcessEncodeWithOverflow(item);
    }
    ABSL_SWISSTABLE_ASSERT(pos_ < end_);
    *pos_ = item;
    ++pos_;
  }

  // Decodes information about probed elements from all available sources.
  // Finds new position for each element and transfers it to the new slots.
  // Returns the total probe length.
  size_t DecodeAndInsertToTable(CommonFields& common,
                                const PolicyFunctions& __restrict policy,
                                void* old_slots) const {
    if (pos_ == buffer_) {
      return 0;
    }
    if constexpr (kGuaranteedFitToBuffer) {
      return DecodeAndInsertImpl(common, policy, buffer_, pos_, old_slots);
    }
    size_t total_probe_length = DecodeAndInsertImpl(
        common, policy, buffer_,
        local_buffer_full_ ? buffer_ + kBufferSize : pos_, old_slots);
    if (!local_buffer_full_) {
      return total_probe_length;
    }
    total_probe_length +=
        DecodeAndInsertToTableOverflow(common, policy, old_slots);
    return total_probe_length;
  }

 private:
  static ProbedItem* AlignToNextItem(void* ptr) {
    return reinterpret_cast<ProbedItem*>(AlignUpTo(
        reinterpret_cast<uintptr_t>(ptr), alignof(ProbedItem)));
  }

  ProbedItem* OverflowBufferStart() const {
    ABSL_SWISSTABLE_ASSERT(!kGuaranteedFitToBuffer &&
                           "OverflowBufferStart should not be called when "
                           "kGuaranteedFitToBuffer is true.");
    // We reuse GrowthInfo memory as well.
    return AlignToNextItem(
        control_ - MetadataBeforeControlSize(/*has_infoz=*/false,
                                 NextCapacity(kMaxLocalBufferOldCapacity)));
  }

  // Encodes item when previously allocated buffer is full.
  // At first that happens when local buffer is full.
  // We switch from the local buffer to the control buffer.
  // Every time this function is called, the available buffer is extended till
  // `item.source_offset` byte in the control buffer.
  // After the buffer is extended, this function wouldn't be called till the
  // buffer is exhausted.
  //
  // If there's no space in the control buffer, we fallback to naive algorithm
  // and mark probed elements as kMarkedForSlowTransfer in the control buffer.
  // In this case, we will call this function for every subsequent probed
  // element.
  ABSL_ATTRIBUTE_NOINLINE void ProcessEncodeWithOverflow(ProbedItem item) {
    if (!local_buffer_full_) {
      local_buffer_full_ = true;
      pos_ = OverflowBufferStart();
    }
    const size_t source_offset = static_cast<size_t>(item.source_offset);
    // We are in fallback mode so we can't reuse control buffer anymore.
    // Probed elements are marked as kMarkedForSlowTransfer in the control
    // buffer.
    if (ABSL_PREDICT_FALSE(marked_elements_starting_position_ !=
                           kNoMarkedElementsSentinel)) {
      control_[source_offset] = ctrl_t::kMarkedForSlowTransfer;
      return;
    }
    // Refresh the end pointer to the new available position.
    // Invariant: if pos < end, then we have at least sizeof(ProbedItem) bytes
    // to write.
    end_ = control_ + source_offset + 1 - sizeof(ProbedItem);
    if (ABSL_PREDICT_TRUE(pos_ < end_)) {
      *pos_ = item;
      ++pos_;
      return;
    }
    control_[source_offset] = ctrl_t::kMarkedForSlowTransfer;
    marked_elements_starting_position_ = source_offset;
    // Now we will always fall down to `ProcessEncodeWithOverflow`.
    ABSL_SWISSTABLE_ASSERT(pos_ >= end_);
  }

  // Decodes information about probed elements from control buffer and processes
  // marked elements.
  // Finds new position for each element and transfers it to the new slots.
  // Returns the total probe length.
  ABSL_ATTRIBUTE_NOINLINE size_t DecodeAndInsertToTableOverflow(
      CommonFields& common, const PolicyFunctions& __restrict policy,
      void* old_slots) const {
    ABSL_SWISSTABLE_ASSERT(local_buffer_full_ &&
                           "must not be called when local buffer is not full");
    size_t total_probe_length = DecodeAndInsertImpl(
        common, policy, OverflowBufferStart(), pos_, old_slots);
    if (ABSL_PREDICT_TRUE(marked_elements_starting_position_ ==
                          kNoMarkedElementsSentinel)) {
      return total_probe_length;
    }
    total_probe_length +=
        ProcessProbedMarkedElements(common, policy, control_, old_slots,
                                    marked_elements_starting_position_);
    return total_probe_length;
  }

  static constexpr size_t kBufferSize =
      kProbedElementsBufferSize / sizeof(ProbedItem);
  ProbedItem buffer_[kBufferSize];
  // If local_buffer_full_ is false, then pos_/end_ are in the local buffer,
  // otherwise, they're in the overflow buffer.
  ProbedItem* pos_ = buffer_;
  const void* end_ = buffer_ + kBufferSize;
  ctrl_t* const control_;
  size_t marked_elements_starting_position_ = kNoMarkedElementsSentinel;
  bool local_buffer_full_ = false;
};

// Grows to next capacity with specified encoder type.
// Encoder is used to store probed elements that are processed later.
// Different encoder is used depending on the capacity of the table.
// Returns total probe length.
template <typename Encoder>
size_t GrowToNextCapacity(CommonFields& common,
                          const PolicyFunctions& __restrict policy,
                          ctrl_t* old_ctrl, void* old_slots) {
  using ProbedItem = typename Encoder::ProbedItem;
  ABSL_SWISSTABLE_ASSERT(common.capacity() <= ProbedItem::kMaxNewCapacity);
  Encoder encoder(old_ctrl);
  policy.transfer_unprobed_elements_to_next_capacity(
      common, old_ctrl, old_slots, &encoder,
      [](void* probed_storage, h2_t h2, size_t source_offset, size_t h1) {
        auto encoder_ptr = static_cast<Encoder*>(probed_storage);
        encoder_ptr->EncodeItem(ProbedItem(h2, source_offset, h1));
      });
  InitializeMirroredControlBytes(common.control(), common.capacity());
  return encoder.DecodeAndInsertToTable(common, policy, old_slots);
}

// Grows to next capacity for relatively small tables so that even if all
// elements are probed, we don't need to overflow the local buffer.
// Returns total probe length.
size_t GrowToNextCapacityThatFitsInLocalBuffer(
    CommonFields& common, const PolicyFunctions& __restrict policy,
    ctrl_t* old_ctrl, void* old_slots) {
  ABSL_SWISSTABLE_ASSERT(common.capacity() <= kMaxLocalBufferNewCapacity);
  return GrowToNextCapacity<
      ProbedItemEncoder<ProbedItem4Bytes, /*kGuaranteedFitToBuffer=*/true>>(
      common, policy, old_ctrl, old_slots);
}

// Grows to next capacity with different encodings. Returns total probe length.
// These functions are useful to simplify profile analysis.
size_t GrowToNextCapacity4BytesEncoder(CommonFields& common,
                                       const PolicyFunctions& __restrict policy,
                                       ctrl_t* old_ctrl, void* old_slots) {
  return GrowToNextCapacity<ProbedItemEncoder<ProbedItem4Bytes>>(
      common, policy, old_ctrl, old_slots);
}
size_t GrowToNextCapacity8BytesEncoder(CommonFields& common,
                                       const PolicyFunctions& __restrict policy,
                                       ctrl_t* old_ctrl, void* old_slots) {
  return GrowToNextCapacity<ProbedItemEncoder<ProbedItem8Bytes>>(
      common, policy, old_ctrl, old_slots);
}
size_t GrowToNextCapacity16BytesEncoder(
    CommonFields& common, const PolicyFunctions& __restrict policy,
    ctrl_t* old_ctrl, void* old_slots) {
  return GrowToNextCapacity<ProbedItemEncoder<ProbedItem16Bytes>>(
      common, policy, old_ctrl, old_slots);
}

// Grows to next capacity for tables with relatively large capacity so that we
// can't guarantee that all probed elements fit in the local buffer. Returns
// total probe length.
size_t GrowToNextCapacityOverflowLocalBuffer(
    CommonFields& common, const PolicyFunctions& __restrict policy,
    ctrl_t* old_ctrl, void* old_slots) {
  const size_t new_capacity = common.capacity();
  if (ABSL_PREDICT_TRUE(new_capacity <= ProbedItem4Bytes::kMaxNewCapacity)) {
    return GrowToNextCapacity4BytesEncoder(common, policy, old_ctrl, old_slots);
  }
  if (ABSL_PREDICT_TRUE(new_capacity <= ProbedItem8Bytes::kMaxNewCapacity)) {
    return GrowToNextCapacity8BytesEncoder(common, policy, old_ctrl, old_slots);
  }
  // 16 bytes encoding supports the maximum swisstable capacity.
  return GrowToNextCapacity16BytesEncoder(common, policy, old_ctrl, old_slots);
}

// Dispatches to the appropriate `GrowToNextCapacity*` function based on the
// capacity of the table. Returns total probe length.
ABSL_ATTRIBUTE_NOINLINE
size_t GrowToNextCapacityDispatch(CommonFields& common,
                                  const PolicyFunctions& __restrict policy,
                                  ctrl_t* old_ctrl, void* old_slots) {
  const size_t new_capacity = common.capacity();
  if (ABSL_PREDICT_TRUE(new_capacity <= kMaxLocalBufferNewCapacity)) {
    return GrowToNextCapacityThatFitsInLocalBuffer(common, policy, old_ctrl,
                                                   old_slots);
  } else {
    return GrowToNextCapacityOverflowLocalBuffer(common, policy, old_ctrl,
                                                 old_slots);
  }
}

void IncrementSmallSizeNonSoo(CommonFields& common,
                              const PolicyFunctions& __restrict policy) {
  ABSL_SWISSTABLE_ASSERT(common.is_small());
  common.increment_size();
  SanitizerUnpoisonMemoryRegion(
      SingleSlotAddress</*kSooEnabled=*/false>(common), policy.slot_size);
}

void IncrementSmallSize(CommonFields& common,
                        const PolicyFunctions& __restrict policy) {
  ABSL_SWISSTABLE_ASSERT(common.is_small());
  if (policy.soo_enabled) {
    common.set_full_soo();
  } else {
    IncrementSmallSizeNonSoo(common, policy);
  }
}

void* Grow1To3AndPrepareInsert(CommonFields& common,
                               const PolicyFunctions& __restrict policy,
                               absl::FunctionRef<size_t(size_t)> get_hash) {
  // TODO(b/413062340): Refactor to reuse more code with
  // GrowSooTableToNextCapacityAndPrepareInsert.
  ABSL_SWISSTABLE_ASSERT(common.capacity() == 1);
  ABSL_SWISSTABLE_ASSERT(!common.empty());
  ABSL_SWISSTABLE_ASSERT(!policy.soo_enabled);
  // 1-element tables can't have any blocked elements.
  ABSL_SWISSTABLE_ASSERT(common.blocked_element_count() == 0);
  constexpr size_t kOldCapacity = 1;
  constexpr size_t kNewCapacity = NextCapacity(kOldCapacity);
  void* old_slots = common.slot_array(kOldCapacity);

  const size_t slot_size = policy.slot_size;
  const size_t slot_align = policy.slot_align;
  void* alloc = policy.get_char_alloc(common);
  HashtablezInfoHandle infoz = common.infoz();
  const bool has_infoz = infoz.IsSampled();
  common.set_capacity(kNewCapacity);

  const auto [new_ctrl, new_slots] =
      AllocBackingArray(common, policy, kNewCapacity, has_infoz, alloc,
                        /*blocked_element_count=*/0);
  common.set_control(new_ctrl);
  SanitizerPoisonMemoryRegion(new_slots, kNewCapacity * slot_size);

  if (ABSL_PREDICT_TRUE(!has_infoz)) {
    // When we're sampled, we already have a seed.
    common.generate_new_seed(/*has_infoz=*/false);
  }
  const size_t new_hash = get_hash(common.seed().seed());
  h2_t new_h2 = H2(new_hash);
  size_t orig_hash =
      policy.hash_slot(policy.hash_fn(common), old_slots, common.seed().seed());
  size_t offset = Resize1To3NewOffset(new_hash, common.seed());
  InitializeThreeElementsControlBytes(H2(orig_hash), new_h2, offset, new_ctrl);

  void* old_element_target = NextSlot(new_slots, slot_size);
  SanitizerUnpoisonMemoryRegion(old_element_target, slot_size);
  policy.transfer_n(&common, old_element_target, old_slots, 1);

  void* new_element_target_slot = SlotAddress(new_slots, offset, slot_size);
  SanitizerUnpoisonMemoryRegion(new_element_target_slot, slot_size);

  policy.dealloc(alloc, kOldCapacity,
                 // old_slots == old_ctrl in case of capacity == 1.
                 static_cast<ctrl_t*>(old_slots),
                 slot_size, slot_align, has_infoz,
                 /*blocked_element_count=*/0);
  PrepareInsertCommon(common);
  ABSL_SWISSTABLE_ASSERT(common.size() == 2);
  GetGrowthInfoFromControl(new_ctrl).InitGrowthLeftNoDeleted(kNewCapacity - 2,
                                                             kNewCapacity);

  if (ABSL_PREDICT_FALSE(has_infoz)) {
    ReportSingleGroupTableGrowthToInfoz(common, infoz, new_hash);
  }
  return new_element_target_slot;
}

// Grows to next capacity and prepares insert for the given new_hash.
// Returns the offset of the new element.
void* GrowToNextCapacityAndPrepareInsert(
    CommonFields& common, const PolicyFunctions& __restrict policy,
    size_t new_hash) {
  const size_t old_capacity = common.capacity();
  ABSL_SWISSTABLE_ASSERT(
      common.growth_info().GetGrowthLeftTotalSlow(old_capacity) == 0);
  ABSL_SWISSTABLE_ASSERT(old_capacity > policy.soo_capacity());
  ABSL_SWISSTABLE_ASSERT(!IsSmallCapacity(old_capacity));
  ABSL_ASSUME(old_capacity > kMaxSmallCapacity);

  const size_t new_capacity = NextCapacity(old_capacity);
  ctrl_t* old_ctrl = common.control();
  void* old_slots = common.slot_array(old_capacity);
  size_t old_blocked_element_count = common.blocked_element_count();

  HashtablezInfoHandle infoz = common.infoz();
  const bool has_infoz = infoz.IsSampled();
  common.set_capacity(new_capacity);
  common.set_blocked_element_count_to_zero();
  const size_t slot_size = policy.slot_size;
  const size_t slot_align = policy.slot_align;
  void* alloc = policy.get_char_alloc(common);

  const auto [new_ctrl, new_slots] =
      AllocBackingArray(common, policy, new_capacity, has_infoz, alloc,
                        /*blocked_element_count=*/0);
  common.set_control(new_ctrl);
  SanitizerPoisonMemoryRegion(new_slots, new_capacity * slot_size);

  h2_t new_h2 = H2(new_hash);
  size_t total_probe_length = 0;
  FindInfo find_info;
  if (ABSL_PREDICT_TRUE(is_single_group(new_capacity))) {
    size_t offset;
    const size_t old_size = common.size();
    GrowIntoSingleGroupShuffleControlBytes(old_ctrl, old_capacity,
                                           old_blocked_element_count, new_ctrl,
                                           new_capacity);
    // We put the new element either at the beginning or at the end of the
    // table with approximately equal probability.
    offset =
        SingleGroupTableH1(new_hash, common.seed()) & 1 ? 0 : new_capacity - 1;

    ABSL_SWISSTABLE_ASSERT(IsEmpty(new_ctrl[offset]));
    SetCtrlInSingleGroupTable(common, offset, new_h2, policy.slot_size);
    find_info = FindInfo{offset, 0};
    // Single group tables have all slots full on resize. So we can transfer
    // all slots without checking the control bytes.
    ABSL_SWISSTABLE_ASSERT(common.size() + old_blocked_element_count ==
                           old_capacity);
    void* target = NextSlot(new_slots, slot_size);
    SanitizerUnpoisonMemoryRegion(target, old_size * slot_size);
    policy.transfer_n(&common, target, old_slots, old_size);
  } else {
    total_probe_length =
        GrowToNextCapacityDispatch(common, policy, old_ctrl, old_slots);
    find_info = find_first_non_full(common, new_hash);
    SetCtrlInLargeTable(common, find_info.offset, new_h2, policy.slot_size);
  }
  ABSL_SWISSTABLE_ASSERT(old_capacity > policy.soo_capacity());
  (*policy.dealloc)(alloc, old_capacity, old_ctrl, slot_size, slot_align,
                    has_infoz, old_blocked_element_count);
  PrepareInsertCommon(common);
  ResetGrowthLeft(GetGrowthInfoFromControl(new_ctrl), new_capacity,
                  common.size());

  if (ABSL_PREDICT_FALSE(has_infoz)) {
    ReportGrowthToInfoz(common, infoz, new_hash, total_probe_length,
                        find_info.probe_length);
  }
  return SlotAddress(new_slots, find_info.offset, policy.slot_size);
}

}  // namespace

void* PrepareInsertSmallNonSoo(CommonFields& common,
                               const PolicyFunctions& __restrict policy,
                               absl::FunctionRef<size_t(size_t)> get_hash) {
  ABSL_SWISSTABLE_ASSERT(common.is_small());
  ABSL_SWISSTABLE_ASSERT(!policy.soo_enabled);
  if (common.capacity() == 1) {
    if (common.empty()) {
      IncrementSmallSizeNonSoo(common, policy);
      if (common.has_infoz()) {
        common.infoz().RecordInsertMiss(get_hash(common.seed().seed()),
                                        /*distance_from_desired=*/0);
      }
      return common.slot_array(/*capacity=*/1);
    } else {
      return Grow1To3AndPrepareInsert(common, policy, get_hash);
    }
  }

  // Growing from 0 to 1 capacity.
  ABSL_SWISSTABLE_ASSERT(common.capacity() == 0);
  constexpr size_t kNewCapacity = 1;

  common.set_capacity(kNewCapacity);
  HashtablezInfoHandle infoz;
  const bool should_sample =
      policy.is_hashtablez_eligible && ShouldSampleNextTable();
  if (ABSL_PREDICT_FALSE(should_sample)) {
    infoz = ForcedTrySample(policy.slot_size, policy.key_size,
                            policy.value_size, policy.soo_capacity());
  }
  const bool has_infoz = infoz.IsSampled();
  void* alloc = policy.get_char_alloc(common);

  const auto [new_ctrl, new_slots] =
      AllocBackingArray(common, policy, kNewCapacity, has_infoz, alloc,
                        /*blocked_element_count=*/0);
  common.set_control(new_ctrl);

  static_assert(NextCapacity(0) == 1);
  PrepareInsertCommon(common);

  if (ABSL_PREDICT_FALSE(has_infoz)) {
    common.generate_new_seed(/*has_infoz=*/true);
    ReportSingleGroupTableGrowthToInfoz(common, infoz,
                                        get_hash(common.seed().seed()));
  }
  return new_slots;
}

namespace {

// Called whenever the table needs to vacate empty slots either by removing
// tombstones via rehash or growth to next capacity.
ABSL_ATTRIBUTE_NOINLINE
void* RehashOrGrowToNextCapacityAndPrepareInsert(
    CommonFields& common, const PolicyFunctions& __restrict policy,
    size_t new_hash) {
  ABSL_SWISSTABLE_ASSERT(
      !common.growth_info().GetGrowthInfoLowerBound().HasNoDeleted());
  const size_t cap = common.capacity();
  ABSL_ASSUME(cap > 0);
  // Do these calculations in 64-bit to avoid overflow.
  if (common.size() * uint64_t{32} <=
      (cap - kMaxBlockedElementsForLargeTables) * uint64_t{25}) {
    // Squash DELETED without growing if there is enough capacity.
    //
    // Rehash in place if the current size is <= 25/32 of capacity.
    // Rationale for such a high factor: 1) DropDeletesWithoutResize() is
    // faster than resize, and 2) it takes quite a bit of work to add
    // tombstones.  In the worst case, seems to take approximately 4
    // insert/erase pairs to create a single tombstone and so if we are
    // rehashing because of tombstones, we can afford to rehash-in-place as
    // long as we are reclaiming at least 1/8 the capacity without doing more
    // than 2X the work.  (Where "work" is defined to be size() for rehashing
    // or rehashing in place, and 1 for an insert or erase.)  But rehashing in
    // place is faster per operation than inserting or even doubling the size
    // of the table, so we actually afford to reclaim even less space from a
    // resize-in-place.  The decision is to rehash in place if we can reclaim
    // at about 1/8th of the usable capacity (specifically 3/28 of the
    // capacity) which means that the total cost of rehashing will be a small
    // fraction of the total work.
    //
    // Here is output of an experiment using the BM_CacheInSteadyState
    // benchmark running the old case (where we rehash-in-place only if we can
    // reclaim at least 7/16*capacity) vs. this code (which rehashes in place
    // if we can recover 3/32*capacity).
    //
    // Note that although in the worst-case number of rehashes jumped up from
    // 15 to 190, but the number of operations per second is almost the same.
    //
    // Abridged output of running BM_CacheInSteadyState benchmark from
    // raw_hash_set_benchmark.   N is the number of insert/erase operations.
    //
    //      | OLD (recover >= 7/16        | NEW (recover >= 3/32)
    // size |    N/s LoadFactor NRehashes |    N/s LoadFactor NRehashes
    //  448 | 145284       0.44        18 | 140118       0.44        19
    //  493 | 152546       0.24        11 | 151417       0.48        28
    //  538 | 151439       0.26        11 | 151152       0.53        38
    //  583 | 151765       0.28        11 | 150572       0.57        50
    //  628 | 150241       0.31        11 | 150853       0.61        66
    //  672 | 149602       0.33        12 | 150110       0.66        90
    //  717 | 149998       0.35        12 | 149531       0.70       129
    //  762 | 149836       0.37        13 | 148559       0.74       190
    //  807 | 149736       0.39        14 | 151107       0.39        14
    //  852 | 150204       0.42        15 | 151019       0.42        15
    return DropDeletesWithoutResizeAndPrepareInsert(common, policy, new_hash);
  } else {
    // Otherwise grow the container.
    return GrowToNextCapacityAndPrepareInsert(common, policy, new_hash);
  }
}

// Slow path for PrepareInsertLarge that is called when the table has deleted
// slots or need to be resized or rehashed.
ABSL_ATTRIBUTE_NOINLINE
void* PrepareInsertLargeSlow(CommonFields& common,
                             const PolicyFunctions& __restrict policy,
                             size_t hash) {
  GrowthInfoAccessor growth_info = common.growth_info();
  const size_t cap = common.capacity();
  ABSL_ASSUME(cap > kMaxSmallCapacity);
  GrowthInfoLowerBound growth_info_lower_bound =
      growth_info.RebalanceGrowthLeftLowerBound(cap);
  if (ABSL_PREDICT_TRUE(
          growth_info_lower_bound.HasNoGrowthLeftAndNoDeleted())) {
    // Table without deleted slots (>95% cases) that needs to be resized.
    return GrowToNextCapacityAndPrepareInsert(common, policy, hash);
  }
  if (ABSL_PREDICT_FALSE(
          growth_info_lower_bound.HasNoGrowthLeftAndHaveDeleted())) {
    // Table with deleted slots that needs to be rehashed or resized.
    return RehashOrGrowToNextCapacityAndPrepareInsert(common, policy, hash);
  }
  // Covers two cases:
  // 1. Table with deleted slots that has space for the inserting element.
  // 2. Table without deleted slots that has space and GrowthInfoView was
  //    rebalanced.
  FindInfo target = find_first_non_full(common, hash);
  PrepareInsertCommon(common);
  growth_info.OverwriteControlAsFull(common.control()[target.offset]);
  SetCtrlInLargeTable(common, target.offset, H2(hash), policy.slot_size);
  common.infoz().RecordInsertMiss(hash, target.probe_length);
  return SlotAddress(common.slot_array(cap), target.offset, policy.slot_size);
}

// Resizes empty non-allocated SOO table to NextCapacity(SooCapacity()),
// forces the table to be sampled and prepares the insert.
// SOO tables need to switch from SOO to heap in order to store the infoz.
// Requires:
//   1. `c.capacity() == SooCapacity()`.
//   2. `c.empty()`.
ABSL_ATTRIBUTE_NOINLINE void*
GrowEmptySooTableToNextCapacityForceSamplingAndPrepareInsert(
    CommonFields& common, const PolicyFunctions& __restrict policy,
    absl::FunctionRef<size_t(size_t)> get_hash) {
  const size_t kNewCapacity = NextCapacity(SooCapacity());
  ResizeEmptyNonAllocatedTableImpl(common, policy, kNewCapacity,
                                   /*blocked_element_count=*/0,
                                   /*force_infoz=*/true);
  PrepareInsertCommon(common);
  common.growth_info().OverwriteEmptyAsFull();
  const size_t new_hash = get_hash(common.seed().seed());
  SetCtrlInSingleGroupTable(common, SooSlotIndex(), H2(new_hash),
                            policy.slot_size);
  common.infoz().RecordInsertMiss(new_hash, /*distance_from_desired=*/0);
  return SlotAddress(common.slot_array(kNewCapacity), SooSlotIndex(),
                     policy.slot_size);
}

// Returns the number of elements to block for the given capacity and reserved
// size.
size_t BlockedElementCountForReservedTable(size_t capacity,
                                           size_t reserved_size) {
  if (!IsCapacityValidForBlockedElements(capacity)) {
    return 0;
  }
  const size_t blocked_elements = CapacityToGrowth(capacity) - reserved_size;
  if (is_single_group(capacity)) {
    // Single group tables never probes, so we can block all the slots.
    return blocked_elements;
  }
  return (std::min)(blocked_elements, kMaxBlockedElementsForLargeTables);
}

// Resizes empty non-allocated table to the capacity to fit new_size elements.
// Requires:
//   1. `c.capacity() == policy.soo_capacity()`.
//   2. `c.empty()`.
//   3. `new_size > policy.soo_capacity()`.
// The table will be attempted to be sampled.
void ReserveEmptyNonAllocatedTableToFitNewSize(
    CommonFields& common, const PolicyFunctions& __restrict policy,
    size_t new_size) {
  ValidateMaxSize(new_size, policy.key_size, policy.slot_size);
  ABSL_ASSUME(new_size > 0);
  const size_t new_capacity = SizeToCapacity(new_size);
  ResizeEmptyNonAllocatedTableImpl(
      common, policy, new_capacity,
      BlockedElementCountForReservedTable(new_capacity, new_size),
      /*force_infoz=*/false);
  // This is after resize, to ensure that we have completed the allocation
  // and have potentially sampled the hashtable.
  common.infoz().RecordReservation(new_size);
}

// Type erased version of raw_hash_set::reserve for tables that have an
// allocated backing array.
//
// Requires:
//   1. `c.capacity() > policy.soo_capacity()` OR `!c.empty()`.
// Reserving already allocated tables is considered to be a rare case.
ABSL_ATTRIBUTE_NOINLINE void ReserveAllocatedTable(
    CommonFields& common, const PolicyFunctions& __restrict policy,
    size_t new_size) {
  const size_t cap = common.capacity();
  ValidateMaxSize(new_size, policy.key_size, policy.slot_size);
  ABSL_ASSUME(new_size > 0);
  const size_t new_capacity = SizeToCapacity(new_size);
  if (cap == policy.soo_capacity()) {
    ABSL_SWISSTABLE_ASSERT(!common.empty());
    ResizeFullSooTable(common, policy, new_capacity,
                       ResizeFullSooTableSamplingMode::kNoSampling);
  } else {
    ABSL_SWISSTABLE_ASSERT(cap > policy.soo_capacity());
    // TODO(b/382423690): consider using GrowToNextCapacity, when applicable.
    ResizeAllocatedTableWithSeedChange(common, policy, new_capacity);
  }
  common.infoz().RecordReservation(new_size);
}

// As `ResizeFullSooTableToNextCapacity`, except that we also force the SOO
// table to be sampled. SOO tables need to switch from SOO to heap in order to
// store the infoz. No-op if sampling is disabled or not possible.
void GrowFullSooTableToNextCapacityForceSampling(
    CommonFields& common, const PolicyFunctions& __restrict policy) {
  AssertFullSoo(common, policy);
  ResizeFullSooTable(
      common, policy, NextCapacity(SooCapacity()),
      ResizeFullSooTableSamplingMode::kForceSampleNoResizeIfUnsampled);
}

}  // namespace

void* GetRefForEmptyClass(CommonFields& common) {
  // Empty base optimization typically make the empty base class address to be
  // the same as the first address of the derived class object.
  // But we generally assume that for empty classes we can return any valid
  // pointer.
  return &common;
}

void ResizeAllocatedTableWithSeedChange(
    CommonFields& common, const PolicyFunctions& __restrict policy,
    size_t new_capacity) {
  ABSL_SWISSTABLE_ASSERT(IsValidCapacity(new_capacity));
  ABSL_SWISSTABLE_ASSERT(new_capacity > policy.soo_capacity());

  const size_t old_capacity = common.capacity();
  ctrl_t* const old_ctrl = common.control();
  void* const old_slots = common.slot_array(old_capacity);
  const size_t old_blocked_element_count = common.blocked_element_count();

  const size_t slot_size = policy.slot_size;
  const size_t slot_align = policy.slot_align;
  HashtablezInfoHandle infoz = common.infoz();
  const bool has_infoz = infoz.IsSampled();
  void* alloc = policy.get_char_alloc(common);

  common.set_capacity(new_capacity);
  common.set_blocked_element_count_to_zero();
  const auto [new_ctrl, new_slots] =
      AllocBackingArray(common, policy, new_capacity, has_infoz, alloc,
                        /*blocked_element_count=*/0);
  common.set_control(new_ctrl);
  common.generate_new_seed(has_infoz);

  size_t total_probe_length = 0;
  ResetCtrl(common, slot_size, /*blocked_element_count=*/0);
  ABSL_SWISSTABLE_ASSERT(old_capacity > 0);
  total_probe_length = FindNewPositionsAndTransferSlots(
      common, policy, old_ctrl, old_slots, old_capacity);
  (*policy.dealloc)(alloc, old_capacity, old_ctrl, slot_size, slot_align,
                    has_infoz, old_blocked_element_count);
  if (GrowthInfoSizeForCapacity(new_capacity) > 0) {
    ResetGrowthLeft(GetGrowthInfoFromControl(new_ctrl), new_capacity,
                    common.size());
  }

  if (ABSL_PREDICT_FALSE(has_infoz)) {
    ReportResizeToInfoz(common, infoz, total_probe_length);
  }
}

// Resizes a full SOO table to the NextCapacity(SooCapacity()).
template <size_t SooSlotMemcpySize, bool TransferUsesMemcpy>
void* GrowSooTableToNextCapacityAndPrepareInsert(
    CommonFields& common, const PolicyFunctions& __restrict policy,
    absl::FunctionRef<size_t(size_t)> get_hash, bool force_sampling) {
  AssertSoo(common, policy);
  if (ABSL_PREDICT_FALSE(force_sampling)) {
    // The table is empty, it is only used for forced sampling of SOO tables.
    return GrowEmptySooTableToNextCapacityForceSamplingAndPrepareInsert(
        common, policy, get_hash);
  }
  ABSL_SWISSTABLE_ASSERT(common.size() == policy.soo_capacity());
  static constexpr size_t kNewCapacity = NextCapacity(SooCapacity());
  const size_t slot_size = policy.slot_size;
  void* alloc = policy.get_char_alloc(common);
  common.set_capacity(kNewCapacity);

  // Since the table is not empty, it will not be sampled.
  // The decision to sample was already made during the first insertion.
  //
  // We do not set control and slots in CommonFields yet to avoid overriding
  // SOO data.
  const auto [new_ctrl, new_slots] = AllocBackingArray(
      common, policy, kNewCapacity, /*has_infoz=*/false, alloc,
      /*blocked_element_count=*/0);

  PrepareInsertCommon(common);
  ABSL_SWISSTABLE_ASSERT(common.size() == 2);
  GetGrowthInfoFromControl(new_ctrl).InitGrowthLeftNoDeleted(kNewCapacity - 2,
                                                             kNewCapacity);
  common.generate_new_seed(/*has_infoz=*/false);
  const h2_t soo_slot_h2 = H2(policy.hash_slot(
      policy.hash_fn(common), common.soo_data(), common.seed().seed()));
  const size_t new_hash = get_hash(common.seed().seed());

  const size_t offset = Resize1To3NewOffset(new_hash, common.seed());
  InitializeThreeElementsControlBytes(soo_slot_h2, H2(new_hash), offset,
                                      new_ctrl);

  SanitizerPoisonMemoryRegion(new_slots, slot_size * kNewCapacity);
  void* target_slot = SlotAddress(new_slots, SooSlotIndex(), slot_size);
  SanitizerUnpoisonMemoryRegion(target_slot, slot_size);
  if constexpr (TransferUsesMemcpy) {
    // Target slot is placed at index 1, but capacity is at
    // minimum 3. So we are allowed to copy at least twice as much
    // memory.
    static_assert(SooSlotIndex() == 1);
    static_assert(SooSlotMemcpySize > 0);
    static_assert(SooSlotMemcpySize <= MaxSooSlotSize());
    ABSL_SWISSTABLE_ASSERT(SooSlotMemcpySize <= 2 * slot_size);
    ABSL_SWISSTABLE_ASSERT(SooSlotMemcpySize >= slot_size);
    void* next_slot = SlotAddress(target_slot, 1, slot_size);
    SanitizerUnpoisonMemoryRegion(next_slot, SooSlotMemcpySize - slot_size);
    std::memcpy(target_slot, common.soo_data(), SooSlotMemcpySize);
    SanitizerPoisonMemoryRegion(next_slot, SooSlotMemcpySize - slot_size);
  } else {
    static_assert(SooSlotMemcpySize == 0);
    policy.transfer_n(&common, target_slot, common.soo_data(), 1);
  }
  common.set_control(new_ctrl);

  // Full SOO table couldn't be sampled. If SOO table is sampled, it would
  // have been resized to the next capacity.
  ABSL_SWISSTABLE_ASSERT(!common.infoz().IsSampled());
  void* new_slot = SlotAddress(new_slots, offset, slot_size);
  SanitizerUnpoisonMemoryRegion(new_slot, slot_size);
  return new_slot;
}

void Rehash(CommonFields& common, const PolicyFunctions& __restrict policy,
            size_t n) {
  const size_t cap = common.capacity();

  auto clear_backing_array = [&]() {
    ClearBackingArrayNoReuse(common, policy, policy.get_char_alloc(common));
  };

  const size_t slot_size = policy.slot_size;

  if (n == 0) {
    if (cap <= policy.soo_capacity()) return;
    if (common.empty()) {
      clear_backing_array();
      return;
    }
    if (common.size() <= policy.soo_capacity()) {
      // When the table is already sampled, we keep it sampled.
      if (common.infoz().IsSampled()) {
        static constexpr size_t kInitialSampledCapacity =
            NextCapacity(SooCapacity());
        if (cap > kInitialSampledCapacity) {
          ResizeAllocatedTableWithSeedChange(common, policy,
                                             kInitialSampledCapacity);
        }
        // This asserts that we didn't lose sampling coverage in `resize`.
        ABSL_SWISSTABLE_ASSERT(common.infoz().IsSampled());
        return;
      }
      ABSL_SWISSTABLE_ASSERT(slot_size <= sizeof(HeapOrSoo));
      ABSL_SWISSTABLE_ASSERT(policy.slot_align <= alignof(HeapOrSoo));
      HeapOrSoo tmp_slot;
      size_t begin_offset = FindFirstFullSlot(0, cap, common.control());
      policy.transfer_n(
          &common, &tmp_slot,
          SlotAddress(common.slot_array(cap), begin_offset, slot_size), 1);
      clear_backing_array();
      policy.transfer_n(&common, common.soo_data(), &tmp_slot, 1);
      common.set_full_soo();
      return;
    }
  }

  // bitor is a faster way of doing `max` here. We will round up to the next
  // power-of-2-minus-1, so bitor is good enough.
  const size_t new_capacity =
      NormalizeCapacity(n | SizeToCapacity(common.size()));
  ValidateMaxCapacity(new_capacity, policy.key_size, policy.slot_size);
  // n == 0 unconditionally rehashes as per the standard.
  if (n == 0 || new_capacity > cap) {
    if (cap == policy.soo_capacity()) {
      if (common.empty()) {
        ResizeEmptyNonAllocatedTableImpl(common, policy, new_capacity,
                                         /*blocked_element_count=*/0,
                                         /*force_infoz=*/false);
      } else {
        ResizeFullSooTable(common, policy, new_capacity,
                           ResizeFullSooTableSamplingMode::kNoSampling);
      }
    } else {
      ResizeAllocatedTableWithSeedChange(common, policy, new_capacity);
    }
    // This is after resize, to ensure that we have completed the allocation
    // and have potentially sampled the hashtable.
    common.infoz().RecordReservation(n);
  }
}

void Copy(CommonFields& common, const PolicyFunctions& __restrict policy,
          const CommonFields& other,
          absl::FunctionRef<void(void*, const void*)> copy_fn) {
  const size_t size = other.size();
  ABSL_SWISSTABLE_ASSERT(size > 0);
  const size_t soo_capacity = policy.soo_capacity();
  const size_t slot_size = policy.slot_size;
  const bool soo_enabled = policy.soo_enabled;
  if (size == 1) {
    if (!soo_enabled) ReserveTableToFitNewSize(common, policy, 1);
    IncrementSmallSize(common, policy);
    const size_t other_capacity = other.capacity();
    const void* other_slot =
        other_capacity <= soo_capacity ? other.soo_data()
        : IsSmallCapacity(other_capacity)
            ? other.slot_array(other_capacity)
            : SlotAddress(other.slot_array(other_capacity),
                          FindFirstFullSlot(0, other_capacity, other.control()),
                          slot_size);
    copy_fn(soo_enabled ? common.soo_data()
                        : SingleSlotAddress</*kSooEnabled=*/false>(common),
            other_slot);

    if (soo_enabled && policy.is_hashtablez_eligible &&
        ShouldSampleNextTable()) {
      GrowFullSooTableToNextCapacityForceSampling(common, policy);
    }
    return;
  }

  ReserveTableToFitNewSize(common, policy, size);
  const size_t blocked_element_count = common.blocked_element_count();
  auto infoz = common.infoz();
  ABSL_SWISSTABLE_ASSERT(other.capacity() > soo_capacity);
  const size_t cap = common.capacity();
  ABSL_SWISSTABLE_ASSERT(cap > soo_capacity);
  ABSL_ASSUME(cap > kMaxSmallCapacity);
  size_t offset = cap;
  const void* hash_fn = policy.hash_fn(common);
  auto hasher = policy.hash_slot;
  const size_t seed = common.seed().seed();
  void* target_slot_array = common.slot_array(cap);
  IterateOverFullSlotsImpl(
      other, slot_size, [&](const ctrl_t*, void* that_slot) {
        // The table is guaranteed to be empty, so we can do faster than
        // a full `insert`.
        const size_t hash = (*hasher)(hash_fn, that_slot, seed);
        FindInfo target = find_first_non_full(common, hash);
        infoz.RecordInsertMiss(hash, target.probe_length);
        offset = target.offset;
        SetCtrl(common, offset, H2(hash), slot_size);
        copy_fn(SlotAddress(target_slot_array, offset, slot_size), that_slot);
        common.maybe_increment_generation_on_insert();
      });
  common.increment_size(size);
  ResetGrowthLeft(common.growth_info(), cap, size + blocked_element_count);
}

void ReserveTableToFitNewSize(CommonFields& common,
                              const PolicyFunctions& __restrict policy,
                              size_t new_size) {
  new_size =
      std::min(new_size, MaxValidSize(policy.key_size, policy.slot_size));
  common.reset_reserved_growth(new_size);
  common.set_reservation_size(new_size);
  ABSL_SWISSTABLE_ASSERT(new_size > policy.soo_capacity());
  const size_t cap = common.capacity();
  if (ABSL_PREDICT_TRUE(common.empty() && cap <= policy.soo_capacity())) {
    return ReserveEmptyNonAllocatedTableToFitNewSize(common, policy, new_size);
  }

  ABSL_SWISSTABLE_ASSERT(!common.empty() || cap > policy.soo_capacity());
  ABSL_SWISSTABLE_ASSERT(cap > 0);
  const size_t max_size_before_growth =
      IsSmallCapacity(cap)
          ? cap
          : common.size() + common.growth_info().GetGrowthLeftTotalSlow(cap);
  if (new_size <= max_size_before_growth) {
    return;
  }
  ReserveAllocatedTable(common, policy, new_size);
}

namespace {
void* PrepareInsertLargeImpl(CommonFields& common,
                             const PolicyFunctions& __restrict policy,
                             size_t hash,
                             Group::NonIterableBitMaskType mask_empty,
                             FindInfo target_group) {
  ABSL_SWISSTABLE_ASSERT(!common.is_small());
  GrowthInfoAccessor growth_info = common.growth_info();
  // When there are no deleted slots in the table
  // and growth_left is positive, we can insert at the first
  // empty slot in the probe sequence (target).
  if (ABSL_PREDICT_FALSE(
          !growth_info.GetGrowthInfoLowerBound().HasNoDeletedAndGrowthLeft())) {
    return PrepareInsertLargeSlow(common, policy, hash);
  }
  PrepareInsertCommon(common);
  growth_info.OverwriteEmptyAsFull();
  const size_t cap = common.capacity();
  ABSL_ASSUME(cap > kMaxSmallCapacity);
  target_group.offset += mask_empty.LowestBitSet();
  target_group.offset &= cap;
  SetCtrl(common, target_group.offset, H2(hash), policy.slot_size);
  common.infoz().RecordInsertMiss(hash, target_group.probe_length);
  return SlotAddress(common.slot_array(cap), target_group.offset,
                     policy.slot_size);
}
}  // namespace

void* PrepareInsertLarge(CommonFields& common,
                         const PolicyFunctions& __restrict policy, size_t hash,
                         Group::NonIterableBitMaskType mask_empty,
                         FindInfo target_group) {
  // NOLINTNEXTLINE(misc-static-assert)
  ABSL_SWISSTABLE_ASSERT(!SwisstableGenerationsEnabled());
  return PrepareInsertLargeImpl(common, policy, hash, mask_empty, target_group);
}

void* PrepareInsertLargeGenerationsEnabled(
    CommonFields& common, const PolicyFunctions& __restrict policy, size_t hash,
    Group::NonIterableBitMaskType mask_empty, FindInfo target_group,
    absl::FunctionRef<size_t(size_t)> recompute_hash) {
  // NOLINTNEXTLINE(misc-static-assert)
  ABSL_SWISSTABLE_ASSERT(SwisstableGenerationsEnabled());
  const size_t cap = common.capacity();
  const size_t growth_left = common.growth_info().GetGrowthLeftTotalSlow(cap);
  // As an optimization, we avoid calling ShouldRehashForBugDetection if we
  // will end up rehashing anyways.
  if (growth_left > 0 && common.should_rehash_for_bug_detection_on_insert()) {
    // Move to a different heap allocation in order to detect bugs.
    ResizeAllocatedTableWithSeedChange(common, policy, cap);
    hash = recompute_hash(common.seed().seed());
    std::tie(target_group, mask_empty) =
        find_first_non_full_group(common, hash);
  }
  return PrepareInsertLargeImpl(common, policy, hash, mask_empty, target_group);
}

namespace {
// Returns true if the following is true
// 1. OptimalMemcpySizeForSooSlotTransfer(left) >
//    OptimalMemcpySizeForSooSlotTransfer(left - 1)
// 2. OptimalMemcpySizeForSooSlotTransfer(left) are equal for all i in [left,
// right].
// This function is used to verify that we have all the possible template
// instantiations for GrowFullSooTableToNextCapacity.
// With this verification the problem may be detected at compile time instead of
// link time.
constexpr bool VerifyOptimalMemcpySizeForSooSlotTransferRange(size_t left,
                                                              size_t right) {
  size_t optimal_size_for_range = OptimalMemcpySizeForSooSlotTransfer(left);
  if (optimal_size_for_range <= OptimalMemcpySizeForSooSlotTransfer(left - 1)) {
    return false;
  }
  for (size_t i = left + 1; i <= right; ++i) {
    if (OptimalMemcpySizeForSooSlotTransfer(i) != optimal_size_for_range) {
      return false;
    }
  }
  return true;
}
}  // namespace

// Extern template instantiation for inline function.
template size_t TryFindNewIndexWithoutProbing(size_t h1, size_t old_index,
                                              size_t old_capacity,
                                              ctrl_t* new_ctrl,
                                              size_t new_capacity);

// We need to instantiate ALL possible template combinations because we define
// the function in the cc file.
template void* GrowSooTableToNextCapacityAndPrepareInsert<0, false>(
    CommonFields&, const PolicyFunctions&, absl::FunctionRef<size_t(size_t)>,
    bool);
template void* GrowSooTableToNextCapacityAndPrepareInsert<
    OptimalMemcpySizeForSooSlotTransfer(1), true>(
    CommonFields&, const PolicyFunctions&, absl::FunctionRef<size_t(size_t)>,
    bool);

static_assert(VerifyOptimalMemcpySizeForSooSlotTransferRange(2, 3));
template void* GrowSooTableToNextCapacityAndPrepareInsert<
    OptimalMemcpySizeForSooSlotTransfer(3), true>(
    CommonFields&, const PolicyFunctions&, absl::FunctionRef<size_t(size_t)>,
    bool);

#if UINTPTR_MAX == UINT32_MAX
static_assert(MaxSooSlotSize() == 4);
static_assert(VerifyOptimalMemcpySizeForSooSlotTransferRange(2, 4));
#else
static_assert(VerifyOptimalMemcpySizeForSooSlotTransferRange(4, 8));
template void* GrowSooTableToNextCapacityAndPrepareInsert<
    OptimalMemcpySizeForSooSlotTransfer(8), true>(
    CommonFields&, const PolicyFunctions&, absl::FunctionRef<size_t(size_t)>,
    bool);
static_assert(MaxSooSlotSize() == 8);
#endif

template void* AllocateBackingArray<BackingArrayAlignment(alignof(size_t)),
                                    std::allocator<char>>(void* alloc,
                                                          size_t n);
template void DeallocateBackingArray<BackingArrayAlignment(alignof(size_t)),
                                     std::allocator<char>>(
    void* alloc, size_t capacity, ctrl_t* ctrl, size_t slot_size,
    size_t slot_align, bool had_infoz, size_t blocked_element_count);

template void Clear<true>(CommonFields& c, const PolicyFunctions& policy,
                          DestroySlotFn destroy_slot, void* alloc);
template void Clear<false>(CommonFields& c, const PolicyFunctions& policy,
                           DestroySlotFn destroy_slot, void* alloc);

}  // namespace container_internal
ABSL_NAMESPACE_END
}  // namespace absl
