[libcxx-commits] [libcxx] [libc++] Add randomize unspecified stability in `__hash_table` (PR #105982)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Fri Aug 30 08:20:34 PDT 2024


================
@@ -1741,6 +1757,70 @@ void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__do_rehash(size_type __nbc) {
   }
 }
 
+template <class _Tp, class _Hash, class _Equal, class _Alloc>
+template <bool _UniqueKeys>
+void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__debug_randomize_order() {
+#ifdef _LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY
+
+  struct __nh_vec {
+    using __nh_allocator = __rebind_alloc<__node_traits, __node_holder>;
+    using __pointer      = typename allocator_traits<__nh_allocator>::pointer;
+    __nh_allocator __nh_alloc;
+    __pointer __p                 = __pointer();
+    size_type __total_nodes       = 0;
+    size_type __initialized_nodes = 0;
+    __nh_vec(size_type __n) : __nh_alloc(), __p(__nh_alloc.allocate(__n)), __total_nodes(__n) {}
+    ~__nh_vec() {
+      if (__p) {
+        std::__destroy(__p, __p + __initialized_nodes);
+        __nh_alloc.deallocate(__p, __total_nodes);
+      }
+    }
+  };
+
+  struct __index_vec {
+    using __index_allocator = __rebind_alloc<__node_traits, size_type>;
+    using __pointer         = typename allocator_traits<__index_allocator>::pointer;
+    __index_allocator __index_alloc;
+    __pointer __p                   = __pointer();
+    size_type __total_indices       = 0;
+    size_type __initialized_indices = 0;
+    __index_vec(size_type __n) : __index_alloc(), __p(__index_alloc.allocate(__n)), __total_indices(__n) {}
+    ~__index_vec() {
+      if (__p) {
+        std::__destroy(__p, __p + __initialized_indices);
+        __index_alloc.deallocate(__p, __total_indices);
+      }
+    }
+  };
+
+  __nh_vec __nhv(size());
+  __index_vec __iv(size());
+
+  // Move nodes into temporary storage.
+  for (; __nhv.__initialized_nodes < __nhv.__total_nodes; ++__nhv.__initialized_nodes)
+    std::__construct_at(std::addressof(__nhv.__p[__nhv.__initialized_nodes]), remove(begin()));
+
+  // Randomize the order of indices.
+  for (; __iv.__initialized_indices < __nhv.__initialized_nodes; ++__iv.__initialized_indices)
+    std::__construct_at(std::addressof(__iv.__p[__iv.__initialized_indices]), __iv.__initialized_indices);
+  __debug_randomize_range<_ClassicAlgPolicy>(__iv.__p, __iv.__p + __iv.__initialized_indices);
+
+  // Reinsert nodes into the hash table in randomized order.
+  for (size_type __i = 0; __i < __iv.__initialized_indices; ++__i) {
+    __node_holder& __nh = __nhv.__p[__iv.__p[__i]];
+    __node_pointer __np = __nh->__upcast();
+    if _LIBCPP_CONSTEXPR_SINCE_CXX17 (_UniqueKeys) {
+      __node_insert_unique_perform(__np);
+    } else {
+      __next_pointer __pn = __node_insert_multi_find_insertion_point(__np->__hash(), __np->__get_value());
+      __node_insert_multi_perform(__np, __pn);
+    }
+    __nh.release();
+  }
+#endif
----------------
ldionne wrote:

```suggestion
#endif // defined(_LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY)
```

https://github.com/llvm/llvm-project/pull/105982


More information about the libcxx-commits mailing list