[vm, compiler] Fix high hash collision rate in a large run of sequential double values.
TEST=many_double_literals_test Change-Id: Ieddaa44ddc0cc67eb8913a62daab44b5579123a2 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/506140 Reviewed-by: Tess Strickland <sstrickl@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
committed by
dart-scoped@luci-project-accounts.iam.gserviceaccount.com
parent
0124cf29fe
commit
58ea063ca8
@@ -640,16 +640,14 @@ void AssemblerBase::Stop(const char* message) {
|
||||
uword ObjIndexPair::Hash(Key key) {
|
||||
switch (key.type()) {
|
||||
case ObjectPoolBuilderEntry::kImmediate128:
|
||||
return key.imm128_.int_storage[0] ^ key.imm128_.int_storage[1] ^
|
||||
key.imm128_.int_storage[2] ^ key.imm128_.int_storage[3];
|
||||
|
||||
return HashBytes(&key.imm128_, sizeof(key.imm128_));
|
||||
#if defined(TARGET_ARCH_IS_32_BIT)
|
||||
case ObjectPoolBuilderEntry::kImmediate64:
|
||||
return key.imm64_;
|
||||
return HashBytes(&key.imm64_, sizeof(key.imm64_));
|
||||
#endif
|
||||
case ObjectPoolBuilderEntry::kImmediate:
|
||||
case ObjectPoolBuilderEntry::kNativeFunction:
|
||||
return key.imm_;
|
||||
return HashBytes(&key.imm_, sizeof(key.imm_));
|
||||
case ObjectPoolBuilderEntry::kTaggedObject:
|
||||
return ObjectHash(*key.obj_);
|
||||
}
|
||||
|
||||
+14
-7
@@ -28,14 +28,21 @@ inline uint32_t FinalizeHash(uint32_t hash, intptr_t hashbits = kBitsPerInt32) {
|
||||
return (hash == 0) ? 1 : hash;
|
||||
}
|
||||
|
||||
inline uint32_t HashBytes(const uint8_t* bytes, intptr_t size) {
|
||||
uint32_t hash = size;
|
||||
while (size > 0) {
|
||||
hash = CombineHashes(hash, *bytes);
|
||||
bytes++;
|
||||
size--;
|
||||
inline uint32_t HashBytes(const void* bytes,
|
||||
intptr_t len,
|
||||
intptr_t hashbits = kBitsPerInt32) {
|
||||
if (len == 0) {
|
||||
return 1;
|
||||
}
|
||||
return hash;
|
||||
uint32_t hash = len;
|
||||
const intptr_t chunks = len / kInt32Size;
|
||||
for (intptr_t i = 0; i < chunks; i++) {
|
||||
hash = CombineHashes(hash, reinterpret_cast<const uint32_t*>(bytes)[i]);
|
||||
}
|
||||
for (intptr_t i = chunks * kInt32Size; i < len; i++) {
|
||||
hash = CombineHashes(hash, reinterpret_cast<const uint8_t*>(bytes)[i]);
|
||||
}
|
||||
return FinalizeHash(hash, hashbits);
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
|
||||
+11
-19
@@ -25978,13 +25978,14 @@ float Float32x4::w() const {
|
||||
}
|
||||
|
||||
bool Float32x4::CanonicalizeEquals(const Instance& other) const {
|
||||
NoSafepointScope no_safepoint;
|
||||
return memcmp(&untag()->value_, Float32x4::Cast(other).untag()->value_,
|
||||
sizeof(simd128_value_t)) == 0;
|
||||
}
|
||||
|
||||
uint32_t Float32x4::CanonicalizeHash() const {
|
||||
return HashBytes(reinterpret_cast<const uint8_t*>(&untag()->value_),
|
||||
sizeof(simd128_value_t));
|
||||
NoSafepointScope no_safepoint;
|
||||
return HashBytes(&untag()->value_, sizeof(simd128_value_t), kHashBits);
|
||||
}
|
||||
|
||||
const char* Float32x4::ToCString() const {
|
||||
@@ -26062,13 +26063,14 @@ void Int32x4::set_value(simd128_value_t value) const {
|
||||
}
|
||||
|
||||
bool Int32x4::CanonicalizeEquals(const Instance& other) const {
|
||||
NoSafepointScope no_safepoint;
|
||||
return memcmp(&untag()->value_, Int32x4::Cast(other).untag()->value_,
|
||||
sizeof(simd128_value_t)) == 0;
|
||||
}
|
||||
|
||||
uint32_t Int32x4::CanonicalizeHash() const {
|
||||
return HashBytes(reinterpret_cast<const uint8_t*>(&untag()->value_),
|
||||
sizeof(simd128_value_t));
|
||||
NoSafepointScope no_safepoint;
|
||||
return HashBytes(&untag()->value_, sizeof(simd128_value_t), kHashBits);
|
||||
}
|
||||
|
||||
const char* Int32x4::ToCString() const {
|
||||
@@ -26122,13 +26124,14 @@ void Float64x2::set_value(simd128_value_t value) const {
|
||||
}
|
||||
|
||||
bool Float64x2::CanonicalizeEquals(const Instance& other) const {
|
||||
NoSafepointScope no_safepoint;
|
||||
return memcmp(&untag()->value_, Float64x2::Cast(other).untag()->value_,
|
||||
sizeof(simd128_value_t)) == 0;
|
||||
}
|
||||
|
||||
uint32_t Float64x2::CanonicalizeHash() const {
|
||||
return HashBytes(reinterpret_cast<const uint8_t*>(&untag()->value_),
|
||||
sizeof(simd128_value_t));
|
||||
NoSafepointScope no_safepoint;
|
||||
return HashBytes(&untag()->value_, sizeof(simd128_value_t), kHashBits);
|
||||
}
|
||||
|
||||
const char* Float64x2::ToCString() const {
|
||||
@@ -26181,19 +26184,8 @@ bool TypedData::CanonicalizeEquals(const Instance& other) const {
|
||||
}
|
||||
|
||||
uint32_t TypedData::CanonicalizeHash() const {
|
||||
const intptr_t len = this->LengthInBytes();
|
||||
if (len == 0) {
|
||||
return 1;
|
||||
}
|
||||
uint32_t hash = len;
|
||||
const intptr_t chunks = len / kInt32Size;
|
||||
for (intptr_t i = 0; i < chunks; i++) {
|
||||
hash = CombineHashes(hash, GetUint32(i * kInt32Size));
|
||||
}
|
||||
for (intptr_t i = chunks * kInt32Size; i < len; i++) {
|
||||
hash = CombineHashes(hash, GetUint8(i));
|
||||
}
|
||||
return FinalizeHash(hash, kHashBits);
|
||||
NoSafepointScope no_safepoint;
|
||||
return HashBytes(DataAddr(0), LengthInBytes(), kHashBits);
|
||||
}
|
||||
|
||||
TypedDataPtr TypedData::New(intptr_t class_id,
|
||||
|
||||
+1
-1
@@ -5959,7 +5959,7 @@ class Instructions : public Object {
|
||||
uint32_t Hash() const { return Hash(ptr()); }
|
||||
|
||||
static uint32_t Hash(const InstructionsPtr instr) {
|
||||
return HashBytes(reinterpret_cast<const uint8_t*>(PayloadStart(instr)),
|
||||
return HashBytes(reinterpret_cast<const void*>(PayloadStart(instr)),
|
||||
Size(instr));
|
||||
}
|
||||
|
||||
|
||||
@@ -162,10 +162,7 @@ struct Span {
|
||||
return memcmp(data, other.data, length * sizeof(T)) == 0;
|
||||
}
|
||||
|
||||
uword Hash() const {
|
||||
return HashBytes(reinterpret_cast<const uint8_t*>(data),
|
||||
length * sizeof(T));
|
||||
}
|
||||
uword Hash() const { return HashBytes(data, length * sizeof(T)); }
|
||||
};
|
||||
|
||||
template <typename T, typename Allocator>
|
||||
@@ -197,7 +194,7 @@ struct Interned {
|
||||
if constexpr (DefinesHashAndEquality<T>) {
|
||||
return data.Hash();
|
||||
} else {
|
||||
return HashBytes(reinterpret_cast<const uint8_t*>(&data), sizeof(T));
|
||||
return HashBytes(&data, sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user