Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHuo Yaoyuan <huoyaoyuan@hotmail.com>2022-05-29 16:12:49 +0300
committerGitHub <noreply@github.com>2022-05-29 16:12:49 +0300
commit1466e404dfac7ad6af7e6877d26885ce42414120 (patch)
tree5c97e71f52887b8286961606e5d0baecc0d46966 /src
parent7aa40101f02ebaa47dfc3c3384af6a94e971817d (diff)
Convert Valuetype.FastEqualsCheck and GetHashCodeOfPtr to managed (#69723)
* Convert GetHashCodeOfPtr to managed * Convert FastEqualsCheck to managed * Add FCall to get object size * Reduce local variable creation * Change FCall to pass MethodTable* * Sort ecallist and move to MethodTableNative
Diffstat (limited to 'src')
-rw-r--r--src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs3
-rw-r--r--src/coreclr/System.Private.CoreLib/src/System/ValueType.cs55
-rw-r--r--src/coreclr/vm/comutilnative.cpp42
-rw-r--r--src/coreclr/vm/comutilnative.h7
-rw-r--r--src/coreclr/vm/ecalllist.h7
5 files changed, 54 insertions, 60 deletions
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs
index cc594304715..cb8ca49e068 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs
@@ -516,6 +516,9 @@ namespace System.Runtime.CompilerServices
return (int)((BaseSize - (uint)(3 * sizeof(IntPtr))) / (uint)(2 * sizeof(int)));
}
}
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ public extern uint GetNumInstanceFieldBytes();
}
// Helper structs used for tail calls via helper.
diff --git a/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs b/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs
index e15ad7512c8..31c98a5bf25 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs
@@ -10,9 +10,11 @@
**
===========================================================*/
+using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
+using System.Threading;
namespace System
{
@@ -22,34 +24,34 @@ namespace System
{
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern",
Justification = "Trimmed fields don't make a difference for equality")]
- public override bool Equals([NotNullWhen(true)] object? obj)
+ public unsafe override bool Equals([NotNullWhen(true)] object? obj)
{
if (null == obj)
{
return false;
}
- Type thisType = this.GetType();
- Type thatType = obj.GetType();
- if (thatType != thisType)
+ if (GetType() != obj.GetType())
{
return false;
}
- object thisObj = (object)this;
- object? thisResult, thatResult;
-
// if there are no GC references in this object we can avoid reflection
// and do a fast memcmp
if (CanCompareBits(this))
- return FastEqualsCheck(thisObj, obj);
+ {
+ return SpanHelpers.SequenceEqual(
+ ref RuntimeHelpers.GetRawData(this),
+ ref RuntimeHelpers.GetRawData(obj),
+ RuntimeHelpers.GetMethodTable(this)->GetNumInstanceFieldBytes());
+ }
- FieldInfo[] thisFields = thisType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ FieldInfo[] thisFields = GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
for (int i = 0; i < thisFields.Length; i++)
{
- thisResult = thisFields[i].GetValue(thisObj);
- thatResult = thisFields[i].GetValue(obj);
+ object? thisResult = thisFields[i].GetValue(this);
+ object? thatResult = thisFields[i].GetValue(obj);
if (thisResult == null)
{
@@ -69,9 +71,6 @@ namespace System
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern bool CanCompareBits(object obj);
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern bool FastEqualsCheck(object a, object b);
-
/*=================================GetHashCode==================================
**Action: Our algorithm for returning the hashcode is a little bit complex. We look
** for the first non-static field and get its hashcode. If the type has no
@@ -85,8 +84,32 @@ namespace System
[MethodImpl(MethodImplOptions.InternalCall)]
public extern override int GetHashCode();
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern int GetHashCodeOfPtr(IntPtr ptr);
+ private static int s_seed;
+
+ internal static int GetHashCodeOfPtr(IntPtr ptr)
+ {
+ int hashCode = (int)ptr;
+
+ if (hashCode == 0)
+ {
+ return 0;
+ }
+
+ int seed = s_seed;
+
+ // Initialize s_seed lazily
+ if (seed == 0)
+ {
+ // We use the first non-0 pointer as the seed, all hashcodes will be based off that.
+ // This is to make sure that we only reveal relative memory addresses and never absolute ones.
+ seed = hashCode;
+ Interlocked.CompareExchange(ref s_seed, seed, 0);
+ seed = s_seed;
+ }
+
+ Debug.Assert(s_seed != 0);
+ return hashCode - seed;
+ }
public override string? ToString()
{
diff --git a/src/coreclr/vm/comutilnative.cpp b/src/coreclr/vm/comutilnative.cpp
index 7f92d23b8cc..5dfaec08323 100644
--- a/src/coreclr/vm/comutilnative.cpp
+++ b/src/coreclr/vm/comutilnative.cpp
@@ -1847,21 +1847,6 @@ FCIMPL1(FC_BOOL_RET, ValueTypeHelper::CanCompareBits, Object* obj)
}
FCIMPLEND
-FCIMPL2(FC_BOOL_RET, ValueTypeHelper::FastEqualsCheck, Object* obj1, Object* obj2)
-{
- FCALL_CONTRACT;
-
- _ASSERTE(obj1 != NULL);
- _ASSERTE(obj2 != NULL);
- _ASSERTE(!obj1->GetMethodTable()->ContainsPointers());
- _ASSERTE(obj1->GetSize() == obj2->GetSize());
-
- TypeHandle pTh = obj1->GetTypeHandle();
-
- FC_RETURN_BOOL(memcmp(obj1->GetData(),obj2->GetData(),pTh.GetSize()) == 0);
-}
-FCIMPLEND
-
static INT32 FastGetValueTypeHashCodeHelper(MethodTable *mt, void *pObjRef)
{
CONTRACTL
@@ -2044,33 +2029,10 @@ FCIMPL1(INT32, ValueTypeHelper::GetHashCode, Object* objUNSAFE)
}
FCIMPLEND
-static LONG s_dwSeed;
-
-FCIMPL1(INT32, ValueTypeHelper::GetHashCodeOfPtr, LPVOID ptr)
+FCIMPL1(UINT32, MethodTableNative::GetNumInstanceFieldBytes, MethodTable* mt)
{
FCALL_CONTRACT;
-
- INT32 hashCode = (INT32)((INT64)(ptr));
-
- if (hashCode == 0)
- {
- return 0;
- }
-
- DWORD dwSeed = s_dwSeed;
-
- // Initialize s_dwSeed lazily
- if (dwSeed == 0)
- {
- // We use the first non-0 pointer as the seed, all hashcodes will be based off that.
- // This is to make sure that we only reveal relative memory addresses and never absolute ones.
- dwSeed = hashCode;
- InterlockedCompareExchange(&s_dwSeed, dwSeed, 0);
- dwSeed = s_dwSeed;
- }
- _ASSERTE(dwSeed != 0);
-
- return hashCode - dwSeed;
+ return mt->GetNumInstanceFieldBytes();
}
FCIMPLEND
diff --git a/src/coreclr/vm/comutilnative.h b/src/coreclr/vm/comutilnative.h
index 42ec3b0663b..cbcc4457ad6 100644
--- a/src/coreclr/vm/comutilnative.h
+++ b/src/coreclr/vm/comutilnative.h
@@ -218,9 +218,12 @@ extern "C" void QCALLTYPE Interlocked_MemoryBarrierProcessWide();
class ValueTypeHelper {
public:
static FCDECL1(FC_BOOL_RET, CanCompareBits, Object* obj);
- static FCDECL2(FC_BOOL_RET, FastEqualsCheck, Object* obj1, Object* obj2);
static FCDECL1(INT32, GetHashCode, Object* objRef);
- static FCDECL1(INT32, GetHashCodeOfPtr, LPVOID ptr);
+};
+
+class MethodTableNative {
+public:
+ static FCDECL1(UINT32, GetNumInstanceFieldBytes, MethodTable* mt);
};
class StreamNative {
diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h
index c85799fd7f1..a14d5855d59 100644
--- a/src/coreclr/vm/ecalllist.h
+++ b/src/coreclr/vm/ecalllist.h
@@ -83,9 +83,7 @@ FCFuncEnd()
FCFuncStart(gValueTypeFuncs)
FCFuncElement("CanCompareBits", ValueTypeHelper::CanCompareBits)
- FCFuncElement("FastEqualsCheck", ValueTypeHelper::FastEqualsCheck)
FCFuncElement("GetHashCode", ValueTypeHelper::GetHashCode)
- FCFuncElement("GetHashCodeOfPtr", ValueTypeHelper::GetHashCodeOfPtr)
FCFuncEnd()
FCFuncStart(gDiagnosticsDebugger)
@@ -605,6 +603,10 @@ FCFuncStart(gRuntimeHelpers)
FCFuncElement("UnregisterForGCReporting", GCReporting::Unregister)
FCFuncEnd()
+FCFuncStart(gMethodTableFuncs)
+ FCFuncElement("GetNumInstanceFieldBytes", MethodTableNative::GetNumInstanceFieldBytes)
+FCFuncEnd()
+
FCFuncStart(gMngdFixedArrayMarshalerFuncs)
FCFuncElement("CreateMarshaler", MngdFixedArrayMarshaler::CreateMarshaler)
FCFuncElement("ConvertSpaceToNative", MngdFixedArrayMarshaler::ConvertSpaceToNative)
@@ -783,6 +785,7 @@ FCClassElement("Marshal", "System.Runtime.InteropServices", gInteropMarshalFuncs
FCClassElement("Math", "System", gMathFuncs)
FCClassElement("MathF", "System", gMathFFuncs)
FCClassElement("MetadataImport", "System.Reflection", gMetaDataImport)
+FCClassElement("MethodTable", "System.Runtime.CompilerServices", gMethodTableFuncs)
FCClassElement("MngdFixedArrayMarshaler", "System.StubHelpers", gMngdFixedArrayMarshalerFuncs)
FCClassElement("MngdNativeArrayMarshaler", "System.StubHelpers", gMngdNativeArrayMarshalerFuncs)
FCClassElement("MngdRefCustomMarshaler", "System.StubHelpers", gMngdRefCustomMarshalerFuncs)