Skip to content

[libc++] Instantiate hash function externally #127040

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions libcxx/include/__configuration/availability.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@
// in all versions of the library are available.
#if !_LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS

# define _LIBCPP_INTRODUCED_IN_LLVM_21 1
# define _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE /* nothing */

# define _LIBCPP_INTRODUCED_IN_LLVM_20 1
# define _LIBCPP_INTRODUCED_IN_LLVM_20_ATTRIBUTE /* nothing */

Expand Down Expand Up @@ -114,6 +117,11 @@

// clang-format off

// LLVM 21
// TODO: Fill this in
# define _LIBCPP_INTRODUCED_IN_LLVM_21 0
# define _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE __attribute__((unavailable))

// LLVM 20
// TODO: Fill this in
# define _LIBCPP_INTRODUCED_IN_LLVM_20 0
Expand Down Expand Up @@ -359,6 +367,11 @@
#define _LIBCPP_AVAILABILITY_HAS_FROM_CHARS_FLOATING_POINT _LIBCPP_INTRODUCED_IN_LLVM_20
#define _LIBCPP_AVAILABILITY_FROM_CHARS_FLOATING_POINT _LIBCPP_INTRODUCED_IN_LLVM_20_ATTRIBUTE

// This controls whether `std::__hash_memory` is available in the dylib, which
// is used for some `std::hash` specializations.
#define _LIBCPP_AVAILABILITY_HAS_HASH_MEMORY _LIBCPP_INTRODUCED_IN_LLVM_21
// No attribute, since we've had hash in the headers before

// Define availability attributes that depend on _LIBCPP_HAS_EXCEPTIONS.
// Those are defined in terms of the availability attributes above, and
// should not be vendor-specific.
Expand Down
16 changes: 12 additions & 4 deletions libcxx/include/__functional/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,14 @@ struct __murmur2_or_cityhash<_Size, 64> {
}
};

#if _LIBCPP_AVAILABILITY_HAS_HASH_MEMORY
[[__gnu__::__pure__]] _LIBCPP_EXPORTED_FROM_ABI size_t __hash_memory(_LIBCPP_NOESCAPE const void*, size_t) _NOEXCEPT;
#else
_LIBCPP_HIDE_FROM_ABI inline size_t __hash_memory(const void* __ptr, size_t __size) _NOEXCEPT {
return __murmur2_or_cityhash<size_t>()(__ptr, __size);
}
#endif

template <class _Tp, size_t = sizeof(_Tp) / sizeof(size_t)>
struct __scalar_hash;

Expand Down Expand Up @@ -277,7 +285,7 @@ struct __scalar_hash<_Tp, 2> : public __unary_function<_Tp, size_t> {
} __s;
} __u;
__u.__t = __v;
return __murmur2_or_cityhash<size_t>()(std::addressof(__u), sizeof(__u));
return std::__hash_memory(std::addressof(__u), sizeof(__u));
}
};

Expand All @@ -293,7 +301,7 @@ struct __scalar_hash<_Tp, 3> : public __unary_function<_Tp, size_t> {
} __s;
} __u;
__u.__t = __v;
return __murmur2_or_cityhash<size_t>()(std::addressof(__u), sizeof(__u));
return std::__hash_memory(std::addressof(__u), sizeof(__u));
}
};

Expand All @@ -310,7 +318,7 @@ struct __scalar_hash<_Tp, 4> : public __unary_function<_Tp, size_t> {
} __s;
} __u;
__u.__t = __v;
return __murmur2_or_cityhash<size_t>()(std::addressof(__u), sizeof(__u));
return std::__hash_memory(std::addressof(__u), sizeof(__u));
}
};

Expand All @@ -333,7 +341,7 @@ struct _LIBCPP_TEMPLATE_VIS hash<_Tp*> : public __unary_function<_Tp*, size_t> {
size_t __a;
} __u;
__u.__t = __v;
return __murmur2_or_cityhash<size_t>()(std::addressof(__u), sizeof(__u));
return std::__hash_memory(std::addressof(__u), sizeof(__u));
}
};

Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__string/char_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ __str_find_last_not_of(const _CharT* __p, _SizeT __sz, _CharT __c, _SizeT __pos)
template <class _Ptr>
inline _LIBCPP_HIDE_FROM_ABI size_t __do_string_hash(_Ptr __p, _Ptr __e) {
typedef typename iterator_traits<_Ptr>::value_type value_type;
return __murmur2_or_cityhash<size_t>()(__p, (__e - __p) * sizeof(value_type));
return std::__hash_memory(__p, (__e - __p) * sizeof(value_type));
}

