@@ -145,7 +145,7 @@ size_t PrepareInsertAfterSoo(size_t hash, size_t slot_size,
145145 assert (common.capacity () == NextCapacity (SooCapacity ()));
146146 // After resize from capacity 1 to 3, we always have exactly the slot with
147147 // index 1 occupied, so we need to insert either at index 0 or index 2.
148- assert ( HashSetResizeHelper:: SooSlotIndex () == 1 );
148+ static_assert ( SooSlotIndex () == 1 , " " );
149149 PrepareInsertCommon (common);
150150 const size_t offset = SingleGroupTableH1 (hash, common.control ()) & 2 ;
151151 common.growth_info ().OverwriteEmptyAsFull ();
@@ -478,49 +478,6 @@ void HashSetResizeHelper::GrowIntoSingleGroupShuffleControlBytes(
478478 // new_ctrl after 2nd store = E0123456EEEEEEESE0123456EEEEEEE
479479}
480480
481- void HashSetResizeHelper::InitControlBytesAfterSoo (ctrl_t * new_ctrl, ctrl_t h2,
482- size_t new_capacity) {
483- assert (is_single_group (new_capacity));
484- static_assert (HashSetResizeHelper::SooSlotIndex () == 1 , " " );
485- // This allows us to avoid branching on had_soo_slot_.
486- assert (had_soo_slot_ || h2 == ctrl_t ::kEmpty );
487-
488- if (Group::kWidth == 16 ) {
489- // Initialize the second 8 bytes in the original and mirrored control bytes.
490- // The ranges can overlap.
491- absl::little_endian::Store64 (new_ctrl + 8 , kMsbs8Bytes );
492- absl::little_endian::Store64 (new_ctrl + new_capacity + 8 , kMsbs8Bytes );
493- }
494- static constexpr uint64_t kAllEmptyExceptSoo =
495- kMsbs8Bytes ^ (static_cast <uint64_t >(static_cast <uint8_t >(ctrl_t ::kEmpty ))
496- << (8 * HashSetResizeHelper::SooSlotIndex ()));
497- // Initialize the first 8 bytes in the original control bytes.
498- // The first 8 bytes are all empty except the SOO slot.
499- // The range may overlap with the mirrored control bytes. These bytes will be
500- // overwritten later.
501- uint64_t first_ctrl_bytes =
502- kAllEmptyExceptSoo ^ (static_cast <uint64_t >(static_cast <uint8_t >(h2))
503- << (8 * HashSetResizeHelper::SooSlotIndex ()));
504- absl::little_endian::Store64 (new_ctrl, first_ctrl_bytes);
505- // Initialize Sentinel byte and the first 7 bytes in the mirrored control
506- // bytes.
507- // We are adding kSentinel as the first byte of the mirrored control bytes.
508- uint64_t mirrored_ctrl_bytes =
509- (first_ctrl_bytes << 8 ) ^
510- static_cast <uint64_t >(static_cast <uint8_t >(ctrl_t ::kSentinel ));
511- absl::little_endian::Store64 (new_ctrl + new_capacity, mirrored_ctrl_bytes);
512-
513- // Example for capacity 3:
514- // new_ctrl after 2 stores = ????????EEEEEEEEEEE
515- // new_ctrl after 3rd store = E0EEEEEEEEEEEEEEEEE
516- // new_ctrl after 4th store = E0ESE0EEEEEEEEEEEEE
517-
518- // Example for capacity 15:
519- // new_ctrl after 2 stores = ????????EEEEEEEE???????EEEEEEEE
520- // new_ctrl after 3rd store = E0EEEEEEEEEEEEEE???????EEEEEEEE
521- // new_ctrl after 4th store = E0EEEEEEEEEEEEESE0EEEEEEEEEEEEE
522- }
523-
524481void HashSetResizeHelper::GrowIntoSingleGroupShuffleTransferableSlots (
525482 void * new_slots, size_t slot_size) const {
526483 ABSL_ASSUME (old_capacity_ > 0 );
@@ -543,14 +500,23 @@ void HashSetResizeHelper::GrowSizeIntoSingleGroupTransferable(
543500 PoisonSingleGroupEmptySlots (c, slot_size);
544501}
545502
546- void HashSetResizeHelper::TransferSlotAfterSoo (CommonFields& c,
547- size_t slot_size) {
503+ void HashSetResizeHelper::InsertOldSooSlotAndInitializeControlBytesLarge (
504+ CommonFields& c, size_t hash, ctrl_t * new_ctrl, void * new_slots,
505+ const PolicyFunctions& policy) {
548506 assert (was_soo_);
549507 assert (had_soo_slot_);
550- assert (is_single_group (c.capacity ()));
551- std::memcpy (SlotAddress (c.slot_array (), SooSlotIndex (), slot_size),
552- old_soo_data (), slot_size);
553- PoisonSingleGroupEmptySlots (c, slot_size);
508+ size_t new_capacity = c.capacity ();
509+
510+ size_t offset = probe (new_ctrl, new_capacity, hash).offset ();
511+ offset = offset == new_capacity ? 0 : offset;
512+ SanitizerPoisonMemoryRegion (new_slots, policy.slot_size * new_capacity);
513+ void * target_slot = SlotAddress (new_slots, offset, policy.slot_size );
514+ SanitizerUnpoisonMemoryRegion (target_slot, policy.slot_size );
515+ policy.transfer (&c, target_slot, c.soo_data ());
516+ c.set_control (new_ctrl);
517+ c.set_slots (new_slots);
518+ ResetCtrl (c, policy.slot_size );
519+ SetCtrl (c, offset, H2 (hash), policy.slot_size );
554520}
555521
556522namespace {
0 commit comments