Commit 4957b284 by Jonathan Wakely Committed by Jonathan Wakely

Modify some library internals to work without <stdint.h>

std::__detail::__clp2 used uint_fast32_t and uint_fast64_t without
checking _GLIBCXX_USE_C99_STDINT_TR1 which was a potential bug. A
simpler implementation based on the new std::__ceil2 code performs
better and doesn't depend on <stdint.h> types.

std::align and other C++11 functions in <memory> where unnecessarily
missing when _GLIBCXX_USE_C99_STDINT_TR1 was not defined.

	* include/bits/hashtable_policy.h (__detail::__clp2): Use faster
	implementation that doesn't depend on <stdint.h> types.
	* include/std/memory (align) [!_GLIBCXX_USE_C99_STDINT_TR1]: Use
	std::size_t when std::uintptr_t is not usable.
	[!_GLIBCXX_USE_C99_STDINT_TR1] (pointer_safety, declare_reachable)
	(undeclare_reachable, declare_no_pointers, undeclare_no_pointers):
	Define independent of _GLIBCXX_USE_C99_STDINT_TR1.

From-SVN: r263003
parent 612c9c70
2018-07-26 Jonathan Wakely <jwakely@redhat.com> 2018-07-26 Jonathan Wakely <jwakely@redhat.com>
* include/bits/hashtable_policy.h (__detail::__clp2): Use faster
implementation that doesn't depend on <stdint.h> types.
* include/std/memory (align) [!_GLIBCXX_USE_C99_STDINT_TR1]: Use
std::size_t when std::uintptr_t is not usable.
[!_GLIBCXX_USE_C99_STDINT_TR1] (pointer_safety, declare_reachable)
(undeclare_reachable, declare_no_pointers, undeclare_no_pointers):
Define independent of _GLIBCXX_USE_C99_STDINT_TR1.
* include/bits/basic_string.h [!_GLIBCXX_USE_C99_STDINT_TR1] * include/bits/basic_string.h [!_GLIBCXX_USE_C99_STDINT_TR1]
(hash<u16string>, hash<u32string>): Remove dependency on (hash<u16string>, hash<u32string>): Remove dependency on
_GLIBCXX_USE_C99_STDINT_TR1. _GLIBCXX_USE_C99_STDINT_TR1.
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
#define _HASHTABLE_POLICY_H 1 #define _HASHTABLE_POLICY_H 1
#include <tuple> // for std::tuple, std::forward_as_tuple #include <tuple> // for std::tuple, std::forward_as_tuple
#include <cstdint> // for std::uint_fast64_t #include <limits> // for std::numeric_limits
#include <bits/stl_algobase.h> // for std::min. #include <bits/stl_algobase.h> // for std::min.
namespace std _GLIBCXX_VISIBILITY(default) namespace std _GLIBCXX_VISIBILITY(default)
...@@ -504,27 +504,15 @@ namespace __detail ...@@ -504,27 +504,15 @@ namespace __detail
{ return __num & (__den - 1); } { return __num & (__den - 1); }
}; };
/// Compute closest power of 2. /// Compute closest power of 2 not less than __n
_GLIBCXX14_CONSTEXPR
inline std::size_t inline std::size_t
__clp2(std::size_t __n) noexcept __clp2(std::size_t __n) noexcept
{ {
#if __SIZEOF_SIZE_T__ >= 8 // Equivalent to return __n ? std::ceil2(__n) : 0;
std::uint_fast64_t __x = __n; if (__n < 2)
#else return __n;
std::uint_fast32_t __x = __n; return 1ul << (numeric_limits<unsigned long>::digits
#endif - __builtin_clzl(__n - 1ul));
// Algorithm from Hacker's Delight, Figure 3-3.
__x = __x - 1;
__x = __x | (__x >> 1);
__x = __x | (__x >> 2);
__x = __x | (__x >> 4);
__x = __x | (__x >> 8);
__x = __x | (__x >>16);
#if __SIZEOF_SIZE_T__ >= 8
__x = __x | (__x >>32);
#endif
return __x + 1;
} }
/// Rehash policy providing power of 2 bucket numbers. Avoids modulo /// Rehash policy providing power of 2 bucket numbers. Avoids modulo
......
...@@ -88,8 +88,7 @@ ...@@ -88,8 +88,7 @@
#endif #endif
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
# include <cstdint> #include <cstdint>
# ifdef _GLIBCXX_USE_C99_STDINT_TR1
namespace std _GLIBCXX_VISIBILITY(default) namespace std _GLIBCXX_VISIBILITY(default)
{ {
_GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_VERSION
...@@ -113,7 +112,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -113,7 +112,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline void* inline void*
align(size_t __align, size_t __size, void*& __ptr, size_t& __space) noexcept align(size_t __align, size_t __size, void*& __ptr, size_t& __space) noexcept
{ {
#ifdef _GLIBCXX_USE_C99_STDINT_TR1
const auto __intptr = reinterpret_cast<uintptr_t>(__ptr); const auto __intptr = reinterpret_cast<uintptr_t>(__ptr);
#else
// Cannot use std::uintptr_t so assume that std::size_t can be used instead.
static_assert(sizeof(size_t) >= sizeof(void*),
"std::size_t must be a suitable substitute for std::uintptr_t");
const auto __intptr = reinterpret_cast<unsigned long long>(__ptr);
#endif
const auto __aligned = (__intptr - 1u + __align) & -__align; const auto __aligned = (__intptr - 1u + __align) & -__align;
const auto __diff = __aligned - __intptr; const auto __diff = __aligned - __intptr;
if ((__size + __diff) > __space) if ((__size + __diff) > __space)
...@@ -147,7 +153,6 @@ get_pointer_safety() noexcept { return pointer_safety::relaxed; } ...@@ -147,7 +153,6 @@ get_pointer_safety() noexcept { return pointer_safety::relaxed; }
_GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
} // namespace } // namespace
#endif // _GLIBCXX_USE_C99_STDINT_TR1
#endif // C++11 #endif // C++11
#endif /* _GLIBCXX_MEMORY */ #endif /* _GLIBCXX_MEMORY */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment