From 75420c5d4a144166a2ce0bd831a434432557fe04 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 4 Jul 2025 22:02:47 +0200 Subject: [PATCH 1/7] jit impl --- src/coreclr/jit/fgprofile.cpp | 1 + src/coreclr/jit/importercalls.cpp | 21 +++++++++++++++++++ src/coreclr/jit/namedintrinsiclist.h | 1 + .../src/System/String.Comparison.cs | 2 +- 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/coreclr/jit/fgprofile.cpp b/src/coreclr/jit/fgprofile.cpp index d3a43675162298..fef6fbed364da7 100644 --- a/src/coreclr/jit/fgprofile.cpp +++ b/src/coreclr/jit/fgprofile.cpp @@ -2535,6 +2535,7 @@ PhaseStatus Compiler::fgPrepareToInstrumentMethod() // These are marked as [Intrinsic] only to be handled (unrolled) for constant inputs. // In other cases they have large managed implementations we want to profile. case NI_System_String_Equals: + case NI_System_String_GetNonRandomizedHashCode: case NI_System_SpanHelpers_Memmove: case NI_System_MemoryExtensions_Equals: case NI_System_MemoryExtensions_SequenceEqual: diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 2184756da0518c..feb73628bf2fb7 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -3547,6 +3547,23 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, break; } + case NI_System_String_GetNonRandomizedHashCode: + { + assert(sig->numArgs == 0); + assert(sig->hasThis()); + if (opts.OptimizationEnabled() && impStackTop().val->OperIs(GT_CNS_STR)) + { + //GenTreeStrCon* strCon = impStackTop().val->AsStrCon(); + //int hashCode = 0; + //if (info.compCompHnd->tryGetNonRandomizedHashCode(strCon->gtScpHnd, strCon->gtSconCPX, &hashCode)) + //{ + // impPopStack(); + // retNode = gtNewIconNode(hashCode, TYP_INT); + //} + } + break; + } + case NI_System_String_get_Length: { GenTree* op1 = impPopStack().val; @@ -10213,6 +10230,10 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) { result = NI_System_String_Equals; } + else if (strcmp(methodName, "GetNonRandomizedHashCode") == 0) + { + result = NI_System_String_GetNonRandomizedHashCode; + } else if (strcmp(methodName, "get_Chars") == 0) { result = NI_System_String_get_Chars; diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h index 72ea2c164fd9eb..546cfc245d2a14 100644 --- a/src/coreclr/jit/namedintrinsiclist.h +++ b/src/coreclr/jit/namedintrinsiclist.h @@ -132,6 +132,7 @@ enum NamedIntrinsic : unsigned short NI_System_Runtime_InteropService_MemoryMarshal_GetArrayDataReference, NI_System_String_Equals, + NI_System_String_GetNonRandomizedHashCode, NI_System_String_get_Chars, NI_System_String_get_Length, NI_System_String_op_Implicit, diff --git a/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs b/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs index f9261106b34c73..d3ceb28de35091 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs @@ -826,7 +826,7 @@ internal static int GetHashCodeOrdinalIgnoreCase(ReadOnlySpan value) // rely on str.GetNonRandomizedHashCode() == GetNonRandomizedHashCode(str.AsSpan()). As such, we must // restructure the comparison so that for odd-length spans, we simulate the null terminator and include // it in the hash computation exactly as does str.GetNonRandomizedHashCode(). - + [Intrinsic] internal unsafe int GetNonRandomizedHashCode() { fixed (char* src = &_firstChar) From 5e39f4b95009452509a37a073b71be45e551ef20 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 5 Jul 2025 13:55:26 +0200 Subject: [PATCH 2/7] allos cns_str substitute --- src/coreclr/jit/compiler.cpp | 2 +- src/coreclr/jit/gentree.cpp | 27 +++++++++++++++++++++++++-- src/coreclr/jit/importer.cpp | 8 ++++---- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index db283b444cd7e7..3fb253ff9b17ac 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -10618,7 +10618,7 @@ const char* Compiler::convertUtf16ToUtf8ForPrinting(const WCHAR* utf16String) { const char* utf8Str = ""; int utf8Len = WideCharToMultiByte(CP_UTF8, 0, utf16String, -1, nullptr, 0, nullptr, nullptr); - if (utf8Len == 0) + if (utf8Len > 0) { char* allocated = new (this, CMK_DebugOnly) char[utf8Len]; diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index ee57e958e439f9..8a08c47d16966f 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -12204,8 +12204,31 @@ void Compiler::gtDispConst(GenTree* tree) } case GT_CNS_STR: - printf(""); - break; + { + GenTreeStrCon* cnsStr = tree->AsStrCon(); + if (cnsStr->IsStringEmptyField()) + { + // Special case: do not call getStringLiteral for the empty string field + printf("\"\""); + break; + } + + char16_t str[512] = {}; + int len = info.compCompHnd->getStringLiteral(cnsStr->gtScpHnd, cnsStr->gtSconCPX, str, sizeof(str)); + if (len == 0) + { + printf("\"\""); + } + else if (len < 0) + { + printf(""); + } + else + { + printf("\"%.32s\"", convertUtf16ToUtf8ForPrinting(reinterpret_cast(str))); + } + } + break; #if defined(FEATURE_SIMD) case GT_CNS_VEC: diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index ff375d4dd485d6..1361ee615e0a8e 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -13848,15 +13848,15 @@ unsigned Compiler::impInlineFetchLocal(unsigned lclNum DEBUGARG(const char* reas // GenTree* Compiler::impInlineFetchArg(InlArgInfo& argInfo, const InlLclVarInfo& lclInfo) { + GenTree* argNode = argInfo.arg->GetNode(); + assert(!argNode->OperIs(GT_RET_EXPR)); + // Cache the relevant arg and lcl info for this argument. // We will modify argInfo but not lclVarInfo. - const bool argCanBeModified = argInfo.argHasLdargaOp || argInfo.argHasStargOp; + const bool argCanBeModified = (argInfo.argHasLdargaOp || argInfo.argHasStargOp) && !argNode->OperIs(GT_CNS_STR); const var_types lclTyp = lclInfo.lclTypeInfo; GenTree* op1 = nullptr; - GenTree* argNode = argInfo.arg->GetNode(); - assert(!argNode->OperIs(GT_RET_EXPR)); - // For TYP_REF args, if the argNode doesn't have any class information // we will lose some type info if we directly substitute it. // We can at least rely on the declared type of the arg here. From 09a72fc1190da49281dbbf229316088422ef36cc Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 5 Jul 2025 13:55:41 +0200 Subject: [PATCH 3/7] impl --- src/coreclr/inc/corinfo.h | 5 + src/coreclr/inc/icorjitinfoimpl_generated.h | 5 + src/coreclr/inc/jiteeversionguid.h | 10 +- src/coreclr/jit/ICorJitInfo_names_generated.h | 1 + .../jit/ICorJitInfo_wrapper_generated.hpp | 11 + src/coreclr/jit/importercalls.cpp | 14 +- .../tools/Common/JitInterface/CorInfoImpl.cs | 5 + .../JitInterface/CorInfoImpl_generated.cs | 304 +++++++++--------- .../ThunkGenerator/ThunkInput.txt | 1 + .../aot/jitinterface/jitinterface_generated.h | 12 + .../tools/superpmi/superpmi-shared/lwmlist.h | 1 + .../superpmi-shared/methodcontext.cpp | 33 ++ .../superpmi/superpmi-shared/methodcontext.h | 5 + .../superpmi-shim-collector/icorjitinfo.cpp | 11 + .../icorjitinfo_generated.cpp | 9 + .../icorjitinfo_generated.cpp | 8 + .../tools/superpmi/superpmi/icorjitinfo.cpp | 9 + src/coreclr/vm/jitinterface.cpp | 77 +++++ 18 files changed, 365 insertions(+), 156 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 266b7c83a6fe07..7738c340c8a8c7 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -2286,6 +2286,11 @@ class ICorStaticInfo int startIndex = 0 /* IN */ ) = 0; + virtual bool tryGetNonRandomizedHashCode ( + CORINFO_MODULE_HANDLE module, /* IN */ + unsigned metaTOK, /* IN */ + int32_t* pHashCode /* OUT */ + ) = 0; //------------------------------------------------------------------------------ // printObjectDescription: Prints a (possibly truncated) textual UTF8 representation of the given diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index ee74e9c984fa98..63c98f8cb72379 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -172,6 +172,11 @@ int getStringLiteral( int bufferSize, int startIndex) override; +bool tryGetNonRandomizedHashCode( + CORINFO_MODULE_HANDLE module, + unsigned metaTOK, + int* pHashCode) override; + size_t printObjectDescription( CORINFO_OBJECT_HANDLE handle, char* buffer, diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 38a900d0178d00..4154568ef63f88 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -37,11 +37,11 @@ #include -constexpr GUID JITEEVersionIdentifier = { /* 2004006b-bdff-4357-8e60-3ae950a4f165 */ - 0x2004006b, - 0xbdff, - 0x4357, - {0x8e, 0x60, 0x3a, 0xe9, 0x50, 0xa4, 0xf1, 0x65} +constexpr GUID JITEEVersionIdentifier = { /* c54dc26c-62aa-4fba-a58c-106ba601d2ba */ + 0xc54dc26c, + 0x62aa, + 0x4fba, + {0xa5, 0x8c, 0x10, 0x6b, 0xa6, 0x01, 0xd2, 0xba} }; #endif // JIT_EE_VERSIONING_GUID_H diff --git a/src/coreclr/jit/ICorJitInfo_names_generated.h b/src/coreclr/jit/ICorJitInfo_names_generated.h index e8e089f0b1dd59..9b3bcee8ca88dc 100644 --- a/src/coreclr/jit/ICorJitInfo_names_generated.h +++ b/src/coreclr/jit/ICorJitInfo_names_generated.h @@ -40,6 +40,7 @@ DEF_CLR_API(findSig) DEF_CLR_API(findCallSiteSig) DEF_CLR_API(getTokenTypeAsHandle) DEF_CLR_API(getStringLiteral) +DEF_CLR_API(tryGetNonRandomizedHashCode) DEF_CLR_API(printObjectDescription) DEF_CLR_API(asCorInfoType) DEF_CLR_API(getClassNameFromMetadata) diff --git a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp index c2a8418e30256d..5f14a752733f7f 100644 --- a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp +++ b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp @@ -365,6 +365,17 @@ int WrapICorJitInfo::getStringLiteral( return temp; } +bool WrapICorJitInfo::tryGetNonRandomizedHashCode( + CORINFO_MODULE_HANDLE module, + unsigned metaTOK, + int* pHashCode) +{ + API_ENTER(tryGetNonRandomizedHashCode); + bool temp = wrapHnd->tryGetNonRandomizedHashCode(module, metaTOK, pHashCode); + API_LEAVE(tryGetNonRandomizedHashCode); + return temp; +} + size_t WrapICorJitInfo::printObjectDescription( CORINFO_OBJECT_HANDLE handle, char* buffer, diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index feb73628bf2fb7..462706182df1be 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -3553,13 +3553,13 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, assert(sig->hasThis()); if (opts.OptimizationEnabled() && impStackTop().val->OperIs(GT_CNS_STR)) { - //GenTreeStrCon* strCon = impStackTop().val->AsStrCon(); - //int hashCode = 0; - //if (info.compCompHnd->tryGetNonRandomizedHashCode(strCon->gtScpHnd, strCon->gtSconCPX, &hashCode)) - //{ - // impPopStack(); - // retNode = gtNewIconNode(hashCode, TYP_INT); - //} + GenTreeStrCon* strCon = impStackTop().val->AsStrCon(); + int hashCode = 0; + if (info.compCompHnd->tryGetNonRandomizedHashCode(strCon->gtScpHnd, strCon->gtSconCPX, &hashCode)) + { + impPopStack(); + retNode = gtNewIconNode(hashCode, TYP_INT); + } } break; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 06b34f71550601..912bcc1f9c5fba 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -1967,6 +1967,11 @@ private int getStringLiteral(CORINFO_MODULE_STRUCT_* module, uint metaTOK, char* return result; } + private bool tryGetNonRandomizedHashCode(CORINFO_MODULE_STRUCT_* module, uint metaTOK, ref int pHashCode) + { + return false; + } + private nuint printObjectDescription(CORINFO_OBJECT_STRUCT_* handle, byte* buffer, nuint bufferSize, nuint* pRequiredBufferSize) { Debug.Assert(handle != null); diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index 6be49af5d42404..e4e308a53a4685 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -538,6 +538,21 @@ private static int _getStringLiteral(IntPtr thisHandle, IntPtr* ppException, COR } } + [UnmanagedCallersOnly] + private static byte _tryGetNonRandomizedHashCode(IntPtr thisHandle, IntPtr* ppException, CORINFO_MODULE_STRUCT_* module, uint metaTOK, int* pHashCode) + { + var _this = GetThis(thisHandle); + try + { + return _this.tryGetNonRandomizedHashCode(module, metaTOK, ref *pHashCode) ? (byte)1 : (byte)0; + } + catch (Exception ex) + { + *ppException = _this.AllocException(ex); + return default; + } + } + [UnmanagedCallersOnly] private static UIntPtr _printObjectDescription(IntPtr thisHandle, IntPtr* ppException, CORINFO_OBJECT_STRUCT_* handle, byte* buffer, UIntPtr bufferSize, UIntPtr* pRequiredBufferSize) { @@ -2651,7 +2666,7 @@ private static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, CORJIT_ private static IntPtr GetUnmanagedCallbacks() { - void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 179); + void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 180); callbacks[0] = (delegate* unmanaged)&_isIntrinsic; callbacks[1] = (delegate* unmanaged)&_notifyMethodInfoUsage; @@ -2689,149 +2704,150 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[33] = (delegate* unmanaged)&_findCallSiteSig; callbacks[34] = (delegate* unmanaged)&_getTokenTypeAsHandle; callbacks[35] = (delegate* unmanaged)&_getStringLiteral; - callbacks[36] = (delegate* unmanaged)&_printObjectDescription; - callbacks[37] = (delegate* unmanaged)&_asCorInfoType; - callbacks[38] = (delegate* unmanaged)&_getClassNameFromMetadata; - callbacks[39] = (delegate* unmanaged)&_getTypeInstantiationArgument; - callbacks[40] = (delegate* unmanaged)&_getMethodInstantiationArgument; - callbacks[41] = (delegate* unmanaged)&_printClassName; - callbacks[42] = (delegate* unmanaged)&_isValueClass; - callbacks[43] = (delegate* unmanaged)&_getClassAttribs; - callbacks[44] = (delegate* unmanaged)&_getClassAssemblyName; - callbacks[45] = (delegate* unmanaged)&_LongLifetimeMalloc; - callbacks[46] = (delegate* unmanaged)&_LongLifetimeFree; - callbacks[47] = (delegate* unmanaged)&_getIsClassInitedFlagAddress; - callbacks[48] = (delegate* unmanaged)&_getClassThreadStaticDynamicInfo; - callbacks[49] = (delegate* unmanaged)&_getClassStaticDynamicInfo; - callbacks[50] = (delegate* unmanaged)&_getStaticBaseAddress; - callbacks[51] = (delegate* unmanaged)&_getClassSize; - callbacks[52] = (delegate* unmanaged)&_getHeapClassSize; - callbacks[53] = (delegate* unmanaged)&_canAllocateOnStack; - callbacks[54] = (delegate* unmanaged)&_getClassAlignmentRequirement; - callbacks[55] = (delegate* unmanaged)&_getClassGClayout; - callbacks[56] = (delegate* unmanaged)&_getClassNumInstanceFields; - callbacks[57] = (delegate* unmanaged)&_getFieldInClass; - callbacks[58] = (delegate* unmanaged)&_getTypeLayout; - callbacks[59] = (delegate* unmanaged)&_checkMethodModifier; - callbacks[60] = (delegate* unmanaged)&_getNewHelper; - callbacks[61] = (delegate* unmanaged)&_getNewArrHelper; - callbacks[62] = (delegate* unmanaged)&_getCastingHelper; - callbacks[63] = (delegate* unmanaged)&_getSharedCCtorHelper; - callbacks[64] = (delegate* unmanaged)&_getTypeForBox; - 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)&_getAsyncInfo; - 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)&_getFpStructLowering; - 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)&_GetCookieForInterpreterCalliSig; - 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)&_getAsyncResumptionStub; - callbacks[159] = (delegate* unmanaged)&_convertPInvokeCalliToCall; - callbacks[160] = (delegate* unmanaged)&_notifyInstructionSetUsage; - callbacks[161] = (delegate* unmanaged)&_updateEntryPointForTailCall; - callbacks[162] = (delegate* unmanaged)&_allocMem; - callbacks[163] = (delegate* unmanaged)&_reserveUnwindInfo; - callbacks[164] = (delegate* unmanaged)&_allocUnwindInfo; - callbacks[165] = (delegate* unmanaged)&_allocGCInfo; - callbacks[166] = (delegate* unmanaged)&_setEHcount; - callbacks[167] = (delegate* unmanaged)&_setEHinfo; - callbacks[168] = (delegate* unmanaged)&_logMsg; - callbacks[169] = (delegate* unmanaged)&_doAssert; - callbacks[170] = (delegate* unmanaged)&_reportFatalError; - callbacks[171] = (delegate* unmanaged)&_getPgoInstrumentationResults; - callbacks[172] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; - callbacks[173] = (delegate* unmanaged)&_recordCallSite; - callbacks[174] = (delegate* unmanaged)&_recordRelocation; - callbacks[175] = (delegate* unmanaged)&_getRelocTypeHint; - callbacks[176] = (delegate* unmanaged)&_getExpectedTargetArchitecture; - callbacks[177] = (delegate* unmanaged)&_getJitFlags; - callbacks[178] = (delegate* unmanaged)&_getSpecialCopyHelper; + callbacks[36] = (delegate* unmanaged)&_tryGetNonRandomizedHashCode; + callbacks[37] = (delegate* unmanaged)&_printObjectDescription; + callbacks[38] = (delegate* unmanaged)&_asCorInfoType; + callbacks[39] = (delegate* unmanaged)&_getClassNameFromMetadata; + callbacks[40] = (delegate* unmanaged)&_getTypeInstantiationArgument; + callbacks[41] = (delegate* unmanaged)&_getMethodInstantiationArgument; + callbacks[42] = (delegate* unmanaged)&_printClassName; + callbacks[43] = (delegate* unmanaged)&_isValueClass; + callbacks[44] = (delegate* unmanaged)&_getClassAttribs; + callbacks[45] = (delegate* unmanaged)&_getClassAssemblyName; + callbacks[46] = (delegate* unmanaged)&_LongLifetimeMalloc; + callbacks[47] = (delegate* unmanaged)&_LongLifetimeFree; + callbacks[48] = (delegate* unmanaged)&_getIsClassInitedFlagAddress; + callbacks[49] = (delegate* unmanaged)&_getClassThreadStaticDynamicInfo; + callbacks[50] = (delegate* unmanaged)&_getClassStaticDynamicInfo; + callbacks[51] = (delegate* unmanaged)&_getStaticBaseAddress; + callbacks[52] = (delegate* unmanaged)&_getClassSize; + callbacks[53] = (delegate* unmanaged)&_getHeapClassSize; + callbacks[54] = (delegate* unmanaged)&_canAllocateOnStack; + callbacks[55] = (delegate* unmanaged)&_getClassAlignmentRequirement; + callbacks[56] = (delegate* unmanaged)&_getClassGClayout; + callbacks[57] = (delegate* unmanaged)&_getClassNumInstanceFields; + callbacks[58] = (delegate* unmanaged)&_getFieldInClass; + callbacks[59] = (delegate* unmanaged)&_getTypeLayout; + callbacks[60] = (delegate* unmanaged)&_checkMethodModifier; + callbacks[61] = (delegate* unmanaged)&_getNewHelper; + callbacks[62] = (delegate* unmanaged)&_getNewArrHelper; + callbacks[63] = (delegate* unmanaged)&_getCastingHelper; + callbacks[64] = (delegate* unmanaged)&_getSharedCCtorHelper; + callbacks[65] = (delegate* unmanaged)&_getTypeForBox; + callbacks[66] = (delegate* unmanaged)&_getBoxHelper; + callbacks[67] = (delegate* unmanaged)&_getUnBoxHelper; + callbacks[68] = (delegate* unmanaged)&_getRuntimeTypePointer; + callbacks[69] = (delegate* unmanaged)&_isObjectImmutable; + callbacks[70] = (delegate* unmanaged)&_getStringChar; + callbacks[71] = (delegate* unmanaged)&_getObjectType; + callbacks[72] = (delegate* unmanaged)&_getReadyToRunHelper; + callbacks[73] = (delegate* unmanaged)&_getReadyToRunDelegateCtorHelper; + callbacks[74] = (delegate* unmanaged)&_initClass; + callbacks[75] = (delegate* unmanaged)&_classMustBeLoadedBeforeCodeIsRun; + callbacks[76] = (delegate* unmanaged)&_getBuiltinClass; + callbacks[77] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; + callbacks[78] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; + callbacks[79] = (delegate* unmanaged)&_canCast; + callbacks[80] = (delegate* unmanaged)&_compareTypesForCast; + callbacks[81] = (delegate* unmanaged)&_compareTypesForEquality; + callbacks[82] = (delegate* unmanaged)&_isMoreSpecificType; + callbacks[83] = (delegate* unmanaged)&_isExactType; + callbacks[84] = (delegate* unmanaged)&_isGenericType; + callbacks[85] = (delegate* unmanaged)&_isNullableType; + callbacks[86] = (delegate* unmanaged)&_isEnum; + callbacks[87] = (delegate* unmanaged)&_getParentType; + callbacks[88] = (delegate* unmanaged)&_getChildType; + callbacks[89] = (delegate* unmanaged)&_isSDArray; + callbacks[90] = (delegate* unmanaged)&_getArrayRank; + callbacks[91] = (delegate* unmanaged)&_getArrayIntrinsicID; + callbacks[92] = (delegate* unmanaged)&_getArrayInitializationData; + callbacks[93] = (delegate* unmanaged)&_canAccessClass; + callbacks[94] = (delegate* unmanaged)&_printFieldName; + callbacks[95] = (delegate* unmanaged)&_getFieldClass; + callbacks[96] = (delegate* unmanaged)&_getFieldType; + callbacks[97] = (delegate* unmanaged)&_getFieldOffset; + callbacks[98] = (delegate* unmanaged)&_getFieldInfo; + callbacks[99] = (delegate* unmanaged)&_getThreadLocalFieldInfo; + callbacks[100] = (delegate* unmanaged)&_getThreadLocalStaticBlocksInfo; + callbacks[101] = (delegate* unmanaged)&_getThreadLocalStaticInfo_NativeAOT; + callbacks[102] = (delegate* unmanaged)&_isFieldStatic; + callbacks[103] = (delegate* unmanaged)&_getArrayOrStringLength; + callbacks[104] = (delegate* unmanaged)&_getBoundaries; + callbacks[105] = (delegate* unmanaged)&_setBoundaries; + callbacks[106] = (delegate* unmanaged)&_getVars; + callbacks[107] = (delegate* unmanaged)&_setVars; + callbacks[108] = (delegate* unmanaged)&_reportRichMappings; + callbacks[109] = (delegate* unmanaged)&_reportMetadata; + callbacks[110] = (delegate* unmanaged)&_allocateArray; + callbacks[111] = (delegate* unmanaged)&_freeArray; + callbacks[112] = (delegate* unmanaged)&_getArgNext; + callbacks[113] = (delegate* unmanaged)&_getArgType; + callbacks[114] = (delegate* unmanaged)&_getExactClasses; + callbacks[115] = (delegate* unmanaged)&_getArgClass; + callbacks[116] = (delegate* unmanaged)&_getHFAType; + callbacks[117] = (delegate* unmanaged)&_runWithErrorTrap; + callbacks[118] = (delegate* unmanaged)&_runWithSPMIErrorTrap; + callbacks[119] = (delegate* unmanaged)&_getEEInfo; + callbacks[120] = (delegate* unmanaged)&_getAsyncInfo; + callbacks[121] = (delegate* unmanaged)&_getMethodDefFromMethod; + callbacks[122] = (delegate* unmanaged)&_printMethodName; + callbacks[123] = (delegate* unmanaged)&_getMethodNameFromMetadata; + callbacks[124] = (delegate* unmanaged)&_getMethodHash; + callbacks[125] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; + callbacks[126] = (delegate* unmanaged)&_getSwiftLowering; + callbacks[127] = (delegate* unmanaged)&_getFpStructLowering; + 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)&_GetCookieForInterpreterCalliSig; + callbacks[144] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; + callbacks[145] = (delegate* unmanaged)&_getJustMyCodeHandle; + callbacks[146] = (delegate* unmanaged)&_GetProfilingHandle; + callbacks[147] = (delegate* unmanaged)&_getCallInfo; + callbacks[148] = (delegate* unmanaged)&_getStaticFieldContent; + callbacks[149] = (delegate* unmanaged)&_getObjectContent; + callbacks[150] = (delegate* unmanaged)&_getStaticFieldCurrentClass; + callbacks[151] = (delegate* unmanaged)&_getVarArgsHandle; + callbacks[152] = (delegate* unmanaged)&_canGetVarArgsHandle; + callbacks[153] = (delegate* unmanaged)&_constructStringLiteral; + callbacks[154] = (delegate* unmanaged)&_emptyStringLiteral; + callbacks[155] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; + callbacks[156] = (delegate* unmanaged)&_GetDelegateCtor; + callbacks[157] = (delegate* unmanaged)&_MethodCompileComplete; + callbacks[158] = (delegate* unmanaged)&_getTailCallHelpers; + callbacks[159] = (delegate* unmanaged)&_getAsyncResumptionStub; + callbacks[160] = (delegate* unmanaged)&_convertPInvokeCalliToCall; + callbacks[161] = (delegate* unmanaged)&_notifyInstructionSetUsage; + callbacks[162] = (delegate* unmanaged)&_updateEntryPointForTailCall; + callbacks[163] = (delegate* unmanaged)&_allocMem; + callbacks[164] = (delegate* unmanaged)&_reserveUnwindInfo; + callbacks[165] = (delegate* unmanaged)&_allocUnwindInfo; + callbacks[166] = (delegate* unmanaged)&_allocGCInfo; + callbacks[167] = (delegate* unmanaged)&_setEHcount; + callbacks[168] = (delegate* unmanaged)&_setEHinfo; + callbacks[169] = (delegate* unmanaged)&_logMsg; + callbacks[170] = (delegate* unmanaged)&_doAssert; + callbacks[171] = (delegate* unmanaged)&_reportFatalError; + callbacks[172] = (delegate* unmanaged)&_getPgoInstrumentationResults; + callbacks[173] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; + callbacks[174] = (delegate* unmanaged)&_recordCallSite; + callbacks[175] = (delegate* unmanaged)&_recordRelocation; + callbacks[176] = (delegate* unmanaged)&_getRelocTypeHint; + callbacks[177] = (delegate* unmanaged)&_getExpectedTargetArchitecture; + callbacks[178] = (delegate* unmanaged)&_getJitFlags; + callbacks[179] = (delegate* unmanaged)&_getSpecialCopyHelper; return (IntPtr)callbacks; } diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index 7b5f8a7d79f292..ce816764f5ce26 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -202,6 +202,7 @@ FUNCTIONS void findCallSiteSig( CORINFO_MODULE_HANDLE module,unsigned methTOK, CORINFO_CONTEXT_HANDLE context, CORINFO_SIG_INFO *sig) CORINFO_CLASS_HANDLE getTokenTypeAsHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken) int getStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, char16_t* buffer, int bufferSize, int startIndex) + bool tryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* pHashCode); size_t printObjectDescription(CORINFO_OBJECT_HANDLE handle, char* buffer, size_t bufferSize, size_t* pRequiredBufferSize) CorInfoType asCorInfoType(CORINFO_CLASS_HANDLE cls) const char* getClassNameFromMetadata(CORINFO_CLASS_HANDLE cls, const char **namespaceName) diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h index f72f9cdeef2ac4..4b456e2e5d22eb 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h @@ -47,6 +47,7 @@ struct JitInterfaceCallbacks void (* findCallSiteSig)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned methTOK, CORINFO_CONTEXT_HANDLE context, CORINFO_SIG_INFO* sig); CORINFO_CLASS_HANDLE (* getTokenTypeAsHandle)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken); int (* getStringLiteral)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned metaTOK, char16_t* buffer, int bufferSize, int startIndex); + bool (* tryGetNonRandomizedHashCode)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* pHashCode); size_t (* printObjectDescription)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_OBJECT_HANDLE handle, char* buffer, size_t bufferSize, size_t* pRequiredBufferSize); CorInfoType (* asCorInfoType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); const char* (* getClassNameFromMetadata)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls, const char** namespaceName); @@ -558,6 +559,17 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } + virtual bool tryGetNonRandomizedHashCode( + CORINFO_MODULE_HANDLE module, + unsigned metaTOK, + int* pHashCode) +{ + CorInfoExceptionClass* pException = nullptr; + bool temp = _callbacks->tryGetNonRandomizedHashCode(_thisHandle, &pException, module, metaTOK, pHashCode); + if (pException != nullptr) throw pException; + return temp; +} + virtual size_t printObjectDescription( CORINFO_OBJECT_HANDLE handle, char* buffer, diff --git a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h index b65429f3153bd4..1185b6156270dc 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -158,6 +158,7 @@ LWM(ExpandRawHandleIntrinsic, Agnostic_ExpandRawHandleIntrinsic, Agnostic_CORINF LWM(IsIntrinsicType, DWORDLONG, DWORD) LWM(IsSDArray, DWORDLONG, DWORD) LWM(GetStringLiteral, DLDDD, DD) +LWM(TryGetNonRandomizedHashCode, DLD, DD) LWM(PrintObjectDescription, DWORDLONG, Agnostic_PrintResult) LWM(PrintClassName, DWORDLONG, Agnostic_PrintResult) LWM(PrintFieldName, DWORDLONG, Agnostic_PrintResult) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 55d5f732db35fb..97e25ce23bce9a 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -5236,6 +5236,39 @@ int MethodContext::repGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned me return srcBufferLength; } +void MethodContext::recTryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* pHashCode, bool result) +{ + if (TryGetNonRandomizedHashCode == nullptr) + TryGetNonRandomizedHashCode = new LightWeightMap(); + + DLD key; + ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding + key.A = CastHandle(module); + key.B = (DWORD)metaTOK; + + DD value; + value.A = (DWORD)result; + value.B = (DWORD)*pHashCode; + + TryGetNonRandomizedHashCode->Add(key, value); + DEBUG_REC(dmpTryGetNonRandomizedHashCode(key, value)); +} + +void MethodContext::dmpTryGetNonRandomizedHashCode(DLD key, DD value) +{ + printf("TryGetNonRandomizedHashCode key mod-%016" PRIX64 " tok-%08X, hashcode-%u, result-%u", key.A, key.B, value.A, value.B); +} + +bool MethodContext::repTryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* pHashCode) +{ + DLD key; + ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding + key.A = CastHandle(module); + key.B = (DWORD)metaTOK; + + return false; +} + void MethodContext::recCanCast(CORINFO_CLASS_HANDLE child, CORINFO_CLASS_HANDLE parent, bool result) { if (CanCast == nullptr) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index 06c1c1e33bd842..0abeb3961abd92 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -668,6 +668,10 @@ class MethodContext void dmpGetStringLiteral(DLDDD key, DD value); int repGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, char16_t* buffer, int bufferSize, int startIndex); + void recTryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* pHashCode, bool result); + void dmpTryGetNonRandomizedHashCode(DLD key, DD value); + bool repTryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* pHashCode); + void recCanCast(CORINFO_CLASS_HANDLE child, CORINFO_CLASS_HANDLE parent, bool result); void dmpCanCast(DLDL key, DWORD value); bool repCanCast(CORINFO_CLASS_HANDLE child, CORINFO_CLASS_HANDLE parent); @@ -1224,6 +1228,7 @@ enum mcPackets Packet_GetAsyncResumptionStub = 231, Packet_GetCookieForInterpreterCalliSig = 232, Packet_GetHelperFtn = 233, + Packet_TryGetNonRandomizedHashCode = 234, }; 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 eab692b4d37cab..9d69232bf0eddf 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -446,6 +446,17 @@ int interceptor_ICJI::getStringLiteral(CORINFO_MODULE_HANDLE module, /* IN * return temp; } +bool interceptor_ICJI::tryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, /* IN */ + unsigned metaTOK, /* IN */ + int* pHashCode /* OUT */ + ) +{ + mc->cr->AddCall("tryGetNonRandomizedHashCode"); + bool temp = original_ICorJitInfo->tryGetNonRandomizedHashCode(module, metaTOK, pHashCode); + mc->recTryGetNonRandomizedHashCode(module, metaTOK, pHashCode, temp); + return temp; +} + size_t interceptor_ICJI::printObjectDescription(CORINFO_OBJECT_HANDLE handle, /* IN */ char* buffer, /* OUT */ size_t bufferSize, /* IN */ 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 ffcf2dc749695c..b4274d643b45e9 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp @@ -307,6 +307,15 @@ int interceptor_ICJI::getStringLiteral( return original_ICorJitInfo->getStringLiteral(module, metaTOK, buffer, bufferSize, startIndex); } +bool interceptor_ICJI::tryGetNonRandomizedHashCode( + CORINFO_MODULE_HANDLE module, + unsigned metaTOK, + int* pHashCode) +{ + mcs->AddCall("tryGetNonRandomizedHashCode"); + return original_ICorJitInfo->tryGetNonRandomizedHashCode(module, metaTOK, pHashCode); +} + size_t interceptor_ICJI::printObjectDescription( CORINFO_OBJECT_HANDLE handle, char* buffer, 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 718959681da80a..e65ebb918f11d4 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp @@ -271,6 +271,14 @@ int interceptor_ICJI::getStringLiteral( return original_ICorJitInfo->getStringLiteral(module, metaTOK, buffer, bufferSize, startIndex); } +bool interceptor_ICJI::tryGetNonRandomizedHashCode( + CORINFO_MODULE_HANDLE module, + unsigned metaTOK, + int* pHashCode) +{ + return original_ICorJitInfo->tryGetNonRandomizedHashCode(module, metaTOK, pHashCode); +} + size_t interceptor_ICJI::printObjectDescription( CORINFO_OBJECT_HANDLE handle, char* buffer, diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index fafda8ea9fda18..b2689f100c5cf4 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -373,6 +373,15 @@ int MyICJI::getStringLiteral(CORINFO_MODULE_HANDLE module, /* IN */ return jitInstance->mc->repGetStringLiteral(module, metaTOK, buffer, bufferSize, startIndex); } +bool MyICJI::tryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, /* IN */ + unsigned metaTOK, /* IN */ + int* pHashCode /* OUT */ + ) +{ + jitInstance->mc->cr->AddCall("tryGetNonRandomizedHashCode"); + return jitInstance->mc->repTryGetNonRandomizedHashCode(module, metaTOK, pHashCode); +} + size_t MyICJI::printObjectDescription(CORINFO_OBJECT_HANDLE handle, /* IN */ char* buffer, /* OUT */ size_t bufferSize, /* IN */ diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index d3c9285468b28e..662779d4dfd1a1 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -649,6 +649,83 @@ int CEEInfo::getStringLiteral ( return result; } + +bool CEEInfo::tryGetNonRandomizedHashCode ( + CORINFO_MODULE_HANDLE moduleHnd, + mdToken metaTOK, + int* pHashCode) +{ + CONTRACTL{ + THROWS; + GC_TRIGGERS; + MODE_PREEMPTIVE; + } CONTRACTL_END; + + Module* module = GetModule(moduleHnd); + + bool result = false; + + JIT_TO_EE_TRANSITION(); + + + if (IsDynamicScope(moduleHnd)) + { + //GCX_COOP(); + //STRINGREF strRef = GetDynamicResolver(moduleHnd)->GetStringLiteral(metaTOK); + //if (strRef != NULL) + //{ + // StringObject* strObj = STRINGREFToObject(strRef); + // int length = (int)strObj->GetStringLength(); + // result = (length >= startIndex) ? (length - startIndex) : 0; + // if (buffer != NULL && result != 0) + // { + // memcpyNoGCRefs(buffer, strObj->GetBuffer() + startIndex, min(bufferSize, result) * sizeof(char16_t)); + // } + //} + } + else + { + ULONG dwCharCount; + LPCWSTR pString; + if (!FAILED((module)->GetMDImport()->GetUserString(metaTOK, &dwCharCount, NULL, &pString))) + { + _ASSERTE(dwCharCount >= 0 && dwCharCount <= INT_MAX); + _ASSERTE(pString != nullptr); + + ULONG length = dwCharCount; + + uint32_t hash1 = (5381 << 16) + 5381; + uint32_t hash2 = hash1; + + uint32_t* ptr = (uint32_t*)pString; + + auto RotateLeft = [](uint32_t value, int offset) -> uint32_t { + return (value << offset) | (value >> (32 - offset)); + }; + + while (length > 2) + { + length -= 4; + hash1 = (RotateLeft(hash1, 5) + hash1) ^ ptr[0]; + hash2 = (RotateLeft(hash2, 5) + hash2) ^ ptr[1]; + ptr += 2; + } + + if (length > 0) + { + hash2 = (RotateLeft(hash2, 5) + hash2) ^ ptr[0]; + } + + *pHashCode = (int)(hash1 + (hash2 * 1566083941)); + result = true; + } + } + + EE_TO_JIT_TRANSITION(); + + return result; +} + size_t CEEInfo::printObjectDescription ( CORINFO_OBJECT_HANDLE handle, char* buffer, From e487132509dd03166a390f98c023fd1fefc6682d Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 5 Jul 2025 15:26:24 +0200 Subject: [PATCH 4/7] Fix impl --- src/coreclr/jit/gentree.cpp | 11 ++++-- src/coreclr/jit/importer.cpp | 9 +++-- src/coreclr/jit/importercalls.cpp | 6 +++ src/coreclr/vm/corelib.h | 1 + src/coreclr/vm/jitinterface.cpp | 63 ++++++------------------------- 5 files changed, 32 insertions(+), 58 deletions(-) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 8a08c47d16966f..4176400bef0215 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -12213,19 +12213,22 @@ void Compiler::gtDispConst(GenTree* tree) break; } - char16_t str[512] = {}; - int len = info.compCompHnd->getStringLiteral(cnsStr->gtScpHnd, cnsStr->gtSconCPX, str, sizeof(str)); + const int MaxLiteralLen = 512; + char16_t str[MaxLiteralLen] = {}; + int len = info.compCompHnd->getStringLiteral(cnsStr->gtScpHnd, cnsStr->gtSconCPX, str, sizeof(str)); if (len == 0) { printf("\"\""); } - else if (len < 0) + else if ((len < 0) || (len >= MaxLiteralLen)) { printf(""); } else { - printf("\"%.32s\"", convertUtf16ToUtf8ForPrinting(reinterpret_cast(str))); + // Trim the string to 64 characters for printing + printf("\"%.64s%s\"", convertUtf16ToUtf8ForPrinting(reinterpret_cast(str)), + len > 64 ? "..." : ""); } } break; diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 1361ee615e0a8e..504058da30e92e 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -13853,9 +13853,12 @@ GenTree* Compiler::impInlineFetchArg(InlArgInfo& argInfo, const InlLclVarInfo& l // Cache the relevant arg and lcl info for this argument. // We will modify argInfo but not lclVarInfo. - const bool argCanBeModified = (argInfo.argHasLdargaOp || argInfo.argHasStargOp) && !argNode->OperIs(GT_CNS_STR); - const var_types lclTyp = lclInfo.lclTypeInfo; - GenTree* op1 = nullptr; + + // NOTE: Any attempt to modify CNS_STR is an Undefined Behavior, + // so we can ignore argHasLdargaOp/argHasStargOp for them + const bool argCanBeModified = (argInfo.argHasLdargaOp || argInfo.argHasStargOp) && !argNode->OperIs(GT_CNS_STR); + const var_types lclTyp = lclInfo.lclTypeInfo; + GenTree* op1 = nullptr; // For TYP_REF args, if the argNode doesn't have any class information // we will lose some type info if we directly substitute it. diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 462706182df1be..603f483d9aa980 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -3554,6 +3554,12 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, if (opts.OptimizationEnabled() && impStackTop().val->OperIs(GT_CNS_STR)) { GenTreeStrCon* strCon = impStackTop().val->AsStrCon(); + + if (strCon->IsStringEmptyField()) + { + break; + } + int hashCode = 0; if (info.compCompHnd->tryGetNonRandomizedHashCode(strCon->gtScpHnd, strCon->gtSconCPX, &hashCode)) { diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 40525a6f65c731..f873afdc14b26d 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -927,6 +927,7 @@ DEFINE_METHOD(STRING, CTORF_READONLYSPANOFCHAR,Ctor, DEFINE_METHOD(STRING, CTORF_SBYTEPTR, Ctor, SM_PtrSByt_RetStr) DEFINE_METHOD(STRING, CTORF_SBYTEPTR_START_LEN, Ctor, SM_PtrSByt_Int_Int_RetStr) DEFINE_METHOD(STRING, CTORF_SBYTEPTR_START_LEN_ENCODING, Ctor, SM_PtrSByt_Int_Int_Encoding_RetStr) +DEFINE_METHOD(STRING, GETNONRANDOMIZEDHASHCODE, GetNonRandomizedHashCode, IM_RetInt) DEFINE_METHOD(STRING, INTERNAL_COPY, InternalCopy, SM_Str_IntPtr_Int_RetVoid) DEFINE_METHOD(STRING, WCSLEN, wcslen, SM_PtrChar_RetInt) DEFINE_METHOD(STRING, STRLEN, strlen, SM_PtrByte_RetInt) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 662779d4dfd1a1..16886bdb4a79cb 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -649,7 +649,6 @@ int CEEInfo::getStringLiteral ( return result; } - bool CEEInfo::tryGetNonRandomizedHashCode ( CORINFO_MODULE_HANDLE moduleHnd, mdToken metaTOK, @@ -661,62 +660,24 @@ bool CEEInfo::tryGetNonRandomizedHashCode ( MODE_PREEMPTIVE; } CONTRACTL_END; - Module* module = GetModule(moduleHnd); - bool result = false; JIT_TO_EE_TRANSITION(); - - if (IsDynamicScope(moduleHnd)) - { - //GCX_COOP(); - //STRINGREF strRef = GetDynamicResolver(moduleHnd)->GetStringLiteral(metaTOK); - //if (strRef != NULL) - //{ - // StringObject* strObj = STRINGREFToObject(strRef); - // int length = (int)strObj->GetStringLength(); - // result = (length >= startIndex) ? (length - startIndex) : 0; - // if (buffer != NULL && result != 0) - // { - // memcpyNoGCRefs(buffer, strObj->GetBuffer() + startIndex, min(bufferSize, result) * sizeof(char16_t)); - // } - //} - } - else + if (!IsDynamicScope(moduleHnd)) { - ULONG dwCharCount; - LPCWSTR pString; - if (!FAILED((module)->GetMDImport()->GetUserString(metaTOK, &dwCharCount, NULL, &pString))) + // If ResolveStringRef returns a pinned reference we can return it by value (IAT_VALUE) + CORINFO_OBJECT_HANDLE pPinnedString = nullptr; + reinterpret_cast(moduleHnd)->ResolveStringRef(metaTOK, reinterpret_cast(&pPinnedString)); + if (pPinnedString != nullptr) { - _ASSERTE(dwCharCount >= 0 && dwCharCount <= INT_MAX); - _ASSERTE(pString != nullptr); - - ULONG length = dwCharCount; - - uint32_t hash1 = (5381 << 16) + 5381; - uint32_t hash2 = hash1; - - uint32_t* ptr = (uint32_t*)pString; - - auto RotateLeft = [](uint32_t value, int offset) -> uint32_t { - return (value << offset) | (value >> (32 - offset)); - }; - - while (length > 2) - { - length -= 4; - hash1 = (RotateLeft(hash1, 5) + hash1) ^ ptr[0]; - hash2 = (RotateLeft(hash2, 5) + hash2) ^ ptr[1]; - ptr += 2; - } - - if (length > 0) - { - hash2 = (RotateLeft(hash2, 5) + hash2) ^ ptr[0]; - } - - *pHashCode = (int)(hash1 + (hash2 * 1566083941)); + GCX_COOP(); + PREPARE_NONVIRTUAL_CALLSITE(METHOD__STRING__GETNONRANDOMIZEDHASHCODE); + DECLARE_ARGHOLDER_ARRAY(args, 1); + args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(getObjectFromJitHandle(pPinnedString)); + int hashCode; + CALL_MANAGED_METHOD(hashCode, int, args); + *pHashCode = hashCode; result = true; } } From b566216012af129490a7e7e010ca395d7ab59771 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 5 Jul 2025 17:13:50 +0200 Subject: [PATCH 5/7] fix assert --- src/coreclr/jit/importer.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index d4fedc8173655c..db7857e31fb170 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -13861,9 +13861,8 @@ GenTree* Compiler::impInlineFetchArg(InlArgInfo& argInfo, const InlLclVarInfo& l // Cache the relevant arg and lcl info for this argument. // We will modify argInfo but not lclVarInfo. - // NOTE: Any attempt to modify CNS_STR is an Undefined Behavior, - // so we can ignore argHasLdargaOp/argHasStargOp for them - const bool argCanBeModified = (argInfo.argHasLdargaOp || argInfo.argHasStargOp) && !argNode->OperIs(GT_CNS_STR); + // NOTE: Any attempt to modify CNS_STR is an Undefined Behavior, so we can ignore argHasLdargaOp for them + const bool argCanBeModified = ((argInfo.argHasLdargaOp && !argNode->OperIs(GT_CNS_STR)) || argInfo.argHasStargOp); const var_types lclTyp = lclInfo.lclTypeInfo; GenTree* op1 = nullptr; From c26ea4814c1ba887ca0a9866ee00de54c1b6a7c6 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 5 Jul 2025 20:08:53 +0200 Subject: [PATCH 6/7] Add IgnoreCase --- src/coreclr/inc/corinfo.h | 3 ++- src/coreclr/inc/icorjitinfoimpl_generated.h | 1 + src/coreclr/inc/jiteeversionguid.h | 10 ++++---- .../jit/ICorJitInfo_wrapper_generated.hpp | 3 ++- src/coreclr/jit/importercalls.cpp | 23 +++++++++++-------- src/coreclr/jit/namedintrinsiclist.h | 1 + .../tools/Common/JitInterface/CorInfoImpl.cs | 2 +- .../JitInterface/CorInfoImpl_generated.cs | 6 ++--- .../ThunkGenerator/ThunkInput.txt | 2 +- .../aot/jitinterface/jitinterface_generated.h | 5 ++-- .../tools/superpmi/superpmi-shared/lwmlist.h | 2 +- .../superpmi-shared/methodcontext.cpp | 16 +++++++------ .../superpmi/superpmi-shared/methodcontext.h | 6 ++--- .../superpmi-shim-collector/icorjitinfo.cpp | 11 +++++---- .../icorjitinfo_generated.cpp | 3 ++- .../icorjitinfo_generated.cpp | 3 ++- .../tools/superpmi/superpmi/icorjitinfo.cpp | 9 ++++---- src/coreclr/vm/corelib.h | 3 ++- src/coreclr/vm/jitinterface.cpp | 18 ++++++++++++--- .../NonRandomizedStringEqualityComparer.cs | 2 +- .../src/System/String.Comparison.cs | 5 ++-- 21 files changed, 81 insertions(+), 53 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index b1a9355395c1ce..b814cce8434c1d 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -2293,7 +2293,8 @@ class ICorStaticInfo virtual bool tryGetNonRandomizedHashCode ( CORINFO_MODULE_HANDLE module, /* IN */ unsigned metaTOK, /* IN */ - int32_t* pHashCode /* OUT */ + bool ignoreCase, /* IN */ + int32_t* pHashCode /* OUT */ ) = 0; //------------------------------------------------------------------------------ diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 63c98f8cb72379..01b3ada6d4e251 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -175,6 +175,7 @@ int getStringLiteral( bool tryGetNonRandomizedHashCode( CORINFO_MODULE_HANDLE module, unsigned metaTOK, + bool ignoreCase, int* pHashCode) override; size_t printObjectDescription( diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index d69f73576a6d72..d450009e26ced1 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -37,11 +37,11 @@ #include -constexpr GUID JITEEVersionIdentifier = { /* b54dc26c-62aa-4fba-a58c-106ba601d2ba */ - 0xb54dc26c, - 0x62aa, - 0x4fba, - {0xa5, 0x8c, 0x10, 0x6b, 0xa6, 0x01, 0xd2, 0xba} +constexpr GUID JITEEVersionIdentifier = { /* 656cf7ee-3332-4a85-abac-ef24dc2980a6 */ + 0x656cf7ee, + 0x3332, + 0x4a85, + {0xab, 0xac, 0xef, 0x24, 0xdc, 0x29, 0x80, 0xa6} }; #endif // JIT_EE_VERSIONING_GUID_H diff --git a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp index 5f14a752733f7f..7766cbc9153816 100644 --- a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp +++ b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp @@ -368,10 +368,11 @@ int WrapICorJitInfo::getStringLiteral( bool WrapICorJitInfo::tryGetNonRandomizedHashCode( CORINFO_MODULE_HANDLE module, unsigned metaTOK, + bool ignoreCase, int* pHashCode) { API_ENTER(tryGetNonRandomizedHashCode); - bool temp = wrapHnd->tryGetNonRandomizedHashCode(module, metaTOK, pHashCode); + bool temp = wrapHnd->tryGetNonRandomizedHashCode(module, metaTOK, ignoreCase, pHashCode); API_LEAVE(tryGetNonRandomizedHashCode); return temp; } diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 1f9b9d530c3e54..a21751fc99e166 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -3613,23 +3613,22 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, } case NI_System_String_GetNonRandomizedHashCode: + case NI_System_String_GetNonRandomizedHashCodeOrdinalIgnoreCase: { assert(sig->numArgs == 0); assert(sig->hasThis()); if (opts.OptimizationEnabled() && impStackTop().val->OperIs(GT_CNS_STR)) { GenTreeStrCon* strCon = impStackTop().val->AsStrCon(); - - if (strCon->IsStringEmptyField()) - { - break; - } - - int hashCode = 0; - if (info.compCompHnd->tryGetNonRandomizedHashCode(strCon->gtScpHnd, strCon->gtSconCPX, &hashCode)) + if (!strCon->IsStringEmptyField()) { - impPopStack(); - retNode = gtNewIconNode(hashCode, TYP_INT); + bool ignoreCase = (ni == NI_System_String_GetNonRandomizedHashCodeOrdinalIgnoreCase); + int hashCode = 0; + if (info.compCompHnd->tryGetNonRandomizedHashCode(strCon->gtScpHnd, strCon->gtSconCPX, ignoreCase, &hashCode)) + { + impPopStack(); + retNode = gtNewIconNode(hashCode, TYP_INT); + } } } break; @@ -10305,6 +10304,10 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) { result = NI_System_String_GetNonRandomizedHashCode; } + else if (strcmp(methodName, "GetNonRandomizedHashCodeOrdinalIgnoreCase") == 0) + { + result = NI_System_String_GetNonRandomizedHashCodeOrdinalIgnoreCase; + } else if (strcmp(methodName, "get_Chars") == 0) { result = NI_System_String_get_Chars; diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h index 546cfc245d2a14..4ea7eba8eb99ba 100644 --- a/src/coreclr/jit/namedintrinsiclist.h +++ b/src/coreclr/jit/namedintrinsiclist.h @@ -133,6 +133,7 @@ enum NamedIntrinsic : unsigned short NI_System_String_Equals, NI_System_String_GetNonRandomizedHashCode, + NI_System_String_GetNonRandomizedHashCodeOrdinalIgnoreCase, NI_System_String_get_Chars, NI_System_String_get_Length, NI_System_String_op_Implicit, diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 912bcc1f9c5fba..d517f36c5472c8 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -1967,7 +1967,7 @@ private int getStringLiteral(CORINFO_MODULE_STRUCT_* module, uint metaTOK, char* return result; } - private bool tryGetNonRandomizedHashCode(CORINFO_MODULE_STRUCT_* module, uint metaTOK, ref int pHashCode) + private bool tryGetNonRandomizedHashCode(CORINFO_MODULE_STRUCT_* module, uint metaTOK, bool ignoreCase, ref int pHashCode) { return false; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index e4e308a53a4685..56a97d12b790b5 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -539,12 +539,12 @@ private static int _getStringLiteral(IntPtr thisHandle, IntPtr* ppException, COR } [UnmanagedCallersOnly] - private static byte _tryGetNonRandomizedHashCode(IntPtr thisHandle, IntPtr* ppException, CORINFO_MODULE_STRUCT_* module, uint metaTOK, int* pHashCode) + private static byte _tryGetNonRandomizedHashCode(IntPtr thisHandle, IntPtr* ppException, CORINFO_MODULE_STRUCT_* module, uint metaTOK, byte ignoreCase, int* pHashCode) { var _this = GetThis(thisHandle); try { - return _this.tryGetNonRandomizedHashCode(module, metaTOK, ref *pHashCode) ? (byte)1 : (byte)0; + return _this.tryGetNonRandomizedHashCode(module, metaTOK, ignoreCase != 0, ref *pHashCode) ? (byte)1 : (byte)0; } catch (Exception ex) { @@ -2704,7 +2704,7 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[33] = (delegate* unmanaged)&_findCallSiteSig; callbacks[34] = (delegate* unmanaged)&_getTokenTypeAsHandle; callbacks[35] = (delegate* unmanaged)&_getStringLiteral; - callbacks[36] = (delegate* unmanaged)&_tryGetNonRandomizedHashCode; + callbacks[36] = (delegate* unmanaged)&_tryGetNonRandomizedHashCode; callbacks[37] = (delegate* unmanaged)&_printObjectDescription; callbacks[38] = (delegate* unmanaged)&_asCorInfoType; callbacks[39] = (delegate* unmanaged)&_getClassNameFromMetadata; diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index ce816764f5ce26..e7640498aee674 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -202,7 +202,7 @@ FUNCTIONS void findCallSiteSig( CORINFO_MODULE_HANDLE module,unsigned methTOK, CORINFO_CONTEXT_HANDLE context, CORINFO_SIG_INFO *sig) CORINFO_CLASS_HANDLE getTokenTypeAsHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken) int getStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, char16_t* buffer, int bufferSize, int startIndex) - bool tryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* pHashCode); + bool tryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, unsigned metaTOK, bool ignoreCase, int* pHashCode); size_t printObjectDescription(CORINFO_OBJECT_HANDLE handle, char* buffer, size_t bufferSize, size_t* pRequiredBufferSize) CorInfoType asCorInfoType(CORINFO_CLASS_HANDLE cls) const char* getClassNameFromMetadata(CORINFO_CLASS_HANDLE cls, const char **namespaceName) diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h index 4b456e2e5d22eb..276847d7c13c95 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h @@ -47,7 +47,7 @@ struct JitInterfaceCallbacks void (* findCallSiteSig)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned methTOK, CORINFO_CONTEXT_HANDLE context, CORINFO_SIG_INFO* sig); CORINFO_CLASS_HANDLE (* getTokenTypeAsHandle)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken); int (* getStringLiteral)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned metaTOK, char16_t* buffer, int bufferSize, int startIndex); - bool (* tryGetNonRandomizedHashCode)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* pHashCode); + bool (* tryGetNonRandomizedHashCode)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned metaTOK, bool ignoreCase, int* pHashCode); size_t (* printObjectDescription)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_OBJECT_HANDLE handle, char* buffer, size_t bufferSize, size_t* pRequiredBufferSize); CorInfoType (* asCorInfoType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); const char* (* getClassNameFromMetadata)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls, const char** namespaceName); @@ -562,10 +562,11 @@ class JitInterfaceWrapper : public ICorJitInfo virtual bool tryGetNonRandomizedHashCode( CORINFO_MODULE_HANDLE module, unsigned metaTOK, + bool ignoreCase, int* pHashCode) { CorInfoExceptionClass* pException = nullptr; - bool temp = _callbacks->tryGetNonRandomizedHashCode(_thisHandle, &pException, module, metaTOK, pHashCode); + bool temp = _callbacks->tryGetNonRandomizedHashCode(_thisHandle, &pException, module, metaTOK, ignoreCase, pHashCode); if (pException != nullptr) throw pException; return temp; } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h index 1185b6156270dc..bb611299baac6b 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -158,7 +158,7 @@ LWM(ExpandRawHandleIntrinsic, Agnostic_ExpandRawHandleIntrinsic, Agnostic_CORINF LWM(IsIntrinsicType, DWORDLONG, DWORD) LWM(IsSDArray, DWORDLONG, DWORD) LWM(GetStringLiteral, DLDDD, DD) -LWM(TryGetNonRandomizedHashCode, DLD, DD) +LWM(TryGetNonRandomizedHashCode, DLDD, DD) LWM(PrintObjectDescription, DWORDLONG, Agnostic_PrintResult) LWM(PrintClassName, DWORDLONG, Agnostic_PrintResult) LWM(PrintFieldName, DWORDLONG, Agnostic_PrintResult) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 2e07cffefd0271..7386427c167f35 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -5240,15 +5240,16 @@ int MethodContext::repGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned me return srcBufferLength; } -void MethodContext::recTryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* pHashCode, bool result) +void MethodContext::recTryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, unsigned metaTOK, bool ignoreCase, int* pHashCode, bool result) { if (TryGetNonRandomizedHashCode == nullptr) - TryGetNonRandomizedHashCode = new LightWeightMap(); + TryGetNonRandomizedHashCode = new LightWeightMap(); - DLD key; + DLDD key; ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding key.A = CastHandle(module); key.B = (DWORD)metaTOK; + key.C = (DWORD)ignoreCase; DD value; value.A = (DWORD)result; @@ -5258,17 +5259,18 @@ void MethodContext::recTryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, DEBUG_REC(dmpTryGetNonRandomizedHashCode(key, value)); } -void MethodContext::dmpTryGetNonRandomizedHashCode(DLD key, DD value) +void MethodContext::dmpTryGetNonRandomizedHashCode(DLDD key, DD value) { - printf("TryGetNonRandomizedHashCode key mod-%016" PRIX64 " tok-%08X, hashcode-%u, result-%u", key.A, key.B, value.A, value.B); + printf("TryGetNonRandomizedHashCode key mod-%016" PRIX64 " tok-%08X, ignoreCase-%u, hashcode-%u, result-%u", key.A, key.B, key.C, value.A, value.B); } -bool MethodContext::repTryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* pHashCode) +bool MethodContext::repTryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, unsigned metaTOK, bool ignoreCase, int* pHashCode) { - DLD key; + DLDD key; ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding key.A = CastHandle(module); key.B = (DWORD)metaTOK; + key.C = (DWORD)ignoreCase; return false; } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index 0abeb3961abd92..fc8bcf482d5888 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -668,9 +668,9 @@ class MethodContext void dmpGetStringLiteral(DLDDD key, DD value); int repGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, char16_t* buffer, int bufferSize, int startIndex); - void recTryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* pHashCode, bool result); - void dmpTryGetNonRandomizedHashCode(DLD key, DD value); - bool repTryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, unsigned metaTOK, int* pHashCode); + void recTryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, unsigned metaTOK, bool ignoreCase, int* pHashCode, bool result); + void dmpTryGetNonRandomizedHashCode(DLDD key, DD value); + bool repTryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, unsigned metaTOK, bool ignoreCase, int* pHashCode); void recCanCast(CORINFO_CLASS_HANDLE child, CORINFO_CLASS_HANDLE parent, bool result); void dmpCanCast(DLDL key, DWORD value); diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index 9d69232bf0eddf..e57361f866a932 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -446,14 +446,15 @@ int interceptor_ICJI::getStringLiteral(CORINFO_MODULE_HANDLE module, /* IN * return temp; } -bool interceptor_ICJI::tryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, /* IN */ - unsigned metaTOK, /* IN */ - int* pHashCode /* OUT */ +bool interceptor_ICJI::tryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, /* IN */ + unsigned metaTOK, /* IN */ + bool ignoreCase, /* IN */ + int* pHashCode /* OUT */ ) { mc->cr->AddCall("tryGetNonRandomizedHashCode"); - bool temp = original_ICorJitInfo->tryGetNonRandomizedHashCode(module, metaTOK, pHashCode); - mc->recTryGetNonRandomizedHashCode(module, metaTOK, pHashCode, temp); + bool temp = original_ICorJitInfo->tryGetNonRandomizedHashCode(module, metaTOK, ignoreCase, pHashCode); + mc->recTryGetNonRandomizedHashCode(module, metaTOK, ignoreCase, pHashCode, temp); return temp; } 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 b4274d643b45e9..c460ecce1da3c8 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp @@ -310,10 +310,11 @@ int interceptor_ICJI::getStringLiteral( bool interceptor_ICJI::tryGetNonRandomizedHashCode( CORINFO_MODULE_HANDLE module, unsigned metaTOK, + bool ignoreCase, int* pHashCode) { mcs->AddCall("tryGetNonRandomizedHashCode"); - return original_ICorJitInfo->tryGetNonRandomizedHashCode(module, metaTOK, pHashCode); + return original_ICorJitInfo->tryGetNonRandomizedHashCode(module, metaTOK, ignoreCase, pHashCode); } size_t interceptor_ICJI::printObjectDescription( 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 e65ebb918f11d4..34aef6fe5e93c2 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp @@ -274,9 +274,10 @@ int interceptor_ICJI::getStringLiteral( bool interceptor_ICJI::tryGetNonRandomizedHashCode( CORINFO_MODULE_HANDLE module, unsigned metaTOK, + bool ignoreCase, int* pHashCode) { - return original_ICorJitInfo->tryGetNonRandomizedHashCode(module, metaTOK, pHashCode); + return original_ICorJitInfo->tryGetNonRandomizedHashCode(module, metaTOK, ignoreCase, pHashCode); } size_t interceptor_ICJI::printObjectDescription( diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index b2689f100c5cf4..b3aa528285cab6 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -373,13 +373,14 @@ int MyICJI::getStringLiteral(CORINFO_MODULE_HANDLE module, /* IN */ return jitInstance->mc->repGetStringLiteral(module, metaTOK, buffer, bufferSize, startIndex); } -bool MyICJI::tryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, /* IN */ - unsigned metaTOK, /* IN */ - int* pHashCode /* OUT */ +bool MyICJI::tryGetNonRandomizedHashCode(CORINFO_MODULE_HANDLE module, /* IN */ + unsigned metaTOK, /* IN */ + bool ignoreCase, /* IN */ + int* pHashCode /* OUT */ ) { jitInstance->mc->cr->AddCall("tryGetNonRandomizedHashCode"); - return jitInstance->mc->repTryGetNonRandomizedHashCode(module, metaTOK, pHashCode); + return jitInstance->mc->repTryGetNonRandomizedHashCode(module, metaTOK, ignoreCase, pHashCode); } size_t MyICJI::printObjectDescription(CORINFO_OBJECT_HANDLE handle, /* IN */ diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index a3184fc3fb751a..0e49af0afd7857 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -929,7 +929,8 @@ DEFINE_METHOD(STRING, CTORF_READONLYSPANOFCHAR,Ctor, DEFINE_METHOD(STRING, CTORF_SBYTEPTR, Ctor, SM_PtrSByt_RetStr) DEFINE_METHOD(STRING, CTORF_SBYTEPTR_START_LEN, Ctor, SM_PtrSByt_Int_Int_RetStr) DEFINE_METHOD(STRING, CTORF_SBYTEPTR_START_LEN_ENCODING, Ctor, SM_PtrSByt_Int_Int_Encoding_RetStr) -DEFINE_METHOD(STRING, GETNONRANDOMIZEDHASHCODE, GetNonRandomizedHashCode, IM_RetInt) +DEFINE_METHOD(STRING, GET_NONRANDOMIZED_HASHCODE, GetNonRandomizedHashCode, IM_RetInt) +DEFINE_METHOD(STRING, GET_NONRANDOMIZED_HASHCODE_IGNORECASE, GetNonRandomizedHashCodeOrdinalIgnoreCase, IM_RetInt) DEFINE_METHOD(STRING, INTERNAL_COPY, InternalCopy, SM_Str_IntPtr_Int_RetVoid) DEFINE_METHOD(STRING, WCSLEN, wcslen, SM_PtrChar_RetInt) DEFINE_METHOD(STRING, STRLEN, strlen, SM_PtrByte_RetInt) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index f59ef3a824b2b9..666334bbcbe39e 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -652,6 +652,7 @@ int CEEInfo::getStringLiteral ( bool CEEInfo::tryGetNonRandomizedHashCode ( CORINFO_MODULE_HANDLE moduleHnd, mdToken metaTOK, + bool ignoreCase, int* pHashCode) { CONTRACTL{ @@ -672,11 +673,22 @@ bool CEEInfo::tryGetNonRandomizedHashCode ( if (pPinnedString != nullptr) { GCX_COOP(); - PREPARE_NONVIRTUAL_CALLSITE(METHOD__STRING__GETNONRANDOMIZEDHASHCODE); + int hashCode; + DECLARE_ARGHOLDER_ARRAY(args, 1); args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(getObjectFromJitHandle(pPinnedString)); - int hashCode; - CALL_MANAGED_METHOD(hashCode, int, args); + if (ignoreCase) + { + // TODO: don't invoke it for non-ASCII strings - we don't want to trigger and depend on ICU. + PREPARE_NONVIRTUAL_CALLSITE(METHOD__STRING__GET_NONRANDOMIZED_HASHCODE_IGNORECASE); + CALL_MANAGED_METHOD(hashCode, int, args); + } + else + { + PREPARE_NONVIRTUAL_CALLSITE(METHOD__STRING__GET_NONRANDOMIZED_HASHCODE); + CALL_MANAGED_METHOD(hashCode, int, args); + } + *pHashCode = hashCode; result = true; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs index 9bc99f7ef4c826..ff903b17f07d20 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/NonRandomizedStringEqualityComparer.cs @@ -112,7 +112,7 @@ internal OrdinalIgnoreCaseComparer(IEqualityComparer wrappedComparer) : { } - public override bool Equals(string? x, string? y) => string.EqualsOrdinalIgnoreCase(x, y); + public override bool Equals(string? x, string? y) => string.Equals(x, y, StringComparison.OrdinalIgnoreCase); public override int GetHashCode(string? obj) { diff --git a/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs b/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs index d3ceb28de35091..c464d6a976b449 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs @@ -920,6 +920,7 @@ internal static unsafe int GetNonRandomizedHashCode(ReadOnlySpan span) // for both for big-endian and for little-endian. private const uint NormalizeToLowercase = 0x0020_0020u; + [Intrinsic] internal unsafe int GetNonRandomizedHashCodeOrdinalIgnoreCase() { uint hash1 = (5381 << 16) + 5381; @@ -929,9 +930,9 @@ internal unsafe int GetNonRandomizedHashCodeOrdinalIgnoreCase() fixed (char* src = &_firstChar) { Debug.Assert(src[Length] == '\0', "src[this.Length] == '\\0'"); - Debug.Assert(((int) src) % 4 == 0, "Managed string should start at 4 bytes boundary"); + Debug.Assert(((int)src) % 4 == 0, "Managed string should start at 4 bytes boundary"); - uint* ptr = (uint*) src; + uint* ptr = (uint*)src; while (length > 2) { From deb1072f7fd04ed704f10be0d48773a527953cbd Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 5 Jul 2025 20:41:55 +0200 Subject: [PATCH 7/7] clean up --- src/coreclr/jit/importercalls.cpp | 7 ++++--- src/coreclr/vm/jitinterface.cpp | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index a21751fc99e166..2679bbed62da82 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -3617,14 +3617,15 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, { assert(sig->numArgs == 0); assert(sig->hasThis()); - if (opts.OptimizationEnabled() && impStackTop().val->OperIs(GT_CNS_STR)) + if (opts.OptimizationEnabled() && !compCurBB->isRunRarely() && impStackTop().val->OperIs(GT_CNS_STR)) { GenTreeStrCon* strCon = impStackTop().val->AsStrCon(); if (!strCon->IsStringEmptyField()) { bool ignoreCase = (ni == NI_System_String_GetNonRandomizedHashCodeOrdinalIgnoreCase); - int hashCode = 0; - if (info.compCompHnd->tryGetNonRandomizedHashCode(strCon->gtScpHnd, strCon->gtSconCPX, ignoreCase, &hashCode)) + int hashCode = 0; + if (info.compCompHnd->tryGetNonRandomizedHashCode(strCon->gtScpHnd, strCon->gtSconCPX, + ignoreCase, &hashCode)) { impPopStack(); retNode = gtNewIconNode(hashCode, TYP_INT); diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 666334bbcbe39e..832e77c36d0aef 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -679,7 +679,9 @@ bool CEEInfo::tryGetNonRandomizedHashCode ( args[ARGNUM_0] = OBJECTREF_TO_ARGHOLDER(getObjectFromJitHandle(pPinnedString)); if (ignoreCase) { - // TODO: don't invoke it for non-ASCII strings - we don't want to trigger and depend on ICU. + // This may trigger ICU loading for non-ASCII output, but it should be fine. + // In most cases this is called for an optimized code for a hot block, so, presumably + // ICU has already been loaded (e.g by Tier0 code). PREPARE_NONVIRTUAL_CALLSITE(METHOD__STRING__GET_NONRANDOMIZED_HASHCODE_IGNORECASE); CALL_MANAGED_METHOD(hashCode, int, args); }