diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 35f7d2f0bdf86..ff82759f6aab6 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -2709,6 +2709,11 @@ class ICorStaticInfo CORINFO_CLASS_HANDLE cls ) = 0; + // Returns whether a class handle represents a Nullable type, if that can be statically determined. + virtual TypeCompareState isNullableType( + CORINFO_CLASS_HANDLE cls + ) = 0; + // Returns TypeCompareState::Must if cls is known to be an enum. // For enums with known exact type returns the underlying // type in underlyingType when the provided pointer is diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 2348162d94854..98b47dced2beb 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -344,6 +344,9 @@ bool isMoreSpecificType( bool isExactType( CORINFO_CLASS_HANDLE cls) override; +TypeCompareState isNullableType( + CORINFO_CLASS_HANDLE cls) override; + TypeCompareState isEnum( CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType) override; diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 0e9f6e2940bcb..743abdaff86ae 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 = { /* 3c216494-65f8-49e2-b69a-7f272193bcc6 */ - 0x3c216494, - 0x65f8, - 0x49e2, - {0xb6, 0x9a, 0x7f, 0x27, 0x21, 0x93, 0xbc, 0xc6} +constexpr GUID JITEEVersionIdentifier = { /* 8f046bcb-ca5f-4692-9277-898b71cb7938 */ + 0x8f046bcb, + 0xca5f, + 0x4692, + {0x92, 0x77, 0x89, 0x8b, 0x71, 0xcb, 0x79, 0x38} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/jit/ICorJitInfo_names_generated.h b/src/coreclr/jit/ICorJitInfo_names_generated.h index 30c499518e007..2e2573a911993 100644 --- a/src/coreclr/jit/ICorJitInfo_names_generated.h +++ b/src/coreclr/jit/ICorJitInfo_names_generated.h @@ -85,6 +85,7 @@ DEF_CLR_API(compareTypesForCast) DEF_CLR_API(compareTypesForEquality) DEF_CLR_API(isMoreSpecificType) DEF_CLR_API(isExactType) +DEF_CLR_API(isNullableType) DEF_CLR_API(isEnum) DEF_CLR_API(getParentType) DEF_CLR_API(getChildType) diff --git a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp index 77af720739ece..85db2ec5efffa 100644 --- a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp +++ b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp @@ -804,6 +804,15 @@ bool WrapICorJitInfo::isExactType( return temp; } +TypeCompareState WrapICorJitInfo::isNullableType( + CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(isNullableType); + TypeCompareState temp = wrapHnd->isNullableType(cls); + API_LEAVE(isNullableType); + return temp; +} + TypeCompareState WrapICorJitInfo::isEnum( CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType) diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 82ba1f02ba260..ccc7be5a7b6fa 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -4717,10 +4717,10 @@ GenTree* Compiler::impSRCSUnsafeIntrinsic(NamedIntrinsic intrinsic, ClassLayout* toLayout = nullptr; var_types toType = TypeHandleToVarType(toTypeHnd, &toLayout); - if (fromType == TYP_REF || info.compCompHnd->getBoxHelper(fromTypeHnd) == CORINFO_HELP_BOX_NULLABLE || - toType == TYP_REF || info.compCompHnd->getBoxHelper(toTypeHnd) == CORINFO_HELP_BOX_NULLABLE) + if (fromType == TYP_REF || info.compCompHnd->isNullableType(fromTypeHnd) != TypeCompareState::MustNot || + toType == TYP_REF || info.compCompHnd->isNullableType(toTypeHnd) != TypeCompareState::MustNot) { - // Fallback to the software implementation to throw when the types don't fit "where T : struct" + // Fallback to the software implementation to throw when the types fail a "default(T) is not null" check. return nullptr; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 9366e1aa65b6d..a75318e7bcd18 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -2941,6 +2941,18 @@ private bool isExactType(CORINFO_CLASS_STRUCT_* cls) return _compilation.IsEffectivelySealed(type); } + private TypeCompareState isNullableType(CORINFO_CLASS_STRUCT_* cls) + { + TypeDesc type = HandleToObject(cls); + + if (type.IsCanonicalDefinitionType(CanonicalFormKind.Any)) + { + return TypeCompareState.May; + } + + return type.IsNullable ? TypeCompareState.Must : TypeCompareState.MustNot; + } + private TypeCompareState isEnum(CORINFO_CLASS_STRUCT_* cls, CORINFO_CLASS_STRUCT_** underlyingType) { Debug.Assert(cls != null); diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index 09ea54f989fde..481c22864356c 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -1210,6 +1210,21 @@ private static byte _isExactType(IntPtr thisHandle, IntPtr* ppException, CORINFO } } + [UnmanagedCallersOnly] + private static TypeCompareState _isNullableType(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls) + { + var _this = GetThis(thisHandle); + try + { + return _this.isNullableType(cls); + } + catch (Exception ex) + { + *ppException = _this.AllocException(ex); + return default; + } + } + [UnmanagedCallersOnly] private static TypeCompareState _isEnum(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls, CORINFO_CLASS_STRUCT_** underlyingType) { @@ -2579,7 +2594,7 @@ private static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, CORJIT_ private static IntPtr GetUnmanagedCallbacks() { - void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 174); + void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 175); callbacks[0] = (delegate* unmanaged)&_isIntrinsic; callbacks[1] = (delegate* unmanaged)&_notifyMethodInfoUsage; @@ -2662,99 +2677,100 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[78] = (delegate* unmanaged)&_compareTypesForEquality; callbacks[79] = (delegate* unmanaged)&_isMoreSpecificType; callbacks[80] = (delegate* unmanaged)&_isExactType; - callbacks[81] = (delegate* unmanaged)&_isEnum; - callbacks[82] = (delegate* unmanaged)&_getParentType; - callbacks[83] = (delegate* unmanaged)&_getChildType; - callbacks[84] = (delegate* unmanaged)&_isSDArray; - callbacks[85] = (delegate* unmanaged)&_getArrayRank; - callbacks[86] = (delegate* unmanaged)&_getArrayIntrinsicID; - callbacks[87] = (delegate* unmanaged)&_getArrayInitializationData; - callbacks[88] = (delegate* unmanaged)&_canAccessClass; - callbacks[89] = (delegate* unmanaged)&_printFieldName; - callbacks[90] = (delegate* unmanaged)&_getFieldClass; - callbacks[91] = (delegate* unmanaged)&_getFieldType; - callbacks[92] = (delegate* unmanaged)&_getFieldOffset; - callbacks[93] = (delegate* unmanaged)&_getFieldInfo; - callbacks[94] = (delegate* unmanaged)&_getThreadLocalFieldInfo; - callbacks[95] = (delegate* unmanaged)&_getThreadLocalStaticBlocksInfo; - callbacks[96] = (delegate* unmanaged)&_getThreadLocalStaticInfo_NativeAOT; - callbacks[97] = (delegate* unmanaged)&_isFieldStatic; - callbacks[98] = (delegate* unmanaged)&_getArrayOrStringLength; - callbacks[99] = (delegate* unmanaged)&_getBoundaries; - callbacks[100] = (delegate* unmanaged)&_setBoundaries; - callbacks[101] = (delegate* unmanaged)&_getVars; - callbacks[102] = (delegate* unmanaged)&_setVars; - callbacks[103] = (delegate* unmanaged)&_reportRichMappings; - callbacks[104] = (delegate* unmanaged)&_reportMetadata; - callbacks[105] = (delegate* unmanaged)&_allocateArray; - callbacks[106] = (delegate* unmanaged)&_freeArray; - callbacks[107] = (delegate* unmanaged)&_getArgNext; - callbacks[108] = (delegate* unmanaged)&_getArgType; - callbacks[109] = (delegate* unmanaged)&_getExactClasses; - callbacks[110] = (delegate* unmanaged)&_getArgClass; - callbacks[111] = (delegate* unmanaged)&_getHFAType; - callbacks[112] = (delegate* unmanaged)&_runWithErrorTrap; - callbacks[113] = (delegate* unmanaged)&_runWithSPMIErrorTrap; - callbacks[114] = (delegate* unmanaged)&_getEEInfo; - callbacks[115] = (delegate* unmanaged)&_getJitTimeLogFilename; - callbacks[116] = (delegate* unmanaged)&_getMethodDefFromMethod; - callbacks[117] = (delegate* unmanaged)&_printMethodName; - callbacks[118] = (delegate* unmanaged)&_getMethodNameFromMetadata; - callbacks[119] = (delegate* unmanaged)&_getMethodHash; - callbacks[120] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; - callbacks[121] = (delegate* unmanaged)&_getSwiftLowering; - callbacks[122] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; - callbacks[123] = (delegate* unmanaged)&_getRISCV64PassStructInRegisterFlags; - callbacks[124] = (delegate* unmanaged)&_getThreadTLSIndex; - callbacks[125] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; - callbacks[126] = (delegate* unmanaged)&_getHelperFtn; - callbacks[127] = (delegate* unmanaged)&_getFunctionEntryPoint; - callbacks[128] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; - callbacks[129] = (delegate* unmanaged)&_getMethodSync; - callbacks[130] = (delegate* unmanaged)&_getLazyStringLiteralHelper; - callbacks[131] = (delegate* unmanaged)&_embedModuleHandle; - callbacks[132] = (delegate* unmanaged)&_embedClassHandle; - callbacks[133] = (delegate* unmanaged)&_embedMethodHandle; - callbacks[134] = (delegate* unmanaged)&_embedFieldHandle; - callbacks[135] = (delegate* unmanaged)&_embedGenericHandle; - callbacks[136] = (delegate* unmanaged)&_getLocationOfThisType; - callbacks[137] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; - callbacks[138] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; - callbacks[139] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; - callbacks[140] = (delegate* unmanaged)&_getJustMyCodeHandle; - callbacks[141] = (delegate* unmanaged)&_GetProfilingHandle; - callbacks[142] = (delegate* unmanaged)&_getCallInfo; - callbacks[143] = (delegate* unmanaged)&_getClassDomainID; - callbacks[144] = (delegate* unmanaged)&_getStaticFieldContent; - callbacks[145] = (delegate* unmanaged)&_getObjectContent; - callbacks[146] = (delegate* unmanaged)&_getStaticFieldCurrentClass; - callbacks[147] = (delegate* unmanaged)&_getVarArgsHandle; - callbacks[148] = (delegate* unmanaged)&_canGetVarArgsHandle; - callbacks[149] = (delegate* unmanaged)&_constructStringLiteral; - callbacks[150] = (delegate* unmanaged)&_emptyStringLiteral; - callbacks[151] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; - callbacks[152] = (delegate* unmanaged)&_GetDelegateCtor; - callbacks[153] = (delegate* unmanaged)&_MethodCompileComplete; - callbacks[154] = (delegate* unmanaged)&_getTailCallHelpers; - callbacks[155] = (delegate* unmanaged)&_convertPInvokeCalliToCall; - callbacks[156] = (delegate* unmanaged)&_notifyInstructionSetUsage; - callbacks[157] = (delegate* unmanaged)&_updateEntryPointForTailCall; - callbacks[158] = (delegate* unmanaged)&_allocMem; - callbacks[159] = (delegate* unmanaged)&_reserveUnwindInfo; - callbacks[160] = (delegate* unmanaged)&_allocUnwindInfo; - callbacks[161] = (delegate* unmanaged)&_allocGCInfo; - callbacks[162] = (delegate* unmanaged)&_setEHcount; - callbacks[163] = (delegate* unmanaged)&_setEHinfo; - callbacks[164] = (delegate* unmanaged)&_logMsg; - callbacks[165] = (delegate* unmanaged)&_doAssert; - callbacks[166] = (delegate* unmanaged)&_reportFatalError; - callbacks[167] = (delegate* unmanaged)&_getPgoInstrumentationResults; - callbacks[168] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; - callbacks[169] = (delegate* unmanaged)&_recordCallSite; - callbacks[170] = (delegate* unmanaged)&_recordRelocation; - callbacks[171] = (delegate* unmanaged)&_getRelocTypeHint; - callbacks[172] = (delegate* unmanaged)&_getExpectedTargetArchitecture; - callbacks[173] = (delegate* unmanaged)&_getJitFlags; + callbacks[81] = (delegate* unmanaged)&_isNullableType; + callbacks[82] = (delegate* unmanaged)&_isEnum; + callbacks[83] = (delegate* unmanaged)&_getParentType; + callbacks[84] = (delegate* unmanaged)&_getChildType; + callbacks[85] = (delegate* unmanaged)&_isSDArray; + callbacks[86] = (delegate* unmanaged)&_getArrayRank; + callbacks[87] = (delegate* unmanaged)&_getArrayIntrinsicID; + callbacks[88] = (delegate* unmanaged)&_getArrayInitializationData; + callbacks[89] = (delegate* unmanaged)&_canAccessClass; + callbacks[90] = (delegate* unmanaged)&_printFieldName; + callbacks[91] = (delegate* unmanaged)&_getFieldClass; + callbacks[92] = (delegate* unmanaged)&_getFieldType; + callbacks[93] = (delegate* unmanaged)&_getFieldOffset; + callbacks[94] = (delegate* unmanaged)&_getFieldInfo; + callbacks[95] = (delegate* unmanaged)&_getThreadLocalFieldInfo; + callbacks[96] = (delegate* unmanaged)&_getThreadLocalStaticBlocksInfo; + callbacks[97] = (delegate* unmanaged)&_getThreadLocalStaticInfo_NativeAOT; + callbacks[98] = (delegate* unmanaged)&_isFieldStatic; + callbacks[99] = (delegate* unmanaged)&_getArrayOrStringLength; + callbacks[100] = (delegate* unmanaged)&_getBoundaries; + callbacks[101] = (delegate* unmanaged)&_setBoundaries; + callbacks[102] = (delegate* unmanaged)&_getVars; + callbacks[103] = (delegate* unmanaged)&_setVars; + callbacks[104] = (delegate* unmanaged)&_reportRichMappings; + callbacks[105] = (delegate* unmanaged)&_reportMetadata; + callbacks[106] = (delegate* unmanaged)&_allocateArray; + callbacks[107] = (delegate* unmanaged)&_freeArray; + callbacks[108] = (delegate* unmanaged)&_getArgNext; + callbacks[109] = (delegate* unmanaged)&_getArgType; + callbacks[110] = (delegate* unmanaged)&_getExactClasses; + callbacks[111] = (delegate* unmanaged)&_getArgClass; + callbacks[112] = (delegate* unmanaged)&_getHFAType; + callbacks[113] = (delegate* unmanaged)&_runWithErrorTrap; + callbacks[114] = (delegate* unmanaged)&_runWithSPMIErrorTrap; + callbacks[115] = (delegate* unmanaged)&_getEEInfo; + callbacks[116] = (delegate* unmanaged)&_getJitTimeLogFilename; + callbacks[117] = (delegate* unmanaged)&_getMethodDefFromMethod; + callbacks[118] = (delegate* unmanaged)&_printMethodName; + callbacks[119] = (delegate* unmanaged)&_getMethodNameFromMetadata; + callbacks[120] = (delegate* unmanaged)&_getMethodHash; + callbacks[121] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; + callbacks[122] = (delegate* unmanaged)&_getSwiftLowering; + callbacks[123] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; + callbacks[124] = (delegate* unmanaged)&_getRISCV64PassStructInRegisterFlags; + callbacks[125] = (delegate* unmanaged)&_getThreadTLSIndex; + callbacks[126] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; + callbacks[127] = (delegate* unmanaged)&_getHelperFtn; + callbacks[128] = (delegate* unmanaged)&_getFunctionEntryPoint; + callbacks[129] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; + callbacks[130] = (delegate* unmanaged)&_getMethodSync; + callbacks[131] = (delegate* unmanaged)&_getLazyStringLiteralHelper; + callbacks[132] = (delegate* unmanaged)&_embedModuleHandle; + callbacks[133] = (delegate* unmanaged)&_embedClassHandle; + callbacks[134] = (delegate* unmanaged)&_embedMethodHandle; + callbacks[135] = (delegate* unmanaged)&_embedFieldHandle; + callbacks[136] = (delegate* unmanaged)&_embedGenericHandle; + callbacks[137] = (delegate* unmanaged)&_getLocationOfThisType; + callbacks[138] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; + callbacks[139] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; + callbacks[140] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; + callbacks[141] = (delegate* unmanaged)&_getJustMyCodeHandle; + callbacks[142] = (delegate* unmanaged)&_GetProfilingHandle; + callbacks[143] = (delegate* unmanaged)&_getCallInfo; + callbacks[144] = (delegate* unmanaged)&_getClassDomainID; + callbacks[145] = (delegate* unmanaged)&_getStaticFieldContent; + callbacks[146] = (delegate* unmanaged)&_getObjectContent; + callbacks[147] = (delegate* unmanaged)&_getStaticFieldCurrentClass; + callbacks[148] = (delegate* unmanaged)&_getVarArgsHandle; + callbacks[149] = (delegate* unmanaged)&_canGetVarArgsHandle; + callbacks[150] = (delegate* unmanaged)&_constructStringLiteral; + callbacks[151] = (delegate* unmanaged)&_emptyStringLiteral; + callbacks[152] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; + callbacks[153] = (delegate* unmanaged)&_GetDelegateCtor; + callbacks[154] = (delegate* unmanaged)&_MethodCompileComplete; + callbacks[155] = (delegate* unmanaged)&_getTailCallHelpers; + callbacks[156] = (delegate* unmanaged)&_convertPInvokeCalliToCall; + callbacks[157] = (delegate* unmanaged)&_notifyInstructionSetUsage; + callbacks[158] = (delegate* unmanaged)&_updateEntryPointForTailCall; + callbacks[159] = (delegate* unmanaged)&_allocMem; + callbacks[160] = (delegate* unmanaged)&_reserveUnwindInfo; + callbacks[161] = (delegate* unmanaged)&_allocUnwindInfo; + callbacks[162] = (delegate* unmanaged)&_allocGCInfo; + callbacks[163] = (delegate* unmanaged)&_setEHcount; + callbacks[164] = (delegate* unmanaged)&_setEHinfo; + callbacks[165] = (delegate* unmanaged)&_logMsg; + callbacks[166] = (delegate* unmanaged)&_doAssert; + callbacks[167] = (delegate* unmanaged)&_reportFatalError; + callbacks[168] = (delegate* unmanaged)&_getPgoInstrumentationResults; + callbacks[169] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; + callbacks[170] = (delegate* unmanaged)&_recordCallSite; + callbacks[171] = (delegate* unmanaged)&_recordRelocation; + callbacks[172] = (delegate* unmanaged)&_getRelocTypeHint; + callbacks[173] = (delegate* unmanaged)&_getExpectedTargetArchitecture; + callbacks[174] = (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 8d6ecabaa77c5..86674ab2b5924 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -244,6 +244,7 @@ FUNCTIONS TypeCompareState compareTypesForEquality(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) bool isMoreSpecificType(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) bool isExactType(CORINFO_CLASS_HANDLE cls) + TypeCompareState isNullableType(CORINFO_CLASS_HANDLE cls) TypeCompareState isEnum(CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType) CORINFO_CLASS_HANDLE getParentType(CORINFO_CLASS_HANDLE cls) CorInfoType getChildType(CORINFO_CLASS_HANDLE clsHnd, CORINFO_CLASS_HANDLE* clsRet) diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h index 754394f16ee9e..db1d0a721d1f1 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h @@ -92,6 +92,7 @@ struct JitInterfaceCallbacks TypeCompareState (* compareTypesForEquality)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2); bool (* isMoreSpecificType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2); bool (* isExactType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); + TypeCompareState (* isNullableType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); TypeCompareState (* isEnum)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType); CORINFO_CLASS_HANDLE (* getParentType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); CorInfoType (* getChildType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE clsHnd, CORINFO_CLASS_HANDLE* clsRet); @@ -992,6 +993,15 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } + virtual TypeCompareState isNullableType( + CORINFO_CLASS_HANDLE cls) +{ + CorInfoExceptionClass* pException = nullptr; + TypeCompareState temp = _callbacks->isNullableType(_thisHandle, &pException, cls); + if (pException != nullptr) throw pException; + return temp; +} + virtual TypeCompareState isEnum( CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType) 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 ef1b277e80533..eebb80ab6b9df 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp @@ -659,6 +659,13 @@ bool interceptor_ICJI::isExactType( return original_ICorJitInfo->isExactType(cls); } +TypeCompareState interceptor_ICJI::isNullableType( + CORINFO_CLASS_HANDLE cls) +{ + mcs->AddCall("isNullableType"); + return original_ICorJitInfo->isNullableType(cls); +} + TypeCompareState interceptor_ICJI::isEnum( CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType) 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 55aef65127347..6a2ca48d87cd7 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp @@ -578,6 +578,12 @@ bool interceptor_ICJI::isExactType( return original_ICorJitInfo->isExactType(cls); } +TypeCompareState interceptor_ICJI::isNullableType( + CORINFO_CLASS_HANDLE cls) +{ + return original_ICorJitInfo->isNullableType(cls); +} + TypeCompareState interceptor_ICJI::isEnum( CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index c8ac3350b2e91..1e7ffc1ca5708 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -4658,6 +4658,31 @@ bool CEEInfo::isExactType(CORINFO_CLASS_HANDLE cls) return result; } +// Returns whether a class handle represents a Nullable type, if that can be statically determined. +TypeCompareState CEEInfo::isNullableType(CORINFO_CLASS_HANDLE cls) +{ + CONTRACTL { + THROWS; + GC_TRIGGERS; + MODE_PREEMPTIVE; + } CONTRACTL_END; + + TypeHandle typeHandle = TypeHandle(); + + TypeCompareState result = TypeCompareState::May; + + JIT_TO_EE_TRANSITION(); + + if (typeHandle != TypeHandle(g_pCanonMethodTableClass)) + { + TypeHandle VMClsHnd(cls); + result = Nullable::IsNullableType(VMClsHnd) ? TypeCompareState::Must : TypeCompareState::MustNot; + } + + EE_TO_JIT_TRANSITION(); + return result; +} + /*********************************************************************/ // Returns TypeCompareState::Must if cls is known to be an enum. // For enums with known exact type returns the underlying