45# define Q_DECL_HOT_FUNCTION __attribute__((hot))
47# define Q_DECL_HOT_FUNCTION
56static_assert(
sizeof(size_t) ==
QT_POINTER_SIZE,
"size_t and pointers have different size.");
61 static constexpr int SeedCount = 2;
64#if !QT_SUPPORTS_INIT_PRIORITY || defined(QT_BOOTSTRAPPED)
65 constexpr HashSeedStorage() =
default;
71 OverriddenByEnvironment = -1,
80 StateResult
state(
int which = -1);
83 return {
state(which).requestedSeed };
88#ifndef QT_BOOTSTRAPPED
94 seeds[0].storeRelaxed(
sizeof(
size_t) >
sizeof(
quint32)
102 seeds[0].storeRelaxed(0);
109[[maybe_unused]] HashSeedStorage::StateResult HashSeedStorage::initialize(
int which)
noexcept
111 StateResult
result = { 0, OverriddenByEnvironment };
112#ifdef QT_BOOTSTRAPPED
114 Q_UNREACHABLE_RETURN(
result);
117 const char *seedstr = getenv(
"QT_HASH_SEED");
119 auto r =
qstrntoll(seedstr, strlen(seedstr), 10);
120 if (
r.used > 0 &&
size_t(
r.used) == strlen(seedstr)) {
123 fprintf(stderr,
"QT_HASH_SEED: forced seed value is not 0; ignored.\n");
134 for (
int i = 0;
i < SeedCount; ++
i) {
135 seeds[
i].storeRelaxed(
x.data[
i]);
139 result.state = JustInitialized;
144inline HashSeedStorage::StateResult HashSeedStorage::state(
int which)
147 StateResult
result = { BadSeed, AlreadyInitialized };
149#if defined(QT_BOOTSTRAPPED)
150 result = { 0, OverriddenByEnvironment };
151#elif !QT_SUPPORTS_INIT_PRIORITY
153 static auto once = [&]() {
160 if (
result.state == AlreadyInitialized && which >= 0)
161 return { seeds[which].
loadRelaxed(), AlreadyInitialized };
169#ifdef Q_DECL_INIT_PRIORITY
170Q_DECL_INIT_PRIORITY(05)
180#if QT_POINTER_SIZE == 4
187 const unsigned int m = 0x5bd1e995;
196 const unsigned char *
data =
reinterpret_cast<const unsigned char *
>(
key);
242 const uint64_t
m = 0xc6a4a7935bd1e995ULL;
247 const unsigned char *
data =
reinterpret_cast<const unsigned char *
>(
key);
248 const unsigned char *
end =
data + (
len & ~7ul);
252 memcpy(&k,
data,
sizeof(uint64_t));
292#define ROTL(x, b) (((x) << (b)) | ((x) >> (sizeof(x) * 8 - (b))))
312template <
int cROUNDS = 2,
int dROUNDS = 4>
struct SipHash64
315 uint64_t
v0 = 0x736f6d6570736575ULL;
316 uint64_t
v1 = 0x646f72616e646f6dULL;
317 uint64_t
v2 = 0x6c7967656e657261ULL;
318 uint64_t
v3 = 0x7465646279746573ULL;
323 inline SipHash64(uint64_t fulllen, uint64_t
seed, uint64_t seed2);
324 inline void addBlock(
const uint8_t *
in,
size_t inlen);
325 inline uint64_t finalize(
const uint8_t *
in,
size_t left);
328template <
int cROUNDS,
int dROUNDS>
329SipHash64<cROUNDS, dROUNDS>::SipHash64(uint64_t inlen, uint64_t
seed, uint64_t seed2)
341SipHash64<cROUNDS, dROUNDS>::addBlock(
const uint8_t *
in,
size_t inlen)
345 const uint8_t *
end =
in + inlen;
347 uint64_t
m = qFromUnaligned<uint64_t>(
in);
350 for (
i = 0;
i < cROUNDS; ++
i)
358SipHash64<cROUNDS, dROUNDS>::finalize(
const uint8_t *
in,
size_t left)
363 b |= ((uint64_t)
in[6]) << 48;
366 b |= ((uint64_t)
in[5]) << 40;
369 b |= ((uint64_t)
in[4]) << 32;
372 b |= ((uint64_t)
in[3]) << 24;
375 b |= ((uint64_t)
in[2]) << 16;
378 b |= ((uint64_t)
in[1]) << 8;
381 b |= ((uint64_t)
in[0]);
389 for (
i = 0;
i < cROUNDS; ++
i)
396 for (
i = 0;
i < dROUNDS; ++
i)
433template <
int cROUNDS = 2,
int dROUNDS = 4>
struct SipHash32
444 inline SipHash32(
size_t fulllen,
uint seed,
uint seed2);
445 inline void addBlock(
const uint8_t *
in,
size_t inlen);
446 inline uint finalize(
const uint8_t *
in,
size_t left);
449template <
int cROUNDS,
int dROUNDS>
inline
450SipHash32<cROUNDS, dROUNDS>::SipHash32(
size_t inlen,
uint seed,
uint seed2)
462SipHash32<cROUNDS, dROUNDS>::addBlock(
const uint8_t *
in,
size_t inlen)
466 const uint8_t *
end =
in + inlen;
468 uint m = qFromUnaligned<uint>(
in);
471 for (
i = 0;
i < cROUNDS; ++
i)
479SipHash32<cROUNDS, dROUNDS>::finalize(
const uint8_t *
in,
size_t left)
498 for (
i = 0;
i < cROUNDS; ++
i)
505 for (
i = 0;
i < dROUNDS; ++
i)
516template <
int cROUNDS = 1,
int dROUNDS = 2>
517using SipHash = std::conditional_t<
sizeof(
void *) == 8,
518 SipHash64<cROUNDS, dROUNDS>, SipHash32<cROUNDS, dROUNDS>>;
522static size_t siphash(
const uint8_t *
in,
size_t inlen,
size_t seed,
size_t seed2)
524 constexpr size_t TailSizeMask =
sizeof(
void *) - 1;
525 SipHash<> hasher(inlen,
seed, seed2);
526 hasher.addBlock(
in, inlen & ~TailSizeMask);
527 return hasher.finalize(
in + (inlen & ~TailSizeMask), inlen & TailSizeMask);
535template <ZeroExtension = None>
static size_t
547 auto quick_from_latin1 = [](
char16_t *dest,
const uchar *
data,
size_t size) {
557 constexpr size_t TailSizeMask =
sizeof(
void *) / 2 - 1;
558 std::array<char16_t, 256>
buf;
563 siphash.addBlock(
reinterpret_cast<uint8_t *
>(
buf.data()),
sizeof(
buf));
568 siphash.addBlock(
reinterpret_cast<uint8_t *
>(
buf.data()),
n * 2);
576#if defined(__SANITIZE_ADDRESS__) || defined(__SANITIZE_THREAD__)
577# define QHASH_AES_SANITIZER_BUILD
578#elif __has_feature(address_sanitizer) || __has_feature(thread_sanitizer)
579# define QHASH_AES_SANITIZER_BUILD
587#if QT_COMPILER_SUPPORTS_HERE(AES) && QT_COMPILER_SUPPORTS_HERE(SSE4_2) && \
588 !defined(QHASH_AES_SANITIZER_BUILD)
590# define QT_FUNCTION_TARGET_STRING_AES_AVX2 "avx2,aes"
591# define QT_FUNCTION_TARGET_STRING_AES_AVX512 \
592 QT_FUNCTION_TARGET_STRING_ARCH_SKYLAKE_AVX512 "," \
593 QT_FUNCTION_TARGET_STRING_AES
594# define QT_FUNCTION_TARGET_STRING_VAES_AVX512 \
595 QT_FUNCTION_TARGET_STRING_ARCH_SKYLAKE_AVX512 "," \
596 QT_FUNCTION_TARGET_STRING_VAES
597# undef QHASH_AES_SANITIZER_BUILD
598# if QT_POINTER_SIZE == 8
599# define mm_set1_epz _mm_set1_epi64x
600# define mm_cvtsz_si128 _mm_cvtsi64_si128
601# define mm_cvtsi128_sz _mm_cvtsi128_si64
602# define mm256_set1_epz _mm256_set1_epi64x
604# define mm_set1_epz _mm_set1_epi32
605# define mm_cvtsz_si128 _mm_cvtsi32_si128
606# define mm_cvtsi128_sz _mm_cvtsi128_si32
607# define mm256_set1_epz _mm256_set1_epi32
630 template <ZeroExtension ZX,
typename T>
static const T *advance(
const T *
ptr, ptrdiff_t
n)
632 if constexpr (ZX ==
None)
636 auto p =
reinterpret_cast<const uchar *
>(
ptr);
638 return reinterpret_cast<const T *
>(
p +
n/2);
641 template <ZeroExtension>
static __m128i loadu128(
const void *
ptr);
644 return _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(
ptr));
650 __m128i
data = _mm_loadl_epi64(
static_cast<const __m128i *
>(
ptr));
651 return _mm_cvtepu8_epi16(
data);
656 hash16bytes(__m128i &state0, __m128i
data)
658 state0 = _mm_xor_si128(state0,
data);
659 state0 = _mm_aesenc_si128(state0, state0);
660 state0 = _mm_aesenc_si128(state0, state0);
661 state0 = _mm_aesenc_si128(state0, state0);
665 template <ZeroExtension ZX>
667 hash2x16bytes(__m128i &state0, __m128i &state1,
const __m128i *src0,
const __m128i *src1)
669 __m128i data0 = loadu128<ZX>(src0);
670 __m128i data1 = loadu128<ZX>(src1);
671 state0 = _mm_xor_si128(data0, state0);
672 state1 = _mm_xor_si128(data1, state1);
673 state0 = _mm_aesenc_si128(state0, state0);
674 state1 = _mm_aesenc_si128(state1, state1);
675 state0 = _mm_aesenc_si128(state0, state0);
676 state1 = _mm_aesenc_si128(state1, state1);
686 {
return _mm256_set_m128i(state1(), state0); }
692 __m128i mseed = mm_cvtsz_si128(
seed);
693 mseed2 = mm_set1_epz(seed2);
696 mseed = _mm_insert_epi16(mseed,
short(
seed), 4);
698 mseed = _mm_shufflehi_epi16(mseed, 0);
701 __m128i
key = _mm_xor_si128(mseed, mseed2);
704 __m128i state0 = _mm_aesenc_si128(
key,
key);
705 this->state0 = state0;
712 __m128i state1 = _mm_aesenc_si128(state0, mseed2);
717template <ZeroExtension ZX>
719aeshash128_16to32(__m128i state0, __m128i state1,
const __m128i *
src,
const __m128i *srcend)
722 const __m128i *src2 = advance<ZX>(srcend, -1);
723 if (advance<ZX>(
src, 1) < srcend) {
725 hash2x16bytes<ZX>(state0, state1,
src, src2);
726 }
else if (
src != srcend) {
728 __m128i
data = loadu128<ZX>(src2);
729 hash16bytes(state0,
data);
733 state0 = _mm_xor_si128(state0, state1);
736 return mm_cvtsi128_sz(state0);
740static const qint8 maskarray[] = {
741 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
742 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
746static const qint8 shufflecontrol[] = {
747 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
748 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
751template <ZeroExtension ZX>
753aeshash128_lt16(__m128i state0,
const __m128i *
src,
const __m128i *srcend,
size_t len)
761 constexpr quintptr CachelineSize = 64;
766 __m128i
mask = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(maskarray + 15 -
len));
771 __m128i control = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(shufflecontrol + 15 -
len));
772 data = loadu128<ZX>(advance<ZX>(srcend, -1));
773 data = _mm_shuffle_epi8(
data, control);
776 hash16bytes(state0,
data);
778 return mm_cvtsi128_sz(state0);
781template <ZeroExtension ZX>
783aeshash128_ge32(__m128i state0, __m128i state1,
const __m128i *
src,
const __m128i *srcend)
786 for ( ; advance<ZX>(
src, 2) < srcend;
src = advance<ZX>(
src, 2))
787 hash2x16bytes<ZX>(state0, state1,
src, advance<ZX>(
src, 1));
789 return aeshash128_16to32<ZX>(state0, state1,
src, srcend);
792# if QT_COMPILER_SUPPORTS_HERE(VAES)
793template <ZeroExtension>
static __m256i loadu256(
const void *
ptr);
796 return _mm256_loadu_si256(
reinterpret_cast<const __m256i *
>(
ptr));
801 __m128i
data = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(
ptr));
802 return _mm256_cvtepu8_epi16(
data);
805template <ZeroExtension ZX>
807aeshash256_lt32_avx256(__m256i state0,
const uchar *
p,
size_t len)
809 __m128i state0_128 = _mm256_castsi256_si128(state0);
812 if constexpr (ZX ==
None) {
813 __mmask32
mask = _bzhi_u32(-1,
unsigned(
len));
816 __mmask16
mask = _bzhi_u32(-1,
unsigned(
len) / 2);
817 __m128i data0 = _mm_maskz_loadu_epi8(
mask,
p);
818 data = _mm256_cvtepu8_epi16(data0);
820 __m128i data0 = _mm256_castsi256_si128(
data);
821 if (
len >=
sizeof(__m128i)) {
822 state0 = _mm256_xor_si256(state0,
data);
823 state0 = _mm256_aesenc_epi128(state0, state0);
824 state0 = _mm256_aesenc_epi128(state0, state0);
829 __m128i low = _mm256_extracti128_si256(state0, 0);
830 __m128i high = _mm256_extracti128_si256(state0, 1);
831 state0_128 = _mm_xor_si128(low, high);
833 hash16bytes(state0_128, data0);
836 return mm_cvtsi128_sz(state0_128);
839template <ZeroExtension ZX>
841aeshash256_ge32(__m256i state0,
const __m128i *
s,
const __m128i *
end,
size_t len)
844 state0 = _mm256_xor_si256(state0,
data);
845 state0 = _mm256_aesenc_epi128(state0, state0);
846 state0 = _mm256_aesenc_epi128(state0, state0);
847 state0 = _mm256_aesenc_epi128(state0, state0);
851 const auto hash2x32bytes = [](__m256i &state0, __m256i &state1,
const void *src0,
853 __m256i data0 = loadu256<ZX>(src0);
854 __m256i data1 = loadu256<ZX>(src1);
855 state0 = _mm256_xor_si256(data0, state0);
856 state1 = _mm256_xor_si256(data1, state1);
857 state0 = _mm256_aesenc_epi128(state0, state0);
858 state1 = _mm256_aesenc_epi128(state1, state1);
859 state0 = _mm256_aesenc_epi128(state0, state0);
860 state1 = _mm256_aesenc_epi128(state1, state1);
863 const __m256i *
src =
reinterpret_cast<const __m256i *
>(
s);
864 const __m256i *srcend =
reinterpret_cast<const __m256i *
>(
end);
866 __m256i state1 = _mm256_aesenc_epi128(state0, mm256_set1_epz(
len));
869 for ( ; advance<ZX>(
src, 2) < srcend;
src = advance<ZX>(
src, 2))
870 hash2x32bytes(state0, state1,
src, advance<ZX>(
src, 1));
872 const __m256i *src2 = advance<ZX>(srcend, -1);
873 if (advance<ZX>(
src, 1) < srcend) {
875 hash2x32bytes(state0, state1,
src, src2);
876 }
else if (
src != srcend) {
878 __m256i
data = loadu256<ZX>(src2);
879 hash32bytes(state0,
data);
883 state0 = _mm256_xor_si256(state0, state1);
886 __m128i low = _mm256_extracti128_si256(state0, 0);
887 __m128i high = _mm256_extracti128_si256(state0, 1);
888 return mm_cvtsi128_sz(_mm_xor_si128(low, high));
891template <ZeroExtension ZX>
893aeshash256(
const uchar *
p,
size_t len,
size_t seed,
size_t seed2)
noexcept
896 auto src =
reinterpret_cast<const __m128i *
>(
p);
897 const auto srcend =
reinterpret_cast<const __m128i *
>(advance<ZX>(
p,
len));
899 if (
len <
sizeof(__m128i))
900 return aeshash128_lt16<ZX>(
state.state0,
src, srcend,
len);
902 if (
len <=
sizeof(__m256i))
903 return aeshash128_16to32<ZX>(
state.state0,
state.state1(),
src, srcend);
905 return aeshash256_ge32<ZX>(
state.state0_256(),
src, srcend,
len);
908template <ZeroExtension ZX>
910aeshash256_avx256(
const uchar *
p,
size_t len,
size_t seed,
size_t seed2)
noexcept
913 auto src =
reinterpret_cast<const __m128i *
>(
p);
914 const auto srcend =
reinterpret_cast<const __m128i *
>(advance<ZX>(
p,
len));
916 if (
len <=
sizeof(__m256i))
917 return aeshash256_lt32_avx256<ZX>(
state.state0_256(),
p,
len);
919 return aeshash256_ge32<ZX>(
state.state0_256(),
src, srcend,
len);
923template <ZeroExtension ZX>
925aeshash128(
const uchar *
p,
size_t len,
size_t seed,
size_t seed2)
noexcept
928 auto src =
reinterpret_cast<const __m128i *
>(
p);
929 const auto srcend =
reinterpret_cast<const __m128i *
>(advance<ZX>(
p,
len));
931 if (
len <
sizeof(__m128i))
932 return aeshash128_lt16<ZX>(
state.state0,
src, srcend,
len);
934 if (
len <=
sizeof(__m256i))
935 return aeshash128_16to32<ZX>(
state.state0,
state.state1(),
src, srcend);
937 return aeshash128_ge32<ZX>(
state.state0,
state.state1(),
src, srcend);
940template <ZeroExtension ZX = None>
941static size_t aeshash(
const uchar *
p,
size_t len,
size_t seed,
size_t seed2)
noexcept
946# if QT_COMPILER_SUPPORTS_HERE(VAES)
949 return aeshash256_avx256<ZX>(
p,
len,
seed, seed2);
950 return aeshash256<ZX>(
p,
len,
seed, seed2);
953 return aeshash128<ZX>(
p,
len,
seed, seed2);
957#if defined(Q_PROCESSOR_ARM) && QT_COMPILER_SUPPORTS_HERE(AES) && !defined(QHASH_AES_SANITIZER_BUILD) && !defined(QT_BOOTSTRAPPED)
959static size_t aeshash(
const uchar *
p,
size_t len,
size_t seed,
size_t seed2)
noexcept
962# if QT_POINTER_SIZE == 8
963 uint64x2_t vseed = vcombine_u64(vcreate_u64(
seed), vcreate_u64(seed2));
964 key = vreinterpretq_u8_u64(vseed);
967 uint32x2_t vseed = vmov_n_u32(
seed);
968 vseed = vset_lane_u32(seed2, vseed, 1);
969 key = vreinterpretq_u8_u32(vcombine_u32(vseed, vseed));
974 const auto hash16bytes = [](uint8x16_t &state0, uint8x16_t
data) {
975 auto state1 = state0;
976 state0 = vaeseq_u8(state0,
data);
977 state0 = vaesmcq_u8(state0);
978 auto state2 = state0;
979 state0 = vaeseq_u8(state0, state1);
980 state0 = vaesmcq_u8(state0);
981 auto state3 = state0;
982 state0 = vaeseq_u8(state0, state2);
983 state0 = vaesmcq_u8(state0);
984 state0 = veorq_u8(state0, state3);
987 uint8x16_t state0 =
key;
999 uint8x16_t state1 = veorq_u8(state0, vdupq_n_u8(255));
1003 const auto *e =
p +
len - 31;
1005 uint8x16_t data0 = vld1q_u8(
p);
1006 uint8x16_t data1 = vld1q_u8(
p + 16);
1007 auto oldstate0 = state0;
1008 auto oldstate1 = state1;
1009 state0 = vaeseq_u8(state0, data0);
1010 state1 = vaeseq_u8(state1, data1);
1011 state0 = vaesmcq_u8(state0);
1012 state1 = vaesmcq_u8(state1);
1013 auto laststate0 = state0;
1014 auto laststate1 = state1;
1015 state0 = vaeseq_u8(state0, oldstate0);
1016 state1 = vaeseq_u8(state1, oldstate1);
1017 state0 = vaesmcq_u8(state0);
1018 state1 = vaesmcq_u8(state1);
1019 state0 = veorq_u8(state0, laststate0);
1020 state1 = veorq_u8(state1, laststate1);
1023 state0 = veorq_u8(state0, state1);
1030 uint8x16_t
data = vld1q_u8(
p);
1031 hash16bytes(state0,
data);
1038 uint8x8_t data8 = vld1_u8(
p);
1039 uint8x16_t
data = vcombine_u8(data8, vdup_n_u8(0));
1040 hash16bytes(state0,
data);
1058 static const qint8 maskarray[] = {
1059 -1, -1, -1, -1, -1, -1, -1,
1060 0, 0, 0, 0, 0, 0, 0,
1062 uint8x8_t
mask = vld1_u8(
reinterpret_cast<const quint8 *
>(maskarray) + 7 -
len);
1064 data8 = vand_u8(data8,
mask);
1068 static const qint8 shufflecontrol[] = {
1069 1, 2, 3, 4, 5, 6, 7,
1070 -1, -1, -1, -1, -1, -1, -1,
1072 uint8x8_t control = vld1_u8(
reinterpret_cast<const quint8 *
>(shufflecontrol) + 7 -
len);
1073 data8 = vld1_u8(
p - 8 +
len);
1074 data8 = vtbl1_u8(data8, control);
1076 uint8x16_t
data = vcombine_u8(data8, vdup_n_u8(0));
1077 hash16bytes(state0,
data);
1081# if QT_POINTER_SIZE == 8
1082 return vgetq_lane_u64(vreinterpretq_u64_u8(state0), 0);
1084 return vgetq_lane_u32(vreinterpretq_u32_u8(state0), 0);
1091#ifdef QT_BOOTSTRAPPED
1098 size_t seed2 =
size;
1102 auto data =
reinterpret_cast<const uchar *
>(
p);
1106#elif defined(Q_PROCESSOR_ARM) && QT_COMPILER_SUPPORTS_HERE(AES) && !defined(QHASH_AES_SANITIZER_BUILD) && !defined(QT_BOOTSTRAPPED)
1124#ifndef QT_BOOTSTRAPPED