-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix ValueType.GetHashCode not calling overriden method on nested field #98754
Changes from 7 commits
1ae14c2
d5a84eb
80235f7
33e0177
d6b8287
758dead
3219160
19e5618
aea4b67
2d27a42
b6fabf5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -95,37 +95,24 @@ public override unsafe bool Equals([NotNullWhen(true)] object? obj) | |
|
||
public override unsafe int GetHashCode() | ||
{ | ||
int hashCode = (int)this.GetMethodTable()->HashCode; | ||
HashCode hashCode = default; | ||
hashCode.Add((IntPtr)this.GetMethodTable()); | ||
|
||
hashCode ^= GetHashCodeImpl(); | ||
|
||
return hashCode; | ||
} | ||
|
||
private unsafe int GetHashCodeImpl() | ||
{ | ||
int numFields = __GetFieldHelper(GetNumFields, out _); | ||
|
||
if (numFields == UseFastHelper) | ||
return FastGetValueTypeHashCodeHelper(this.GetMethodTable(), ref this.GetRawData()); | ||
hashCode.AddBytes(GetSpanForField(this.GetMethodTable(), ref this.GetRawData())); | ||
else | ||
hashCode.Add(RegularGetValueTypeHashCode(ref this.GetRawData(), numFields)); | ||
|
||
return RegularGetValueTypeHashCode(ref this.GetRawData(), numFields); | ||
return hashCode.ToHashCode(); | ||
} | ||
|
||
private static unsafe int FastGetValueTypeHashCodeHelper(MethodTable* type, ref byte data) | ||
private static unsafe ReadOnlySpan<byte> GetSpanForField(MethodTable* type, ref byte data) | ||
{ | ||
// Sanity check - if there are GC references, we should not be hashing bytes | ||
Debug.Assert(!type->ContainsGCPointers); | ||
|
||
int size = (int)type->ValueTypeSize; | ||
int hashCode = 0; | ||
|
||
for (int i = 0; i < size / 4; i++) | ||
{ | ||
hashCode ^= Unsafe.As<byte, int>(ref Unsafe.Add(ref data, i * 4)); | ||
} | ||
|
||
return hashCode; | ||
return new ReadOnlySpan<byte>(ref data, (int)type->ValueTypeSize); | ||
} | ||
|
||
private unsafe int RegularGetValueTypeHashCode(ref byte data, int numFields) | ||
|
@@ -150,7 +137,9 @@ private unsafe int RegularGetValueTypeHashCode(ref byte data, int numFields) | |
} | ||
else if (fieldType->IsPrimitive) | ||
{ | ||
hashCode = FastGetValueTypeHashCodeHelper(fieldType, ref fieldData); | ||
HashCode hash = default; | ||
hash.AddBytes(GetSpanForField(fieldType, ref fieldData)); | ||
hashCode = hash.ToHashCode(); | ||
} | ||
else if (fieldType->IsValueType) | ||
{ | ||
|
@@ -164,7 +153,7 @@ private unsafe int RegularGetValueTypeHashCode(ref byte data, int numFields) | |
var fieldValue = (ValueType)RuntimeImports.RhBox(fieldType, ref fieldData); | ||
if (fieldValue != null) | ||
{ | ||
hashCode = fieldValue.GetHashCodeImpl(); | ||
hashCode = fieldValue.GetHashCode(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think The only reason we had There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it feasible to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be fine to use If we really wanted to, we could probably unify this to the point of sharing a part of this file, maybe with an ifdef or two. From a quick look |
||
} | ||
else | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method should take
ref HashCode
argument instead of creating a new instance here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant change
RegularGetValueTypeHashCode
to takeref HashCode
argument and deleteHashCode hash = default;
that this comment is attached to.