[PATCH] [libcxx] Fix __is_power2 and __next_power2. Change hashmap to handle new behavior.
Eric Fiselier
eric at efcs.ca
Sun Aug 17 17:12:59 PDT 2014
Hi mclow.lists, danalbert,
__is_power2 reports that 1 and 2 are not powers of 2. Fix this.
Change all uses of __is_power2 in hashtable to check if N <= 2 first so that the old behavior is kept.
Also calling __clz(0) is undefined behavior. Handle 0 and 1 as special cases in __next_pow2.
I use these functions in the polymorphic allocator implementation I'm working on. For that reason I think we should fix this.
http://reviews.llvm.org/D4948
Files:
include/__hash_table
Index: include/__hash_table
===================================================================
--- include/__hash_table
+++ include/__hash_table
@@ -63,7 +63,7 @@
bool
__is_power2(size_t __bc)
{
- return __bc > 2 && !(__bc & (__bc - 1));
+ return __bc && !(__bc & (__bc - 1));
}
inline _LIBCPP_INLINE_VISIBILITY
@@ -77,7 +77,8 @@
size_t
__next_pow2(size_t __n)
{
- return size_t(1) << (std::numeric_limits<size_t>::digits - __clz(__n-1));
+ return __n < 2 ? __n + 1
+ : size_t(1) << (std::numeric_limits<size_t>::digits - __clz(__n-1));
}
template <class _Tp, class _Hash, class _Equal, class _Alloc> class __hash_table;
@@ -1615,7 +1616,7 @@
{
if (size()+1 > __bc * max_load_factor() || __bc == 0)
{
- rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
+ rehash(_VSTD::max<size_type>(2 * __bc + (__bc <= 2 || !__is_power2(__bc)),
size_type(ceil(float(size() + 1) / max_load_factor()))));
__bc = bucket_count();
__chash = __constrain_hash(__nd->__hash_, __bc);
@@ -1658,7 +1659,7 @@
size_type __bc = bucket_count();
if (size()+1 > __bc * max_load_factor() || __bc == 0)
{
- rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
+ rehash(_VSTD::max<size_type>(2 * __bc + (__bc <= 2 || !__is_power2(__bc)),
size_type(ceil(float(size() + 1) / max_load_factor()))));
__bc = bucket_count();
}
@@ -1728,7 +1729,7 @@
size_type __bc = bucket_count();
if (size()+1 > __bc * max_load_factor() || __bc == 0)
{
- rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
+ rehash(_VSTD::max<size_type>(2 * __bc + (__bc <= 2 || !__is_power2(__bc)),
size_type(ceil(float(size() + 1) / max_load_factor()))));
__bc = bucket_count();
}
@@ -1776,7 +1777,7 @@
__node_holder __h = __construct_node(__x, __hash);
if (size()+1 > __bc * max_load_factor() || __bc == 0)
{
- rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
+ rehash(_VSTD::max<size_type>(2 * __bc + (__bc <= 2 || !__is_power2(__bc)),
size_type(ceil(float(size() + 1) / max_load_factor()))));
__bc = bucket_count();
__chash = __constrain_hash(__hash, __bc);
@@ -1946,8 +1947,9 @@
__n = _VSTD::max<size_type>
(
__n,
- __is_power2(__bc) ? __next_pow2(size_t(ceil(float(size()) / max_load_factor()))) :
- __next_prime(size_t(ceil(float(size()) / max_load_factor())))
+ (__bc > 2 && __is_power2(__bc))
+ ? __next_pow2(size_t(ceil(float(size()) / max_load_factor())))
+ : __next_prime(size_t(ceil(float(size()) / max_load_factor())))
);
if (__n < __bc)
__rehash(__n);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D4948.12597.patch
Type: text/x-patch
Size: 3023 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140818/57dff330/attachment.bin>
More information about the cfe-commits
mailing list