From b8a4c9f316cc344ae8df70ef904214e0a78a9675 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 23 May 2022 17:11:26 +0800 Subject: [PATCH 1/6] Convert GetHashCodeOfPtr to managed --- .../src/System/ValueType.cs | 30 +++++++++++++++++-- src/coreclr/vm/comutilnative.cpp | 30 ------------------- src/coreclr/vm/comutilnative.h | 1 - src/coreclr/vm/ecalllist.h | 1 - 4 files changed, 28 insertions(+), 34 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs b/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs index e15ad7512c8199..3e77188649fac1 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 { @@ -85,8 +87,32 @@ public override bool Equals([NotNullWhen(true)] object? obj) [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 7f92d23b8cce6f..f11c7e6c05a6e2 100644 --- a/src/coreclr/vm/comutilnative.cpp +++ b/src/coreclr/vm/comutilnative.cpp @@ -2044,36 +2044,6 @@ FCIMPL1(INT32, ValueTypeHelper::GetHashCode, Object* objUNSAFE) } FCIMPLEND -static LONG s_dwSeed; - -FCIMPL1(INT32, ValueTypeHelper::GetHashCodeOfPtr, LPVOID ptr) -{ - 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; -} -FCIMPLEND - static MethodTable * g_pStreamMT; static WORD g_slotBeginRead, g_slotEndRead; static WORD g_slotBeginWrite, g_slotEndWrite; diff --git a/src/coreclr/vm/comutilnative.h b/src/coreclr/vm/comutilnative.h index 42ec3b0663b915..7e5cf2f33044a7 100644 --- a/src/coreclr/vm/comutilnative.h +++ b/src/coreclr/vm/comutilnative.h @@ -220,7 +220,6 @@ class ValueTypeHelper { 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 StreamNative { diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index 70ff5aad34602e..c87d527c031f63 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -85,7 +85,6 @@ FCFuncStart(gValueTypeFuncs) FCFuncElement("CanCompareBits", ValueTypeHelper::CanCompareBits) FCFuncElement("FastEqualsCheck", ValueTypeHelper::FastEqualsCheck) FCFuncElement("GetHashCode", ValueTypeHelper::GetHashCode) - FCFuncElement("GetHashCodeOfPtr", ValueTypeHelper::GetHashCodeOfPtr) FCFuncEnd() FCFuncStart(gDiagnosticsDebugger) From 6cdc78bda6f82e13c104b1de97f9aa9bdb5eac6c Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Mon, 23 May 2022 17:32:05 +0800 Subject: [PATCH 2/6] Convert FastEqualsCheck to managed --- .../src/System/ValueType.cs | 13 +++++++++++-- src/coreclr/vm/comutilnative.cpp | 15 --------------- src/coreclr/vm/comutilnative.h | 1 - src/coreclr/vm/ecalllist.h | 1 - 4 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs b/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs index 3e77188649fac1..cc9d1b94558ad1 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs @@ -71,8 +71,17 @@ public override bool Equals([NotNullWhen(true)] object? obj) [MethodImpl(MethodImplOptions.InternalCall)] private static extern bool CanCompareBits(object obj); - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern bool FastEqualsCheck(object a, object b); + private static unsafe bool FastEqualsCheck(object a, object b) + { + MethodTable* pMT = RuntimeHelpers.GetMethodTable(a); + Debug.Assert(!pMT->ContainsGCPointers); + Debug.Assert(!pMT->HasComponentSize); + + // See RuntimeHelpers.GetRawObjectDataSize + // Omitting component size for value type + nuint rawSize = pMT->BaseSize - (nuint)(2 * sizeof(IntPtr)); + return SpanHelpers.SequenceEqual(ref RuntimeHelpers.GetRawData(a), ref RuntimeHelpers.GetRawData(b), rawSize); + } /*=================================GetHashCode================================== **Action: Our algorithm for returning the hashcode is a little bit complex. We look diff --git a/src/coreclr/vm/comutilnative.cpp b/src/coreclr/vm/comutilnative.cpp index f11c7e6c05a6e2..444aa7657dea27 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 diff --git a/src/coreclr/vm/comutilnative.h b/src/coreclr/vm/comutilnative.h index 7e5cf2f33044a7..adb0c6c64b4d07 100644 --- a/src/coreclr/vm/comutilnative.h +++ b/src/coreclr/vm/comutilnative.h @@ -218,7 +218,6 @@ 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); }; diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index c87d527c031f63..f6d6437d254e5c 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -83,7 +83,6 @@ FCFuncEnd() FCFuncStart(gValueTypeFuncs) FCFuncElement("CanCompareBits", ValueTypeHelper::CanCompareBits) - FCFuncElement("FastEqualsCheck", ValueTypeHelper::FastEqualsCheck) FCFuncElement("GetHashCode", ValueTypeHelper::GetHashCode) FCFuncEnd() From a90b2d94e2c6e49e9dfd8ea24374eed6277252f3 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Fri, 27 May 2022 04:18:20 +0800 Subject: [PATCH 3/6] Add FCall to get object size --- .../src/System/ValueType.cs | 17 +++++------------ src/coreclr/vm/comutilnative.cpp | 7 +++++++ src/coreclr/vm/comutilnative.h | 1 + src/coreclr/vm/ecalllist.h | 1 + 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs b/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs index cc9d1b94558ad1..3ddb1426fca795 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs @@ -44,7 +44,9 @@ public override bool Equals([NotNullWhen(true)] object? obj) // 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), GetObjectSize(this)); + } FieldInfo[] thisFields = thisType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); @@ -71,17 +73,8 @@ public override bool Equals([NotNullWhen(true)] object? obj) [MethodImpl(MethodImplOptions.InternalCall)] private static extern bool CanCompareBits(object obj); - private static unsafe bool FastEqualsCheck(object a, object b) - { - MethodTable* pMT = RuntimeHelpers.GetMethodTable(a); - Debug.Assert(!pMT->ContainsGCPointers); - Debug.Assert(!pMT->HasComponentSize); - - // See RuntimeHelpers.GetRawObjectDataSize - // Omitting component size for value type - nuint rawSize = pMT->BaseSize - (nuint)(2 * sizeof(IntPtr)); - return SpanHelpers.SequenceEqual(ref RuntimeHelpers.GetRawData(a), ref RuntimeHelpers.GetRawData(b), rawSize); - } + [MethodImpl(MethodImplOptions.InternalCall)] + private static extern uint GetObjectSize(object obj); /*=================================GetHashCode================================== **Action: Our algorithm for returning the hashcode is a little bit complex. We look diff --git a/src/coreclr/vm/comutilnative.cpp b/src/coreclr/vm/comutilnative.cpp index 444aa7657dea27..bbcb904563eb0a 100644 --- a/src/coreclr/vm/comutilnative.cpp +++ b/src/coreclr/vm/comutilnative.cpp @@ -1827,6 +1827,13 @@ NOINLINE static FC_BOOL_RET CanCompareBitsHelper(MethodTable* mt, OBJECTREF objR FC_RETURN_BOOL(ret); } +FCIMPL1(UINT32, ValueTypeHelper::GetObjectSize, Object* obj) +{ + FCALL_CONTRACT; + return obj->GetTypeHandle().GetSize(); +} +FCIMPLEND + // Return true if the valuetype does not contain pointer, is tightly packed, // does not have floating point number field and does not override Equals method. FCIMPL1(FC_BOOL_RET, ValueTypeHelper::CanCompareBits, Object* obj) diff --git a/src/coreclr/vm/comutilnative.h b/src/coreclr/vm/comutilnative.h index adb0c6c64b4d07..60ba0b336daaab 100644 --- a/src/coreclr/vm/comutilnative.h +++ b/src/coreclr/vm/comutilnative.h @@ -218,6 +218,7 @@ extern "C" void QCALLTYPE Interlocked_MemoryBarrierProcessWide(); class ValueTypeHelper { public: static FCDECL1(FC_BOOL_RET, CanCompareBits, Object* obj); + static FCDECL1(UINT32, GetObjectSize, Object* obj); static FCDECL1(INT32, GetHashCode, Object* objRef); }; diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index f6d6437d254e5c..01c015cab8842d 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -83,6 +83,7 @@ FCFuncEnd() FCFuncStart(gValueTypeFuncs) FCFuncElement("CanCompareBits", ValueTypeHelper::CanCompareBits) + FCFuncElement("GetObjectSize", ValueTypeHelper::GetObjectSize) FCFuncElement("GetHashCode", ValueTypeHelper::GetHashCode) FCFuncEnd() From c5fa6307be2488c2ab29461d8c4e624d39ccbde6 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 28 May 2022 14:02:18 +0800 Subject: [PATCH 4/6] Reduce local variable creation --- .../System.Private.CoreLib/src/System/ValueType.cs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs b/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs index 3ddb1426fca795..7359877916a8e4 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs @@ -30,17 +30,12 @@ public override bool Equals([NotNullWhen(true)] object? 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)) @@ -48,12 +43,12 @@ public override bool Equals([NotNullWhen(true)] object? obj) return SpanHelpers.SequenceEqual(ref RuntimeHelpers.GetRawData(this), ref RuntimeHelpers.GetRawData(obj), GetObjectSize(this)); } - 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) { From 2234639407b77ad993f9cdb0185ac90448107bb4 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 28 May 2022 14:51:06 +0800 Subject: [PATCH 5/6] Change FCall to pass MethodTable* --- .../Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs | 3 +++ .../System.Private.CoreLib/src/System/ValueType.cs | 10 +++++----- src/coreclr/vm/comutilnative.cpp | 4 ++-- src/coreclr/vm/comutilnative.h | 2 +- src/coreclr/vm/ecalllist.h | 6 +++++- 5 files changed, 16 insertions(+), 9 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 cc594304715ab1..cb8ca49e068593 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 @@ public int MultiDimensionalArrayRank 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 7359877916a8e4..31c98a5bf254a0 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs @@ -24,7 +24,7 @@ public abstract class ValueType { [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) { @@ -40,7 +40,10 @@ public override bool Equals([NotNullWhen(true)] object? obj) // and do a fast memcmp if (CanCompareBits(this)) { - return SpanHelpers.SequenceEqual(ref RuntimeHelpers.GetRawData(this), ref RuntimeHelpers.GetRawData(obj), GetObjectSize(this)); + return SpanHelpers.SequenceEqual( + ref RuntimeHelpers.GetRawData(this), + ref RuntimeHelpers.GetRawData(obj), + RuntimeHelpers.GetMethodTable(this)->GetNumInstanceFieldBytes()); } FieldInfo[] thisFields = GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); @@ -68,9 +71,6 @@ public override bool Equals([NotNullWhen(true)] object? obj) [MethodImpl(MethodImplOptions.InternalCall)] private static extern bool CanCompareBits(object obj); - [MethodImpl(MethodImplOptions.InternalCall)] - private static extern uint GetObjectSize(object obj); - /*=================================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 diff --git a/src/coreclr/vm/comutilnative.cpp b/src/coreclr/vm/comutilnative.cpp index bbcb904563eb0a..f7e7fa35ce3c92 100644 --- a/src/coreclr/vm/comutilnative.cpp +++ b/src/coreclr/vm/comutilnative.cpp @@ -1827,10 +1827,10 @@ NOINLINE static FC_BOOL_RET CanCompareBitsHelper(MethodTable* mt, OBJECTREF objR FC_RETURN_BOOL(ret); } -FCIMPL1(UINT32, ValueTypeHelper::GetObjectSize, Object* obj) +FCIMPL1(UINT32, ValueTypeHelper::GetNumInstanceFieldBytes, MethodTable* mt) { FCALL_CONTRACT; - return obj->GetTypeHandle().GetSize(); + return mt->GetNumInstanceFieldBytes(); } FCIMPLEND diff --git a/src/coreclr/vm/comutilnative.h b/src/coreclr/vm/comutilnative.h index 60ba0b336daaab..7e71e07a5cca16 100644 --- a/src/coreclr/vm/comutilnative.h +++ b/src/coreclr/vm/comutilnative.h @@ -218,7 +218,7 @@ extern "C" void QCALLTYPE Interlocked_MemoryBarrierProcessWide(); class ValueTypeHelper { public: static FCDECL1(FC_BOOL_RET, CanCompareBits, Object* obj); - static FCDECL1(UINT32, GetObjectSize, Object* obj); + static FCDECL1(UINT32, GetNumInstanceFieldBytes, MethodTable* mt); static FCDECL1(INT32, GetHashCode, Object* objRef); }; diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index 01c015cab8842d..42db537bd4833c 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -83,7 +83,6 @@ FCFuncEnd() FCFuncStart(gValueTypeFuncs) FCFuncElement("CanCompareBits", ValueTypeHelper::CanCompareBits) - FCFuncElement("GetObjectSize", ValueTypeHelper::GetObjectSize) FCFuncElement("GetHashCode", ValueTypeHelper::GetHashCode) FCFuncEnd() @@ -606,6 +605,10 @@ FCFuncStart(gRuntimeHelpers) FCFuncElement("UnregisterForGCReporting", GCReporting::Unregister) FCFuncEnd() +FCFuncStart(gMethodTableFuncs) + FCFuncElement("GetNumInstanceFieldBytes", ValueTypeHelper::GetNumInstanceFieldBytes) +FCFuncEnd() + FCFuncStart(gMngdFixedArrayMarshalerFuncs) FCFuncElement("CreateMarshaler", MngdFixedArrayMarshaler::CreateMarshaler) FCFuncElement("ConvertSpaceToNative", MngdFixedArrayMarshaler::ConvertSpaceToNative) @@ -811,6 +814,7 @@ FCClassElement("RuntimeMethodHandle", "System", gRuntimeMethodHandle) FCClassElement("RuntimeModule", "System.Reflection", gCOMModuleFuncs) FCClassElement("RuntimeType", "System", gSystem_RuntimeType) FCClassElement("RuntimeTypeHandle", "System", gCOMTypeHandleFuncs) +FCClassElement("MethodTable", "System.Runtime.CompilerServices", gMethodTableFuncs) FCClassElement("Signature", "System", gSignatureNative) FCClassElement("StackTrace", "System.Diagnostics", gDiagnosticsStackTrace) From 3b9f8483ad0cd626af3ffd1bd98e90385a415263 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Sat, 28 May 2022 19:04:31 +0800 Subject: [PATCH 6/6] Sort ecallist and move to MethodTableNative --- src/coreclr/vm/comutilnative.cpp | 14 +++++++------- src/coreclr/vm/comutilnative.h | 6 +++++- src/coreclr/vm/ecalllist.h | 4 ++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/coreclr/vm/comutilnative.cpp b/src/coreclr/vm/comutilnative.cpp index f7e7fa35ce3c92..5dfaec08323c2f 100644 --- a/src/coreclr/vm/comutilnative.cpp +++ b/src/coreclr/vm/comutilnative.cpp @@ -1827,13 +1827,6 @@ NOINLINE static FC_BOOL_RET CanCompareBitsHelper(MethodTable* mt, OBJECTREF objR FC_RETURN_BOOL(ret); } -FCIMPL1(UINT32, ValueTypeHelper::GetNumInstanceFieldBytes, MethodTable* mt) -{ - FCALL_CONTRACT; - return mt->GetNumInstanceFieldBytes(); -} -FCIMPLEND - // Return true if the valuetype does not contain pointer, is tightly packed, // does not have floating point number field and does not override Equals method. FCIMPL1(FC_BOOL_RET, ValueTypeHelper::CanCompareBits, Object* obj) @@ -2036,6 +2029,13 @@ FCIMPL1(INT32, ValueTypeHelper::GetHashCode, Object* objUNSAFE) } FCIMPLEND +FCIMPL1(UINT32, MethodTableNative::GetNumInstanceFieldBytes, MethodTable* mt) +{ + FCALL_CONTRACT; + return mt->GetNumInstanceFieldBytes(); +} +FCIMPLEND + static MethodTable * g_pStreamMT; static WORD g_slotBeginRead, g_slotEndRead; static WORD g_slotBeginWrite, g_slotEndWrite; diff --git a/src/coreclr/vm/comutilnative.h b/src/coreclr/vm/comutilnative.h index 7e71e07a5cca16..cbcc4457ad626c 100644 --- a/src/coreclr/vm/comutilnative.h +++ b/src/coreclr/vm/comutilnative.h @@ -218,10 +218,14 @@ extern "C" void QCALLTYPE Interlocked_MemoryBarrierProcessWide(); class ValueTypeHelper { public: static FCDECL1(FC_BOOL_RET, CanCompareBits, Object* obj); - static FCDECL1(UINT32, GetNumInstanceFieldBytes, MethodTable* mt); static FCDECL1(INT32, GetHashCode, Object* objRef); }; +class MethodTableNative { +public: + static FCDECL1(UINT32, GetNumInstanceFieldBytes, MethodTable* mt); +}; + class StreamNative { public: static FCDECL1(FC_BOOL_RET, HasOverriddenBeginEndRead, Object *stream); diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index 42db537bd4833c..b241fde469e053 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -606,7 +606,7 @@ FCFuncStart(gRuntimeHelpers) FCFuncEnd() FCFuncStart(gMethodTableFuncs) - FCFuncElement("GetNumInstanceFieldBytes", ValueTypeHelper::GetNumInstanceFieldBytes) + FCFuncElement("GetNumInstanceFieldBytes", MethodTableNative::GetNumInstanceFieldBytes) FCFuncEnd() FCFuncStart(gMngdFixedArrayMarshalerFuncs) @@ -787,6 +787,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("MissingMemberException", "System", gMissingMemberExceptionFuncs) FCClassElement("MngdFixedArrayMarshaler", "System.StubHelpers", gMngdFixedArrayMarshalerFuncs) FCClassElement("MngdNativeArrayMarshaler", "System.StubHelpers", gMngdNativeArrayMarshalerFuncs) @@ -814,7 +815,6 @@ FCClassElement("RuntimeMethodHandle", "System", gRuntimeMethodHandle) FCClassElement("RuntimeModule", "System.Reflection", gCOMModuleFuncs) FCClassElement("RuntimeType", "System", gSystem_RuntimeType) FCClassElement("RuntimeTypeHandle", "System", gCOMTypeHandleFuncs) -FCClassElement("MethodTable", "System.Runtime.CompilerServices", gMethodTableFuncs) FCClassElement("Signature", "System", gSignatureNative) FCClassElement("StackTrace", "System.Diagnostics", gDiagnosticsStackTrace)