summaryrefslogtreecommitdiff
path: root/absl/container/internal/raw_hash_set.h
diff options
context:
space:
mode:
authorGravatar Samuel Benzaquen <sbenza@google.com>2022-12-01 10:08:04 -0800
committerGravatar Copybara-Service <copybara-worker@google.com>2022-12-01 10:09:01 -0800
commit1063d2b829bbf1b5cf03f5f8e1e9fe4c71c9f966 (patch)
treeb3b7c59af09d843a93a41fd0614d89df4f1cdff2 /absl/container/internal/raw_hash_set.h
parenta23d720c30e2fff8dde9605bcabe39ce5b4069fc (diff)
Move the vtable into a function to delay instantiation until the function is
called. When the variable is a global the compiler is allowed to instantiate it more aggresively and it might happen before the types involved are complete. When it is inside a function the compiler can't instantiate it until after the functions are called. Remove an unused member from the vtable. Replace transfer_slot_fn with a generic function when relocation is available to reduce duplication. PiperOrigin-RevId: 492227302 Change-Id: I07499f63b91c59c0ae42402683387c7b84a6f0ee
Diffstat (limited to 'absl/container/internal/raw_hash_set.h')
-rw-r--r--absl/container/internal/raw_hash_set.h44
1 files changed, 25 insertions, 19 deletions
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index ab59856e..f7c63467 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -1058,7 +1058,6 @@ ABSL_ATTRIBUTE_NOINLINE void InitializeSlots(CommonFields& c,
// work.
struct PolicyFunctions {
size_t slot_size;
- size_t slot_align;
// Return the hash of the pointed-to slot.
size_t (*hash_slot)(void* set, void* slot);
@@ -1098,6 +1097,14 @@ ABSL_ATTRIBUTE_NOINLINE void DeallocateStandard(void*,
AllocSize(n, policy.slot_size, AlignOfSlot));
}
+// For trivially relocatable types we use memcpy directly. This allows us to
+// share the same function body for raw_hash_set instantiations that have the
+// same slot size as long as they are relocatable.
+template <size_t SizeOfSlot>
+ABSL_ATTRIBUTE_NOINLINE void TransferRelocatable(void*, void* dst, void* src) {
+ memcpy(dst, src, SizeOfSlot);
+}
+
// Type-erased version of raw_hash_set::drop_deletes_without_resize.
void DropDeletesWithoutResize(CommonFields& common, size_t& growth_left,
const PolicyFunctions& policy, void* tmp_space);
@@ -1538,7 +1545,7 @@ class raw_hash_set : private CommonFields {
// Already guaranteed to be empty; so nothing to do.
} else {
destroy_slots();
- ClearBackingArray(common(), growth_left(), kPolicyFunctions,
+ ClearBackingArray(common(), growth_left(), GetPolicyFunctions(),
/*reuse=*/cap < 128);
}
}
@@ -1846,7 +1853,7 @@ class raw_hash_set : private CommonFields {
void rehash(size_t n) {
if (n == 0 && capacity() == 0) return;
if (n == 0 && size() == 0) {
- ClearBackingArray(common(), growth_left(), kPolicyFunctions,
+ ClearBackingArray(common(), growth_left(), GetPolicyFunctions(),
/*reuse=*/false);
return;
}
@@ -2127,7 +2134,8 @@ class raw_hash_set : private CommonFields {
inline void drop_deletes_without_resize() {
// Stack-allocate space for swapping elements.
alignas(slot_type) unsigned char tmp[sizeof(slot_type)];
- DropDeletesWithoutResize(common(), growth_left(), kPolicyFunctions, tmp);
+ DropDeletesWithoutResize(common(), growth_left(), GetPolicyFunctions(),
+ tmp);
}
// Called whenever the table *might* need to conditionally grow.
@@ -2347,15 +2355,19 @@ class raw_hash_set : private CommonFields {
AllocSize(n, sizeof(slot_type), alignof(slot_type)));
}
- static constexpr PolicyFunctions kPolicyFunctions = {
- sizeof(slot_type),
- alignof(slot_type),
- &raw_hash_set::hash_slot_fn,
- &raw_hash_set::transfer_slot_fn,
- (std::is_same<SlotAlloc, std::allocator<slot_type>>::value
- ? &DeallocateStandard<alignof(slot_type)>
- : &raw_hash_set::dealloc_fn),
- };
+ static const PolicyFunctions& GetPolicyFunctions() {
+ static constexpr PolicyFunctions value = {
+ sizeof(slot_type),
+ &raw_hash_set::hash_slot_fn,
+ PolicyTraits::transfer_uses_memcpy()
+ ? TransferRelocatable<sizeof(slot_type)>
+ : &raw_hash_set::transfer_slot_fn,
+ (std::is_same<SlotAlloc, std::allocator<slot_type>>::value
+ ? &DeallocateStandard<alignof(slot_type)>
+ : &raw_hash_set::dealloc_fn),
+ };
+ return value;
+ }
// Bundle together growth_left (number of slots that can be filled without
// rehashing) plus other objects which might be empty. CompressedTuple will
@@ -2366,12 +2378,6 @@ class raw_hash_set : private CommonFields {
settings_{0u, hasher{}, key_equal{}, allocator_type{}};
};
-#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-template <class Policy, class Hash, class Eq, class Alloc>
-constexpr PolicyFunctions
- raw_hash_set<Policy, Hash, Eq, Alloc>::kPolicyFunctions;
-#endif
-
// Erases all elements that satisfy the predicate `pred` from the container `c`.
template <typename P, typename H, typename E, typename A, typename Predicate>
typename raw_hash_set<P, H, E, A>::size_type EraseIf(