_LIBCPP_END_NAMESPACE_STD
Expand Down
15 changes: 15 additions & 0 deletions libcxx/lib/abi/CHANGELOG.TXT
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,21 @@ To generate a summary, re-generate the new ABI list using the

New entries should be added directly below the "Version" header.

------------
Version 21.0
------------

* [libc++] Instantiate hash function externally

This has multiple benefits:
- There is a single instance of our hash function, reducing object file size
- The hash implementation isn't instantiated in every TU anymore, reducing compile times
- Behind an ABI configuration macro, it would be possible to salt the hash

All platforms
-------------
Symbol added: _ZNSt3__113__hash_memoryEPKvm

------------
Version 20.0
------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1305,6 +1305,7 @@
{'is_defined': True, 'name': '__ZNSt3__113shared_futureIvED1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__113shared_futureIvED2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__113shared_futureIvEaSERKS1_', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__113__hash_memoryEPKvm', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__114__num_get_base10__get_baseERNS_8ios_baseE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__114__num_get_base5__srcE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZNSt3__114__num_put_base12__format_intEPcPKcbj', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,7 @@
{'is_defined': True, 'name': '_ZNSt6__ndk113shared_futureIvED1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk113shared_futureIvED2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk113shared_futureIvEaSERKS1_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk113__hash_memoryEPKvj', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk114__num_get_base10__get_baseERNS_8ios_baseE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk114__num_get_base5__srcE', 'size': 33, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZNSt6__ndk114__num_put_base12__format_intEPcPKcbj', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED2Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113shared_futureIvEaSERKS1_', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113__hash_memoryEPKvm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__114__num_get_base10__get_baseERNS_8ios_baseE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__114__num_get_base5__srcE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__114__num_put_base12__format_intEPcPKcbj', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED2Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113shared_futureIvEaSERKS1_', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__113__hash_memoryEPKvm', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__114__num_get_base10__get_baseERNS_8ios_baseE', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__114__num_get_base5__srcE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt3__114__num_put_base12__format_intEPcPKcbj', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1305,6 +1305,7 @@
{'is_defined': True, 'name': '__ZNSt3__113shared_futureIvED1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__113shared_futureIvED2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__113shared_futureIvEaSERKS1_', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__113__hash_memoryEPKvm', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__114__num_get_base10__get_baseERNS_8ios_baseE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__114__num_get_base5__srcE', 'size': 0, 'type': 'OBJECT'}
{'is_defined': True, 'name': '__ZNSt3__114__num_put_base12__format_intEPcPKcbj', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,7 @@
{'is_defined': True, 'name': '_ZNSt6__ndk113shared_futureIvED1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk113shared_futureIvED2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk113shared_futureIvEaSERKS1_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk113__hash_memoryEPKvm', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk114__num_get_base10__get_baseERNS_8ios_baseE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt6__ndk114__num_get_base5__srcE', 'size': 33, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZNSt6__ndk114__num_put_base12__format_intEPcPKcbj', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -956,6 +956,7 @@
{'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113shared_futureIvEaSERKS1_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113__hash_memoryEPKvm', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__114__num_get_base10__get_baseERNS_8ios_baseE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__114__num_get_base5__srcE', 'size': 33, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZNSt3__114__num_put_base12__format_intEPcPKcbj', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,7 @@
{'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113shared_futureIvEaSERKS1_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113__hash_memoryEPKvm', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__114__num_get_base10__get_baseERNS_8ios_baseE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__114__num_get_base5__srcE', 'size': 33, 'type': 'OBJECT'}
{'is_defined': True, 'name': '_ZNSt3__114__num_put_base12__format_intEPcPKcbj', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -924,6 +924,7 @@
{'is_defined': True, 'name': '_ZNSt3__113random_deviceclEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113shared_futureIvED2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113__hash_memoryEPKvm', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__113shared_futureIvEaSERKS1_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__114__num_get_base10__get_baseERNS_8ios_baseE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__114__num_get_base5__srcE', 'size': 33, 'type': 'OBJECT'}
Expand Down
4 changes: 4 additions & 0 deletions libcxx/src/functional.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@ bad_function_call::~bad_function_call() noexcept {}
const char* bad_function_call::what() const noexcept { return "std::bad_function_call"; }
#endif

size_t __hash_memory(_LIBCPP_NOESCAPE const void* ptr, size_t size) noexcept {
return __murmur2_or_cityhash<size_t>()(ptr, size);
}

_LIBCPP_END_NAMESPACE_STD
Loading