diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index e273ca5f2698b..7333b15c7d5df 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -2082,6 +2082,22 @@ 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 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; + // 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 f396963d68ba9..fc415320cad83 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/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index cc3976dbfc203..ff075893ec782 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/jit/ICorJitInfo_names_generated.h b/src/coreclr/jit/ICorJitInfo_names_generated.h index f7c218d90d029..d6526b94ee9ee 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 5b044f211e8dc..3410d97d1fc56 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/jit/compiler.h b/src/coreclr/jit/compiler.h index 7013184028a87..ce8cfe9f57f0d 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 f2c0f458c1050..a2ef25e6a5f97 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 ad0c4d2b90281..85682710ea199 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -2490,6 +2490,42 @@ 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, + // ie. it applies to cases such as `typeof(...).GetGenericTypeDefinition()`. + CORINFO_CLASS_HANDLE hClassType = NO_CLASS_HANDLE; + if (gtIsTypeof(type, &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* handle = gtNewIconEmbClsHndNode(hClassResult); + GenTree* retNode = gtNewHelperCallNode(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE, TYP_REF, handle); + + // 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 322ce25ca96f8..e8de998ebed2c 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 93e4ce7893f98..c4e8ceeee4d5a 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/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 27a55a6414910..0033a75866930 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); diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index b5adbf01d25a9..62014eb27bfa1 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) { @@ -2609,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; @@ -2618,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; } diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index ae10f997204ca..1ddf962175b02 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 8c9a4786ea3d5..74f884b3afa9e 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-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h index eb4968fbb4488..236bb4181ce5c 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 e818afbac539c..066a6fac585bb 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 669455c729939..408203e64c910 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 77def3e6276ae..24495dbaa1734 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-shim-counter/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp index 61b210ca3c09a..332c9d13d0a63 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 840291e26701a..989c587d47d89 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) diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index 1ec06bedca508..370d99ecad912 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. // diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 3b8c32e20fcd5..a1609b03b0e86 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -7820,6 +7820,40 @@ 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 th(type); + + if (th.HasInstantiation() && !th.IsGenericTypeDefinition()) + { + th = ClassLoader::LoadTypeDefThrowing( + th.GetModule(), + th.GetMethodTable()->GetCl(), + ClassLoader::ThrowIfNotFound, + ClassLoader::PermitUninstDefOrRef); + + _ASSERTE(th.IsGenericTypeDefinition()); + } + + result = CORINFO_CLASS_HANDLE(th.AsPtr()); + + EE_TO_JIT_TRANSITION(); + + _ASSERTE(result != NULL); + + return result; +} + /************************************************************* * Check if the caller and calle are in the same assembly * i.e. do not inline across assemblies diff --git a/src/libraries/System.Private.CoreLib/src/System/Type.cs b/src/libraries/System.Private.CoreLib/src/System/Type.cs index 6c9185193dabf..3437d8f377bd4 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); diff --git a/src/tests/JIT/Intrinsics/TypeIntrinsics.cs b/src/tests/JIT/Intrinsics/TypeIntrinsics.cs index 3821f74bf1876..1418f7328e1b2 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,44 @@ 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<,>)); + + // 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<,>)); + + // Test for failures + GetGenericTypeDefinitionThrows(); + GetGenericTypeDefinitionThrows(); + GetGenericTypeDefinitionThrows(); + } + private static int _varInt = 42; private static int? _varNullableInt = 42; private static decimal _varDecimal = 42M; @@ -309,6 +348,30 @@ private static void IsGenericTypeTests() [MethodImpl(MethodImplOptions.NoInlining)] private static dynamic CreateDynamic2() => new { Name = "Test" }; + [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 = "") { @@ -329,6 +392,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