Skip to content

Commit 7253ff8

Browse files
goldvitalycopybara-github
authored andcommitted
Move SOO processing inside of InitializeSlots and move it once.
That reduces binary size by moving more code to type erased InitializeSlots. It also make SOO element to be moved once that can be useful for expensive to move types. PiperOrigin-RevId: 721938625 Change-Id: I449753440fe91cb1bb5a1569e23d1986f5b0a642
1 parent 0f102ad commit 7253ff8

File tree

3 files changed

+200
-155
lines changed

3 files changed

+200
-155
lines changed

absl/container/internal/raw_hash_set.cc

Lines changed: 16 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
524481
void 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

556522
namespace {

0 commit comments

Comments
 (0)