5#ifndef V8_OBJECTS_SWISS_HASH_TABLE_HELPERS_H_
6#define V8_OBJECTS_SWISS_HASH_TABLE_HELPERS_H_
21#ifndef V8_SWISS_TABLE_HAVE_SSE2_HOST
22#if (defined(__SSE2__) || \
23 (defined(_MSC_VER) && \
24 (defined(_M_X64) || (defined(_M_IX86) && _M_IX86_FP >= 2))))
25#define V8_SWISS_TABLE_HAVE_SSE2_HOST 1
27#define V8_SWISS_TABLE_HAVE_SSE2_HOST 0
31#ifndef V8_SWISS_TABLE_HAVE_SSSE3_HOST
33#define V8_SWISS_TABLE_HAVE_SSSE3_HOST 1
35#define V8_SWISS_TABLE_HAVE_SSSE3_HOST 0
39#if V8_SWISS_TABLE_HAVE_SSSE3_HOST && !V8_SWISS_TABLE_HAVE_SSE2_HOST
40#error "Bad configuration!"
50#ifndef V8_SWISS_TABLE_HAVE_SSE2_TARGET
51#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
53#define V8_SWISS_TABLE_HAVE_SSE2_TARGET 1
55#define V8_SWISS_TABLE_HAVE_SSE2_TARGET 0
59#if V8_SWISS_TABLE_HAVE_SSE2_HOST
63#if V8_SWISS_TABLE_HAVE_SSSE3_HOST
69namespace swiss_table {
77template <
size_t GroupSize>
121template <
class T,
int SignificantBits,
int Shift = 0>
123 static_assert(std::is_unsigned<T>::value);
155 constexpr int total_significant_bits = SignificantBits <<
Shift;
156 constexpr int extra_bits =
sizeof(
T) * 8 - total_significant_bits;
162 return a.mask_ == b.
mask_;
165 return a.mask_ != b.
mask_;
183 "Special markers need to have the MSB to make checking for them efficient");
185 "kEmpty and kDeleted must be smaller than kSentinel to make the "
186 "SIMD test of IsEmptyOrDeleted() efficient");
188 "kSentinel must be -1 to elide loading it from memory into SIMD "
189 "registers (pcmpeqd xmm, xmm)");
190static_assert(
kEmpty == -128,
191 "kEmpty must be -128 to make the SIMD check for its "
192 "existence efficient (psignb xmm, xmm)");
193static_assert(~kEmpty & ~kDeleted &
kSentinel & 0x7F,
194 "kEmpty and kDeleted must share an unset bit that is not shared "
195 "by kSentinel to make the scalar test for MatchEmptyOrDeleted() "
198 "kDeleted must be -2 to make the implementation of "
199 "ConvertSpecialToEmptyAndFullToDeleted efficient");
208 "Special markers need to have the MSB to make checking for them efficient");
212inline static uint32_t
H1(uint32_t hash) {
return (hash >>
kH2Bits); }
218 return hash & ((1 <<
kH2Bits) - 1);
221#if V8_SWISS_TABLE_HAVE_SSE2_HOST
222struct GroupSse2Impl {
223 static constexpr size_t kWidth = 16;
225 explicit GroupSse2Impl(
const ctrl_t*
pos) {
226 ctrl = _mm_loadu_si128(
reinterpret_cast<const __m128i*
>(
pos));
230 BitMask<uint32_t, kWidth> Match(h2_t hash)
const {
231 auto match = _mm_set1_epi8(hash);
232 return BitMask<uint32_t, kWidth>(
233 _mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl)));
237 BitMask<uint32_t, kWidth> MatchEmpty()
const {
238#if V8_SWISS_TABLE_HAVE_SSSE3_HOST
240 return BitMask<uint32_t, kWidth>(
241 _mm_movemask_epi8(_mm_sign_epi8(ctrl, ctrl)));
243 return Match(
static_cast<h2_t
>(kEmpty));
292 :
ctrl(
base::ReadLittleEndianValue<uint64_t>(
293 reinterpret_cast<uintptr_t>(const_cast<
ctrl_t*>(
pos)))) {}
295 static constexpr uint64_t
kMsbs = 0x8080808080808080ULL;
296 static constexpr uint64_t
kLsbs = 0x0101010101010101ULL;
326#if defined(V8_ENABLE_SWISS_NAME_DICTIONARY) && DEBUG
342#elif V8_SWISS_TABLE_HAVE_SSE2_TARGET
344#if V8_SWISS_TABLE_HAVE_SSE2_HOST
345using Group = GroupSse2Impl;
347#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
352#warning "Did not detect required SSE2 support on ia32/x64."
int TrailingZeros() const
friend bool operator!=(const BitMask &a, const BitMask &b)
friend bool operator==(const BitMask &a, const BitMask &b)
int HighestBitSet() const
uint32_t offset(int i) const
ProbeSequence(uint32_t hash, uint32_t mask)
constexpr unsigned CountLeadingZeros(T value)
constexpr unsigned CountTrailingZerosNonZero(T value)
static uint32_t H1(uint32_t hash)
static constexpr int kNotFullMask
static swiss_table::ctrl_t H2(uint32_t hash)
static constexpr int kH2Bits
#define DCHECK_NE(v1, v2)
#define DCHECK_EQ(v1, v2)
BitMask< uint64_t, kWidth, 3 > Match(h2_t hash) const
BitMask< uint64_t, kWidth, 3 > MatchEmpty() const
GroupPortableImpl(const ctrl_t *pos)
static constexpr size_t kWidth
static constexpr uint64_t kMsbs
static constexpr uint64_t kLsbs
static constexpr size_t kWidth
GroupSse2Polyfill(const ctrl_t *pos)
BitMask< uint32_t, kWidth > MatchEmpty() const
BitMask< uint32_t, kWidth > Match(h2_t hash) const
uint32_t MatchEmptyOrDeletedMask() const