diff options
author | Evan Brown <ezb@google.com> | 2024-03-12 14:29:39 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2024-03-12 14:31:30 -0700 |
commit | 038561296676d1cae4a3cee30f8c924befbb6083 (patch) | |
tree | 724042c21eb6dfc0913a1eff86ffc7da3e0f4274 | |
parent | 3c1f9be71ee280539f02e57c5e461b0271f54e91 (diff) |
Add extern templates for common swisstable types.
Motivation: mitigate linker input size increase from swisstable optimizations.
Note: the changes in raw_hash_set.h are fixing build errors that happened when adding the explicit instantiations. The change in unchecked_deref is because set iterators have const reference access whereas map iterators have mutable reference access and the function is never actually called for sets (it's used in raw_hash_map) so it wasn't needed before. I'm not sure why the soo_slot/soo_iterator problems didn't cause compile errors earlier.
PiperOrigin-RevId: 615174043
Change-Id: Iac5eb2332a76e9b70021156fbb2b8def47a5391d
-rw-r--r-- | CMake/AbseilDll.cmake | 4 | ||||
-rw-r--r-- | absl/container/BUILD.bazel | 10 | ||||
-rw-r--r-- | absl/container/CMakeLists.txt | 14 | ||||
-rw-r--r-- | absl/container/flat_hash_map.cc | 40 | ||||
-rw-r--r-- | absl/container/flat_hash_map.h | 41 | ||||
-rw-r--r-- | absl/container/flat_hash_set.cc | 36 | ||||
-rw-r--r-- | absl/container/flat_hash_set.h | 29 | ||||
-rw-r--r-- | absl/container/internal/raw_hash_set.h | 32 | ||||
-rw-r--r-- | absl/container/node_hash_map.cc | 40 | ||||
-rw-r--r-- | absl/container/node_hash_map.h | 40 | ||||
-rw-r--r-- | absl/container/node_hash_set.cc | 36 | ||||
-rw-r--r-- | absl/container/node_hash_set.h | 30 |
12 files changed, 345 insertions, 7 deletions
diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake index 47f3beeb..4beafd7a 100644 --- a/CMake/AbseilDll.cmake +++ b/CMake/AbseilDll.cmake @@ -68,7 +68,9 @@ set(ABSL_INTERNAL_DLL_FILES "container/btree_set.h" "container/fixed_array.h" "container/flat_hash_map.h" + "container/flat_hash_map.cc" "container/flat_hash_set.h" + "container/flat_hash_set.cc" "container/inlined_vector.h" "container/internal/btree.h" "container/internal/btree_container.h" @@ -91,7 +93,9 @@ set(ABSL_INTERNAL_DLL_FILES "container/internal/raw_hash_set.h" "container/internal/tracked.h" "container/node_hash_map.h" + "container/node_hash_map.cc" "container/node_hash_set.h" + "container/node_hash_set.cc" "crc/crc32c.cc" "crc/crc32c.h" "crc/internal/cpu_detect.cc" diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel index 0de45263..366bf3cd 100644 --- a/absl/container/BUILD.bazel +++ b/absl/container/BUILD.bazel @@ -242,6 +242,7 @@ NOTEST_TAGS_MOBILE = [ cc_library( name = "flat_hash_map", + srcs = ["flat_hash_map.cc"], hdrs = ["flat_hash_map.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, @@ -249,7 +250,9 @@ cc_library( ":container_memory", ":hash_function_defaults", ":raw_hash_map", + ":raw_hash_set", "//absl/algorithm:container", + "//absl/base:config", "//absl/base:core_headers", "//absl/memory", ], @@ -279,6 +282,7 @@ cc_test( cc_library( name = "flat_hash_set", + srcs = ["flat_hash_set.cc"], hdrs = ["flat_hash_set.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, @@ -287,6 +291,7 @@ cc_library( ":hash_function_defaults", ":raw_hash_set", "//absl/algorithm:container", + "//absl/base:config", "//absl/base:core_headers", "//absl/memory", ], @@ -318,6 +323,7 @@ cc_test( cc_library( name = "node_hash_map", + srcs = ["node_hash_map.cc"], hdrs = ["node_hash_map.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, @@ -326,7 +332,9 @@ cc_library( ":hash_function_defaults", ":node_slot_policy", ":raw_hash_map", + ":raw_hash_set", "//absl/algorithm:container", + "//absl/base:config", "//absl/base:core_headers", "//absl/memory", ], @@ -353,6 +361,7 @@ cc_test( cc_library( name = "node_hash_set", + srcs = ["node_hash_set.cc"], hdrs = ["node_hash_set.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, @@ -362,6 +371,7 @@ cc_library( ":node_slot_policy", ":raw_hash_set", "//absl/algorithm:container", + "//absl/base:config", "//absl/base:core_headers", "//absl/memory", ], diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt index 4b08e6a3..8e64adb1 100644 --- a/absl/container/CMakeLists.txt +++ b/absl/container/CMakeLists.txt @@ -283,13 +283,17 @@ absl_cc_library( flat_hash_map HDRS "flat_hash_map.h" + SRCS + "flat_hash_map.cc" COPTS ${ABSL_DEFAULT_COPTS} DEPS + absl::config absl::container_memory absl::core_headers absl::hash_function_defaults absl::raw_hash_map + absl::raw_hash_set absl::algorithm_container absl::memory PUBLIC @@ -321,9 +325,12 @@ absl_cc_library( flat_hash_set HDRS "flat_hash_set.h" + SRCS + "flat_hash_set.cc" COPTS ${ABSL_DEFAULT_COPTS} DEPS + absl::config absl::container_memory absl::hash_function_defaults absl::raw_hash_set @@ -362,14 +369,18 @@ absl_cc_library( node_hash_map HDRS "node_hash_map.h" + SRCS + "node_hash_map.cc" COPTS ${ABSL_DEFAULT_COPTS} DEPS + absl::config absl::container_memory absl::core_headers absl::hash_function_defaults absl::node_slot_policy absl::raw_hash_map + absl::raw_hash_set absl::algorithm_container absl::memory PUBLIC @@ -398,9 +409,12 @@ absl_cc_library( node_hash_set HDRS "node_hash_set.h" + SRCS + "node_hash_set.cc" COPTS ${ABSL_DEFAULT_COPTS} DEPS + absl::config absl::container_memory absl::core_headers absl::hash_function_defaults diff --git a/absl/container/flat_hash_map.cc b/absl/container/flat_hash_map.cc new file mode 100644 index 00000000..d5a25317 --- /dev/null +++ b/absl/container/flat_hash_map.cc @@ -0,0 +1,40 @@ +// Copyright 2024 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/flat_hash_map.h" + +#include <cstdint> +#include <string> + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, int32_t, int32_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, std::string, int32_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, int32_t, std::string); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, int64_t, int64_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, std::string, int64_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, int64_t, std::string); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, uint32_t, uint32_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, std::string, uint32_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, uint32_t, std::string); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, uint64_t, uint64_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, std::string, uint64_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, uint64_t, std::string); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, std::string, std::string); + +ABSL_NAMESPACE_END +} // namespace absl diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h index a33c794f..2f4457d6 100644 --- a/absl/container/flat_hash_map.h +++ b/absl/container/flat_hash_map.h @@ -31,15 +31,20 @@ #define ABSL_CONTAINER_FLAT_HASH_MAP_H_ #include <cstddef> +#include <cstdint> +#include <memory> #include <new> +#include <string> #include <type_traits> #include <utility> #include "absl/algorithm/container.h" +#include "absl/base/config.h" #include "absl/base/macros.h" #include "absl/container/internal/container_memory.h" #include "absl/container/internal/hash_function_defaults.h" // IWYU pragma: export #include "absl/container/internal/raw_hash_map.h" // IWYU pragma: export +#include "absl/container/internal/raw_hash_set.h" // IWYU pragma: export #include "absl/memory/memory.h" namespace absl { @@ -632,6 +637,42 @@ struct IsUnorderedContainer< } // namespace container_algorithm_internal +// Explicit template instantiations for common map types in order to decrease +// linker input size. Note that explicitly instantiating flat_hash_map itself +// doesn't help because it has no non-alias members. If we need to decrease +// linker input size more, we could potentially (a) add more key/value types, +// e.g. string_view/Cord, (b) instantiate some template member functions, e.g. +// operator[]/find. The EXTERN argument is `extern` for the declaration and +// empty for the definition. +#define ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(TEMPLATE, KEY, VALUE) \ + TEMPLATE class absl::container_internal::raw_hash_map< \ + absl::container_internal::FlatHashMapPolicy<KEY, VALUE>, \ + absl::container_internal::hash_default_hash<KEY>, \ + absl::container_internal::hash_default_eq<KEY>, \ + std::allocator<std::pair<const KEY, VALUE>>>; \ + TEMPLATE class absl::container_internal::raw_hash_set< \ + absl::container_internal::FlatHashMapPolicy<KEY, VALUE>, \ + absl::container_internal::hash_default_hash<KEY>, \ + absl::container_internal::hash_default_eq<KEY>, \ + std::allocator<std::pair<const KEY, VALUE>>>; + +// We use exact-width integer types rather than `int`/`long`/`long long` because +// these are the types recommended in the Google C++ style guide and which are +// commonly used in Google code. +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, int32_t, int32_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, std::string, int32_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, int32_t, std::string); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, int64_t, int64_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, std::string, int64_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, int64_t, std::string); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, uint32_t, uint32_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, std::string, uint32_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, uint32_t, std::string); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, uint64_t, uint64_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, std::string, uint64_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, uint64_t, std::string); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, std::string, std::string); + ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/flat_hash_set.cc b/absl/container/flat_hash_set.cc new file mode 100644 index 00000000..d07081b8 --- /dev/null +++ b/absl/container/flat_hash_set.cc @@ -0,0 +1,36 @@ +// Copyright 2024 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/flat_hash_set.h" + +#include <cstdint> +#include <string> + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(template, int8_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(template, int16_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(template, int32_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(template, int64_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(template, uint8_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(template, uint16_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(template, uint32_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(template, uint64_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(template, std::string); + +ABSL_NAMESPACE_END +} // namespace absl diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h index 5f72f954..88c7ab21 100644 --- a/absl/container/flat_hash_set.h +++ b/absl/container/flat_hash_set.h @@ -30,11 +30,14 @@ #define ABSL_CONTAINER_FLAT_HASH_SET_H_ #include <cstddef> +#include <cstdint> #include <memory> +#include <string> #include <type_traits> #include <utility> #include "absl/algorithm/container.h" +#include "absl/base/config.h" #include "absl/base/macros.h" #include "absl/container/internal/container_memory.h" #include "absl/container/internal/hash_function_defaults.h" // IWYU pragma: export @@ -523,6 +526,32 @@ struct IsUnorderedContainer<absl::flat_hash_set<Key, Hash, KeyEqual, Allocator>> } // namespace container_algorithm_internal +// Explicit template instantiations for common set types in order to decrease +// linker input size. Note that explicitly instantiating flat_hash_set itself +// doesn't help because it has no non-alias members. If we need to decrease +// linker input size more, we could potentially (a) add more key types, e.g. +// string_view/Cord, (b) instantiate some template member functions, e.g. +// find/insert/emplace. The EXTERN argument is `extern` for the declaration and +// empty for the definition. +#define ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(TEMPLATE, KEY) \ + TEMPLATE class absl::container_internal::raw_hash_set< \ + absl::container_internal::FlatHashSetPolicy<KEY>, \ + absl::container_internal::hash_default_hash<KEY>, \ + absl::container_internal::hash_default_eq<KEY>, std::allocator<KEY>>; + +// We use exact-width integer types rather than `int`/`long`/`long long` because +// these are the types recommended in the Google C++ style guide and which are +// commonly used in Google code. +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(extern template, int8_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(extern template, int16_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(extern template, int32_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(extern template, int64_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(extern template, uint8_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(extern template, uint16_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(extern template, uint32_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(extern template, uint64_t); +ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(extern template, std::string); + ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index 258458b0..575491c7 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h @@ -1839,7 +1839,7 @@ class HashSetResizeHelper { // Reads `capacity` and updates all other fields based on the result of // the allocation. // - // It also may do the folowing actions: + // It also may do the following actions: // 1. initialize control bytes // 2. initialize slots // 3. deallocate old slots. @@ -2204,9 +2204,14 @@ class raw_hash_set { bool is_soo() const { return fits_in_soo(capacity()); } bool is_full_soo() const { return is_soo() && !empty(); } - // Give an early error when key_type is not hashable/eq. - auto KeyTypeCanBeHashed(const Hash& h, const key_type& k) -> decltype(h(k)); - auto KeyTypeCanBeEq(const Eq& eq, const key_type& k) -> decltype(eq(k, k)); + // Give an early error when key_type is not hashable/eq. Definitions are + // provided because otherwise explicit template instantiation fails on MSVC. + auto KeyTypeCanBeHashed(const Hash& h, const key_type& k) -> decltype(h(k)) { + ABSL_UNREACHABLE(); + } + auto KeyTypeCanBeEq(const Eq& eq, const key_type& k) -> decltype(eq(k, k)) { + ABSL_UNREACHABLE(); + } using AllocTraits = absl::allocator_traits<allocator_type>; using SlotAlloc = typename absl::allocator_traits< @@ -2395,7 +2400,18 @@ class raw_hash_set { const_iterator operator++(int) { return inner_++; } friend bool operator==(const const_iterator& a, const const_iterator& b) { + // Suppress erroneous uninitialized memory errors on GCC. This seems to be + // because the slot pointer in the inner_ iterator is uninitialized, even + // though that pointer is not used when uninitialized. + // Similar bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112637. +#if !defined(__clang__) && defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif return a.inner_ == b.inner_; +#if !defined(__clang__) && defined(__GNUC__) +#pragma GCC diagnostic pop +#endif } friend bool operator!=(const const_iterator& a, const const_iterator& b) { return !(a == b); @@ -3719,7 +3735,9 @@ class raw_hash_set { return const_cast<raw_hash_set*>(this)->iterator_at(i); } - reference unchecked_deref(iterator it) { return it.unchecked_deref(); } + reference unchecked_deref(iterator it) { + return const_cast<reference>(it.unchecked_deref()); + } private: friend struct RawHashSetTestOnlyAccess; @@ -3769,13 +3787,13 @@ class raw_hash_set { return static_cast<slot_type*>(common().soo_data()); } const slot_type* soo_slot() const { - return reinterpret_cast<raw_hash_set*>(this)->soo_slot(); + return const_cast<raw_hash_set*>(this)->soo_slot(); } iterator soo_iterator() { return {SooControl(), soo_slot(), common().generation_ptr()}; } const_iterator soo_iterator() const { - return reinterpret_cast<raw_hash_set*>(this)->soo_iterator(); + return const_cast<raw_hash_set*>(this)->soo_iterator(); } HashtablezInfoHandle infoz() { assert(!is_soo()); diff --git a/absl/container/node_hash_map.cc b/absl/container/node_hash_map.cc new file mode 100644 index 00000000..ccf8c599 --- /dev/null +++ b/absl/container/node_hash_map.cc @@ -0,0 +1,40 @@ +// Copyright 2024 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/node_hash_map.h" + +#include <cstdint> +#include <string> + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, int32_t, int32_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, std::string, int32_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, int32_t, std::string); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, int64_t, int64_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, std::string, int64_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, int64_t, std::string); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, uint32_t, uint32_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, std::string, uint32_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, uint32_t, std::string); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, uint64_t, uint64_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, std::string, uint64_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, uint64_t, std::string); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, std::string, std::string); + +ABSL_NAMESPACE_END +} // namespace absl diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h index cb41543c..acc21542 100644 --- a/absl/container/node_hash_map.h +++ b/absl/container/node_hash_map.h @@ -37,11 +37,15 @@ #define ABSL_CONTAINER_NODE_HASH_MAP_H_ #include <cstddef> +#include <cstdint> +#include <memory> +#include <string> #include <tuple> #include <type_traits> #include <utility> #include "absl/algorithm/container.h" +#include "absl/base/config.h" #include "absl/base/macros.h" #include "absl/container/internal/container_memory.h" #include "absl/container/internal/hash_function_defaults.h" // IWYU pragma: export @@ -623,6 +627,42 @@ struct IsUnorderedContainer< } // namespace container_algorithm_internal +// Explicit template instantiations for common map types in order to decrease +// linker input size. Note that explicitly instantiating node_hash_map itself +// doesn't help because it has no non-alias members. If we need to decrease +// linker input size more, we could potentially (a) add more key/value types, +// e.g. string_view/Cord, (b) instantiate some template member functions, e.g. +// operator[]/find. The EXTERN argument is `extern` for the declaration and +// empty for the definition. +#define ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(TEMPLATE, KEY, VALUE) \ + TEMPLATE class absl::container_internal::raw_hash_map< \ + absl::container_internal::NodeHashMapPolicy<KEY, VALUE>, \ + absl::container_internal::hash_default_hash<KEY>, \ + absl::container_internal::hash_default_eq<KEY>, \ + std::allocator<std::pair<const KEY, VALUE>>>; \ + TEMPLATE class absl::container_internal::raw_hash_set< \ + absl::container_internal::NodeHashMapPolicy<KEY, VALUE>, \ + absl::container_internal::hash_default_hash<KEY>, \ + absl::container_internal::hash_default_eq<KEY>, \ + std::allocator<std::pair<const KEY, VALUE>>>; + +// We use exact-width integer types rather than `int`/`long`/`long long` because +// these are the types recommended in the Google C++ style guide and which are +// commonly used in Google code. +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, int32_t, int32_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, std::string, int32_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, int32_t, std::string); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, int64_t, int64_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, std::string, int64_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, int64_t, std::string); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, uint32_t, uint32_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, std::string, uint32_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, uint32_t, std::string); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, uint64_t, uint64_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, std::string, uint64_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, uint64_t, std::string); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, std::string, std::string); + ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/node_hash_set.cc b/absl/container/node_hash_set.cc new file mode 100644 index 00000000..39226c61 --- /dev/null +++ b/absl/container/node_hash_set.cc @@ -0,0 +1,36 @@ +// Copyright 2024 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/node_hash_set.h" + +#include <cstdint> +#include <string> + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(template, int8_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(template, int16_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(template, int32_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(template, int64_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(template, uint8_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(template, uint16_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(template, uint32_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(template, uint64_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(template, std::string); + +ABSL_NAMESPACE_END +} // namespace absl diff --git a/absl/container/node_hash_set.h b/absl/container/node_hash_set.h index 8cc4b624..77b49f9b 100644 --- a/absl/container/node_hash_set.h +++ b/absl/container/node_hash_set.h @@ -36,9 +36,13 @@ #define ABSL_CONTAINER_NODE_HASH_SET_H_ #include <cstddef> +#include <cstdint> +#include <memory> +#include <string> #include <type_traits> #include "absl/algorithm/container.h" +#include "absl/base/config.h" #include "absl/base/macros.h" #include "absl/container/internal/container_memory.h" #include "absl/container/internal/hash_function_defaults.h" // IWYU pragma: export @@ -518,6 +522,32 @@ struct IsUnorderedContainer<absl::node_hash_set<Key, Hash, KeyEqual, Allocator>> : std::true_type {}; } // namespace container_algorithm_internal + +// Explicit template instantiations for common set types in order to decrease +// linker input size. Note that explicitly instantiating node_hash_set itself +// doesn't help because it has no non-alias members. If we need to decrease +// linker input size more, we could potentially (a) add more key types, e.g. +// string_view/Cord, (b) instantiate some template member functions, e.g. +// find/insert/emplace. +#define ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(TEMPLATE, KEY) \ + TEMPLATE class absl::container_internal::raw_hash_set< \ + absl::container_internal::NodeHashSetPolicy<KEY>, \ + absl::container_internal::hash_default_hash<KEY>, \ + absl::container_internal::hash_default_eq<KEY>, std::allocator<KEY>>; + +// We use exact-width integer types rather than `int`/`long`/`long long` because +// these are the types recommended in the Google C++ style guide and which are +// commonly used in Google code. +ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(extern template, int8_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(extern template, int16_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(extern template, int32_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(extern template, int64_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(extern template, uint8_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(extern template, uint16_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(extern template, uint32_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(extern template, uint64_t); +ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(extern template, std::string); + ABSL_NAMESPACE_END } // namespace absl |