27#include <private/qrandom_p.h>
28#include <private/qsimd_p.h>
30#ifndef QT_BOOTSTRAPPED
33#include <private/qlocale_tools_p.h>
39#if defined(QT_NO_DEBUG) && !defined(NDEBUG)
45# define Q_DECL_HOT_FUNCTION __attribute__((hot))
47# define Q_DECL_HOT_FUNCTION
54static_assert(
sizeof(size_t) ==
QT_POINTER_SIZE,
"size_t and pointers have different size.");
59 static constexpr int SeedCount = 2;
62#if !QT_SUPPORTS_INIT_PRIORITY || defined(QT_BOOTSTRAPPED)
63 constexpr HashSeedStorage() =
default;
69 OverriddenByEnvironment = -1,
78 StateResult
state(
int which = -1);
81 return {
state(which).requestedSeed };
105[[maybe_unused]] HashSeedStorage::StateResult HashSeedStorage::initialize(
int which)
noexcept
107 StateResult
result = { 0, OverriddenByEnvironment };
108#ifdef QT_BOOTSTRAPPED
110 Q_UNREACHABLE_RETURN(
result);
113 const char *seedstr = getenv(
"QT_HASH_SEED");
115 auto r =
qstrntoll(seedstr, strlen(seedstr), 10);
116 if (
r.used > 0 &&
size_t(
r.used) == strlen(seedstr)) {
119 fprintf(stderr,
"QT_HASH_SEED: forced seed value is not 0; ignored.\n");
130 for (
int i = 0;
i < SeedCount; ++
i) {
131 seeds[
i].storeRelaxed(
x.data[
i]);
135 result.state = JustInitialized;
140inline HashSeedStorage::StateResult HashSeedStorage::state(
int which)
143 StateResult
result = { BadSeed, AlreadyInitialized };
145#if defined(QT_BOOTSTRAPPED)
146 result = { 0, OverriddenByEnvironment };
147#elif !QT_SUPPORTS_INIT_PRIORITY
149 static auto once = [&]() {
156 if (
result.state == AlreadyInitialized && which >= 0)
157 return { seeds[which].loadRelaxed(), AlreadyInitialized };
165#ifdef Q_DECL_INIT_PRIORITY
166Q_DECL_INIT_PRIORITY(05)
176#if QT_POINTER_SIZE == 4
183 const unsigned int m = 0x5bd1e995;
192 const unsigned char *
data =
reinterpret_cast<const unsigned char *
>(
key);
238 const uint64_t
m = 0xc6a4a7935bd1e995ULL;
243 const unsigned char *
data =
reinterpret_cast<const unsigned char *
>(
key);
244 const unsigned char *
end =
data + (
len & ~7ul);
248 memcpy(&k,
data,
sizeof(uint64_t));
284#if QT_POINTER_SIZE == 8
294#define ROTL(x, b) (uint64_t)(((x) << (b)) | ((x) >> (64 - (b))))
315static uint64_t
siphash(
const uint8_t *
in, uint64_t inlen, uint64_t
seed, uint64_t seed2)
318 uint64_t
v0 = 0x736f6d6570736575ULL;
319 uint64_t
v1 = 0x646f72616e646f6dULL;
320 uint64_t
v2 = 0x6c7967656e657261ULL;
321 uint64_t
v3 = 0x7465646279746573ULL;
326 const uint8_t *
end =
in + (inlen & ~7ULL);
327 const int left = inlen & 7;
335 uint64_t
m = qFromUnaligned<uint64_t>(
in);
345#if defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 700
350 b |= ((uint64_t)
in[6]) << 48;
352 b |= ((uint64_t)
in[5]) << 40;
354 b |= ((uint64_t)
in[4]) << 32;
356 b |= ((uint64_t)
in[3]) << 24;
358 b |= ((uint64_t)
in[2]) << 16;
360 b |= ((uint64_t)
in[1]) << 8;
362 b |= ((uint64_t)
in[0]);
399#define ROTL(x, b) (uint32_t)(((x) << (b)) | ((x) >> (32 - (b))))
431 const uint8_t *
end =
in + (inlen & ~3ULL);
432 const int left = inlen & 3;
440 uint m = qFromUnaligned<uint>(
in);
449#if defined(Q_CC_GNU_ONLY) && Q_CC_GNU >= 700
481#if defined(__SANITIZE_ADDRESS__) || defined(__SANITIZE_THREAD__)
482# define QHASH_AES_SANITIZER_BUILD
483#elif __has_feature(address_sanitizer) || __has_feature(thread_sanitizer)
484# define QHASH_AES_SANITIZER_BUILD
492#if QT_COMPILER_SUPPORTS_HERE(AES) && QT_COMPILER_SUPPORTS_HERE(SSE4_2) && \
493 !defined(QHASH_AES_SANITIZER_BUILD)
495# define QT_FUNCTION_TARGET_STRING_AES_AVX2 "avx2,aes"
496# define QT_FUNCTION_TARGET_STRING_AES_AVX512 \
497 QT_FUNCTION_TARGET_STRING_ARCH_SKYLAKE_AVX512 "," \
498 QT_FUNCTION_TARGET_STRING_AES
499# define QT_FUNCTION_TARGET_STRING_VAES_AVX512 \
500 QT_FUNCTION_TARGET_STRING_ARCH_SKYLAKE_AVX512 "," \
501 QT_FUNCTION_TARGET_STRING_VAES
502# undef QHASH_AES_SANITIZER_BUILD
503# if QT_POINTER_SIZE == 8
504# define mm_set1_epz _mm_set1_epi64x
505# define mm_cvtsz_si128 _mm_cvtsi64_si128
506# define mm_cvtsi128_sz _mm_cvtsi128_si64
507# define mm256_set1_epz _mm256_set1_epi64x
509# define mm_set1_epz _mm_set1_epi32
510# define mm_cvtsz_si128 _mm_cvtsi32_si128
511# define mm_cvtsi128_sz _mm_cvtsi128_si32
512# define mm256_set1_epz _mm256_set1_epi32
530 hash16bytes(__m128i &state0, __m128i
data)
532 state0 = _mm_xor_si128(state0,
data);
533 state0 = _mm_aesenc_si128(state0, state0);
534 state0 = _mm_aesenc_si128(state0, state0);
535 state0 = _mm_aesenc_si128(state0, state0);
540 hash2x16bytes(__m128i &state0, __m128i &state1,
const __m128i *src0,
const __m128i *src1)
542 __m128i data0 = _mm_loadu_si128(src0);
543 __m128i data1 = _mm_loadu_si128(src1);
544 state0 = _mm_xor_si128(data0, state0);
545 state1 = _mm_xor_si128(data1, state1);
546 state0 = _mm_aesenc_si128(state0, state0);
547 state1 = _mm_aesenc_si128(state1, state1);
548 state0 = _mm_aesenc_si128(state0, state0);
549 state1 = _mm_aesenc_si128(state1, state1);
559 {
return _mm256_set_m128i(state1(), state0); }
565 __m128i mseed = mm_cvtsz_si128(
seed);
566 mseed2 = mm_set1_epz(seed2);
569 mseed = _mm_insert_epi16(mseed,
short(
seed), 4);
571 mseed = _mm_shufflehi_epi16(mseed, 0);
574 __m128i
key = _mm_xor_si128(mseed, mseed2);
577 __m128i state0 = _mm_aesenc_si128(
key,
key);
578 this->state0 = state0;
585 __m128i state1 = _mm_aesenc_si128(state0, mseed2);
591aeshash128_16to32(__m128i state0, __m128i state1,
const __m128i *
src,
const __m128i *srcend)
594 if (
src + 1 < srcend) {
596 hash2x16bytes(state0, state1,
src, srcend - 1);
597 }
else if (
src != srcend) {
599 __m128i
data = _mm_loadu_si128(srcend - 1);
600 hash16bytes(state0,
data);
604 state0 = _mm_xor_si128(state0, state1);
607 return mm_cvtsi128_sz(state0);
611aeshash128_lt16(__m128i state0,
const uchar *
p,
size_t len)
622 if ((
quintptr(
p) & (PageSize / 2)) == 0) {
625 static const qint8 maskarray[] = {
626 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
627 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
629 __m128i
mask = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(maskarray + 15 -
len));
630 data = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(
p));
635 static const qint8 shufflecontrol[] = {
636 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
637 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
639 __m128i control = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(shufflecontrol + 15 -
len));
640 data = _mm_loadu_si128(
reinterpret_cast<const __m128i *
>(
p +
len) - 1);
641 data = _mm_shuffle_epi8(
data, control);
644 hash16bytes(state0,
data);
646 return mm_cvtsi128_sz(state0);
650aeshash128_ge32(__m128i state0, __m128i state1,
const __m128i *
src,
const __m128i *srcend)
653 for ( ;
src + 2 < srcend;
src += 2)
654 hash2x16bytes(state0, state1,
src,
src + 1);
656 return aeshash128_16to32(state0, state1,
src, srcend);
659# if QT_COMPILER_SUPPORTS_HERE(VAES)
661aeshash256_lt32_avx256(__m256i state0,
const uchar *
p,
size_t len)
663 __m128i state0_128 = _mm256_castsi256_si128(state0);
665 __mmask32
mask = _bzhi_u32(-1,
unsigned(
len));
666 __m256i
data = _mm256_maskz_loadu_epi8(
mask,
p);
667 __m128i data0 = _mm256_castsi256_si128(
data);
668 if (
len >=
sizeof(__m128i)) {
669 state0 = _mm256_xor_si256(state0,
data);
670 state0 = _mm256_aesenc_epi128(state0, state0);
671 state0 = _mm256_aesenc_epi128(state0, state0);
676 __m128i low = _mm256_extracti128_si256(state0, 0);
677 __m128i high = _mm256_extracti128_si256(state0, 1);
678 state0_128 = _mm_xor_si128(low, high);
680 hash16bytes(state0_128, data0);
683 return mm_cvtsi128_sz(state0_128);
687aeshash256_ge32(__m256i state0,
const uchar *
p,
size_t len)
690 state0 = _mm256_xor_si256(state0,
data);
691 state0 = _mm256_aesenc_epi128(state0, state0);
692 state0 = _mm256_aesenc_epi128(state0, state0);
693 state0 = _mm256_aesenc_epi128(state0, state0);
697 const auto hash2x32bytes = [](__m256i &state0, __m256i &state1,
const __m256i *src0,
699 __m256i data0 = _mm256_loadu_si256(src0);
700 __m256i data1 = _mm256_loadu_si256(src1);
701 state0 = _mm256_xor_si256(data0, state0);
702 state1 = _mm256_xor_si256(data1, state1);
703 state0 = _mm256_aesenc_epi128(state0, state0);
704 state1 = _mm256_aesenc_epi128(state1, state1);
705 state0 = _mm256_aesenc_epi128(state0, state0);
706 state1 = _mm256_aesenc_epi128(state1, state1);
709 const __m256i *
src =
reinterpret_cast<const __m256i *
>(
p);
710 const __m256i *srcend =
reinterpret_cast<const __m256i *
>(
p +
len);
712 __m256i state1 = _mm256_aesenc_epi128(state0, mm256_set1_epz(
len));
715 for ( ;
src + 2 < srcend;
src += 2)
716 hash2x32bytes(state0, state1,
src,
src + 1);
718 if (
src + 1 < srcend) {
720 hash2x32bytes(state0, state1,
src, srcend - 1);
721 }
else if (
src != srcend) {
723 __m256i
data = _mm256_loadu_si256(srcend - 1);
724 hash32bytes(state0,
data);
728 state0 = _mm256_xor_si256(state0, state1);
731 __m128i low = _mm256_extracti128_si256(state0, 0);
732 __m128i high = _mm256_extracti128_si256(state0, 1);
733 return mm_cvtsi128_sz(_mm_xor_si128(low, high));
737aeshash256(
const uchar *
p,
size_t len,
size_t seed,
size_t seed2)
noexcept
740 auto src =
reinterpret_cast<const __m128i *
>(
p);
741 const auto srcend =
reinterpret_cast<const __m128i *
>(
p +
len);
743 if (
len <
sizeof(__m128i))
744 return aeshash128_lt16(
state.state0,
p,
len);
746 if (
len <=
sizeof(__m256i))
747 return aeshash128_16to32(
state.state0,
state.state1(),
src, srcend);
749 return aeshash256_ge32(
state.state0_256(),
p,
len);
753aeshash256_avx256(
const uchar *
p,
size_t len,
size_t seed,
size_t seed2)
noexcept
756 if (
len <=
sizeof(__m256i))
757 return aeshash256_lt32_avx256(
state.state0_256(),
p,
len);
759 return aeshash256_ge32(
state.state0_256(),
p,
len);
764aeshash128(
const uchar *
p,
size_t len,
size_t seed,
size_t seed2)
noexcept
767 auto src =
reinterpret_cast<const __m128i *
>(
p);
768 const auto srcend =
reinterpret_cast<const __m128i *
>(
p +
len);
770 if (
len <
sizeof(__m128i))
771 return aeshash128_lt16(
state.state0,
p,
len);
773 if (
len <=
sizeof(__m256i))
774 return aeshash128_16to32(
state.state0,
state.state1(),
src, srcend);
776 return aeshash128_ge32(
state.state0,
state.state1(),
src, srcend);
779static size_t aeshash(
const uchar *
p,
size_t len,
size_t seed,
size_t seed2)
noexcept
781# if QT_COMPILER_SUPPORTS_HERE(VAES)
784 return aeshash256_avx256(
p,
len,
seed, seed2);
785 return aeshash256(
p,
len,
seed, seed2);
788 return aeshash128(
p,
len,
seed, seed2);
792#if defined(Q_PROCESSOR_ARM) && QT_COMPILER_SUPPORTS_HERE(AES) && !defined(QHASH_AES_SANITIZER_BUILD) && !defined(QT_BOOTSTRAPPED)
794static size_t aeshash(
const uchar *
p,
size_t len,
size_t seed,
size_t seed2)
noexcept
797# if QT_POINTER_SIZE == 8
798 uint64x2_t vseed = vcombine_u64(vcreate_u64(
seed), vcreate_u64(seed2));
799 key = vreinterpretq_u8_u64(vseed);
802 uint32x2_t vseed = vmov_n_u32(
seed);
803 vseed = vset_lane_u32(seed2, vseed, 1);
804 key = vreinterpretq_u8_u32(vcombine_u32(vseed, vseed));
809 const auto hash16bytes = [](uint8x16_t &state0, uint8x16_t
data) {
810 auto state1 = state0;
811 state0 = vaeseq_u8(state0,
data);
812 state0 = vaesmcq_u8(state0);
813 auto state2 = state0;
814 state0 = vaeseq_u8(state0, state1);
815 state0 = vaesmcq_u8(state0);
816 auto state3 = state0;
817 state0 = vaeseq_u8(state0, state2);
818 state0 = vaesmcq_u8(state0);
819 state0 = veorq_u8(state0, state3);
822 uint8x16_t state0 =
key;
834 uint8x16_t state1 = veorq_u8(state0, vdupq_n_u8(255));
838 const auto *
e =
p +
len - 31;
840 uint8x16_t data0 = vld1q_u8(
p);
841 uint8x16_t data1 = vld1q_u8(
p + 16);
842 auto oldstate0 = state0;
843 auto oldstate1 = state1;
844 state0 = vaeseq_u8(state0, data0);
845 state1 = vaeseq_u8(state1, data1);
846 state0 = vaesmcq_u8(state0);
847 state1 = vaesmcq_u8(state1);
848 auto laststate0 = state0;
849 auto laststate1 = state1;
850 state0 = vaeseq_u8(state0, oldstate0);
851 state1 = vaeseq_u8(state1, oldstate1);
852 state0 = vaesmcq_u8(state0);
853 state1 = vaesmcq_u8(state1);
854 state0 = veorq_u8(state0, laststate0);
855 state1 = veorq_u8(state1, laststate1);
858 state0 = veorq_u8(state0, state1);
865 uint8x16_t
data = vld1q_u8(
p);
866 hash16bytes(state0,
data);
873 uint8x8_t data8 = vld1_u8(
p);
874 uint8x16_t
data = vcombine_u8(data8, vdup_n_u8(0));
875 hash16bytes(state0,
data);
893 static const qint8 maskarray[] = {
894 -1, -1, -1, -1, -1, -1, -1,
897 uint8x8_t
mask = vld1_u8(
reinterpret_cast<const quint8 *
>(maskarray) + 7 -
len);
899 data8 = vand_u8(data8,
mask);
903 static const qint8 shufflecontrol[] = {
905 -1, -1, -1, -1, -1, -1, -1,
907 uint8x8_t control = vld1_u8(
reinterpret_cast<const quint8 *
>(shufflecontrol) + 7 -
len);
908 data8 = vld1_u8(
p - 8 +
len);
909 data8 = vtbl1_u8(data8, control);
911 uint8x16_t
data = vcombine_u8(data8, vdup_n_u8(0));
912 hash16bytes(state0,
data);
916# if QT_POINTER_SIZE == 8
917 return vgetq_lane_u64(vreinterpretq_u64_u8(state0), 0);
919 return vgetq_lane_u32(vreinterpretq_u32_u8(state0), 0);
926#ifdef QT_BOOTSTRAPPED
938 return aeshash(
reinterpret_cast<const uchar *
>(
p),
size,
seed, seed2);
939#elif defined(Q_PROCESSOR_ARM) && QT_COMPILER_SUPPORTS_HERE(AES) && !defined(QHASH_AES_SANITIZER_BUILD) && !defined(QT_BOOTSTRAPPED)
940# if defined(Q_OS_LINUX)
947 return aeshash(
reinterpret_cast<const uchar *
>(
p),
size,
seed, seed2);
1076#if QT_DEPRECATED_SINCE(6,6)
1088int qGlobalQHashSeed()
1117void qSetGlobalQHashSeed(
int newSeed)
1119 if (
Q_LIKELY(newSeed == 0 || newSeed == -1)) {
1126 fprintf(stderr,
"qSetGlobalQHashSeed: forced seed value is not 0; ignoring call\n");
1148 auto n =
key.size();
1149 auto p =
key.utf16();
1154 h = (
h << 4) + *
p++;
1155 h ^= (
h & 0xf0000000) >> 23;
1430 if constexpr (
sizeof(double) ==
sizeof(
size_t)) {
1432 memcpy(&k, &
key,
sizeof(
double));
1439#if !defined(Q_OS_DARWIN) || defined(Q_QDOC)
1448 key +=
static_cast<long double>(0.0);
1449 if constexpr (
sizeof(
long double) ==
sizeof(
size_t)) {
1451 memcpy(&k, &
key,
sizeof(
long double));
3857#ifdef QT_HAS_CONSTEXPR_BITOPS
3860 "NEntries must be a power of 2 for bucketForHash() to work.");
void storeRelaxed(T newValue) noexcept
size_t qHash(double key, size_t seed) noexcept
size_t qHash(long double key, size_t seed) noexcept
\inmodule QtCore \reentrant
static Q_DECL_CONST_FUNCTION QRandomGenerator * system()
\threadsafe
quint32 generate()
Generates a 32-bit random quantity and returns it.
quint64 generate64()
Generates a 64-bit random quantity and returns it.
constexpr size_t bucketsForCapacity(size_t requestedCapacity) noexcept
Q_DECL_CONST_FUNCTION constexpr size_t hash(size_t key, size_t seed) noexcept
Combined button and popup list for selecting options.
Q_DECL_CONST_FUNCTION QT_POPCOUNT_CONSTEXPR uint qPopulationCount(quint32 v) noexcept
#define Q_BASIC_ATOMIC_INITIALIZER(a)
#define Q_DECL_COLD_FUNCTION
#define QT_WARNING_DISABLE_GCC(text)
size_t qHashBits(const void *p, size_t size, size_t seed) noexcept
Q_NEVER_INLINE static Q_DECL_HOT_FUNCTION uint siphash(const uint8_t *in, uint inlen, uint seed, uint seed2)
Q_NEVER_INLINE static Q_DECL_HOT_FUNCTION uint64_t murmurhash(const void *key, uint64_t len, uint64_t seed) noexcept
static Q_CONSTINIT HashSeedStorage qt_qhash_seed
size_t qHash(QByteArrayView key, size_t seed) noexcept
#define Q_DECL_HOT_FUNCTION
uint qt_hash(QStringView key, uint chained) noexcept
constexpr quint32 qNextPowerOfTwo(quint32 v)
constexpr const T & qMax(const T &a, const T &b)
GLint GLfloat GLfloat GLfloat v2
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLfloat GLfloat GLfloat GLfloat v3
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLfloat GLfloat GLfloat GLfloat h
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
QRandomGenerator::InitialRandomData qt_initial_random_value() noexcept
#define qCpuHasFeature(feature)
#define QT_FUNCTION_TARGET(x)
static uint64_t qCpuFeatures()
QT_BEGIN_NAMESPACE typedef signed char qint8
QRandomGenerator generator(sseq)
static constexpr size_t NEntries
static Q_CORE_EXPORT void setDeterministicGlobalSeed()
\threadsafe
static Q_CORE_EXPORT void resetRandomGlobalSeed()
\threadsafe
static Q_CORE_EXPORT QHashSeed globalSeed() noexcept
\threadsafe