From f5c77e58b6e037e282cedb5f8db684b5128800c1 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 18 Jan 2024 14:44:16 +0100 Subject: [PATCH 01/23] Add getTypeDefinition definition --- src/coreclr/inc/corinfo.h | 15 +++++++++++++++ src/coreclr/inc/icorjitinfoimpl_generated.h | 3 +++ src/coreclr/jit/ICorJitInfo_names_generated.h | 1 + src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp | 9 +++++++++ .../JitInterface/ThunkGenerator/ThunkInput.txt | 1 + .../aot/jitinterface/jitinterface_generated.h | 10 ++++++++++ .../icorjitinfo_generated.cpp | 7 +++++++ .../icorjitinfo_generated.cpp | 6 ++++++ 8 files changed, 52 insertions(+) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index e273ca5f2698bc..213d2601b93793 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -2082,6 +2082,21 @@ class ICorStaticInfo CORINFO_METHOD_HANDLE meth1Hnd, CORINFO_METHOD_HANDLE meth2Hnd) = 0; + //------------------------------------------------------------------------------ + // getTypeDefinition: Get the (unconstructed) type definition from a given type handle. + // + // Arguments: + // type - The input type handle + // + // Return Value: + // The type handle for the (unconstructed) type definition from type. + // + // Remarks: + // This is equivalent of Type.GetGenericTypeDefinition(). Given a generic type handle, it will + // return the original type definition (eg. for Foo it will return Foo<>). If the input + // type handle represents a type that is not generic, it will just return the same type. + virtual CORINFO_CLASS_HANDLE getTypeDefinition(CORINFO_CLASS_HANDLE type) = 0; + // Decides if you have any limitations for inlining. If everything's OK, it will return // INLINE_PASS. // diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index f396963d68ba95..fc415320cad835 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -48,6 +48,9 @@ bool haveSameMethodDefinition( CORINFO_METHOD_HANDLE meth1Hnd, CORINFO_METHOD_HANDLE meth2Hnd) override; +CORINFO_CLASS_HANDLE getTypeDefinition( + CORINFO_CLASS_HANDLE type) override; + CorInfoInline canInline( CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd) override; diff --git a/src/coreclr/jit/ICorJitInfo_names_generated.h b/src/coreclr/jit/ICorJitInfo_names_generated.h index f7c218d90d0293..d6526b94ee9ee2 100644 --- a/src/coreclr/jit/ICorJitInfo_names_generated.h +++ b/src/coreclr/jit/ICorJitInfo_names_generated.h @@ -11,6 +11,7 @@ DEF_CLR_API(setMethodAttribs) DEF_CLR_API(getMethodSig) DEF_CLR_API(getMethodInfo) DEF_CLR_API(haveSameMethodDefinition) +DEF_CLR_API(getTypeDefinition) DEF_CLR_API(canInline) DEF_CLR_API(beginInlining) DEF_CLR_API(reportInliningDecision) diff --git a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp index 5b044f211e8dc9..3410d97d1fc565 100644 --- a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp +++ b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp @@ -79,6 +79,15 @@ bool WrapICorJitInfo::haveSameMethodDefinition( return temp; } +CORINFO_CLASS_HANDLE WrapICorJitInfo::getTypeDefinition( + CORINFO_CLASS_HANDLE type) +{ + API_ENTER(getTypeDefinition); + CORINFO_CLASS_HANDLE temp = wrapHnd->getTypeDefinition(type); + API_LEAVE(getTypeDefinition); + return temp; +} + CorInfoInline WrapICorJitInfo::canInline( CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd) diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index ae10f997204ca0..1ddf962175b026 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -170,6 +170,7 @@ FUNCTIONS void getMethodSig( CORINFO_METHOD_HANDLE ftn, CORINFO_SIG_INFO *sig, CORINFO_CLASS_HANDLE memberParent ); bool getMethodInfo(CORINFO_METHOD_HANDLE ftn, CORINFO_METHOD_INFO* info, CORINFO_CONTEXT_HANDLE context); bool haveSameMethodDefinition(CORINFO_METHOD_HANDLE meth1Hnd, CORINFO_METHOD_HANDLE meth2Hnd); + CORINFO_CLASS_HANDLE getTypeDefinition(CORINFO_CLASS_HANDLE type); CorInfoInline canInline( CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd); void beginInlining(CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd); void reportInliningDecision(CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd, CorInfoInline inlineResult, const char * reason); diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h index 8c9a4786ea3d50..74f884b3afa9e9 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h @@ -18,6 +18,7 @@ struct JitInterfaceCallbacks void (* getMethodSig)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, CORINFO_SIG_INFO* sig, CORINFO_CLASS_HANDLE memberParent); bool (* getMethodInfo)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, CORINFO_METHOD_INFO* info, CORINFO_CONTEXT_HANDLE context); bool (* haveSameMethodDefinition)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE meth1Hnd, CORINFO_METHOD_HANDLE meth2Hnd); + CORINFO_CLASS_HANDLE (* getTypeDefinition)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE type); CorInfoInline (* canInline)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd); void (* beginInlining)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd); void (* reportInliningDecision)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd, CorInfoInline inlineResult, const char* reason); @@ -269,6 +270,15 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } + virtual CORINFO_CLASS_HANDLE getTypeDefinition( + CORINFO_CLASS_HANDLE type) +{ + CorInfoExceptionClass* pException = nullptr; + CORINFO_CLASS_HANDLE temp = _callbacks->getTypeDefinition(_thisHandle, &pException, type); + if (pException != nullptr) throw pException; + return temp; +} + virtual CorInfoInline canInline( CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd) diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp index 61b210ca3c09a2..332c9d13d0a635 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp @@ -67,6 +67,13 @@ bool interceptor_ICJI::haveSameMethodDefinition( return original_ICorJitInfo->haveSameMethodDefinition(meth1Hnd, meth2Hnd); } +CORINFO_CLASS_HANDLE interceptor_ICJI::getTypeDefinition( + CORINFO_CLASS_HANDLE type) +{ + mcs->AddCall("getTypeDefinition"); + return original_ICorJitInfo->getTypeDefinition(type); +} + CorInfoInline interceptor_ICJI::canInline( CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd) diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp index 840291e26701a6..989c587d47d892 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp @@ -60,6 +60,12 @@ bool interceptor_ICJI::haveSameMethodDefinition( return original_ICorJitInfo->haveSameMethodDefinition(meth1Hnd, meth2Hnd); } +CORINFO_CLASS_HANDLE interceptor_ICJI::getTypeDefinition( + CORINFO_CLASS_HANDLE type) +{ + return original_ICorJitInfo->getTypeDefinition(type); +} + CorInfoInline interceptor_ICJI::canInline( CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd) From 7b27bb2da1d5ba3bf441bc0c28688d1c6e6c452e Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 18 Jan 2024 15:12:41 +0100 Subject: [PATCH 02/23] Implement CEEInfo::getTypeDefinition --- src/coreclr/vm/jitinterface.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 3b8c32e20fcd57..5192cd703635a0 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -7820,6 +7820,32 @@ bool CEEInfo::haveSameMethodDefinition( return result; } +CORINFO_CLASS_HANDLE CEEInfo::getTypeDefinition(CORINFO_CLASS_HANDLE type) +{ + CONTRACTL { + THROWS; + GC_TRIGGERS; + MODE_PREEMPTIVE; + } CONTRACTL_END; + + CORINFO_CLASS_HANDLE result = NULL; + + JIT_TO_EE_TRANSITION(); + + TypeHandle constructedHandle(type); + TypeHandle definitionHandle = ClassLoader::LoadTypeDefThrowing( + constructedHandle.GetModule(), + constructedHandle.GetMethodTable()->GetCl(), + ClassLoader::ThrowIfNotFound, + ClassLoader::PermitUninstDefOrRef); + + result = CORINFO_CLASS_HANDLE(definitionHandle.AsPtr()); + + EE_TO_JIT_TRANSITION(); + + return result; +} + /************************************************************* * Check if the caller and calle are in the same assembly * i.e. do not inline across assemblies From f7e895123a4b1b6e05d49fecd0c64de8eedb5aee Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 18 Jan 2024 16:22:39 +0100 Subject: [PATCH 03/23] Tweak CEEInfo::getTypeDefinition --- src/coreclr/vm/jitinterface.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 5192cd703635a0..f8c94bce355a15 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -7823,25 +7823,31 @@ bool CEEInfo::haveSameMethodDefinition( CORINFO_CLASS_HANDLE CEEInfo::getTypeDefinition(CORINFO_CLASS_HANDLE type) { CONTRACTL { - THROWS; + NOTHROW; GC_TRIGGERS; MODE_PREEMPTIVE; } CONTRACTL_END; CORINFO_CLASS_HANDLE result = NULL; - JIT_TO_EE_TRANSITION(); + JIT_TO_EE_TRANSITION_LEAF(); TypeHandle constructedHandle(type); TypeHandle definitionHandle = ClassLoader::LoadTypeDefThrowing( constructedHandle.GetModule(), constructedHandle.GetMethodTable()->GetCl(), - ClassLoader::ThrowIfNotFound, - ClassLoader::PermitUninstDefOrRef); + ClassLoader::ReturnNullIfNotFound, + ClassLoader::PermitUninstDefOrRef, + /* tokenNotToLoad */ tdAllTypes); result = CORINFO_CLASS_HANDLE(definitionHandle.AsPtr()); - EE_TO_JIT_TRANSITION(); + JIT_TO_EE_TRANSITION_LEAF(); + + // We forbid loading new types here, and we expect the resulting types to + // always be available. That is because if we are trying to get the type + // definition of some 'Foo' type, then 'Foo<>' must also be loaded. + _ASSERTE(result != NULL); return result; } From 9d6ec4897b24a3cc26dcdf164fee708cda18c109 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 18 Jan 2024 16:23:45 +0100 Subject: [PATCH 04/23] Make Type.GetGenericTypeDefinition() an intrinsic --- src/coreclr/jit/compiler.h | 1 + src/coreclr/jit/fgbasic.cpp | 1 + src/coreclr/jit/importer.cpp | 21 +++++++++++++++++++ src/coreclr/jit/importercalls.cpp | 15 +++++++++++++ src/coreclr/jit/namedintrinsiclist.h | 1 + .../System.Private.CoreLib/src/System/Type.cs | 1 + 6 files changed, 40 insertions(+) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 7013184028a878..ce8cfe9f57f0d6 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -4589,6 +4589,7 @@ class Compiler #endif void impResetLeaveBlock(BasicBlock* block, unsigned jmpAddr); GenTree* impTypeIsAssignable(GenTree* typeTo, GenTree* typeFrom); + GenTree* impGetGenericTypeDefinition(GenTree* type); // Mirrors StringComparison.cs enum StringComparison diff --git a/src/coreclr/jit/fgbasic.cpp b/src/coreclr/jit/fgbasic.cpp index f2c0f458c10505..a2ef25e6a5f97c 100644 --- a/src/coreclr/jit/fgbasic.cpp +++ b/src/coreclr/jit/fgbasic.cpp @@ -1387,6 +1387,7 @@ void Compiler::fgFindJumpTargets(const BYTE* codeAddr, IL_OFFSET codeSize, Fixed case NI_System_Type_get_IsByRefLike: case NI_System_Type_get_IsGenericType: case NI_System_Type_GetTypeFromHandle: + case NI_System_Type_GetGenericTypeDefinition: case NI_System_String_get_Length: case NI_System_Buffers_Binary_BinaryPrimitives_ReverseEndianness: #if defined(FEATURE_HW_INTRINSICS) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index ad0c4d2b902813..2f0c9bcf911d4d 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -2490,6 +2490,27 @@ GenTree* Compiler::impTypeIsAssignable(GenTree* typeTo, GenTree* typeFrom) return nullptr; } + +GenTree* Compiler::impGetGenericTypeDefinition(GenTree* type) +{ + // this intrinsic requires the first arg to be some `typeof()` expression, + // ie. it applies to cases such as `typeof(...).GetGenericTypeDefinition()`. + CORINFO_CLASS_HANDLE hClassType = NO_CLASS_HANDLE; + if (gtIsTypeof(type, &hClassType)) + { + CORINFO_CLASS_HANDLE hClassResult = info.compCompHnd->getTypeDefinition(hClassType); + + GenTree* retNode = gtNewIconEmbClsHndNode(hClassResult); + + // Drop the typeof(T) node + impPopStack(); + + return retNode; + } + + return nullptr; +} + /***************************************************************************** * 'logMsg' is true if a log message needs to be logged. false if the caller has * already logged it (presumably in a more detailed fashion than done here) diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 322ce25ca96f8e..e8de998ebed2c4 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -3321,6 +3321,9 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, case NI_System_Type_op_Equality: case NI_System_Type_op_Inequality: + // This allows folding "typeof(...).GetGenericTypeDefinition() == typeof(...)" + case NI_System_Type_GetGenericTypeDefinition: + // These may lead to early dead code elimination case NI_System_Type_get_IsValueType: case NI_System_Type_get_IsPrimitive: @@ -3856,6 +3859,14 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, break; } + case NI_System_Type_GetGenericTypeDefinition: + { + GenTree* type = impStackTop(0).val; + + retNode = impGetGenericTypeDefinition(type); + break; + } + case NI_System_Type_op_Equality: case NI_System_Type_op_Inequality: { @@ -10220,6 +10231,10 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) { result = NI_System_Type_GetTypeFromHandle; } + else if (strcmp(methodName, "GetGenericTypeDefinition") == 0) + { + result = NI_System_Type_GetGenericTypeDefinition; + } else if (strcmp(methodName, "IsAssignableFrom") == 0) { result = NI_System_Type_IsAssignableFrom; diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h index 93e4ce7893f98b..c4e8ceeee4d5ab 100644 --- a/src/coreclr/jit/namedintrinsiclist.h +++ b/src/coreclr/jit/namedintrinsiclist.h @@ -89,6 +89,7 @@ enum NamedIntrinsic : unsigned short NI_System_Type_op_Equality, NI_System_Type_op_Inequality, NI_System_Type_GetTypeFromHandle, + NI_System_Type_GetGenericTypeDefinition, NI_System_Array_Clone, NI_System_Array_GetLength, NI_System_Array_GetLowerBound, diff --git a/src/libraries/System.Private.CoreLib/src/System/Type.cs b/src/libraries/System.Private.CoreLib/src/System/Type.cs index 6c9185193dabf5..3437d8f377bd44 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Type.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Type.cs @@ -74,6 +74,7 @@ public bool IsInterface public virtual int GetArrayRank() => throw new NotSupportedException(SR.NotSupported_SubclassOverride); + [Intrinsic] public virtual Type GetGenericTypeDefinition() => throw new NotSupportedException(SR.NotSupported_SubclassOverride); public virtual Type[] GenericTypeArguments => (IsGenericType && !IsGenericTypeDefinition) ? GetGenericArguments() : EmptyTypes; public virtual Type[] GetGenericArguments() => throw new NotSupportedException(SR.NotSupported_SubclassOverride); From b5375052a32f18984f7f75b2f0f97fdff86f6781 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 18 Jan 2024 16:31:09 +0100 Subject: [PATCH 05/23] Add GetGenericTypeDefinition() intrinsic tests --- src/tests/JIT/Intrinsics/TypeIntrinsics.cs | 35 ++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/tests/JIT/Intrinsics/TypeIntrinsics.cs b/src/tests/JIT/Intrinsics/TypeIntrinsics.cs index 3821f74bf18761..1376d8b020d416 100644 --- a/src/tests/JIT/Intrinsics/TypeIntrinsics.cs +++ b/src/tests/JIT/Intrinsics/TypeIntrinsics.cs @@ -134,6 +134,7 @@ public static int TestEntryPoint() IsPrimitiveTests(); IsGenericTypeTests(); + GetGenericTypeDefinitionTests(); return 100 + _errors; } @@ -276,6 +277,30 @@ private static void IsGenericTypeTests() IsTrue(new ClassUsingIsGenericTypeOnT().IsGenericTypeFromOtherGenericType()); } + private static void GetGenericTypeDefinitionTests() + { + AreEqual(typeof(GenericEnumClass).GetGenericTypeDefinition(), typeof(GenericEnumClass<>)); + AreEqual(typeof(GenericEnumClass<>).GetGenericTypeDefinition(), typeof(GenericEnumClass<>)); + AreEqual(typeof(IGenericInterface).GetGenericTypeDefinition(), typeof(IGenericInterface<>)); + AreEqual(typeof(IGenericInterface<>).GetGenericTypeDefinition(), typeof(IGenericInterface<>)); + AreEqual(typeof(GenericStruct).GetGenericTypeDefinition(), typeof(GenericStruct<>)); + AreEqual(typeof(GenericStruct<>).GetGenericTypeDefinition(), typeof(GenericStruct<>)); + AreEqual(typeof(SimpleEnum?).GetGenericTypeDefinition(), typeof(Nullable<>)); + AreEqual(typeof(int?).GetGenericTypeDefinition(), typeof(Nullable<>)); + AreEqual(typeof(IntPtr?).GetGenericTypeDefinition(), typeof(Nullable<>)); + AreEqual(typeof(Nullable<>).GetGenericTypeDefinition(), typeof(Nullable<>)); + AreEqual(typeof(KeyValuePair).GetGenericTypeDefinition(), typeof(KeyValuePair<,>)); + AreEqual(typeof(KeyValuePair<,>).GetGenericTypeDefinition(), typeof(KeyValuePair<,>)); + AreEqual(typeof(Dictionary).GetGenericTypeDefinition(), typeof(Dictionary<,>)); + AreEqual(typeof(Dictionary<,>).GetGenericTypeDefinition(), typeof(Dictionary<,>)); + AreEqual(typeof(List).GetGenericTypeDefinition(), typeof(List<>)); + AreEqual(typeof(List<>).GetGenericTypeDefinition(), typeof(List<>)); + AreEqual(typeof(Action<>).GetGenericTypeDefinition(), typeof(Action<>)); + AreEqual(typeof(Action).GetGenericTypeDefinition(), typeof(Action<>)); + AreEqual(typeof(Func).GetGenericTypeDefinition(), typeof(Func<,>)); + AreEqual(typeof(Func<,>).GetGenericTypeDefinition(), typeof(Func<,>)); + } + private static int _varInt = 42; private static int? _varNullableInt = 42; private static decimal _varDecimal = 42M; @@ -329,6 +354,16 @@ static void IsFalse(bool expression, [CallerLineNumber] int line = 0, [CallerFil } } + [MethodImpl(MethodImplOptions.NoInlining)] + static void AreEqual(Type left, Type right, [CallerLineNumber] int line = 0, [CallerFilePath] string file = "") + { + if (left != right) + { + Console.WriteLine($"{file}:L{line} test failed (expected: '{left}' to be equal to '{right}')."); + _errors++; + } + } + static void ThrowsNRE(Action action, [CallerLineNumber] int line = 0, [CallerFilePath] string file = "") { try From a02c9a1381fe01ab3a6ef41cdddf0f55714a0cfb Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 18 Jan 2024 19:01:05 +0100 Subject: [PATCH 06/23] Only expand intrinsic for generic types --- src/coreclr/inc/corinfo.h | 4 ++-- src/coreclr/jit/importer.cpp | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 213d2601b93793..17891090e4c811 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -2093,8 +2093,8 @@ class ICorStaticInfo // // Remarks: // This is equivalent of Type.GetGenericTypeDefinition(). Given a generic type handle, it will - // return the original type definition (eg. for Foo it will return Foo<>). If the input - // type handle represents a type that is not generic, it will just return the same type. + // return the original type definition (eg. for Foo it will return Foo<>). This method + // should only be called when the input type is in fact a generic type. virtual CORINFO_CLASS_HANDLE getTypeDefinition(CORINFO_CLASS_HANDLE type) = 0; // Decides if you have any limitations for inlining. If everything's OK, it will return diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 2f0c9bcf911d4d..62ac1abffce0cf 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -2493,19 +2493,25 @@ GenTree* Compiler::impTypeIsAssignable(GenTree* typeTo, GenTree* typeFrom) GenTree* Compiler::impGetGenericTypeDefinition(GenTree* type) { - // this intrinsic requires the first arg to be some `typeof()` expression, + // This intrinsic requires the first arg to be some `typeof()` expression, // ie. it applies to cases such as `typeof(...).GetGenericTypeDefinition()`. CORINFO_CLASS_HANDLE hClassType = NO_CLASS_HANDLE; if (gtIsTypeof(type, &hClassType)) { - CORINFO_CLASS_HANDLE hClassResult = info.compCompHnd->getTypeDefinition(hClassType); + // Check that the 'typeof()' expression is being used on a type that is in fact generic. + // If that is not the case, we don't expand the intrinsic. This will end up using + // the usual Type.GetGenericTypeDefinition() at runtime, which will throw in this case. + if (info.compCompHnd->getTypeInstantiationArgument(hClassType, 0) != NO_CLASS_HANDLE) + { + CORINFO_CLASS_HANDLE hClassResult = info.compCompHnd->getTypeDefinition(hClassType); - GenTree* retNode = gtNewIconEmbClsHndNode(hClassResult); + GenTree* retNode = gtNewIconEmbClsHndNode(hClassResult); - // Drop the typeof(T) node - impPopStack(); + // Drop the typeof(T) node + impPopStack(); - return retNode; + return retNode; + } } return nullptr; From 23f8ebccbca7c35ec2a21b73c6e75b22220044bd Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 18 Jan 2024 19:04:04 +0100 Subject: [PATCH 07/23] Use normal JIT_TO_EE transition --- src/coreclr/vm/jitinterface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index f8c94bce355a15..e79bba81aadc4a 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -7830,7 +7830,7 @@ CORINFO_CLASS_HANDLE CEEInfo::getTypeDefinition(CORINFO_CLASS_HANDLE type) CORINFO_CLASS_HANDLE result = NULL; - JIT_TO_EE_TRANSITION_LEAF(); + JIT_TO_EE_TRANSITION(); TypeHandle constructedHandle(type); TypeHandle definitionHandle = ClassLoader::LoadTypeDefThrowing( @@ -7842,7 +7842,7 @@ CORINFO_CLASS_HANDLE CEEInfo::getTypeDefinition(CORINFO_CLASS_HANDLE type) result = CORINFO_CLASS_HANDLE(definitionHandle.AsPtr()); - JIT_TO_EE_TRANSITION_LEAF(); + JIT_TO_EE_TRANSITION(); // We forbid loading new types here, and we expect the resulting types to // always be available. That is because if we are trying to get the type From d6a925d36ac71b230164154ae22fb94dc0267c94 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 18 Jan 2024 20:01:47 +0100 Subject: [PATCH 08/23] Apply review suggestions for CEEInfo::getTypeDefinition --- src/coreclr/vm/jitinterface.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index e79bba81aadc4a..e1ab5d2362002c 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -7823,7 +7823,7 @@ bool CEEInfo::haveSameMethodDefinition( CORINFO_CLASS_HANDLE CEEInfo::getTypeDefinition(CORINFO_CLASS_HANDLE type) { CONTRACTL { - NOTHROW; + THROWS; GC_TRIGGERS; MODE_PREEMPTIVE; } CONTRACTL_END; @@ -7833,20 +7833,19 @@ CORINFO_CLASS_HANDLE CEEInfo::getTypeDefinition(CORINFO_CLASS_HANDLE type) JIT_TO_EE_TRANSITION(); TypeHandle constructedHandle(type); + + _ASSERTE(constructedHandle.HasInstantiation()); + TypeHandle definitionHandle = ClassLoader::LoadTypeDefThrowing( constructedHandle.GetModule(), constructedHandle.GetMethodTable()->GetCl(), - ClassLoader::ReturnNullIfNotFound, - ClassLoader::PermitUninstDefOrRef, - /* tokenNotToLoad */ tdAllTypes); + ClassLoader::ThrowIfNotFound, + ClassLoader::PermitUninstDefOrRef); result = CORINFO_CLASS_HANDLE(definitionHandle.AsPtr()); JIT_TO_EE_TRANSITION(); - // We forbid loading new types here, and we expect the resulting types to - // always be available. That is because if we are trying to get the type - // definition of some 'Foo' type, then 'Foo<>' must also be loaded. _ASSERTE(result != NULL); return result; From cf937db45f9fad3ac33b5f9e5e9264d6222f7138 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 18 Jan 2024 20:29:02 +0100 Subject: [PATCH 09/23] Implement managed version of getTypeDefinition --- src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 27a55a64149101..0033a758669307 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -1248,6 +1248,11 @@ private bool haveSameMethodDefinition(CORINFO_METHOD_STRUCT_* methHnd1, CORINFO_ return meth1.GetTypicalMethodDefinition() == meth2.GetTypicalMethodDefinition(); } + private CORINFO_CLASS_STRUCT_* getTypeDefinition(CORINFO_CLASS_STRUCT_* type) + { + return ObjectToHandle(HandleToObject(type).GetTypeDefinition()); + } + private CorInfoInline canInline(CORINFO_METHOD_STRUCT_* callerHnd, CORINFO_METHOD_STRUCT_* calleeHnd) { MethodDesc callerMethod = HandleToObject(callerHnd); From 98952fcf1328cbfae13948dd7e617b5029bd6187 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 18 Jan 2024 20:52:31 +0100 Subject: [PATCH 10/23] Fix EE_TO_JIT transition --- src/coreclr/vm/jitinterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index e1ab5d2362002c..de70b4ed21628e 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -7844,7 +7844,7 @@ CORINFO_CLASS_HANDLE CEEInfo::getTypeDefinition(CORINFO_CLASS_HANDLE type) result = CORINFO_CLASS_HANDLE(definitionHandle.AsPtr()); - JIT_TO_EE_TRANSITION(); + EE_TO_JIT_TRANSITION(); _ASSERTE(result != NULL); From f65d626a96b51044884213f87f11d729c867b698 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Mon, 11 Mar 2024 15:12:04 -0700 Subject: [PATCH 11/23] Implement missing superPMI methods --- .../tools/superpmi/superpmi-shared/lwmlist.h | 1 + .../superpmi-shared/methodcontext.cpp | 23 +++++++++++++++++++ .../superpmi/superpmi-shared/methodcontext.h | 5 ++++ .../superpmi-shim-collector/icorjitinfo.cpp | 9 ++++++++ .../tools/superpmi/superpmi/icorjitinfo.cpp | 8 +++++++ 5 files changed, 46 insertions(+) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h index eb4968fbb44880..236bb4181ce5c3 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -110,6 +110,7 @@ LWM(GetMethodDefFromMethod, DWORDLONG, DWORD) LWM(GetMethodHash, DWORDLONG, DWORD) LWM(GetMethodInfo, DLDL, Agnostic_GetMethodInfo) LWM(HaveSameMethodDefinition, DLDL, DWORD) +LWM(GetTypeDefinition, DWORDLONG, DWORDLONG) LWM(GetMethodNameFromMetadata, Agnostic_CORINFO_METHODNAME_TOKENin, Agnostic_CORINFO_METHODNAME_TOKENout) LWM(GetMethodSig, DLDL, Agnostic_CORINFO_SIG_INFO) LWM(GetMethodSync, DWORDLONG, DLDL) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index e818afbac539c9..066a6fac585bb6 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -3094,6 +3094,29 @@ bool MethodContext::repHaveSameMethodDefinition(CORINFO_METHOD_HANDLE methHnd1, return value != 0; } +void MethodContext::recGetTypeDefinition(CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE result) +{ + if (GetTypeDefinition == nullptr) + GetTypeDefinition = new LightWeightMap(); + + DWORDLONG key = CastHandle(cls); + DWORDLONG value = CastHandle(result); + GetTypeDefinition->Add(key, value); + DEBUG_REC(dmpGetTypeDefinition(key, value)); +} +void MethodContext::dmpGetTypeDefinition(DWORDLONG key, DWORDLONG value) +{ + printf("GetTypeDefinition key cls-%016" PRIX64 ", value cls-%016" PRIX64 "", key, value); +} +CORINFO_CLASS_HANDLE MethodContext::repGetTypeDefinition(CORINFO_CLASS_HANDLE cls) +{ + DWORDLONG key = CastHandle(cls); + DWORDLONG value = LookupByKeyOrMiss(GetTypeDefinition, key, ": key %016" PRIX64 "", key); + DEBUG_REP(dmpGetTypeDefinition(key, value)); + CORINFO_CLASS_HANDLE result = (CORINFO_CLASS_HANDLE)value; + return result; +} + void MethodContext::recGetNewHelper(CORINFO_CLASS_HANDLE classHandle, bool hasSideEffects, CorInfoHelpFunc result, diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index 669455c729939f..408203e64c9106 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -422,6 +422,10 @@ class MethodContext void dmpHaveSameMethodDefinition(const DLDL& key, DWORD value); bool repHaveSameMethodDefinition(CORINFO_METHOD_HANDLE methHnd1, CORINFO_METHOD_HANDLE methHnd2); + void recGetTypeDefinition(CORINFO_CLASS_HANDLE type, CORINFO_CLASS_HANDLE result); + void dmpGetTypeDefinition(DWORDLONG key, DWORDLONG value); + CORINFO_CLASS_HANDLE repGetTypeDefinition(CORINFO_CLASS_HANDLE type); + void recGetNewHelper(CORINFO_CLASS_HANDLE classHandle, bool hasSideEffects, CorInfoHelpFunc result, @@ -1185,6 +1189,7 @@ enum mcPackets Packet_GetClassThreadStaticDynamicInfo = 219, Packet_IsGenericType = 220, Packet_GetTypeForBoxOnStack = 221, + Packet_GetTypeDefinition = 222, }; void SetDebugDumpVariables(); diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index 77def3e6276ae5..24495dbaa17346 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -107,6 +107,15 @@ bool interceptor_ICJI::haveSameMethodDefinition( return result; } +CORINFO_CLASS_HANDLE interceptor_ICJI::getTypeDefinition( + CORINFO_CLASS_HANDLE type) +{ + CORINFO_CLASS_HANDLE result = original_ICorJitInfo->getTypeDefinition(type); + mc->recGetTypeDefinition(type, result); + + return result; +} + // Decides if you have any limitations for inlining. If everything's OK, it will return // INLINE_PASS. // diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index 1ec06bedca508e..370d99ecad912a 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -96,6 +96,14 @@ bool MyICJI::haveSameMethodDefinition( return value; } +CORINFO_CLASS_HANDLE MyICJI::getTypeDefinition( + CORINFO_CLASS_HANDLE type) +{ + jitInstance->mc->cr->AddCall("getTypeDefinition"); + CORINFO_CLASS_HANDLE value = jitInstance->mc->repGetTypeDefinition(type); + return value; +} + // Decides if you have any limitations for inlining. If everything's OK, it will return // INLINE_PASS. // From cfad15d453e51dfa6320ba6e69a01908621b7b67 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 16 Jun 2024 12:32:54 -0700 Subject: [PATCH 12/23] Remove extra blank line --- src/coreclr/jit/importer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 62ac1abffce0cf..e35bdcb8029f2b 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -2490,7 +2490,6 @@ GenTree* Compiler::impTypeIsAssignable(GenTree* typeTo, GenTree* typeFrom) return nullptr; } - GenTree* Compiler::impGetGenericTypeDefinition(GenTree* type) { // This intrinsic requires the first arg to be some `typeof()` expression, From f3b54026312ea3ca239e5bae22973805cbf8603d Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 16 Jun 2024 13:52:56 -0700 Subject: [PATCH 13/23] Add missing handle -> 'Type' conversion --- src/coreclr/jit/importer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index e35bdcb8029f2b..def691cc4e850e 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -2504,7 +2504,8 @@ GenTree* Compiler::impGetGenericTypeDefinition(GenTree* type) { CORINFO_CLASS_HANDLE hClassResult = info.compCompHnd->getTypeDefinition(hClassType); - GenTree* retNode = gtNewIconEmbClsHndNode(hClassResult); + GenTree* handle = gtNewIconEmbClsHndNode(hClassResult); + GenTree* retNode = gtNewHelperCallNode(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE, TYP_REF, handle); // Drop the typeof(T) node impPopStack(); From b44805d395e2e5bb85551179798646fef60e6595 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 16 Jun 2024 19:37:36 -0700 Subject: [PATCH 14/23] Add '__Canon' tests as well --- src/tests/JIT/Intrinsics/TypeIntrinsics.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/tests/JIT/Intrinsics/TypeIntrinsics.cs b/src/tests/JIT/Intrinsics/TypeIntrinsics.cs index 1376d8b020d416..9f58aa356b44ad 100644 --- a/src/tests/JIT/Intrinsics/TypeIntrinsics.cs +++ b/src/tests/JIT/Intrinsics/TypeIntrinsics.cs @@ -299,6 +299,15 @@ private static void GetGenericTypeDefinitionTests() AreEqual(typeof(Action).GetGenericTypeDefinition(), typeof(Action<>)); AreEqual(typeof(Func).GetGenericTypeDefinition(), typeof(Func<,>)); AreEqual(typeof(Func<,>).GetGenericTypeDefinition(), typeof(Func<,>)); + + // Test for __Canon + AreEqual(GetGenericTypeDefinition>(), typeof(GenericEnumClass<>)); + AreEqual(GetGenericTypeDefinition>(), typeof(IGenericInterface<>)); + AreEqual(GetGenericTypeDefinition>(), typeof(GenericStruct<>)); + AreEqual(GetGenericTypeDefinition>(), typeof(Dictionary<,>)); + AreEqual(GetGenericTypeDefinition>(), typeof(List<>)); + AreEqual(GetGenericTypeDefinition>(), typeof(Action<>)); + AreEqual(GetGenericTypeDefinition>(), typeof(Func<,>)); } private static int _varInt = 42; @@ -334,6 +343,9 @@ private static void GetGenericTypeDefinitionTests() [MethodImpl(MethodImplOptions.NoInlining)] private static dynamic CreateDynamic2() => new { Name = "Test" }; + [MethodImpl(MethodImplOptions.NoInlining)] + private static Type GetGenericTypeDefinition() => typeof(T).GetGenericTypeDefinition(); + [MethodImpl(MethodImplOptions.NoInlining)] static void IsTrue(bool expression, [CallerLineNumber] int line = 0, [CallerFilePath] string file = "") { From 447f949d1516a8a508b30927e2f6532616720767 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sun, 16 Jun 2024 19:41:03 -0700 Subject: [PATCH 15/23] Add tests for failure cases as well --- src/tests/JIT/Intrinsics/TypeIntrinsics.cs | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/tests/JIT/Intrinsics/TypeIntrinsics.cs b/src/tests/JIT/Intrinsics/TypeIntrinsics.cs index 9f58aa356b44ad..1418f7328e1b20 100644 --- a/src/tests/JIT/Intrinsics/TypeIntrinsics.cs +++ b/src/tests/JIT/Intrinsics/TypeIntrinsics.cs @@ -308,6 +308,11 @@ private static void GetGenericTypeDefinitionTests() AreEqual(GetGenericTypeDefinition>(), typeof(List<>)); AreEqual(GetGenericTypeDefinition>(), typeof(Action<>)); AreEqual(GetGenericTypeDefinition>(), typeof(Func<,>)); + + // Test for failures + GetGenericTypeDefinitionThrows(); + GetGenericTypeDefinitionThrows(); + GetGenericTypeDefinitionThrows(); } private static int _varInt = 42; @@ -346,6 +351,27 @@ private static void GetGenericTypeDefinitionTests() [MethodImpl(MethodImplOptions.NoInlining)] private static Type GetGenericTypeDefinition() => typeof(T).GetGenericTypeDefinition(); + [MethodImpl(MethodImplOptions.NoInlining)] + private static void GetGenericTypeDefinitionThrows([CallerLineNumber] int line = 0, [CallerFilePath] string file = "") + { + bool success = false; + + try + { + _ = typeof(T).GetGenericTypeDefinition(); + } + catch (InvalidOperationException) + { + success = true; + } + + if (!success) + { + Console.WriteLine($"{file}:L{line} test failed (expected: 'InvalidOperationException')."); + _errors++; + } + } + [MethodImpl(MethodImplOptions.NoInlining)] static void IsTrue(bool expression, [CallerLineNumber] int line = 0, [CallerFilePath] string file = "") { From 1ccc84f1bc53c8e8137ec8dd3daea09f1f51839d Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 10 Jul 2024 00:02:34 -0700 Subject: [PATCH 16/23] Run ThunkGenerator again --- .../Common/JitInterface/CorInfoImpl_generated.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index b5adbf01d25a96..763f4bb0e4fd87 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -115,6 +115,21 @@ private static byte _haveSameMethodDefinition(IntPtr thisHandle, IntPtr* ppExcep } } + [UnmanagedCallersOnly] + private static CORINFO_CLASS_STRUCT_* _getTypeDefinition(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* type) + { + var _this = GetThis(thisHandle); + try + { + return _this.getTypeDefinition(type); + } + catch (Exception ex) + { + *ppException = _this.AllocException(ex); + return default; + } + } + [UnmanagedCallersOnly] private static CorInfoInline _canInline(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* callerHnd, CORINFO_METHOD_STRUCT_* calleeHnd) { From 7175c3a11e6cee63698ac3d6489848178cf9dee5 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 10 Jul 2024 22:40:00 -0700 Subject: [PATCH 17/23] Add docs for 'impGetGenericTypeDefinition' --- src/coreclr/jit/importer.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index def691cc4e850e..85682710ea1992 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -2490,6 +2490,15 @@ GenTree* Compiler::impTypeIsAssignable(GenTree* typeTo, GenTree* typeFrom) return nullptr; } +//------------------------------------------------------------------------ +// impGetGenericTypeDefinition: gets the generic type definition from a 'typeof' expression. +// +// Arguments: +// type - The 'GenTree' node to inspect. +// +// Notes: +// If successful, this method will call 'impPopStack()' before returning. +// GenTree* Compiler::impGetGenericTypeDefinition(GenTree* type) { // This intrinsic requires the first arg to be some `typeof()` expression, From ae66298c3bd09db74fdb357ccd4c17c3d9f56820 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 10 Jul 2024 22:49:20 -0700 Subject: [PATCH 18/23] Add assert in 'getTypeDefinition' --- src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 0033a758669307..0078196d2eab51 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -1250,6 +1250,8 @@ private bool haveSameMethodDefinition(CORINFO_METHOD_STRUCT_* methHnd1, CORINFO_ private CORINFO_CLASS_STRUCT_* getTypeDefinition(CORINFO_CLASS_STRUCT_* type) { + Debug.Assert(HandleToObject(type).HasInstantiation); + return ObjectToHandle(HandleToObject(type).GetTypeDefinition()); } From 9a2aa1ecd0f22b35a9361654abce0da8ff300f26 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 11 Jul 2024 15:38:37 -0700 Subject: [PATCH 19/23] Remove assert Co-authored-by: Jan Kotas --- src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 0078196d2eab51..0033a758669307 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -1250,8 +1250,6 @@ private bool haveSameMethodDefinition(CORINFO_METHOD_STRUCT_* methHnd1, CORINFO_ private CORINFO_CLASS_STRUCT_* getTypeDefinition(CORINFO_CLASS_STRUCT_* type) { - Debug.Assert(HandleToObject(type).HasInstantiation); - return ObjectToHandle(HandleToObject(type).GetTypeDefinition()); } From a2eb42e239aa772beddb22c2ddc3dad794a94d38 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 11 Jul 2024 15:39:31 -0700 Subject: [PATCH 20/23] Allow non instantiated generics in new JIT interface method Co-authored-by: Jan Kotas --- src/coreclr/vm/jitinterface.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index de70b4ed21628e..0fd02e1cbf5e33 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -7832,17 +7832,20 @@ CORINFO_CLASS_HANDLE CEEInfo::getTypeDefinition(CORINFO_CLASS_HANDLE type) JIT_TO_EE_TRANSITION(); - TypeHandle constructedHandle(type); + TypeHandle th(type); - _ASSERTE(constructedHandle.HasInstantiation()); + if (th.IsTypicalTypeDefinition()) + { + th = ClassLoader::LoadTypeDefThrowing( + th.GetModule(), + th.GetMethodTable()->GetCl(), + ClassLoader::ThrowIfNotFound, + ClassLoader::PermitUninstDefOrRef); - TypeHandle definitionHandle = ClassLoader::LoadTypeDefThrowing( - constructedHandle.GetModule(), - constructedHandle.GetMethodTable()->GetCl(), - ClassLoader::ThrowIfNotFound, - ClassLoader::PermitUninstDefOrRef); + _ASSERTE(th.IsTypicalTypeDefinition()); + } - result = CORINFO_CLASS_HANDLE(definitionHandle.AsPtr()); + result = CORINFO_CLASS_HANDLE(th.AsPtr()); EE_TO_JIT_TRANSITION(); From a2a8d60634eb1c89748d7ee5adf04e4da5457411 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Tue, 16 Jul 2024 14:11:40 -0700 Subject: [PATCH 21/23] Update docs for 'getTypeDefinition' --- src/coreclr/inc/corinfo.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 17891090e4c811..7333b15c7d5df6 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -2093,7 +2093,8 @@ class ICorStaticInfo // // Remarks: // This is equivalent of Type.GetGenericTypeDefinition(). Given a generic type handle, it will - // return the original type definition (eg. for Foo it will return Foo<>). This method + // return the original type definition (eg. for Foo it will return Foo<>). If called with + // an unconstructed generic type, the method returns the same type as the input. This method // should only be called when the input type is in fact a generic type. virtual CORINFO_CLASS_HANDLE getTypeDefinition(CORINFO_CLASS_HANDLE type) = 0; From 89319d7deac6b3ed032ea0fcd4214f50659d8f7c Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 17 Jul 2024 10:40:58 -0700 Subject: [PATCH 22/23] Tweak condition in 'CEEInfo::getTypeDefinition' --- src/coreclr/vm/jitinterface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 0fd02e1cbf5e33..a1609b03b0e866 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -7834,7 +7834,7 @@ CORINFO_CLASS_HANDLE CEEInfo::getTypeDefinition(CORINFO_CLASS_HANDLE type) TypeHandle th(type); - if (th.IsTypicalTypeDefinition()) + if (th.HasInstantiation() && !th.IsGenericTypeDefinition()) { th = ClassLoader::LoadTypeDefThrowing( th.GetModule(), @@ -7842,7 +7842,7 @@ CORINFO_CLASS_HANDLE CEEInfo::getTypeDefinition(CORINFO_CLASS_HANDLE type) ClassLoader::ThrowIfNotFound, ClassLoader::PermitUninstDefOrRef); - _ASSERTE(th.IsTypicalTypeDefinition()); + _ASSERTE(th.IsGenericTypeDefinition()); } result = CORINFO_CLASS_HANDLE(th.AsPtr()); From 4cbe7f301f2a3917c274c9ccc923cd302fd93f54 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 18 Jul 2024 15:14:47 -0700 Subject: [PATCH 23/23] Run ThunkGenerator again --- src/coreclr/inc/jiteeversionguid.h | 10 +- .../JitInterface/CorInfoImpl_generated.cs | 341 +++++++++--------- 2 files changed, 176 insertions(+), 175 deletions(-) diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index cc3976dbfc203e..ff075893ec7826 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* 64fe30fb-0a27-4b1d-b89e-306e552ac848 */ - 0x64fe30fb, - 0x0a27, - 0x4b1d, - {0xb8, 0x9e, 0x30, 0x6e, 0x55, 0x2a, 0xc8, 0x48} +constexpr GUID JITEEVersionIdentifier = { /* 273ba350-32bf-4714-beb0-7fa46c11364d */ + 0x273ba350, + 0x32bf, + 0x4714, + {0xbe, 0xb0, 0x7f, 0xa4, 0x6c, 0x11, 0x36, 0x4d} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index 763f4bb0e4fd87..62014eb27bfa16 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -2624,7 +2624,7 @@ private static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, CORJIT_ private static IntPtr GetUnmanagedCallbacks() { - void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 176); + void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 177); callbacks[0] = (delegate* unmanaged)&_isIntrinsic; callbacks[1] = (delegate* unmanaged)&_notifyMethodInfoUsage; @@ -2633,175 +2633,176 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[4] = (delegate* unmanaged)&_getMethodSig; callbacks[5] = (delegate* unmanaged)&_getMethodInfo; callbacks[6] = (delegate* unmanaged)&_haveSameMethodDefinition; - callbacks[7] = (delegate* unmanaged)&_canInline; - callbacks[8] = (delegate* unmanaged)&_beginInlining; - callbacks[9] = (delegate* unmanaged)&_reportInliningDecision; - callbacks[10] = (delegate* unmanaged)&_canTailCall; - callbacks[11] = (delegate* unmanaged)&_reportTailCallDecision; - callbacks[12] = (delegate* unmanaged)&_getEHinfo; - callbacks[13] = (delegate* unmanaged)&_getMethodClass; - callbacks[14] = (delegate* unmanaged)&_getMethodVTableOffset; - callbacks[15] = (delegate* unmanaged)&_resolveVirtualMethod; - callbacks[16] = (delegate* unmanaged)&_getUnboxedEntry; - callbacks[17] = (delegate* unmanaged)&_getDefaultComparerClass; - callbacks[18] = (delegate* unmanaged)&_getDefaultEqualityComparerClass; - callbacks[19] = (delegate* unmanaged)&_expandRawHandleIntrinsic; - callbacks[20] = (delegate* unmanaged)&_isIntrinsicType; - callbacks[21] = (delegate* unmanaged)&_getUnmanagedCallConv; - callbacks[22] = (delegate* unmanaged)&_pInvokeMarshalingRequired; - callbacks[23] = (delegate* unmanaged)&_satisfiesMethodConstraints; - callbacks[24] = (delegate* unmanaged)&_methodMustBeLoadedBeforeCodeIsRun; - callbacks[25] = (delegate* unmanaged)&_getGSCookie; - callbacks[26] = (delegate* unmanaged)&_setPatchpointInfo; - callbacks[27] = (delegate* unmanaged)&_getOSRInfo; - callbacks[28] = (delegate* unmanaged)&_resolveToken; - callbacks[29] = (delegate* unmanaged)&_findSig; - callbacks[30] = (delegate* unmanaged)&_findCallSiteSig; - callbacks[31] = (delegate* unmanaged)&_getTokenTypeAsHandle; - callbacks[32] = (delegate* unmanaged)&_getStringLiteral; - callbacks[33] = (delegate* unmanaged)&_printObjectDescription; - callbacks[34] = (delegate* unmanaged)&_asCorInfoType; - callbacks[35] = (delegate* unmanaged)&_getClassNameFromMetadata; - callbacks[36] = (delegate* unmanaged)&_getTypeInstantiationArgument; - callbacks[37] = (delegate* unmanaged)&_printClassName; - callbacks[38] = (delegate* unmanaged)&_isValueClass; - callbacks[39] = (delegate* unmanaged)&_getClassAttribs; - callbacks[40] = (delegate* unmanaged)&_getClassModule; - callbacks[41] = (delegate* unmanaged)&_getModuleAssembly; - callbacks[42] = (delegate* unmanaged)&_getAssemblyName; - callbacks[43] = (delegate* unmanaged)&_LongLifetimeMalloc; - callbacks[44] = (delegate* unmanaged)&_LongLifetimeFree; - callbacks[45] = (delegate* unmanaged)&_getIsClassInitedFlagAddress; - callbacks[46] = (delegate* unmanaged)&_getClassThreadStaticDynamicInfo; - callbacks[47] = (delegate* unmanaged)&_getClassStaticDynamicInfo; - callbacks[48] = (delegate* unmanaged)&_getStaticBaseAddress; - callbacks[49] = (delegate* unmanaged)&_getClassSize; - callbacks[50] = (delegate* unmanaged)&_getHeapClassSize; - callbacks[51] = (delegate* unmanaged)&_canAllocateOnStack; - callbacks[52] = (delegate* unmanaged)&_getClassAlignmentRequirement; - callbacks[53] = (delegate* unmanaged)&_getClassGClayout; - callbacks[54] = (delegate* unmanaged)&_getClassNumInstanceFields; - callbacks[55] = (delegate* unmanaged)&_getFieldInClass; - callbacks[56] = (delegate* unmanaged)&_getTypeLayout; - callbacks[57] = (delegate* unmanaged)&_checkMethodModifier; - callbacks[58] = (delegate* unmanaged)&_getNewHelper; - callbacks[59] = (delegate* unmanaged)&_getNewArrHelper; - callbacks[60] = (delegate* unmanaged)&_getCastingHelper; - callbacks[61] = (delegate* unmanaged)&_getSharedCCtorHelper; - callbacks[62] = (delegate* unmanaged)&_getTypeForBox; - callbacks[63] = (delegate* unmanaged)&_getTypeForBoxOnStack; - callbacks[64] = (delegate* unmanaged)&_getBoxHelper; - callbacks[65] = (delegate* unmanaged)&_getUnBoxHelper; - callbacks[66] = (delegate* unmanaged)&_getRuntimeTypePointer; - callbacks[67] = (delegate* unmanaged)&_isObjectImmutable; - callbacks[68] = (delegate* unmanaged)&_getStringChar; - callbacks[69] = (delegate* unmanaged)&_getObjectType; - callbacks[70] = (delegate* unmanaged)&_getReadyToRunHelper; - callbacks[71] = (delegate* unmanaged)&_getReadyToRunDelegateCtorHelper; - callbacks[72] = (delegate* unmanaged)&_initClass; - callbacks[73] = (delegate* unmanaged)&_classMustBeLoadedBeforeCodeIsRun; - callbacks[74] = (delegate* unmanaged)&_getBuiltinClass; - callbacks[75] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; - callbacks[76] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; - callbacks[77] = (delegate* unmanaged)&_canCast; - callbacks[78] = (delegate* unmanaged)&_compareTypesForCast; - callbacks[79] = (delegate* unmanaged)&_compareTypesForEquality; - callbacks[80] = (delegate* unmanaged)&_isMoreSpecificType; - callbacks[81] = (delegate* unmanaged)&_isExactType; - callbacks[82] = (delegate* unmanaged)&_isGenericType; - callbacks[83] = (delegate* unmanaged)&_isNullableType; - callbacks[84] = (delegate* unmanaged)&_isEnum; - callbacks[85] = (delegate* unmanaged)&_getParentType; - callbacks[86] = (delegate* unmanaged)&_getChildType; - callbacks[87] = (delegate* unmanaged)&_isSDArray; - callbacks[88] = (delegate* unmanaged)&_getArrayRank; - callbacks[89] = (delegate* unmanaged)&_getArrayIntrinsicID; - callbacks[90] = (delegate* unmanaged)&_getArrayInitializationData; - callbacks[91] = (delegate* unmanaged)&_canAccessClass; - callbacks[92] = (delegate* unmanaged)&_printFieldName; - callbacks[93] = (delegate* unmanaged)&_getFieldClass; - callbacks[94] = (delegate* unmanaged)&_getFieldType; - callbacks[95] = (delegate* unmanaged)&_getFieldOffset; - callbacks[96] = (delegate* unmanaged)&_getFieldInfo; - callbacks[97] = (delegate* unmanaged)&_getThreadLocalFieldInfo; - callbacks[98] = (delegate* unmanaged)&_getThreadLocalStaticBlocksInfo; - callbacks[99] = (delegate* unmanaged)&_getThreadLocalStaticInfo_NativeAOT; - callbacks[100] = (delegate* unmanaged)&_isFieldStatic; - callbacks[101] = (delegate* unmanaged)&_getArrayOrStringLength; - callbacks[102] = (delegate* unmanaged)&_getBoundaries; - callbacks[103] = (delegate* unmanaged)&_setBoundaries; - callbacks[104] = (delegate* unmanaged)&_getVars; - callbacks[105] = (delegate* unmanaged)&_setVars; - callbacks[106] = (delegate* unmanaged)&_reportRichMappings; - callbacks[107] = (delegate* unmanaged)&_reportMetadata; - callbacks[108] = (delegate* unmanaged)&_allocateArray; - callbacks[109] = (delegate* unmanaged)&_freeArray; - callbacks[110] = (delegate* unmanaged)&_getArgNext; - callbacks[111] = (delegate* unmanaged)&_getArgType; - callbacks[112] = (delegate* unmanaged)&_getExactClasses; - callbacks[113] = (delegate* unmanaged)&_getArgClass; - callbacks[114] = (delegate* unmanaged)&_getHFAType; - callbacks[115] = (delegate* unmanaged)&_runWithErrorTrap; - callbacks[116] = (delegate* unmanaged)&_runWithSPMIErrorTrap; - callbacks[117] = (delegate* unmanaged)&_getEEInfo; - callbacks[118] = (delegate* unmanaged)&_getJitTimeLogFilename; - callbacks[119] = (delegate* unmanaged)&_getMethodDefFromMethod; - callbacks[120] = (delegate* unmanaged)&_printMethodName; - callbacks[121] = (delegate* unmanaged)&_getMethodNameFromMetadata; - callbacks[122] = (delegate* unmanaged)&_getMethodHash; - callbacks[123] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; - callbacks[124] = (delegate* unmanaged)&_getSwiftLowering; - callbacks[125] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; - callbacks[126] = (delegate* unmanaged)&_getRISCV64PassStructInRegisterFlags; - callbacks[127] = (delegate* unmanaged)&_getThreadTLSIndex; - callbacks[128] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; - callbacks[129] = (delegate* unmanaged)&_getHelperFtn; - callbacks[130] = (delegate* unmanaged)&_getFunctionEntryPoint; - callbacks[131] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; - callbacks[132] = (delegate* unmanaged)&_getMethodSync; - callbacks[133] = (delegate* unmanaged)&_getLazyStringLiteralHelper; - callbacks[134] = (delegate* unmanaged)&_embedModuleHandle; - callbacks[135] = (delegate* unmanaged)&_embedClassHandle; - callbacks[136] = (delegate* unmanaged)&_embedMethodHandle; - callbacks[137] = (delegate* unmanaged)&_embedFieldHandle; - callbacks[138] = (delegate* unmanaged)&_embedGenericHandle; - callbacks[139] = (delegate* unmanaged)&_getLocationOfThisType; - callbacks[140] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; - callbacks[141] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; - callbacks[142] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; - callbacks[143] = (delegate* unmanaged)&_getJustMyCodeHandle; - callbacks[144] = (delegate* unmanaged)&_GetProfilingHandle; - callbacks[145] = (delegate* unmanaged)&_getCallInfo; - callbacks[146] = (delegate* unmanaged)&_getStaticFieldContent; - callbacks[147] = (delegate* unmanaged)&_getObjectContent; - callbacks[148] = (delegate* unmanaged)&_getStaticFieldCurrentClass; - callbacks[149] = (delegate* unmanaged)&_getVarArgsHandle; - callbacks[150] = (delegate* unmanaged)&_canGetVarArgsHandle; - callbacks[151] = (delegate* unmanaged)&_constructStringLiteral; - callbacks[152] = (delegate* unmanaged)&_emptyStringLiteral; - callbacks[153] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; - callbacks[154] = (delegate* unmanaged)&_GetDelegateCtor; - callbacks[155] = (delegate* unmanaged)&_MethodCompileComplete; - callbacks[156] = (delegate* unmanaged)&_getTailCallHelpers; - callbacks[157] = (delegate* unmanaged)&_convertPInvokeCalliToCall; - callbacks[158] = (delegate* unmanaged)&_notifyInstructionSetUsage; - callbacks[159] = (delegate* unmanaged)&_updateEntryPointForTailCall; - callbacks[160] = (delegate* unmanaged)&_allocMem; - callbacks[161] = (delegate* unmanaged)&_reserveUnwindInfo; - callbacks[162] = (delegate* unmanaged)&_allocUnwindInfo; - callbacks[163] = (delegate* unmanaged)&_allocGCInfo; - callbacks[164] = (delegate* unmanaged)&_setEHcount; - callbacks[165] = (delegate* unmanaged)&_setEHinfo; - callbacks[166] = (delegate* unmanaged)&_logMsg; - callbacks[167] = (delegate* unmanaged)&_doAssert; - callbacks[168] = (delegate* unmanaged)&_reportFatalError; - callbacks[169] = (delegate* unmanaged)&_getPgoInstrumentationResults; - callbacks[170] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; - callbacks[171] = (delegate* unmanaged)&_recordCallSite; - callbacks[172] = (delegate* unmanaged)&_recordRelocation; - callbacks[173] = (delegate* unmanaged)&_getRelocTypeHint; - callbacks[174] = (delegate* unmanaged)&_getExpectedTargetArchitecture; - callbacks[175] = (delegate* unmanaged)&_getJitFlags; + callbacks[7] = (delegate* unmanaged)&_getTypeDefinition; + callbacks[8] = (delegate* unmanaged)&_canInline; + callbacks[9] = (delegate* unmanaged)&_beginInlining; + callbacks[10] = (delegate* unmanaged)&_reportInliningDecision; + callbacks[11] = (delegate* unmanaged)&_canTailCall; + callbacks[12] = (delegate* unmanaged)&_reportTailCallDecision; + callbacks[13] = (delegate* unmanaged)&_getEHinfo; + callbacks[14] = (delegate* unmanaged)&_getMethodClass; + callbacks[15] = (delegate* unmanaged)&_getMethodVTableOffset; + callbacks[16] = (delegate* unmanaged)&_resolveVirtualMethod; + callbacks[17] = (delegate* unmanaged)&_getUnboxedEntry; + callbacks[18] = (delegate* unmanaged)&_getDefaultComparerClass; + callbacks[19] = (delegate* unmanaged)&_getDefaultEqualityComparerClass; + callbacks[20] = (delegate* unmanaged)&_expandRawHandleIntrinsic; + callbacks[21] = (delegate* unmanaged)&_isIntrinsicType; + callbacks[22] = (delegate* unmanaged)&_getUnmanagedCallConv; + callbacks[23] = (delegate* unmanaged)&_pInvokeMarshalingRequired; + callbacks[24] = (delegate* unmanaged)&_satisfiesMethodConstraints; + callbacks[25] = (delegate* unmanaged)&_methodMustBeLoadedBeforeCodeIsRun; + callbacks[26] = (delegate* unmanaged)&_getGSCookie; + callbacks[27] = (delegate* unmanaged)&_setPatchpointInfo; + callbacks[28] = (delegate* unmanaged)&_getOSRInfo; + callbacks[29] = (delegate* unmanaged)&_resolveToken; + callbacks[30] = (delegate* unmanaged)&_findSig; + callbacks[31] = (delegate* unmanaged)&_findCallSiteSig; + callbacks[32] = (delegate* unmanaged)&_getTokenTypeAsHandle; + callbacks[33] = (delegate* unmanaged)&_getStringLiteral; + callbacks[34] = (delegate* unmanaged)&_printObjectDescription; + callbacks[35] = (delegate* unmanaged)&_asCorInfoType; + callbacks[36] = (delegate* unmanaged)&_getClassNameFromMetadata; + callbacks[37] = (delegate* unmanaged)&_getTypeInstantiationArgument; + callbacks[38] = (delegate* unmanaged)&_printClassName; + callbacks[39] = (delegate* unmanaged)&_isValueClass; + callbacks[40] = (delegate* unmanaged)&_getClassAttribs; + callbacks[41] = (delegate* unmanaged)&_getClassModule; + callbacks[42] = (delegate* unmanaged)&_getModuleAssembly; + callbacks[43] = (delegate* unmanaged)&_getAssemblyName; + callbacks[44] = (delegate* unmanaged)&_LongLifetimeMalloc; + callbacks[45] = (delegate* unmanaged)&_LongLifetimeFree; + callbacks[46] = (delegate* unmanaged)&_getIsClassInitedFlagAddress; + callbacks[47] = (delegate* unmanaged)&_getClassThreadStaticDynamicInfo; + callbacks[48] = (delegate* unmanaged)&_getClassStaticDynamicInfo; + callbacks[49] = (delegate* unmanaged)&_getStaticBaseAddress; + callbacks[50] = (delegate* unmanaged)&_getClassSize; + callbacks[51] = (delegate* unmanaged)&_getHeapClassSize; + callbacks[52] = (delegate* unmanaged)&_canAllocateOnStack; + callbacks[53] = (delegate* unmanaged)&_getClassAlignmentRequirement; + callbacks[54] = (delegate* unmanaged)&_getClassGClayout; + callbacks[55] = (delegate* unmanaged)&_getClassNumInstanceFields; + callbacks[56] = (delegate* unmanaged)&_getFieldInClass; + callbacks[57] = (delegate* unmanaged)&_getTypeLayout; + callbacks[58] = (delegate* unmanaged)&_checkMethodModifier; + callbacks[59] = (delegate* unmanaged)&_getNewHelper; + callbacks[60] = (delegate* unmanaged)&_getNewArrHelper; + callbacks[61] = (delegate* unmanaged)&_getCastingHelper; + callbacks[62] = (delegate* unmanaged)&_getSharedCCtorHelper; + callbacks[63] = (delegate* unmanaged)&_getTypeForBox; + callbacks[64] = (delegate* unmanaged)&_getTypeForBoxOnStack; + callbacks[65] = (delegate* unmanaged)&_getBoxHelper; + callbacks[66] = (delegate* unmanaged)&_getUnBoxHelper; + callbacks[67] = (delegate* unmanaged)&_getRuntimeTypePointer; + callbacks[68] = (delegate* unmanaged)&_isObjectImmutable; + callbacks[69] = (delegate* unmanaged)&_getStringChar; + callbacks[70] = (delegate* unmanaged)&_getObjectType; + callbacks[71] = (delegate* unmanaged)&_getReadyToRunHelper; + callbacks[72] = (delegate* unmanaged)&_getReadyToRunDelegateCtorHelper; + callbacks[73] = (delegate* unmanaged)&_initClass; + callbacks[74] = (delegate* unmanaged)&_classMustBeLoadedBeforeCodeIsRun; + callbacks[75] = (delegate* unmanaged)&_getBuiltinClass; + callbacks[76] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; + callbacks[77] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; + callbacks[78] = (delegate* unmanaged)&_canCast; + callbacks[79] = (delegate* unmanaged)&_compareTypesForCast; + callbacks[80] = (delegate* unmanaged)&_compareTypesForEquality; + callbacks[81] = (delegate* unmanaged)&_isMoreSpecificType; + callbacks[82] = (delegate* unmanaged)&_isExactType; + callbacks[83] = (delegate* unmanaged)&_isGenericType; + callbacks[84] = (delegate* unmanaged)&_isNullableType; + callbacks[85] = (delegate* unmanaged)&_isEnum; + callbacks[86] = (delegate* unmanaged)&_getParentType; + callbacks[87] = (delegate* unmanaged)&_getChildType; + callbacks[88] = (delegate* unmanaged)&_isSDArray; + callbacks[89] = (delegate* unmanaged)&_getArrayRank; + callbacks[90] = (delegate* unmanaged)&_getArrayIntrinsicID; + callbacks[91] = (delegate* unmanaged)&_getArrayInitializationData; + callbacks[92] = (delegate* unmanaged)&_canAccessClass; + callbacks[93] = (delegate* unmanaged)&_printFieldName; + callbacks[94] = (delegate* unmanaged)&_getFieldClass; + callbacks[95] = (delegate* unmanaged)&_getFieldType; + callbacks[96] = (delegate* unmanaged)&_getFieldOffset; + callbacks[97] = (delegate* unmanaged)&_getFieldInfo; + callbacks[98] = (delegate* unmanaged)&_getThreadLocalFieldInfo; + callbacks[99] = (delegate* unmanaged)&_getThreadLocalStaticBlocksInfo; + callbacks[100] = (delegate* unmanaged)&_getThreadLocalStaticInfo_NativeAOT; + callbacks[101] = (delegate* unmanaged)&_isFieldStatic; + callbacks[102] = (delegate* unmanaged)&_getArrayOrStringLength; + callbacks[103] = (delegate* unmanaged)&_getBoundaries; + callbacks[104] = (delegate* unmanaged)&_setBoundaries; + callbacks[105] = (delegate* unmanaged)&_getVars; + callbacks[106] = (delegate* unmanaged)&_setVars; + callbacks[107] = (delegate* unmanaged)&_reportRichMappings; + callbacks[108] = (delegate* unmanaged)&_reportMetadata; + callbacks[109] = (delegate* unmanaged)&_allocateArray; + callbacks[110] = (delegate* unmanaged)&_freeArray; + callbacks[111] = (delegate* unmanaged)&_getArgNext; + callbacks[112] = (delegate* unmanaged)&_getArgType; + callbacks[113] = (delegate* unmanaged)&_getExactClasses; + callbacks[114] = (delegate* unmanaged)&_getArgClass; + callbacks[115] = (delegate* unmanaged)&_getHFAType; + callbacks[116] = (delegate* unmanaged)&_runWithErrorTrap; + callbacks[117] = (delegate* unmanaged)&_runWithSPMIErrorTrap; + callbacks[118] = (delegate* unmanaged)&_getEEInfo; + callbacks[119] = (delegate* unmanaged)&_getJitTimeLogFilename; + callbacks[120] = (delegate* unmanaged)&_getMethodDefFromMethod; + callbacks[121] = (delegate* unmanaged)&_printMethodName; + callbacks[122] = (delegate* unmanaged)&_getMethodNameFromMetadata; + callbacks[123] = (delegate* unmanaged)&_getMethodHash; + callbacks[124] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; + callbacks[125] = (delegate* unmanaged)&_getSwiftLowering; + callbacks[126] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; + callbacks[127] = (delegate* unmanaged)&_getRISCV64PassStructInRegisterFlags; + callbacks[128] = (delegate* unmanaged)&_getThreadTLSIndex; + callbacks[129] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; + callbacks[130] = (delegate* unmanaged)&_getHelperFtn; + callbacks[131] = (delegate* unmanaged)&_getFunctionEntryPoint; + callbacks[132] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; + callbacks[133] = (delegate* unmanaged)&_getMethodSync; + callbacks[134] = (delegate* unmanaged)&_getLazyStringLiteralHelper; + callbacks[135] = (delegate* unmanaged)&_embedModuleHandle; + callbacks[136] = (delegate* unmanaged)&_embedClassHandle; + callbacks[137] = (delegate* unmanaged)&_embedMethodHandle; + callbacks[138] = (delegate* unmanaged)&_embedFieldHandle; + callbacks[139] = (delegate* unmanaged)&_embedGenericHandle; + callbacks[140] = (delegate* unmanaged)&_getLocationOfThisType; + callbacks[141] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; + callbacks[142] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; + callbacks[143] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; + callbacks[144] = (delegate* unmanaged)&_getJustMyCodeHandle; + callbacks[145] = (delegate* unmanaged)&_GetProfilingHandle; + callbacks[146] = (delegate* unmanaged)&_getCallInfo; + callbacks[147] = (delegate* unmanaged)&_getStaticFieldContent; + callbacks[148] = (delegate* unmanaged)&_getObjectContent; + callbacks[149] = (delegate* unmanaged)&_getStaticFieldCurrentClass; + callbacks[150] = (delegate* unmanaged)&_getVarArgsHandle; + callbacks[151] = (delegate* unmanaged)&_canGetVarArgsHandle; + callbacks[152] = (delegate* unmanaged)&_constructStringLiteral; + callbacks[153] = (delegate* unmanaged)&_emptyStringLiteral; + callbacks[154] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; + callbacks[155] = (delegate* unmanaged)&_GetDelegateCtor; + callbacks[156] = (delegate* unmanaged)&_MethodCompileComplete; + callbacks[157] = (delegate* unmanaged)&_getTailCallHelpers; + callbacks[158] = (delegate* unmanaged)&_convertPInvokeCalliToCall; + callbacks[159] = (delegate* unmanaged)&_notifyInstructionSetUsage; + callbacks[160] = (delegate* unmanaged)&_updateEntryPointForTailCall; + callbacks[161] = (delegate* unmanaged)&_allocMem; + callbacks[162] = (delegate* unmanaged)&_reserveUnwindInfo; + callbacks[163] = (delegate* unmanaged)&_allocUnwindInfo; + callbacks[164] = (delegate* unmanaged)&_allocGCInfo; + callbacks[165] = (delegate* unmanaged)&_setEHcount; + callbacks[166] = (delegate* unmanaged)&_setEHinfo; + callbacks[167] = (delegate* unmanaged)&_logMsg; + callbacks[168] = (delegate* unmanaged)&_doAssert; + callbacks[169] = (delegate* unmanaged)&_reportFatalError; + callbacks[170] = (delegate* unmanaged)&_getPgoInstrumentationResults; + callbacks[171] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; + callbacks[172] = (delegate* unmanaged)&_recordCallSite; + callbacks[173] = (delegate* unmanaged)&_recordRelocation; + callbacks[174] = (delegate* unmanaged)&_getRelocTypeHint; + callbacks[175] = (delegate* unmanaged)&_getExpectedTargetArchitecture; + callbacks[176] = (delegate* unmanaged)&_getJitFlags; return (IntPtr)callbacks; }