From 0fdefe26bf33ee6050f4e1a8ce465b3fe64678ab Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 24 Sep 2022 04:38:07 +0200 Subject: [PATCH 01/61] handle static readonly for frozen objects in jit --- src/coreclr/inc/corinfo.h | 5 ++ src/coreclr/inc/icorjitinfoimpl_generated.h | 3 + src/coreclr/inc/jiteeversionguid.h | 10 +-- src/coreclr/jit/ICorJitInfo_API_names.h | 1 + src/coreclr/jit/ICorJitInfo_API_wrapper.hpp | 9 +++ src/coreclr/jit/importer.cpp | 43 +++++++---- .../tools/Common/JitInterface/CorInfoBase.cs | 76 +++++++++++-------- .../tools/Common/JitInterface/CorInfoImpl.cs | 7 ++ .../ThunkGenerator/ThunkInput.txt | 1 + .../tools/aot/jitinterface/jitinterface.h | 10 +++ .../tools/superpmi/superpmi-shared/lwmlist.h | 1 + .../superpmi-shared/methodcontext.cpp | 24 ++++++ .../superpmi/superpmi-shared/methodcontext.h | 5 ++ .../superpmi-shim-collector/icorjitinfo.cpp | 8 ++ .../superpmi-shim-counter/icorjitinfo.cpp | 7 ++ .../superpmi-shim-simple/icorjitinfo.cpp | 6 ++ .../tools/superpmi/superpmi/icorjitinfo.cpp | 6 ++ src/coreclr/vm/jitinterface.cpp | 42 ++++++++++ src/coreclr/vm/jitinterface.h | 1 + 19 files changed, 217 insertions(+), 48 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 848e1a53314c8..f715dee3c3d40 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -3150,6 +3150,11 @@ class ICorDynamicInfo : public ICorStaticInfo void **ppIndirection = NULL ) = 0; + // Returns frozen object handle if field is a static readonly field of an initialized type + virtual void* getFrozenHandleFromInitedStaticField( + CORINFO_FIELD_HANDLE field + ) = 0; + // If pIsSpeculative is NULL, return the class handle for the value of ref-class typed // static readonly fields, if there is a unique location for the static and the class // is already initialized. diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 4e0e1094eb250..9cf06b691da2a 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -605,6 +605,9 @@ void* getFieldAddress( CORINFO_FIELD_HANDLE field, void** ppIndirection) override; +void* getFrozenHandleFromInitedStaticField( + CORINFO_FIELD_HANDLE field) override; + CORINFO_CLASS_HANDLE getStaticFieldCurrentClass( CORINFO_FIELD_HANDLE field, bool* pIsSpeculative) override; diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 8ec7e89f0ef06..0ebe0c417ef48 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 = { /* 11b4ea58-c400-4c3d-995e-4e2f0676f6e8 */ - 0x11b4ea58, - 0xc400, - 0x4c3d, - {0x99, 0x5e, 0x4e, 0x2f, 0x6, 0x76, 0xf6, 0xe8} +constexpr GUID JITEEVersionIdentifier = { /* ebc78c0f-f765-41ea-9cf3-519e36dc6ce2 */ + 0xebc78c0f, + 0xf765, + 0x41ea, + {0x9c, 0xf3, 0x51, 0x9e, 0x36, 0xdc, 0x6c, 0xe2} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/jit/ICorJitInfo_API_names.h b/src/coreclr/jit/ICorJitInfo_API_names.h index 9ebd42f381af6..f0ce623bf568b 100644 --- a/src/coreclr/jit/ICorJitInfo_API_names.h +++ b/src/coreclr/jit/ICorJitInfo_API_names.h @@ -152,6 +152,7 @@ DEF_CLR_API(canAccessFamily) DEF_CLR_API(isRIDClassDomainID) DEF_CLR_API(getClassDomainID) DEF_CLR_API(getFieldAddress) +DEF_CLR_API(getFrozenHandleFromInitedStaticField) DEF_CLR_API(getStaticFieldCurrentClass) DEF_CLR_API(getVarArgsHandle) DEF_CLR_API(canGetVarArgsHandle) diff --git a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp index 4bedcebcf3b0c..11be587704bbf 100644 --- a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp +++ b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp @@ -1450,6 +1450,15 @@ void* WrapICorJitInfo::getFieldAddress( return temp; } +void* WrapICorJitInfo::getFrozenHandleFromInitedStaticField( + CORINFO_FIELD_HANDLE field) +{ + API_ENTER(getFrozenHandleFromInitedStaticField); + void* temp = wrapHnd->getFrozenHandleFromInitedStaticField(field); + API_LEAVE(getFrozenHandleFromInitedStaticField); + return temp; +} + CORINFO_CLASS_HANDLE WrapICorJitInfo::getStaticFieldCurrentClass( CORINFO_FIELD_HANDLE field, bool* pIsSpeculative) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index a42812060d38b..512c88d178167 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -15287,7 +15287,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) // Replace static read-only fields with constant if possible if ((aflags & CORINFO_ACCESS_GET) && (fieldInfo.fieldFlags & CORINFO_FLG_FIELD_FINAL) && !(fieldInfo.fieldFlags & CORINFO_FLG_FIELD_STATIC_IN_HEAP) && - (varTypeIsIntegral(lclTyp) || varTypeIsFloating(lclTyp))) + (varTypeIsIntegral(lclTyp) || varTypeIsFloating(lclTyp) || (lclTyp == TYP_REF))) { CorInfoInitClassResult initClassResult = info.compCompHnd->initClass(resolvedToken.hField, info.compMethodHnd, @@ -15295,22 +15295,39 @@ void Compiler::impImportBlockCode(BasicBlock* block) if (initClassResult & CORINFO_INITCLASS_INITIALIZED) { - void** pFldAddr = nullptr; - void* fldAddr = - info.compCompHnd->getFieldAddress(resolvedToken.hField, (void**)&pFldAddr); + if (varTypeIsIntegral(lclTyp) || varTypeIsFloating(lclTyp)) + { + void** pFldAddr = nullptr; + void* fldAddr = + info.compCompHnd->getFieldAddress(resolvedToken.hField, (void**)&pFldAddr); - // We should always be able to access this static's address directly - // - assert(pFldAddr == nullptr); + // We should always be able to access this static's address directly + // + assert(pFldAddr == nullptr); - op1 = impImportStaticReadOnlyField(fldAddr, lclTyp); + op1 = impImportStaticReadOnlyField(fldAddr, lclTyp); - // Widen small types since we're propagating the value - // instead of producing an indir. - // - op1->gtType = genActualType(lclTyp); + // Widen small types since we're propagating the value + // instead of producing an indir. + // + op1->gtType = genActualType(lclTyp); - goto FIELD_DONE; + goto FIELD_DONE; + } + else + { + assert(lclTyp == TYP_REF); + void* frozenHandle = + info.compCompHnd->getFrozenHandleFromInitedStaticField(resolvedToken.hField); + if (frozenHandle != nullptr) + { + setMethodHasFrozenObjects(); + op1 = gtNewIconEmbHndNode(frozenHandle, nullptr, GTF_ICON_OBJ_HDL, nullptr); + op1->gtType = TYP_REF; + INDEBUG(op1->AsIntCon()->gtTargetHandle = (size_t)frozenHandle); + goto FIELD_DONE; + } + } } } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs index 8d8c426a7130d..d69aa43576f6b 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs @@ -2198,6 +2198,21 @@ private static uint _getClassDomainID(IntPtr thisHandle, IntPtr* ppException, CO } } + [UnmanagedCallersOnly] + private static void* _getFrozenHandleFromInitedStaticField(IntPtr thisHandle, IntPtr* ppException, CORINFO_FIELD_STRUCT_* field) + { + var _this = GetThis(thisHandle); + try + { + return _this.getFrozenHandleFromInitedStaticField(field); + } + catch (Exception ex) + { + *ppException = _this.AllocException(ex); + return default; + } + } + [UnmanagedCallersOnly] private static CORINFO_CLASS_STRUCT_* _getStaticFieldCurrentClass(IntPtr thisHandle, IntPtr* ppException, CORINFO_FIELD_STRUCT_* field, byte* pIsSpeculative) { @@ -2625,7 +2640,7 @@ private static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, CORJIT_ private static IntPtr GetUnmanagedCallbacks() { - void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 177); + void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 178); callbacks[0] = (delegate* unmanaged)&_isIntrinsic; callbacks[1] = (delegate* unmanaged)&_getMethodAttribs; @@ -2775,35 +2790,36 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[145] = (delegate* unmanaged)&_isRIDClassDomainID; callbacks[146] = (delegate* unmanaged)&_getClassDomainID; callbacks[147] = (delegate* unmanaged)&_getFieldAddress; - callbacks[148] = (delegate* unmanaged)&_getStaticFieldCurrentClass; - callbacks[149] = (delegate* unmanaged)&_getVarArgsHandle; - callbacks[150] = (delegate* unmanaged)&_canGetVarArgsHandle; - callbacks[151] = (delegate* unmanaged)&_constructStringLiteral; - callbacks[152] = (delegate* unmanaged)&_emptyStringLiteral; - callbacks[153] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; - callbacks[154] = (delegate* unmanaged)&_addActiveDependency; - callbacks[155] = (delegate* unmanaged)&_GetDelegateCtor; - callbacks[156] = (delegate* unmanaged)&_MethodCompileComplete; - callbacks[157] = (delegate* unmanaged)&_getTailCallHelpers; - callbacks[158] = (delegate* unmanaged)&_convertPInvokeCalliToCall; - callbacks[159] = (delegate* unmanaged)&_notifyInstructionSetUsage; - callbacks[160] = (delegate* unmanaged)&_updateEntryPointForTailCall; - callbacks[161] = (delegate* unmanaged)&_allocMem; - callbacks[162] = (delegate* unmanaged)&_reserveUnwindInfo; - callbacks[163] = (delegate* unmanaged)&_allocUnwindInfo; - callbacks[164] = (delegate* unmanaged)&_allocGCInfo; - callbacks[165] = (delegate* unmanaged)&_setEHcount; - callbacks[166] = (delegate* unmanaged)&_setEHinfo; - callbacks[167] = (delegate* unmanaged)&_logMsg; - callbacks[168] = (delegate* unmanaged)&_doAssert; - callbacks[169] = (delegate* unmanaged)&_reportFatalError; - callbacks[170] = (delegate* unmanaged)&_getPgoInstrumentationResults; - callbacks[171] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; - callbacks[172] = (delegate* unmanaged)&_recordCallSite; - callbacks[173] = (delegate* unmanaged)&_recordRelocation; - callbacks[174] = (delegate* unmanaged)&_getRelocTypeHint; - callbacks[175] = (delegate* unmanaged)&_getExpectedTargetArchitecture; - callbacks[176] = (delegate* unmanaged)&_getJitFlags; + callbacks[148] = (delegate* unmanaged)&_getFrozenHandleFromInitedStaticField; + 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)&_addActiveDependency; + callbacks[156] = (delegate* unmanaged)&_GetDelegateCtor; + callbacks[157] = (delegate* unmanaged)&_MethodCompileComplete; + callbacks[158] = (delegate* unmanaged)&_getTailCallHelpers; + 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; return (IntPtr)callbacks; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index cc087e8b31e21..56235666b4781 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3306,6 +3306,13 @@ private uint getClassDomainID(CORINFO_CLASS_STRUCT_* cls, ref void* ppIndirectio } } +#pragma warning disable CA1822 // Mark members as static + private void* getFrozenHandleFromInitedStaticField(CORINFO_FIELD_STRUCT_* field) +#pragma warning restore CA1822 // Mark members as static + { + return null; + } + private CORINFO_CLASS_STRUCT_* getStaticFieldCurrentClass(CORINFO_FIELD_STRUCT_* field, byte* pIsSpeculative) { if (pIsSpeculative != null) diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index 0294eced60258..89629af04fb78 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -303,6 +303,7 @@ FUNCTIONS bool isRIDClassDomainID(CORINFO_CLASS_HANDLE cls); unsigned getClassDomainID (CORINFO_CLASS_HANDLE cls, void **ppIndirection); void* getFieldAddress(CORINFO_FIELD_HANDLE field, VOIDSTARSTAR ppIndirection); + void* getFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE field); CORINFO_CLASS_HANDLE getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, BoolStar pIsSpeculative); CORINFO_VARARGS_HANDLE getVarArgsHandle(CORINFO_SIG_INFO *pSig, void **ppIndirection); bool canGetVarArgsHandle(CORINFO_SIG_INFO *pSig); diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface.h b/src/coreclr/tools/aot/jitinterface/jitinterface.h index f12f60b98cb9c..6c870466a29b5 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface.h @@ -159,6 +159,7 @@ struct JitInterfaceCallbacks bool (* isRIDClassDomainID)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); unsigned (* getClassDomainID)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls, void** ppIndirection); void* (* getFieldAddress)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, void** ppIndirection); + void* (* getFrozenHandleFromInitedStaticField)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field); CORINFO_CLASS_HANDLE (* getStaticFieldCurrentClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, bool* pIsSpeculative); CORINFO_VARARGS_HANDLE (* getVarArgsHandle)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_SIG_INFO* pSig, void** ppIndirection); bool (* canGetVarArgsHandle)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_SIG_INFO* pSig); @@ -1623,6 +1624,15 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } + virtual void* getFrozenHandleFromInitedStaticField( + CORINFO_FIELD_HANDLE field) +{ + CorInfoExceptionClass* pException = nullptr; + void* temp = _callbacks->getFrozenHandleFromInitedStaticField(_thisHandle, &pException, field); + if (pException != nullptr) throw pException; + return temp; +} + virtual CORINFO_CLASS_HANDLE getStaticFieldCurrentClass( CORINFO_FIELD_HANDLE field, bool* pIsSpeculative) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h index a40f741eea317..4a4b924fbad2c 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -80,6 +80,7 @@ LWM(GetDelegateCtor, Agnostic_GetDelegateCtorIn, Agnostic_GetDelegateCtorOut) LWM(GetEEInfo, DWORD, Agnostic_CORINFO_EE_INFO) LWM(GetEHinfo, DLD, Agnostic_CORINFO_EH_CLAUSE) LWM(GetFieldAddress, DWORDLONG, Agnostic_GetFieldAddress) +LWM(GetFrozenHandleFromInitedStaticField, DWORDLONG, DWORDLONG) LWM(GetStaticFieldCurrentClass, DWORDLONG, Agnostic_GetStaticFieldCurrentClass) LWM(GetFieldClass, DWORDLONG, DWORDLONG) LWM(GetFieldInClass, DLD, DWORDLONG) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 5eea6f742ba21..f375111d6ff9d 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -3653,6 +3653,30 @@ void* MethodContext::repGetFieldAddress(CORINFO_FIELD_HANDLE field, void** ppInd return temp; } +void MethodContext::recGetFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE field, void* result) +{ + if (GetFrozenHandleFromInitedStaticField == nullptr) + GetFrozenHandleFromInitedStaticField = new LightWeightMap(); + + DWORDLONG key = CastHandle(field); + DWORDLONG value = DWORDLONG(result); + GetFrozenHandleFromInitedStaticField->Add(key, value); + DEBUG_REC(dmpGetFrozenHandleFromInitedStaticField(key, value)); +} +void MethodContext::dmpGetFrozenHandleFromInitedStaticField(DWORDLONG key, DWORDLONG value) +{ + printf("GetFrozenHandleFromInitedStaticField key field-%016llX, value field-%016llX", key, value); +} +void* MethodContext::repGetFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE field) +{ + DWORDLONG key = CastHandle(field); + AssertMapAndKeyExist(GetFrozenHandleFromInitedStaticField, key, ": key %016llX", key); + DWORDLONG value = GetFrozenHandleFromInitedStaticField->Get(key); + DEBUG_REP(dmpGetFrozenHandleFromInitedStaticField(key, value)); + void* result = (void*)value; + return result; +} + void MethodContext::recGetStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, bool isSpeculative, CORINFO_CLASS_HANDLE result) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index 96c19e8664d78..9afa759671bd5 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -480,6 +480,10 @@ class MethodContext void dmpGetFieldAddress(DWORDLONG key, const Agnostic_GetFieldAddress& value); void* repGetFieldAddress(CORINFO_FIELD_HANDLE field, void** ppIndirection); + void recGetFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE field, void* result); + void dmpGetFrozenHandleFromInitedStaticField(DWORDLONG key, DWORDLONG value); + void* repGetFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE field); + void recGetStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, bool isSpeculative, CORINFO_CLASS_HANDLE result); void dmpGetStaticFieldCurrentClass(DWORDLONG key, const Agnostic_GetStaticFieldCurrentClass& value); CORINFO_CLASS_HANDLE repGetStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, bool* pIsSpeculative); @@ -1139,6 +1143,7 @@ enum mcPackets Packet_GetExactClasses = 195, Packet_GetRuntimeTypePointer = 196, Packet_ObjectToString = 197, + Packet_GetFrozenHandleFromInitedStaticField = 198, }; 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 b19faebf60967..eaca5917bffa0 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -1723,6 +1723,14 @@ void* interceptor_ICJI::getFieldAddress(CORINFO_FIELD_HANDLE field, void** ppInd return temp; } +void* interceptor_ICJI::getFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE field) +{ + mc->cr->AddCall("getFrozenHandleFromInitedStaticField"); + void* result = original_ICorJitInfo->getFrozenHandleFromInitedStaticField(field); + mc->recGetFrozenHandleFromInitedStaticField(field, result); + return result; +} + // return the class handle for the current value of a static field CORINFO_CLASS_HANDLE interceptor_ICJI::getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, bool* pIsSpeculative) { diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp index 2a12825c89907..0ab289b5be48f 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -1188,6 +1188,13 @@ void* interceptor_ICJI::getFieldAddress( return original_ICorJitInfo->getFieldAddress(field, ppIndirection); } +void* interceptor_ICJI::getFrozenHandleFromInitedStaticField( + CORINFO_FIELD_HANDLE field) +{ + mcs->AddCall("getFrozenHandleFromInitedStaticField"); + return original_ICorJitInfo->getFrozenHandleFromInitedStaticField(field); +} + CORINFO_CLASS_HANDLE interceptor_ICJI::getStaticFieldCurrentClass( CORINFO_FIELD_HANDLE field, bool* pIsSpeculative) diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp index 808ccc3ab473d..a44a5de5ec484 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -1040,6 +1040,12 @@ void* interceptor_ICJI::getFieldAddress( return original_ICorJitInfo->getFieldAddress(field, ppIndirection); } +void* interceptor_ICJI::getFrozenHandleFromInitedStaticField( + CORINFO_FIELD_HANDLE field) +{ + return original_ICorJitInfo->getFrozenHandleFromInitedStaticField(field); +} + CORINFO_CLASS_HANDLE interceptor_ICJI::getStaticFieldCurrentClass( CORINFO_FIELD_HANDLE field, bool* pIsSpeculative) diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index efdfafffb8d3b..0005a7367cb21 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -1503,6 +1503,12 @@ void* MyICJI::getFieldAddress(CORINFO_FIELD_HANDLE field, void** ppIndirection) return jitInstance->mc->repGetFieldAddress(field, ppIndirection); } +void* MyICJI::getFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE field) +{ + jitInstance->mc->cr->AddCall("getFrozenHandleFromInitedStaticField"); + return jitInstance->mc->repGetFrozenHandleFromInitedStaticField(field); +} + // return the class handle for the current value of a static field CORINFO_CLASS_HANDLE MyICJI::getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, bool* pIsSpeculative) { diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 2aa473dc6e9d7..391fb5562d73a 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11788,6 +11788,42 @@ void* CEEJitInfo::getFieldAddress(CORINFO_FIELD_HANDLE fieldHnd, return result; } +void* CEEJitInfo::getFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE fieldHnd) +{ + CONTRACTL { + THROWS; + GC_TRIGGERS; + MODE_PREEMPTIVE; + } CONTRACTL_END; + + void* ptr = nullptr; + + JIT_TO_EE_TRANSITION(); + + bool isSpeculative; + if (getStaticFieldCurrentClass(fieldHnd, &isSpeculative) != NULL && !isSpeculative) + { + GCX_COOP(); + + FieldDesc* field = (FieldDesc*)fieldHnd; + _ASSERT(field->IsStatic() && field->IsObjRef()); + OBJECTREF fieldObj = field->GetStaticOBJECTREF(); + if (fieldObj != NULL) + { + Object* obj = OBJECTREFToObject(fieldObj); + if (!obj->GetMethodTable()->GetLoaderAllocator()->CanUnload() && + GCHeapUtilities::GetGCHeap()->IsInFrozenSegment(obj)) + { + ptr = (void*)obj; + } + } + } + + EE_TO_JIT_TRANSITION(); + + return ptr; +} + /*********************************************************************/ CORINFO_CLASS_HANDLE CEEJitInfo::getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE fieldHnd, bool* pIsSpeculative) @@ -14328,6 +14364,12 @@ void* CEEInfo::getFieldAddress(CORINFO_FIELD_HANDLE fieldHnd, return result; } +void* CEEInfo::getFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE CORINFO_FIELD_HANDLE) +{ + LIMITED_METHOD_CONTRACT; + UNREACHABLE(); // only called on derived class. +} + CORINFO_CLASS_HANDLE CEEInfo::getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE fieldHnd, bool* pIsSpeculative) { diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 9b517406ce4f1..be86632d80576 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -925,6 +925,7 @@ class CEEJitInfo : public CEEInfo InfoAccessType constructStringLiteral(CORINFO_MODULE_HANDLE scopeHnd, mdToken metaTok, void **ppValue) override final; InfoAccessType emptyStringLiteral(void ** ppValue) override final; void* getFieldAddress(CORINFO_FIELD_HANDLE field, void **ppIndirection) override final; + void* getFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE field) override final; CORINFO_CLASS_HANDLE getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, bool* pIsSpeculative) override final; void* getMethodSync(CORINFO_METHOD_HANDLE ftnHnd, void **ppIndirection) override final; From 07fdafc9a9583674763f94b728f7f8e533b695d1 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 24 Sep 2022 05:28:53 +0200 Subject: [PATCH 02/61] Address Jan's feedback --- src/coreclr/vm/jitinterface.cpp | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 391fb5562d73a..e73bbf143cfbd 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11800,21 +11800,26 @@ void* CEEJitInfo::getFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE fiel JIT_TO_EE_TRANSITION(); - bool isSpeculative; - if (getStaticFieldCurrentClass(fieldHnd, &isSpeculative) != NULL && !isSpeculative) + FieldDesc* field = (FieldDesc*)fieldHnd; + if (field->IsStatic() && field->IsObjRef() && !field->IsThreadStatic()) { - GCX_COOP(); - - FieldDesc* field = (FieldDesc*)fieldHnd; - _ASSERT(field->IsStatic() && field->IsObjRef()); - OBJECTREF fieldObj = field->GetStaticOBJECTREF(); - if (fieldObj != NULL) + MethodTable* pEnclosingMT = field->GetEnclosingMethodTable(); + if (!pEnclosingMT->IsSharedByGenericInstantiations()) { - Object* obj = OBJECTREFToObject(fieldObj); - if (!obj->GetMethodTable()->GetLoaderAllocator()->CanUnload() && - GCHeapUtilities::GetGCHeap()->IsInFrozenSegment(obj)) + // Allocate space for the local class if necessary, but don't trigger + // class construction. + DomainLocalModule* pLocalModule = pEnclosingMT->GetDomainLocalModule(); + pLocalModule->PopulateClass(pEnclosingMT); + + GCX_COOP(); + OBJECTREF fieldObj = field->GetStaticOBJECTREF(); + if (fieldObj != NULL && pEnclosingMT->IsClassInited() && IsFdInitOnly(field->GetAttributes())) { - ptr = (void*)obj; + Object* obj = OBJECTREFToObject(fieldObj); + if (GCHeapUtilities::GetGCHeap()->IsInFrozenSegment(obj)) + { + ptr = (void*)obj; + } } } } From ad6914595caf42667338649ee9b3fca3e2692886 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 24 Sep 2022 08:20:38 +0200 Subject: [PATCH 03/61] Address feedback --- src/coreclr/inc/corinfo.h | 11 +- src/coreclr/inc/icorjitinfoimpl_generated.h | 5 +- src/coreclr/jit/ICorJitInfo_API_names.h | 2 +- src/coreclr/jit/ICorJitInfo_API_wrapper.hpp | 11 +- src/coreclr/jit/compiler.h | 2 +- src/coreclr/jit/importer.cpp | 173 ++++-------------- .../tools/Common/JitInterface/CorInfoBase.cs | 6 +- .../tools/Common/JitInterface/CorInfoImpl.cs | 4 +- .../ThunkGenerator/ThunkInput.txt | 4 +- .../tools/aot/jitinterface/jitinterface.h | 9 +- .../tools/superpmi/superpmi-shared/lwmlist.h | 2 +- .../superpmi-shared/methodcontext.cpp | 53 ++++-- .../superpmi/superpmi-shared/methodcontext.h | 8 +- .../superpmi-shim-collector/icorjitinfo.cpp | 8 +- .../superpmi-shim-counter/icorjitinfo.cpp | 9 +- .../superpmi-shim-simple/icorjitinfo.cpp | 7 +- .../tools/superpmi/superpmi/icorjitinfo.cpp | 6 +- src/coreclr/vm/jitinterface.cpp | 92 +++++++++- src/coreclr/vm/jitinterface.h | 2 +- 19 files changed, 209 insertions(+), 205 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index f715dee3c3d40..f812e70881055 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -3150,9 +3150,14 @@ class ICorDynamicInfo : public ICorStaticInfo void **ppIndirection = NULL ) = 0; - // Returns frozen object handle if field is a static readonly field of an initialized type - virtual void* getFrozenHandleFromInitedStaticField( - CORINFO_FIELD_HANDLE field + // Returns true if the given field is "static readonly" and its value will never change + // also, returns its actual value via pValue argument. For now, it's either: + // * integer/floating point primitive + // * null + // * frozen object + virtual bool getReadonlyStaticFieldValue( + CORINFO_FIELD_HANDLE field, + uint64_t *pValue ) = 0; // If pIsSpeculative is NULL, return the class handle for the value of ref-class typed diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 9cf06b691da2a..70a8ff6d468fd 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -605,8 +605,9 @@ void* getFieldAddress( CORINFO_FIELD_HANDLE field, void** ppIndirection) override; -void* getFrozenHandleFromInitedStaticField( - CORINFO_FIELD_HANDLE field) override; +bool getReadonlyStaticFieldValue( + CORINFO_FIELD_HANDLE field, + uint64_t* pValue) override; CORINFO_CLASS_HANDLE getStaticFieldCurrentClass( CORINFO_FIELD_HANDLE field, diff --git a/src/coreclr/jit/ICorJitInfo_API_names.h b/src/coreclr/jit/ICorJitInfo_API_names.h index f0ce623bf568b..dc817238d9ab0 100644 --- a/src/coreclr/jit/ICorJitInfo_API_names.h +++ b/src/coreclr/jit/ICorJitInfo_API_names.h @@ -152,7 +152,7 @@ DEF_CLR_API(canAccessFamily) DEF_CLR_API(isRIDClassDomainID) DEF_CLR_API(getClassDomainID) DEF_CLR_API(getFieldAddress) -DEF_CLR_API(getFrozenHandleFromInitedStaticField) +DEF_CLR_API(getReadonlyStaticFieldValue) DEF_CLR_API(getStaticFieldCurrentClass) DEF_CLR_API(getVarArgsHandle) DEF_CLR_API(canGetVarArgsHandle) diff --git a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp index 11be587704bbf..6abbe84472fc3 100644 --- a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp +++ b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp @@ -1450,12 +1450,13 @@ void* WrapICorJitInfo::getFieldAddress( return temp; } -void* WrapICorJitInfo::getFrozenHandleFromInitedStaticField( - CORINFO_FIELD_HANDLE field) +bool WrapICorJitInfo::getReadonlyStaticFieldValue( + CORINFO_FIELD_HANDLE field, + uint64_t* pValue) { - API_ENTER(getFrozenHandleFromInitedStaticField); - void* temp = wrapHnd->getFrozenHandleFromInitedStaticField(field); - API_LEAVE(getFrozenHandleFromInitedStaticField); + API_ENTER(getReadonlyStaticFieldValue); + bool temp = wrapHnd->getReadonlyStaticFieldValue(field, pValue); + API_LEAVE(getReadonlyStaticFieldValue); return temp; } diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 8504476d2cdf6..3e41a94129645 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -3639,7 +3639,7 @@ class Compiler GenTree* impInitClass(CORINFO_RESOLVED_TOKEN* pResolvedToken); - GenTree* impImportStaticReadOnlyField(void* fldAddr, var_types lclTyp); + GenTree* impImportStaticReadOnlyField(UINT64 value, var_types valueType); GenTree* impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_ACCESS_FLAGS access, diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 512c88d178167..bb9475f740d59 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -8083,133 +8083,56 @@ GenTree* Compiler::impInitClass(CORINFO_RESOLVED_TOKEN* pResolvedToken) return node; } -GenTree* Compiler::impImportStaticReadOnlyField(void* fldAddr, var_types lclTyp) +GenTree* Compiler::impImportStaticReadOnlyField(UINT64 value, var_types valueType) { - GenTree* op1 = nullptr; - -#if defined(DEBUG) - // If we're replaying under SuperPMI, we're going to read the data stored by SuperPMI and use it - // for optimization. Unfortunately, SuperPMI doesn't implement a guarantee on the alignment of - // this data, so for some platforms which don't allow unaligned access (e.g., Linux arm32), - // this can fault. We should fix SuperPMI to guarantee alignment, but that is a big change. - // Instead, simply fix up the data here for future use. - - // This variable should be the largest size element, with the largest alignment requirement, - // and the native C++ compiler should guarantee sufficient alignment. - double aligned_data = 0.0; - void* p_aligned_data = &aligned_data; - if (info.compMethodSuperPMIIndex != -1) - { - switch (lclTyp) - { - case TYP_BOOL: - case TYP_BYTE: - case TYP_UBYTE: - static_assert_no_msg(sizeof(unsigned __int8) == sizeof(bool)); - static_assert_no_msg(sizeof(unsigned __int8) == sizeof(signed char)); - static_assert_no_msg(sizeof(unsigned __int8) == sizeof(unsigned char)); - // No alignment necessary for byte. - break; - - case TYP_SHORT: - case TYP_USHORT: - static_assert_no_msg(sizeof(unsigned __int16) == sizeof(short)); - static_assert_no_msg(sizeof(unsigned __int16) == sizeof(unsigned short)); - if ((size_t)fldAddr % sizeof(unsigned __int16) != 0) - { - *(unsigned __int16*)p_aligned_data = GET_UNALIGNED_16(fldAddr); - fldAddr = p_aligned_data; - } - break; - - case TYP_INT: - case TYP_UINT: - case TYP_FLOAT: - static_assert_no_msg(sizeof(unsigned __int32) == sizeof(int)); - static_assert_no_msg(sizeof(unsigned __int32) == sizeof(unsigned int)); - static_assert_no_msg(sizeof(unsigned __int32) == sizeof(float)); - if ((size_t)fldAddr % sizeof(unsigned __int32) != 0) - { - *(unsigned __int32*)p_aligned_data = GET_UNALIGNED_32(fldAddr); - fldAddr = p_aligned_data; - } - break; - - case TYP_LONG: - case TYP_ULONG: - case TYP_DOUBLE: - static_assert_no_msg(sizeof(unsigned __int64) == sizeof(__int64)); - static_assert_no_msg(sizeof(unsigned __int64) == sizeof(double)); - if ((size_t)fldAddr % sizeof(unsigned __int64) != 0) - { - *(unsigned __int64*)p_aligned_data = GET_UNALIGNED_64(fldAddr); - fldAddr = p_aligned_data; - } - break; - - default: - assert(!"Unexpected lclTyp"); - break; - } - } -#endif // DEBUG - - switch (lclTyp) + GenTree* tree = nullptr; + switch (valueType) { - int ival; - __int64 lval; - double dval; - case TYP_BOOL: - ival = *((bool*)fldAddr); - goto IVAL_COMMON; - case TYP_BYTE: - ival = *((signed char*)fldAddr); - goto IVAL_COMMON; - case TYP_UBYTE: - ival = *((unsigned char*)fldAddr); - goto IVAL_COMMON; - case TYP_SHORT: - ival = *((short*)fldAddr); - goto IVAL_COMMON; - case TYP_USHORT: - ival = *((unsigned short*)fldAddr); - goto IVAL_COMMON; - case TYP_UINT: case TYP_INT: - ival = *((int*)fldAddr); - IVAL_COMMON: - op1 = gtNewIconNode(ival); + tree = gtNewIconNode((ssize_t)value); break; case TYP_LONG: case TYP_ULONG: - lval = *((__int64*)fldAddr); - op1 = gtNewLconNode(lval); + tree = gtNewLconNode((INT64)value); break; case TYP_FLOAT: - dval = *((float*)fldAddr); - op1 = gtNewDconNode(dval); - op1->gtType = TYP_FLOAT; + tree = gtNewDconNode(*((float*)&value)); break; case TYP_DOUBLE: - dval = *((double*)fldAddr); - op1 = gtNewDconNode(dval); + tree = gtNewDconNode(*((double*)&value)); break; - default: - assert(!"Unexpected lclTyp"); + case TYP_REF: + { + if (value == 0) + { + tree = gtNewNull(); + } + else + { + setMethodHasFrozenObjects(); + tree = gtNewIconEmbHndNode((void*)value, nullptr, GTF_ICON_OBJ_HDL, nullptr); + tree->gtType = TYP_REF; + INDEBUG(tree->AsIntCon()->gtTargetHandle = (size_t)value); + } break; + } + default: + return nullptr; } - return op1; + assert(tree != nullptr); + tree->gtType = genActualType(valueType); + return tree; } GenTree* Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedToken, @@ -15286,51 +15209,19 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CORINFO_FIELD_STATIC_ADDRESS: // Replace static read-only fields with constant if possible if ((aflags & CORINFO_ACCESS_GET) && (fieldInfo.fieldFlags & CORINFO_FLG_FIELD_FINAL) && - !(fieldInfo.fieldFlags & CORINFO_FLG_FIELD_STATIC_IN_HEAP) && - (varTypeIsIntegral(lclTyp) || varTypeIsFloating(lclTyp) || (lclTyp == TYP_REF))) + !(fieldInfo.fieldFlags & CORINFO_FLG_FIELD_STATIC_IN_HEAP)) { - CorInfoInitClassResult initClassResult = - info.compCompHnd->initClass(resolvedToken.hField, info.compMethodHnd, - impTokenLookupContextHandle); - - if (initClassResult & CORINFO_INITCLASS_INITIALIZED) + UINT64 value; + if (info.compCompHnd->getReadonlyStaticFieldValue(resolvedToken.hField, &value)) { - if (varTypeIsIntegral(lclTyp) || varTypeIsFloating(lclTyp)) + GenTree* cnsValue = impImportStaticReadOnlyField(value, lclTyp); + if (cnsValue != nullptr) { - void** pFldAddr = nullptr; - void* fldAddr = - info.compCompHnd->getFieldAddress(resolvedToken.hField, (void**)&pFldAddr); - - // We should always be able to access this static's address directly - // - assert(pFldAddr == nullptr); - - op1 = impImportStaticReadOnlyField(fldAddr, lclTyp); - - // Widen small types since we're propagating the value - // instead of producing an indir. - // - op1->gtType = genActualType(lclTyp); - + op1 = cnsValue; goto FIELD_DONE; } - else - { - assert(lclTyp == TYP_REF); - void* frozenHandle = - info.compCompHnd->getFrozenHandleFromInitedStaticField(resolvedToken.hField); - if (frozenHandle != nullptr) - { - setMethodHasFrozenObjects(); - op1 = gtNewIconEmbHndNode(frozenHandle, nullptr, GTF_ICON_OBJ_HDL, nullptr); - op1->gtType = TYP_REF; - INDEBUG(op1->AsIntCon()->gtTargetHandle = (size_t)frozenHandle); - goto FIELD_DONE; - } - } } } - FALLTHROUGH; case CORINFO_FIELD_STATIC_RVA_ADDRESS: diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs index d69aa43576f6b..c8eac9a44247d 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs @@ -2199,12 +2199,12 @@ private static uint _getClassDomainID(IntPtr thisHandle, IntPtr* ppException, CO } [UnmanagedCallersOnly] - private static void* _getFrozenHandleFromInitedStaticField(IntPtr thisHandle, IntPtr* ppException, CORINFO_FIELD_STRUCT_* field) + private static byte _getReadonlyStaticFieldValue(IntPtr thisHandle, IntPtr* ppException, CORINFO_FIELD_STRUCT_* field, ulong* pValue) { var _this = GetThis(thisHandle); try { - return _this.getFrozenHandleFromInitedStaticField(field); + return _this.getReadonlyStaticFieldValue(field, ref *pValue) ? (byte)1 : (byte)0; } catch (Exception ex) { @@ -2790,7 +2790,7 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[145] = (delegate* unmanaged)&_isRIDClassDomainID; callbacks[146] = (delegate* unmanaged)&_getClassDomainID; callbacks[147] = (delegate* unmanaged)&_getFieldAddress; - callbacks[148] = (delegate* unmanaged)&_getFrozenHandleFromInitedStaticField; + callbacks[148] = (delegate* unmanaged)&_getReadonlyStaticFieldValue; callbacks[149] = (delegate* unmanaged)&_getStaticFieldCurrentClass; callbacks[150] = (delegate* unmanaged)&_getVarArgsHandle; callbacks[151] = (delegate* unmanaged)&_canGetVarArgsHandle; diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 56235666b4781..fe798522b7116 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3307,10 +3307,10 @@ private uint getClassDomainID(CORINFO_CLASS_STRUCT_* cls, ref void* ppIndirectio } #pragma warning disable CA1822 // Mark members as static - private void* getFrozenHandleFromInitedStaticField(CORINFO_FIELD_STRUCT_* field) + private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* field, ref ulong pHandle) #pragma warning restore CA1822 // Mark members as static { - return null; + return false; } private CORINFO_CLASS_STRUCT_* getStaticFieldCurrentClass(CORINFO_FIELD_STRUCT_* field, byte* pIsSpeculative) diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index 89629af04fb78..0b39f744e5a60 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -58,6 +58,7 @@ GSCookie**,IntPtr** bool*,ref bool BoolStar,byte*,bool*,bool* uint32_t*,ref uint +uint64_t*,ref ulong void **,ref void* VOIDSTARSTAR,void **,void **,void ** int32_t*,int* @@ -70,6 +71,7 @@ wchar_t*,char* const wchar_t*,String uint32_t**,ref uint* +uint64_t**,ref ulong* unsigned*,ref uint CORJIT_FLAGS*,ref CORJIT_FLAGS CORINFO_CONST_LOOKUP*,ref CORINFO_CONST_LOOKUP @@ -303,7 +305,7 @@ FUNCTIONS bool isRIDClassDomainID(CORINFO_CLASS_HANDLE cls); unsigned getClassDomainID (CORINFO_CLASS_HANDLE cls, void **ppIndirection); void* getFieldAddress(CORINFO_FIELD_HANDLE field, VOIDSTARSTAR ppIndirection); - void* getFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE field); + bool getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint64_t *pValue); CORINFO_CLASS_HANDLE getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, BoolStar pIsSpeculative); CORINFO_VARARGS_HANDLE getVarArgsHandle(CORINFO_SIG_INFO *pSig, void **ppIndirection); bool canGetVarArgsHandle(CORINFO_SIG_INFO *pSig); diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface.h b/src/coreclr/tools/aot/jitinterface/jitinterface.h index 6c870466a29b5..5aea3a0e44057 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface.h @@ -159,7 +159,7 @@ struct JitInterfaceCallbacks bool (* isRIDClassDomainID)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); unsigned (* getClassDomainID)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls, void** ppIndirection); void* (* getFieldAddress)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, void** ppIndirection); - void* (* getFrozenHandleFromInitedStaticField)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field); + bool (* getReadonlyStaticFieldValue)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, uint64_t* pValue); CORINFO_CLASS_HANDLE (* getStaticFieldCurrentClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, bool* pIsSpeculative); CORINFO_VARARGS_HANDLE (* getVarArgsHandle)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_SIG_INFO* pSig, void** ppIndirection); bool (* canGetVarArgsHandle)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_SIG_INFO* pSig); @@ -1624,11 +1624,12 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } - virtual void* getFrozenHandleFromInitedStaticField( - CORINFO_FIELD_HANDLE field) + virtual bool getReadonlyStaticFieldValue( + CORINFO_FIELD_HANDLE field, + uint64_t* pValue) { CorInfoExceptionClass* pException = nullptr; - void* temp = _callbacks->getFrozenHandleFromInitedStaticField(_thisHandle, &pException, field); + bool temp = _callbacks->getReadonlyStaticFieldValue(_thisHandle, &pException, field, pValue); 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 4a4b924fbad2c..dde3813f23e62 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -80,7 +80,7 @@ LWM(GetDelegateCtor, Agnostic_GetDelegateCtorIn, Agnostic_GetDelegateCtorOut) LWM(GetEEInfo, DWORD, Agnostic_CORINFO_EE_INFO) LWM(GetEHinfo, DLD, Agnostic_CORINFO_EH_CLAUSE) LWM(GetFieldAddress, DWORDLONG, Agnostic_GetFieldAddress) -LWM(GetFrozenHandleFromInitedStaticField, DWORDLONG, DWORDLONG) +LWM(GetReadonlyStaticFieldValue, DWORDLONG, DLD) LWM(GetStaticFieldCurrentClass, DWORDLONG, Agnostic_GetStaticFieldCurrentClass) LWM(GetFieldClass, DWORDLONG, DWORDLONG) LWM(GetFieldInClass, DLD, DWORDLONG) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index f375111d6ff9d..215beb5bdb38d 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -3653,29 +3653,58 @@ void* MethodContext::repGetFieldAddress(CORINFO_FIELD_HANDLE field, void** ppInd return temp; } -void MethodContext::recGetFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE field, void* result) +void MethodContext::recGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint64_t value, bool result) { - if (GetFrozenHandleFromInitedStaticField == nullptr) - GetFrozenHandleFromInitedStaticField = new LightWeightMap(); + if (GetReadonlyStaticFieldValue == nullptr) + GetReadonlyStaticFieldValue = new LightWeightMap(); + + DWORDLONG key = CastHandle(field); + DLD val; + val.A = (DWORDLONG)value; + val.B = (DWORD)result; + GetReadonlyStaticFieldValue->Add(key, val); + DEBUG_REC(dmpGetReadonlyStaticFieldValue(key, val)); +} +void MethodContext::dmpGetReadonlyStaticFieldValue(DWORDLONG key, DLD value) +{ + printf("GetReadonlyStaticFieldValue key field-%016llX, value-%016llX result-%08X", key, value.A, value.B); +} +bool MethodContext::repGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint64_t* value) +{ + DWORDLONG key = CastHandle(field); + AssertMapAndKeyExist(GetReadonlyStaticFieldValue, key, ": key %016llX", key); + + DLD val = GetReadonlyStaticFieldValue->Get(key); + DEBUG_REP(dmpGetReadonlyStaticFieldValue(key, val)); + + *value = (uint64_t)val.A; + return (bool)val.B; +} + +/* +void MethodContext::recGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, void* result) +{ + if (GetReadonlyStaticFieldValue == nullptr) + GetReadonlyStaticFieldValue = new LightWeightMap(); DWORDLONG key = CastHandle(field); DWORDLONG value = DWORDLONG(result); - GetFrozenHandleFromInitedStaticField->Add(key, value); - DEBUG_REC(dmpGetFrozenHandleFromInitedStaticField(key, value)); + GetReadonlyStaticFieldValue->Add(key, value); + DEBUG_REC(dmpGetReadonlyStaticFieldValue(key, value)); } -void MethodContext::dmpGetFrozenHandleFromInitedStaticField(DWORDLONG key, DWORDLONG value) +void MethodContext::dmpGetReadonlyStaticFieldValue(DWORDLONG key, DWORDLONG value) { - printf("GetFrozenHandleFromInitedStaticField key field-%016llX, value field-%016llX", key, value); + printf("GetReadonlyStaticFieldValue key field-%016llX, value field-%016llX", key, value); } -void* MethodContext::repGetFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE field) +void* MethodContext::repGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field) { DWORDLONG key = CastHandle(field); - AssertMapAndKeyExist(GetFrozenHandleFromInitedStaticField, key, ": key %016llX", key); - DWORDLONG value = GetFrozenHandleFromInitedStaticField->Get(key); - DEBUG_REP(dmpGetFrozenHandleFromInitedStaticField(key, value)); + AssertMapAndKeyExist(GetReadonlyStaticFieldValue, key, ": key %016llX", key); + DWORDLONG value = GetReadonlyStaticFieldValue->Get(key); + DEBUG_REP(dmpGetReadonlyStaticFieldValue(key, value)); void* result = (void*)value; return result; -} +}*/ void MethodContext::recGetStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, bool isSpeculative, diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index 9afa759671bd5..8bb34b9640330 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -480,9 +480,9 @@ class MethodContext void dmpGetFieldAddress(DWORDLONG key, const Agnostic_GetFieldAddress& value); void* repGetFieldAddress(CORINFO_FIELD_HANDLE field, void** ppIndirection); - void recGetFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE field, void* result); - void dmpGetFrozenHandleFromInitedStaticField(DWORDLONG key, DWORDLONG value); - void* repGetFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE field); + void recGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint64_t value, bool result); + void dmpGetReadonlyStaticFieldValue(DWORDLONG key, DLD value); + bool repGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint64_t* pValue); void recGetStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, bool isSpeculative, CORINFO_CLASS_HANDLE result); void dmpGetStaticFieldCurrentClass(DWORDLONG key, const Agnostic_GetStaticFieldCurrentClass& value); @@ -1143,7 +1143,7 @@ enum mcPackets Packet_GetExactClasses = 195, Packet_GetRuntimeTypePointer = 196, Packet_ObjectToString = 197, - Packet_GetFrozenHandleFromInitedStaticField = 198, + Packet_GetReadonlyStaticFieldValue = 198, }; 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 eaca5917bffa0..e1bf9ffcb56c4 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -1723,11 +1723,11 @@ void* interceptor_ICJI::getFieldAddress(CORINFO_FIELD_HANDLE field, void** ppInd return temp; } -void* interceptor_ICJI::getFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE field) +bool interceptor_ICJI::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint64_t* pValue) { - mc->cr->AddCall("getFrozenHandleFromInitedStaticField"); - void* result = original_ICorJitInfo->getFrozenHandleFromInitedStaticField(field); - mc->recGetFrozenHandleFromInitedStaticField(field, result); + mc->cr->AddCall("getReadonlyStaticFieldValue"); + bool result = original_ICorJitInfo->getReadonlyStaticFieldValue(field, pValue); + mc->recGetReadonlyStaticFieldValue(field, *pValue, result); return result; } diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp index 0ab289b5be48f..a82bef0d7e452 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -1188,11 +1188,12 @@ void* interceptor_ICJI::getFieldAddress( return original_ICorJitInfo->getFieldAddress(field, ppIndirection); } -void* interceptor_ICJI::getFrozenHandleFromInitedStaticField( - CORINFO_FIELD_HANDLE field) +bool interceptor_ICJI::getReadonlyStaticFieldValue( + CORINFO_FIELD_HANDLE field, + uint64_t* pValue) { - mcs->AddCall("getFrozenHandleFromInitedStaticField"); - return original_ICorJitInfo->getFrozenHandleFromInitedStaticField(field); + mcs->AddCall("getReadonlyStaticFieldValue"); + return original_ICorJitInfo->getReadonlyStaticFieldValue(field, pValue); } CORINFO_CLASS_HANDLE interceptor_ICJI::getStaticFieldCurrentClass( diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp index a44a5de5ec484..2afc4f6301dd8 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -1040,10 +1040,11 @@ void* interceptor_ICJI::getFieldAddress( return original_ICorJitInfo->getFieldAddress(field, ppIndirection); } -void* interceptor_ICJI::getFrozenHandleFromInitedStaticField( - CORINFO_FIELD_HANDLE field) +bool interceptor_ICJI::getReadonlyStaticFieldValue( + CORINFO_FIELD_HANDLE field, + uint64_t* pValue) { - return original_ICorJitInfo->getFrozenHandleFromInitedStaticField(field); + return original_ICorJitInfo->getReadonlyStaticFieldValue(field, pValue); } CORINFO_CLASS_HANDLE interceptor_ICJI::getStaticFieldCurrentClass( diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index 0005a7367cb21..0afd8ae9a2129 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -1503,10 +1503,10 @@ void* MyICJI::getFieldAddress(CORINFO_FIELD_HANDLE field, void** ppIndirection) return jitInstance->mc->repGetFieldAddress(field, ppIndirection); } -void* MyICJI::getFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE field) +bool MyICJI::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint64_t* pValue) { - jitInstance->mc->cr->AddCall("getFrozenHandleFromInitedStaticField"); - return jitInstance->mc->repGetFrozenHandleFromInitedStaticField(field); + jitInstance->mc->cr->AddCall("getReadonlyStaticFieldValue"); + return jitInstance->mc->repGetReadonlyStaticFieldValue(field, pValue); } // return the class handle for the current value of a static field diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index e73bbf143cfbd..ac182c198681e 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11788,7 +11788,7 @@ void* CEEJitInfo::getFieldAddress(CORINFO_FIELD_HANDLE fieldHnd, return result; } -void* CEEJitInfo::getFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE fieldHnd) +bool CEEJitInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint64_t* pValue) { CONTRACTL { THROWS; @@ -11796,12 +11796,15 @@ void* CEEJitInfo::getFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE fiel MODE_PREEMPTIVE; } CONTRACTL_END; - void* ptr = nullptr; + _ASSERT(fieldHnd != NULL); + _ASSERT(pValue != NULL); + + bool result = false; JIT_TO_EE_TRANSITION(); FieldDesc* field = (FieldDesc*)fieldHnd; - if (field->IsStatic() && field->IsObjRef() && !field->IsThreadStatic()) + if (field->IsStatic() && !field->IsThreadStatic()) { MethodTable* pEnclosingMT = field->GetEnclosingMethodTable(); if (!pEnclosingMT->IsSharedByGenericInstantiations()) @@ -11812,13 +11815,82 @@ void* CEEJitInfo::getFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE fiel pLocalModule->PopulateClass(pEnclosingMT); GCX_COOP(); - OBJECTREF fieldObj = field->GetStaticOBJECTREF(); - if (fieldObj != NULL && pEnclosingMT->IsClassInited() && IsFdInitOnly(field->GetAttributes())) + if (pEnclosingMT->IsClassInited() && IsFdInitOnly(field->GetAttributes())) { - Object* obj = OBJECTREFToObject(fieldObj); - if (GCHeapUtilities::GetGCHeap()->IsInFrozenSegment(obj)) + if (field->IsObjRef()) + { + OBJECTREF fieldObj = field->GetStaticOBJECTREF(); + if (fieldObj != NULL) + { + Object* obj = OBJECTREFToObject(fieldObj); + if (GCHeapUtilities::GetGCHeap()->IsInFrozenSegment(obj)) + { + *pValue = (uint64_t)obj; + result = true; + } + } + else + { + *pValue = 0; + result = true; + } + } + else { - ptr = (void*)obj; + void* fldAddr = field->GetStaticAddressHandle(field->IsRVA() ? nullptr : (void*)field->GetBase()); + if (fldAddr != nullptr) + { + _ASSERTE(!pEnclosingMT->ContainsGenericVariables()); + result = true; + switch (field->GetFieldType()) + { + case ELEMENT_TYPE_BOOLEAN: + *pValue = (uint64_t)*((uint8_t*)fldAddr); + break; + case ELEMENT_TYPE_CHAR: + *pValue = (uint64_t)*((uint16_t*)fldAddr); + break; + case ELEMENT_TYPE_I1: + *pValue = (uint64_t)*((int8_t*)fldAddr); + break; + case ELEMENT_TYPE_U1: + *pValue = (uint64_t)*((uint8_t*)fldAddr); + break; + case ELEMENT_TYPE_I2: + *pValue = (uint64_t)*((int16_t*)fldAddr); + break; + case ELEMENT_TYPE_U2: + *pValue = (uint64_t)*((uint16_t*)fldAddr); + break; + case ELEMENT_TYPE_I4: + *pValue = (uint64_t)*((int32_t*)fldAddr); + break; + case ELEMENT_TYPE_U4: + *pValue = (uint64_t)*((uint32_t*)fldAddr); + break; + case ELEMENT_TYPE_I8: + *pValue = (uint64_t)*((int32_t*)fldAddr); + break; + case ELEMENT_TYPE_U8: + *pValue = (uint64_t)*((uint64_t*)fldAddr); + break; + case ELEMENT_TYPE_R4: + *pValue = (uint64_t)*((float*)fldAddr); + break; + case ELEMENT_TYPE_R8: + *pValue = (uint64_t)*((double*)fldAddr); + break; + case ELEMENT_TYPE_I: + *pValue = (uint64_t)*((intptr_t*)fldAddr); + break; + case ELEMENT_TYPE_U: + *pValue = (uint64_t)*((uintptr_t*)fldAddr); + break; + default: + result = false; + break; + } + } } } } @@ -11826,7 +11898,7 @@ void* CEEJitInfo::getFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE fiel EE_TO_JIT_TRANSITION(); - return ptr; + return result; } /*********************************************************************/ @@ -14369,7 +14441,7 @@ void* CEEInfo::getFieldAddress(CORINFO_FIELD_HANDLE fieldHnd, return result; } -void* CEEInfo::getFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE CORINFO_FIELD_HANDLE) +bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint64_t* pValue) { LIMITED_METHOD_CONTRACT; UNREACHABLE(); // only called on derived class. diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index be86632d80576..3ffc6d774c586 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -925,7 +925,7 @@ class CEEJitInfo : public CEEInfo InfoAccessType constructStringLiteral(CORINFO_MODULE_HANDLE scopeHnd, mdToken metaTok, void **ppValue) override final; InfoAccessType emptyStringLiteral(void ** ppValue) override final; void* getFieldAddress(CORINFO_FIELD_HANDLE field, void **ppIndirection) override final; - void* getFrozenHandleFromInitedStaticField(CORINFO_FIELD_HANDLE field) override final; + bool getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint64_t *pValue) override final; CORINFO_CLASS_HANDLE getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, bool* pIsSpeculative) override final; void* getMethodSync(CORINFO_METHOD_HANDLE ftnHnd, void **ppIndirection) override final; From f10b886549a2751c0ff510e1e3f92ea748dbf3dd Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 24 Sep 2022 09:36:19 +0200 Subject: [PATCH 04/61] Mitigate regressions via getObjectType --- src/coreclr/inc/corinfo.h | 4 + src/coreclr/inc/icorjitinfoimpl_generated.h | 3 + src/coreclr/jit/ICorJitInfo_API_names.h | 1 + src/coreclr/jit/ICorJitInfo_API_wrapper.hpp | 9 + src/coreclr/jit/gentree.cpp | 14 ++ .../tools/Common/JitInterface/CorInfoBase.cs | 238 ++++++++++-------- .../tools/Common/JitInterface/CorInfoImpl.cs | 7 + .../ThunkGenerator/ThunkInput.txt | 1 + .../tools/aot/jitinterface/jitinterface.h | 10 + .../tools/superpmi/superpmi-shared/lwmlist.h | 1 + .../superpmi-shared/methodcontext.cpp | 23 ++ .../superpmi/superpmi-shared/methodcontext.h | 5 + .../superpmi-shim-collector/icorjitinfo.cpp | 8 + .../superpmi-shim-counter/icorjitinfo.cpp | 7 + .../superpmi-shim-simple/icorjitinfo.cpp | 6 + .../tools/superpmi/superpmi/icorjitinfo.cpp | 7 + src/coreclr/vm/jitinterface.cpp | 26 ++ 17 files changed, 259 insertions(+), 111 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index f812e70881055..b08d5c26e6ea3 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -2486,6 +2486,10 @@ class ICorStaticInfo CORINFO_CLASS_HANDLE cls ) = 0; + virtual CORINFO_CLASS_HANDLE getObjectType( + void* typeObj + ) = 0; + virtual bool getReadyToRunHelper( CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_LOOKUP_KIND * pGenericLookupKind, diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 70a8ff6d468fd..0acbe25d4fef8 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -288,6 +288,9 @@ CorInfoHelpFunc getUnBoxHelper( void* getRuntimeTypePointer( CORINFO_CLASS_HANDLE cls) override; +CORINFO_CLASS_HANDLE getObjectType( + void* typeObj) override; + bool getReadyToRunHelper( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, diff --git a/src/coreclr/jit/ICorJitInfo_API_names.h b/src/coreclr/jit/ICorJitInfo_API_names.h index dc817238d9ab0..6e306d6b1e9e7 100644 --- a/src/coreclr/jit/ICorJitInfo_API_names.h +++ b/src/coreclr/jit/ICorJitInfo_API_names.h @@ -72,6 +72,7 @@ DEF_CLR_API(getTypeForBox) DEF_CLR_API(getBoxHelper) DEF_CLR_API(getUnBoxHelper) DEF_CLR_API(getRuntimeTypePointer) +DEF_CLR_API(getObjectType) DEF_CLR_API(getReadyToRunHelper) DEF_CLR_API(getReadyToRunDelegateCtorHelper) DEF_CLR_API(getHelperName) diff --git a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp index 6abbe84472fc3..49cc32abdc4ea 100644 --- a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp +++ b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp @@ -672,6 +672,15 @@ void* WrapICorJitInfo::getRuntimeTypePointer( return temp; } +CORINFO_CLASS_HANDLE WrapICorJitInfo::getObjectType( + void* typeObj) +{ + API_ENTER(getObjectType); + CORINFO_CLASS_HANDLE temp = wrapHnd->getObjectType(typeObj); + API_LEAVE(getObjectType); + return temp; +} + bool WrapICorJitInfo::getReadyToRunHelper( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 1e97a840a3263..baa099d055c01 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -17574,6 +17574,20 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, b break; } + case GT_CNS_INT: + { + if (tree->IsIconHandle(GTF_ICON_OBJ_HDL)) + { + objClass = info.compCompHnd->getObjectType((void*)tree->AsIntCon()->IconValue()); + if (objClass != NO_CLASS_HANDLE) + { + // if we manage to get the class handle it's definitely not null + *pIsNonNull = true; + } + } + break; + } + case GT_RET_EXPR: { // If we see a RET_EXPR, recurse through to examine the diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs index c8eac9a44247d..a8e12f59ee85f 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs @@ -1017,6 +1017,21 @@ private static CorInfoHelpFunc _getUnBoxHelper(IntPtr thisHandle, IntPtr* ppExce } } + [UnmanagedCallersOnly] + private static CORINFO_CLASS_STRUCT_* _getObjectType(IntPtr thisHandle, IntPtr* ppException, void* typeObj) + { + var _this = GetThis(thisHandle); + try + { + return _this.getObjectType(typeObj); + } + catch (Exception ex) + { + *ppException = _this.AllocException(ex); + return default; + } + } + [UnmanagedCallersOnly] private static byte _getReadyToRunHelper(IntPtr thisHandle, IntPtr* ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, CORINFO_CONST_LOOKUP* pLookup) { @@ -2640,7 +2655,7 @@ private static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, CORJIT_ private static IntPtr GetUnmanagedCallbacks() { - void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 178); + void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 179); callbacks[0] = (delegate* unmanaged)&_isIntrinsic; callbacks[1] = (delegate* unmanaged)&_getMethodAttribs; @@ -2710,116 +2725,117 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[65] = (delegate* unmanaged)&_getBoxHelper; callbacks[66] = (delegate* unmanaged)&_getUnBoxHelper; callbacks[67] = (delegate* unmanaged)&_getRuntimeTypePointer; - callbacks[68] = (delegate* unmanaged)&_getReadyToRunHelper; - callbacks[69] = (delegate* unmanaged)&_getReadyToRunDelegateCtorHelper; - callbacks[70] = (delegate* unmanaged)&_getHelperName; - callbacks[71] = (delegate* unmanaged)&_initClass; - callbacks[72] = (delegate* unmanaged)&_classMustBeLoadedBeforeCodeIsRun; - callbacks[73] = (delegate* unmanaged)&_getBuiltinClass; - callbacks[74] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; - callbacks[75] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; - callbacks[76] = (delegate* unmanaged)&_canCast; - callbacks[77] = (delegate* unmanaged)&_areTypesEquivalent; - callbacks[78] = (delegate* unmanaged)&_compareTypesForCast; - callbacks[79] = (delegate* unmanaged)&_compareTypesForEquality; - callbacks[80] = (delegate* unmanaged)&_mergeClasses; - callbacks[81] = (delegate* unmanaged)&_isMoreSpecificType; - callbacks[82] = (delegate* unmanaged)&_getParentType; - callbacks[83] = (delegate* unmanaged)&_getChildType; - callbacks[84] = (delegate* unmanaged)&_satisfiesClassConstraints; - 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)&_getFieldName; - callbacks[91] = (delegate* unmanaged)&_getFieldClass; - callbacks[92] = (delegate* unmanaged)&_getFieldType; - callbacks[93] = (delegate* unmanaged)&_getFieldOffset; - callbacks[94] = (delegate* unmanaged)&_getFieldInfo; - callbacks[95] = (delegate* unmanaged)&_isFieldStatic; - callbacks[96] = (delegate* unmanaged)&_getBoundaries; - callbacks[97] = (delegate* unmanaged)&_setBoundaries; - callbacks[98] = (delegate* unmanaged)&_getVars; - callbacks[99] = (delegate* unmanaged)&_setVars; - callbacks[100] = (delegate* unmanaged)&_reportRichMappings; - callbacks[101] = (delegate* unmanaged)&_allocateArray; - callbacks[102] = (delegate* unmanaged)&_freeArray; - callbacks[103] = (delegate* unmanaged)&_getArgNext; - callbacks[104] = (delegate* unmanaged)&_getArgType; - callbacks[105] = (delegate* unmanaged)&_getExactClasses; - callbacks[106] = (delegate* unmanaged)&_getArgClass; - callbacks[107] = (delegate* unmanaged)&_getHFAType; - callbacks[108] = (delegate* unmanaged)&_GetErrorHRESULT; - callbacks[109] = (delegate* unmanaged)&_GetErrorMessage; - callbacks[110] = (delegate* unmanaged)&_FilterException; - callbacks[111] = (delegate* unmanaged)&_ThrowExceptionForJitResult; - callbacks[112] = (delegate* unmanaged)&_ThrowExceptionForHelper; - 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)&_getMethodName; - callbacks[119] = (delegate* unmanaged)&_getMethodNameFromMetadata; - callbacks[120] = (delegate* unmanaged)&_getMethodHash; - callbacks[121] = (delegate* unmanaged)&_findNameOfToken; - callbacks[122] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; - callbacks[123] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; - callbacks[124] = (delegate* unmanaged)&_getThreadTLSIndex; - callbacks[125] = (delegate* unmanaged)&_getInlinedCallFrameVptr; - 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)&_canAccessFamily; - callbacks[145] = (delegate* unmanaged)&_isRIDClassDomainID; - callbacks[146] = (delegate* unmanaged)&_getClassDomainID; - callbacks[147] = (delegate* unmanaged)&_getFieldAddress; - callbacks[148] = (delegate* unmanaged)&_getReadonlyStaticFieldValue; - 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)&_addActiveDependency; - callbacks[156] = (delegate* unmanaged)&_GetDelegateCtor; - callbacks[157] = (delegate* unmanaged)&_MethodCompileComplete; - callbacks[158] = (delegate* unmanaged)&_getTailCallHelpers; - 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[68] = (delegate* unmanaged)&_getObjectType; + callbacks[69] = (delegate* unmanaged)&_getReadyToRunHelper; + callbacks[70] = (delegate* unmanaged)&_getReadyToRunDelegateCtorHelper; + callbacks[71] = (delegate* unmanaged)&_getHelperName; + callbacks[72] = (delegate* unmanaged)&_initClass; + callbacks[73] = (delegate* unmanaged)&_classMustBeLoadedBeforeCodeIsRun; + callbacks[74] = (delegate* unmanaged)&_getBuiltinClass; + callbacks[75] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; + callbacks[76] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; + callbacks[77] = (delegate* unmanaged)&_canCast; + callbacks[78] = (delegate* unmanaged)&_areTypesEquivalent; + callbacks[79] = (delegate* unmanaged)&_compareTypesForCast; + callbacks[80] = (delegate* unmanaged)&_compareTypesForEquality; + callbacks[81] = (delegate* unmanaged)&_mergeClasses; + callbacks[82] = (delegate* unmanaged)&_isMoreSpecificType; + callbacks[83] = (delegate* unmanaged)&_getParentType; + callbacks[84] = (delegate* unmanaged)&_getChildType; + callbacks[85] = (delegate* unmanaged)&_satisfiesClassConstraints; + callbacks[86] = (delegate* unmanaged)&_isSDArray; + callbacks[87] = (delegate* unmanaged)&_getArrayRank; + callbacks[88] = (delegate* unmanaged)&_getArrayIntrinsicID; + callbacks[89] = (delegate* unmanaged)&_getArrayInitializationData; + callbacks[90] = (delegate* unmanaged)&_canAccessClass; + callbacks[91] = (delegate* unmanaged)&_getFieldName; + callbacks[92] = (delegate* unmanaged)&_getFieldClass; + callbacks[93] = (delegate* unmanaged)&_getFieldType; + callbacks[94] = (delegate* unmanaged)&_getFieldOffset; + callbacks[95] = (delegate* unmanaged)&_getFieldInfo; + callbacks[96] = (delegate* unmanaged)&_isFieldStatic; + callbacks[97] = (delegate* unmanaged)&_getBoundaries; + callbacks[98] = (delegate* unmanaged)&_setBoundaries; + callbacks[99] = (delegate* unmanaged)&_getVars; + callbacks[100] = (delegate* unmanaged)&_setVars; + callbacks[101] = (delegate* unmanaged)&_reportRichMappings; + callbacks[102] = (delegate* unmanaged)&_allocateArray; + callbacks[103] = (delegate* unmanaged)&_freeArray; + callbacks[104] = (delegate* unmanaged)&_getArgNext; + callbacks[105] = (delegate* unmanaged)&_getArgType; + callbacks[106] = (delegate* unmanaged)&_getExactClasses; + callbacks[107] = (delegate* unmanaged)&_getArgClass; + callbacks[108] = (delegate* unmanaged)&_getHFAType; + callbacks[109] = (delegate* unmanaged)&_GetErrorHRESULT; + callbacks[110] = (delegate* unmanaged)&_GetErrorMessage; + callbacks[111] = (delegate* unmanaged)&_FilterException; + callbacks[112] = (delegate* unmanaged)&_ThrowExceptionForJitResult; + callbacks[113] = (delegate* unmanaged)&_ThrowExceptionForHelper; + callbacks[114] = (delegate* unmanaged)&_runWithErrorTrap; + callbacks[115] = (delegate* unmanaged)&_runWithSPMIErrorTrap; + callbacks[116] = (delegate* unmanaged)&_getEEInfo; + callbacks[117] = (delegate* unmanaged)&_getJitTimeLogFilename; + callbacks[118] = (delegate* unmanaged)&_getMethodDefFromMethod; + callbacks[119] = (delegate* unmanaged)&_getMethodName; + callbacks[120] = (delegate* unmanaged)&_getMethodNameFromMetadata; + callbacks[121] = (delegate* unmanaged)&_getMethodHash; + callbacks[122] = (delegate* unmanaged)&_findNameOfToken; + callbacks[123] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; + callbacks[124] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; + callbacks[125] = (delegate* unmanaged)&_getThreadTLSIndex; + callbacks[126] = (delegate* unmanaged)&_getInlinedCallFrameVptr; + callbacks[127] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; + callbacks[128] = (delegate* unmanaged)&_getHelperFtn; + callbacks[129] = (delegate* unmanaged)&_getFunctionEntryPoint; + callbacks[130] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; + callbacks[131] = (delegate* unmanaged)&_getMethodSync; + callbacks[132] = (delegate* unmanaged)&_getLazyStringLiteralHelper; + callbacks[133] = (delegate* unmanaged)&_embedModuleHandle; + callbacks[134] = (delegate* unmanaged)&_embedClassHandle; + callbacks[135] = (delegate* unmanaged)&_embedMethodHandle; + callbacks[136] = (delegate* unmanaged)&_embedFieldHandle; + callbacks[137] = (delegate* unmanaged)&_embedGenericHandle; + callbacks[138] = (delegate* unmanaged)&_getLocationOfThisType; + callbacks[139] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; + callbacks[140] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; + callbacks[141] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; + callbacks[142] = (delegate* unmanaged)&_getJustMyCodeHandle; + callbacks[143] = (delegate* unmanaged)&_GetProfilingHandle; + callbacks[144] = (delegate* unmanaged)&_getCallInfo; + callbacks[145] = (delegate* unmanaged)&_canAccessFamily; + callbacks[146] = (delegate* unmanaged)&_isRIDClassDomainID; + callbacks[147] = (delegate* unmanaged)&_getClassDomainID; + callbacks[148] = (delegate* unmanaged)&_getFieldAddress; + callbacks[149] = (delegate* unmanaged)&_getReadonlyStaticFieldValue; + 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)&_addActiveDependency; + callbacks[157] = (delegate* unmanaged)&_GetDelegateCtor; + callbacks[158] = (delegate* unmanaged)&_MethodCompileComplete; + callbacks[159] = (delegate* unmanaged)&_getTailCallHelpers; + 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; return (IntPtr)callbacks; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index fe798522b7116..6646c1629b2de 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -2350,6 +2350,13 @@ private CorInfoHelpFunc getUnBoxHelper(CORINFO_CLASS_STRUCT_* cls) return (void*)IntPtr.Zero; } +#pragma warning disable CA1822 // Mark members as static + private CORINFO_CLASS_STRUCT_* getObjectType(void* typeObj) +#pragma warning restore CA1822 // Mark members as static + { + return (CORINFO_CLASS_STRUCT_*)IntPtr.Zero; + } + private byte* getHelperName(CorInfoHelpFunc helpFunc) { return (byte*)GetPin(StringToUTF8(helpFunc.ToString())); diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index 0b39f744e5a60..e83f4a78934fc 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -225,6 +225,7 @@ FUNCTIONS CorInfoHelpFunc getBoxHelper(CORINFO_CLASS_HANDLE cls) CorInfoHelpFunc getUnBoxHelper(CORINFO_CLASS_HANDLE cls) void* getRuntimeTypePointer(CORINFO_CLASS_HANDLE cls) + CORINFO_CLASS_HANDLE getObjectType(void* typeObj) bool getReadyToRunHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_LOOKUP_KIND * pGenericLookupKind, CorInfoHelpFunc id, CORINFO_CONST_LOOKUP *pLookup) void getReadyToRunDelegateCtorHelper(CORINFO_RESOLVED_TOKEN * pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, CORINFO_LOOKUP *pLookup) const char* getHelperName(CorInfoHelpFunc helpFunc) diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface.h b/src/coreclr/tools/aot/jitinterface/jitinterface.h index 5aea3a0e44057..99f4359d3c655 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface.h @@ -79,6 +79,7 @@ struct JitInterfaceCallbacks CorInfoHelpFunc (* getBoxHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); CorInfoHelpFunc (* getUnBoxHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); void* (* getRuntimeTypePointer)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); + CORINFO_CLASS_HANDLE (* getObjectType)(void * thisHandle, CorInfoExceptionClass** ppException, void* typeObj); bool (* getReadyToRunHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, CORINFO_CONST_LOOKUP* pLookup); void (* getReadyToRunDelegateCtorHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pTargetMethod, unsigned int targetConstraint, CORINFO_CLASS_HANDLE delegateType, CORINFO_LOOKUP* pLookup); const char* (* getHelperName)(void * thisHandle, CorInfoExceptionClass** ppException, CorInfoHelpFunc helpFunc); @@ -864,6 +865,15 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } + virtual CORINFO_CLASS_HANDLE getObjectType( + void* typeObj) +{ + CorInfoExceptionClass* pException = nullptr; + CORINFO_CLASS_HANDLE temp = _callbacks->getObjectType(_thisHandle, &pException, typeObj); + if (pException != nullptr) throw pException; + return temp; +} + virtual bool getReadyToRunHelper( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, diff --git a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h index dde3813f23e62..7dec7d97fcb0d 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -140,6 +140,7 @@ LWM(GetTypeForPrimitiveNumericClass, DWORDLONG, DWORD) LWM(GetUnboxedEntry, DWORDLONG, DLD); LWM(GetUnBoxHelper, DWORDLONG, DWORD) LWM(GetRuntimeTypePointer, DWORDLONG, DWORDLONG) +LWM(GetObjectType, DWORDLONG, DWORDLONG) LWM(GetVarArgsHandle, GetVarArgsHandleValue, DLDL) LWM(GetVars, DWORDLONG, Agnostic_GetVars) LWM(InitClass, Agnostic_InitClass, DWORD) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 215beb5bdb38d..01837d744aa0a 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -2210,6 +2210,29 @@ void* MethodContext::repGetRuntimeTypePointer(CORINFO_CLASS_HANDLE cls) return (void*)value; } +void MethodContext::recGetObjectType(void* typeObj, CORINFO_CLASS_HANDLE result) +{ + if (GetObjectType == nullptr) + GetObjectType = new LightWeightMap(); + + DWORDLONG key = (DWORDLONG)typeObj; + DWORDLONG value = (DWORDLONG)result; + GetObjectType->Add(key, value); + DEBUG_REC(dmpGetObjectType(key, value)); +} +void MethodContext::dmpGetObjectType(DWORDLONG key, DWORDLONG value) +{ + printf("GetObjectType key obj-%016llX, value res-%016llX", key, value); +} +CORINFO_CLASS_HANDLE MethodContext::repGetObjectType(void* typeObj) +{ + DWORDLONG key = (DWORDLONG)typeObj; + AssertMapAndKeyExist(GetObjectType, key, ": key %016llX", key); + DWORDLONG value = GetObjectType->Get(key); + DEBUG_REP(dmpGetObjectType(key, value)); + return (CORINFO_CLASS_HANDLE)value; +} + void MethodContext::recGetReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index 8bb34b9640330..eb7c716b91f6d 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -314,6 +314,10 @@ class MethodContext void dmpGetRuntimeTypePointer(DWORDLONG key, DWORDLONG value); void* repGetRuntimeTypePointer(CORINFO_CLASS_HANDLE cls); + void recGetObjectType(void* typeObj, CORINFO_CLASS_HANDLE result); + void dmpGetObjectType(DWORDLONG key, DWORDLONG value); + CORINFO_CLASS_HANDLE repGetObjectType(void* typeObj); + void recGetReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, @@ -1144,6 +1148,7 @@ enum mcPackets Packet_GetRuntimeTypePointer = 196, Packet_ObjectToString = 197, Packet_GetReadonlyStaticFieldValue = 198, + Packet_GetObjectType = 199, }; 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 e1bf9ffcb56c4..d55f13b2a3012 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -798,6 +798,14 @@ void* interceptor_ICJI::getRuntimeTypePointer(CORINFO_CLASS_HANDLE cls) return temp; } +CORINFO_CLASS_HANDLE interceptor_ICJI::getObjectType(void* typeObj) +{ + mc->cr->AddCall("getObjectType"); + CORINFO_CLASS_HANDLE temp = original_ICorJitInfo->getObjectType(typeObj); + mc->recGetObjectType(typeObj, temp); + return temp; +} + bool interceptor_ICJI::getReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp index a82bef0d7e452..6e2f9f007b41b 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -551,6 +551,13 @@ void* interceptor_ICJI::getRuntimeTypePointer( return original_ICorJitInfo->getRuntimeTypePointer(cls); } +CORINFO_CLASS_HANDLE interceptor_ICJI::getObjectType( + void* typeObj) +{ + mcs->AddCall("getObjectType"); + return original_ICorJitInfo->getObjectType(typeObj); +} + bool interceptor_ICJI::getReadyToRunHelper( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp index 2afc4f6301dd8..3a6ccd6cc7164 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -483,6 +483,12 @@ void* interceptor_ICJI::getRuntimeTypePointer( return original_ICorJitInfo->getRuntimeTypePointer(cls); } +CORINFO_CLASS_HANDLE interceptor_ICJI::getObjectType( + void* typeObj) +{ + return original_ICorJitInfo->getObjectType(typeObj); +} + bool interceptor_ICJI::getReadyToRunHelper( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index 0afd8ae9a2129..e4d7658007676 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -679,6 +679,13 @@ void* MyICJI::getRuntimeTypePointer(CORINFO_CLASS_HANDLE cls) return result; } +CORINFO_CLASS_HANDLE MyICJI::getObjectType(void* typeObj) +{ + jitInstance->mc->cr->AddCall("getObjectType"); + CORINFO_CLASS_HANDLE result = jitInstance->mc->repGetObjectType(typeObj); + return result; +} + bool MyICJI::getReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index ac182c198681e..ce0d5d05f16ad 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -6015,6 +6015,32 @@ void* CEEInfo::getRuntimeTypePointer(CORINFO_CLASS_HANDLE clsHnd) return pointer; } +/***********************************************************************/ +CORINFO_CLASS_HANDLE CEEInfo::getObjectType(void* typeObj) +{ + CONTRACTL{ + THROWS; + GC_TRIGGERS; + MODE_PREEMPTIVE; + } CONTRACTL_END; + + CORINFO_CLASS_HANDLE handle = NULL; + + JIT_TO_EE_TRANSITION(); + + if (typeObj != nullptr) + { + GCX_COOP(); + Object* obj = (Object*)typeObj; + VALIDATEOBJECT(obj); + handle = (CORINFO_CLASS_HANDLE)obj->GetMethodTable(); + } + + EE_TO_JIT_TRANSITION(); + + return handle; +} + /***********************************************************************/ bool CEEInfo::getReadyToRunHelper( CORINFO_RESOLVED_TOKEN * pResolvedToken, From 97c3cdf16da000d7d2f8d4fc3433de708b047249 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 24 Sep 2022 12:21:40 +0200 Subject: [PATCH 05/61] use memcpy --- src/coreclr/inc/corinfo.h | 3 +- src/coreclr/inc/icorjitinfoimpl_generated.h | 3 +- src/coreclr/jit/ICorJitInfo_API_wrapper.hpp | 5 +- src/coreclr/jit/compiler.h | 2 +- src/coreclr/jit/importer.cpp | 45 +++++++--- .../tools/Common/JitInterface/CorInfoBase.cs | 6 +- .../tools/Common/JitInterface/CorInfoImpl.cs | 2 +- .../ThunkGenerator/ThunkInput.txt | 4 +- .../tools/aot/jitinterface/jitinterface.h | 7 +- .../tools/superpmi/superpmi-shared/lwmlist.h | 2 +- .../superpmi-shared/methodcontext.cpp | 82 ++++++++++--------- .../superpmi/superpmi-shared/methodcontext.h | 6 +- .../superpmi-shim-collector/icorjitinfo.cpp | 6 +- .../superpmi-shim-counter/icorjitinfo.cpp | 5 +- .../superpmi-shim-simple/icorjitinfo.cpp | 5 +- .../tools/superpmi/superpmi/icorjitinfo.cpp | 4 +- src/coreclr/vm/jitinterface.cpp | 48 +++-------- src/coreclr/vm/jitinterface.h | 1 - 18 files changed, 121 insertions(+), 115 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index b08d5c26e6ea3..1b4befc32de34 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -3161,7 +3161,8 @@ class ICorDynamicInfo : public ICorStaticInfo // * frozen object virtual bool getReadonlyStaticFieldValue( CORINFO_FIELD_HANDLE field, - uint64_t *pValue + uint8_t *buffer, + int bufferSize ) = 0; // If pIsSpeculative is NULL, return the class handle for the value of ref-class typed diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 0acbe25d4fef8..6a54465d383dc 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -610,7 +610,8 @@ void* getFieldAddress( bool getReadonlyStaticFieldValue( CORINFO_FIELD_HANDLE field, - uint64_t* pValue) override; + uint8_t* buffer, + int bufferSize) override; CORINFO_CLASS_HANDLE getStaticFieldCurrentClass( CORINFO_FIELD_HANDLE field, diff --git a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp index 49cc32abdc4ea..4c2e2b95ef40f 100644 --- a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp +++ b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp @@ -1461,10 +1461,11 @@ void* WrapICorJitInfo::getFieldAddress( bool WrapICorJitInfo::getReadonlyStaticFieldValue( CORINFO_FIELD_HANDLE field, - uint64_t* pValue) + uint8_t* buffer, + int bufferSize) { API_ENTER(getReadonlyStaticFieldValue); - bool temp = wrapHnd->getReadonlyStaticFieldValue(field, pValue); + bool temp = wrapHnd->getReadonlyStaticFieldValue(field, buffer, bufferSize); API_LEAVE(getReadonlyStaticFieldValue); return temp; } diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 3e41a94129645..3a72605a8eee6 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -3639,7 +3639,7 @@ class Compiler GenTree* impInitClass(CORINFO_RESOLVED_TOKEN* pResolvedToken); - GenTree* impImportStaticReadOnlyField(UINT64 value, var_types valueType); + GenTree* impImportStaticReadOnlyField(uint8_t* buffer, int bufferSize, var_types valueType); GenTree* impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_ACCESS_FLAGS access, diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 63de90e3d1013..baeed615943f5 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -8116,8 +8116,11 @@ GenTree* Compiler::impInitClass(CORINFO_RESOLVED_TOKEN* pResolvedToken) return node; } -GenTree* Compiler::impImportStaticReadOnlyField(UINT64 value, var_types valueType) +GenTree* Compiler::impImportStaticReadOnlyField(uint8_t* buffer, int bufferSize, var_types valueType) { + // We plan to support bigger values for structs, but for now it's always 64bit + assert(bufferSize == sizeof(INT64)); + GenTree* tree = nullptr; switch (valueType) { @@ -8128,34 +8131,53 @@ GenTree* Compiler::impImportStaticReadOnlyField(UINT64 value, var_types valueTyp case TYP_USHORT: case TYP_UINT: case TYP_INT: - tree = gtNewIconNode((ssize_t)value); + { + ssize_t i32; + memcpy(&i32, buffer, sizeof(ssize_t)); + tree = gtNewIconNode(i32); break; + } case TYP_LONG: case TYP_ULONG: - tree = gtNewLconNode((INT64)value); + { + INT64 i64; + memcpy(&i64, buffer, sizeof(INT64)); + tree = gtNewLconNode(i64); break; + } case TYP_FLOAT: - tree = gtNewDconNode(*((float*)&value)); + { + float f32; + memcpy(&f32, buffer, sizeof(float)); + tree = gtNewDconNode(f32); break; + } case TYP_DOUBLE: - tree = gtNewDconNode(*((double*)&value)); + { + float f64; + memcpy(&f64, buffer, sizeof(double)); + tree = gtNewDconNode(f64); break; + } case TYP_REF: { - if (value == 0) + ssize_t ptr; + memcpy(&ptr, buffer, sizeof(ssize_t)); + + if (ptr == 0) { tree = gtNewNull(); } else { setMethodHasFrozenObjects(); - tree = gtNewIconEmbHndNode((void*)value, nullptr, GTF_ICON_OBJ_HDL, nullptr); + tree = gtNewIconEmbHndNode((void*)ptr, nullptr, GTF_ICON_OBJ_HDL, nullptr); tree->gtType = TYP_REF; - INDEBUG(tree->AsIntCon()->gtTargetHandle = (size_t)value); + INDEBUG(tree->AsIntCon()->gtTargetHandle = (size_t)ptr); } break; } @@ -15247,10 +15269,11 @@ void Compiler::impImportBlockCode(BasicBlock* block) if ((aflags & CORINFO_ACCESS_GET) && (fieldInfo.fieldFlags & CORINFO_FLG_FIELD_FINAL) && !(fieldInfo.fieldFlags & CORINFO_FLG_FIELD_STATIC_IN_HEAP)) { - UINT64 value; - if (info.compCompHnd->getReadonlyStaticFieldValue(resolvedToken.hField, &value)) + const int bufferSize = sizeof(uint64_t); + uint8_t buffer[bufferSize] = {0}; + if (info.compCompHnd->getReadonlyStaticFieldValue(resolvedToken.hField, buffer, bufferSize)) { - GenTree* cnsValue = impImportStaticReadOnlyField(value, lclTyp); + GenTree* cnsValue = impImportStaticReadOnlyField(buffer, bufferSize, lclTyp); if (cnsValue != nullptr) { op1 = cnsValue; diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs index a8e12f59ee85f..47805909574f7 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs @@ -2214,12 +2214,12 @@ private static uint _getClassDomainID(IntPtr thisHandle, IntPtr* ppException, CO } [UnmanagedCallersOnly] - private static byte _getReadonlyStaticFieldValue(IntPtr thisHandle, IntPtr* ppException, CORINFO_FIELD_STRUCT_* field, ulong* pValue) + private static byte _getReadonlyStaticFieldValue(IntPtr thisHandle, IntPtr* ppException, CORINFO_FIELD_STRUCT_* field, byte* buffer, int bufferSize) { var _this = GetThis(thisHandle); try { - return _this.getReadonlyStaticFieldValue(field, ref *pValue) ? (byte)1 : (byte)0; + return _this.getReadonlyStaticFieldValue(field, buffer, bufferSize) ? (byte)1 : (byte)0; } catch (Exception ex) { @@ -2806,7 +2806,7 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[146] = (delegate* unmanaged)&_isRIDClassDomainID; callbacks[147] = (delegate* unmanaged)&_getClassDomainID; callbacks[148] = (delegate* unmanaged)&_getFieldAddress; - callbacks[149] = (delegate* unmanaged)&_getReadonlyStaticFieldValue; + callbacks[149] = (delegate* unmanaged)&_getReadonlyStaticFieldValue; callbacks[150] = (delegate* unmanaged)&_getStaticFieldCurrentClass; callbacks[151] = (delegate* unmanaged)&_getVarArgsHandle; callbacks[152] = (delegate* unmanaged)&_canGetVarArgsHandle; diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 6646c1629b2de..6ef615b5ca1ab 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3314,7 +3314,7 @@ private uint getClassDomainID(CORINFO_CLASS_STRUCT_* cls, ref void* ppIndirectio } #pragma warning disable CA1822 // Mark members as static - private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* field, ref ulong pHandle) + private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* field, byte* buffer, int bufferSize) #pragma warning restore CA1822 // Mark members as static { return false; diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index e83f4a78934fc..7ae8475d1506a 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -58,7 +58,6 @@ GSCookie**,IntPtr** bool*,ref bool BoolStar,byte*,bool*,bool* uint32_t*,ref uint -uint64_t*,ref ulong void **,ref void* VOIDSTARSTAR,void **,void **,void ** int32_t*,int* @@ -71,7 +70,6 @@ wchar_t*,char* const wchar_t*,String uint32_t**,ref uint* -uint64_t**,ref ulong* unsigned*,ref uint CORJIT_FLAGS*,ref CORJIT_FLAGS CORINFO_CONST_LOOKUP*,ref CORINFO_CONST_LOOKUP @@ -306,7 +304,7 @@ FUNCTIONS bool isRIDClassDomainID(CORINFO_CLASS_HANDLE cls); unsigned getClassDomainID (CORINFO_CLASS_HANDLE cls, void **ppIndirection); void* getFieldAddress(CORINFO_FIELD_HANDLE field, VOIDSTARSTAR ppIndirection); - bool getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint64_t *pValue); + bool getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint8_t *buffer, int bufferSize); CORINFO_CLASS_HANDLE getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, BoolStar pIsSpeculative); CORINFO_VARARGS_HANDLE getVarArgsHandle(CORINFO_SIG_INFO *pSig, void **ppIndirection); bool canGetVarArgsHandle(CORINFO_SIG_INFO *pSig); diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface.h b/src/coreclr/tools/aot/jitinterface/jitinterface.h index 99f4359d3c655..b00339b2b4e95 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface.h @@ -160,7 +160,7 @@ struct JitInterfaceCallbacks bool (* isRIDClassDomainID)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); unsigned (* getClassDomainID)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls, void** ppIndirection); void* (* getFieldAddress)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, void** ppIndirection); - bool (* getReadonlyStaticFieldValue)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, uint64_t* pValue); + bool (* getReadonlyStaticFieldValue)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize); CORINFO_CLASS_HANDLE (* getStaticFieldCurrentClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, bool* pIsSpeculative); CORINFO_VARARGS_HANDLE (* getVarArgsHandle)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_SIG_INFO* pSig, void** ppIndirection); bool (* canGetVarArgsHandle)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_SIG_INFO* pSig); @@ -1636,10 +1636,11 @@ class JitInterfaceWrapper : public ICorJitInfo virtual bool getReadonlyStaticFieldValue( CORINFO_FIELD_HANDLE field, - uint64_t* pValue) + uint8_t* buffer, + int bufferSize) { CorInfoExceptionClass* pException = nullptr; - bool temp = _callbacks->getReadonlyStaticFieldValue(_thisHandle, &pException, field, pValue); + bool temp = _callbacks->getReadonlyStaticFieldValue(_thisHandle, &pException, field, buffer, bufferSize); 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 7dec7d97fcb0d..b0af2f1e3f250 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -80,7 +80,7 @@ LWM(GetDelegateCtor, Agnostic_GetDelegateCtorIn, Agnostic_GetDelegateCtorOut) LWM(GetEEInfo, DWORD, Agnostic_CORINFO_EE_INFO) LWM(GetEHinfo, DLD, Agnostic_CORINFO_EH_CLAUSE) LWM(GetFieldAddress, DWORDLONG, Agnostic_GetFieldAddress) -LWM(GetReadonlyStaticFieldValue, DWORDLONG, DLD) +LWM(GetReadonlyStaticFieldValue, DLD, DD) LWM(GetStaticFieldCurrentClass, DWORDLONG, Agnostic_GetStaticFieldCurrentClass) LWM(GetFieldClass, DWORDLONG, DWORDLONG) LWM(GetFieldInClass, DLD, DWORDLONG) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 01837d744aa0a..294fab25b45b0 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -3676,58 +3676,60 @@ void* MethodContext::repGetFieldAddress(CORINFO_FIELD_HANDLE field, void** ppInd return temp; } -void MethodContext::recGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint64_t value, bool result) +void MethodContext::recGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize, bool result) { if (GetReadonlyStaticFieldValue == nullptr) - GetReadonlyStaticFieldValue = new LightWeightMap(); + GetReadonlyStaticFieldValue = new LightWeightMap(); - DWORDLONG key = CastHandle(field); - DLD val; - val.A = (DWORDLONG)value; - val.B = (DWORD)result; - GetReadonlyStaticFieldValue->Add(key, val); - DEBUG_REC(dmpGetReadonlyStaticFieldValue(key, val)); -} -void MethodContext::dmpGetReadonlyStaticFieldValue(DWORDLONG key, DLD value) -{ - printf("GetReadonlyStaticFieldValue key field-%016llX, value-%016llX result-%08X", key, value.A, value.B); -} -bool MethodContext::repGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint64_t* value) -{ - DWORDLONG key = CastHandle(field); - AssertMapAndKeyExist(GetReadonlyStaticFieldValue, key, ": key %016llX", key); - - DLD val = GetReadonlyStaticFieldValue->Get(key); - DEBUG_REP(dmpGetReadonlyStaticFieldValue(key, val)); + DLD key; + ZeroMemory(&key, sizeof(key)); + key.A = CastHandle(field); + key.B = (DWORD)bufferSize; - *value = (uint64_t)val.A; - return (bool)val.B; -} + DWORD tmpBuf = (DWORD)-1; + if (buffer != nullptr && result) + tmpBuf = (DWORD)GetReadonlyStaticFieldValue->AddBuffer((uint8_t*)buffer, (uint32_t)bufferSize); -/* -void MethodContext::recGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, void* result) -{ - if (GetReadonlyStaticFieldValue == nullptr) - GetReadonlyStaticFieldValue = new LightWeightMap(); + DD value; + value.A = (DWORD)result; + value.B = (DWORD)tmpBuf; - DWORDLONG key = CastHandle(field); - DWORDLONG value = DWORDLONG(result); GetReadonlyStaticFieldValue->Add(key, value); DEBUG_REC(dmpGetReadonlyStaticFieldValue(key, value)); } -void MethodContext::dmpGetReadonlyStaticFieldValue(DWORDLONG key, DWORDLONG value) +void MethodContext::dmpGetReadonlyStaticFieldValue(DLD key, DD value) { - printf("GetReadonlyStaticFieldValue key field-%016llX, value field-%016llX", key, value); + printf("GetReadonlyStaticFieldValue key fld-%016llX bufSize-%u, result-%u", key.A, key.B, value.A); + GetReadonlyStaticFieldValue->Unlock(); } -void* MethodContext::repGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field) +bool MethodContext::repGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize) { - DWORDLONG key = CastHandle(field); - AssertMapAndKeyExist(GetReadonlyStaticFieldValue, key, ": key %016llX", key); - DWORDLONG value = GetReadonlyStaticFieldValue->Get(key); - DEBUG_REP(dmpGetReadonlyStaticFieldValue(key, value)); - void* result = (void*)value; - return result; -}*/ + if (GetReadonlyStaticFieldValue == nullptr) + return false; + + DLD key; + ZeroMemory(&key, sizeof(key)); + key.A = CastHandle(field); + key.B = (DWORD)bufferSize; + + int itemIndex = GetReadonlyStaticFieldValue->GetIndex(key); + if (itemIndex < 0) + { + return false; + } + else + { + DD value = GetReadonlyStaticFieldValue->Get(key); + DEBUG_REP(dmpGetReadonlyStaticFieldValue(key, value)); + if (buffer != nullptr && (bool)value.A) + { + uint8_t* srcBuffer = (uint8_t*)GetReadonlyStaticFieldValue->GetBuffer(value.B); + Assert(srcBuffer != nullptr); + memcpy(buffer, srcBuffer, bufferSize); + } + return (bool)value.A; + } +} void MethodContext::recGetStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, bool isSpeculative, diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index eb7c716b91f6d..219b5573cd0e1 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -484,9 +484,9 @@ class MethodContext void dmpGetFieldAddress(DWORDLONG key, const Agnostic_GetFieldAddress& value); void* repGetFieldAddress(CORINFO_FIELD_HANDLE field, void** ppIndirection); - void recGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint64_t value, bool result); - void dmpGetReadonlyStaticFieldValue(DWORDLONG key, DLD value); - bool repGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint64_t* pValue); + void recGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize, bool result); + void dmpGetReadonlyStaticFieldValue(DLD key, DD value); + bool repGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize); void recGetStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, bool isSpeculative, CORINFO_CLASS_HANDLE result); void dmpGetStaticFieldCurrentClass(DWORDLONG key, const Agnostic_GetStaticFieldCurrentClass& value); diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index d55f13b2a3012..b90a955fa53ff 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -1731,11 +1731,11 @@ void* interceptor_ICJI::getFieldAddress(CORINFO_FIELD_HANDLE field, void** ppInd return temp; } -bool interceptor_ICJI::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint64_t* pValue) +bool interceptor_ICJI::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize) { mc->cr->AddCall("getReadonlyStaticFieldValue"); - bool result = original_ICorJitInfo->getReadonlyStaticFieldValue(field, pValue); - mc->recGetReadonlyStaticFieldValue(field, *pValue, result); + bool result = original_ICorJitInfo->getReadonlyStaticFieldValue(field, buffer, bufferSize); + mc->recGetReadonlyStaticFieldValue(field, buffer, bufferSize, result); return result; } diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp index 6e2f9f007b41b..1e86378f5155b 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -1197,10 +1197,11 @@ void* interceptor_ICJI::getFieldAddress( bool interceptor_ICJI::getReadonlyStaticFieldValue( CORINFO_FIELD_HANDLE field, - uint64_t* pValue) + uint8_t* buffer, + int bufferSize) { mcs->AddCall("getReadonlyStaticFieldValue"); - return original_ICorJitInfo->getReadonlyStaticFieldValue(field, pValue); + return original_ICorJitInfo->getReadonlyStaticFieldValue(field, buffer, bufferSize); } CORINFO_CLASS_HANDLE interceptor_ICJI::getStaticFieldCurrentClass( diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp index 3a6ccd6cc7164..1058681597f71 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -1048,9 +1048,10 @@ void* interceptor_ICJI::getFieldAddress( bool interceptor_ICJI::getReadonlyStaticFieldValue( CORINFO_FIELD_HANDLE field, - uint64_t* pValue) + uint8_t* buffer, + int bufferSize) { - return original_ICorJitInfo->getReadonlyStaticFieldValue(field, pValue); + return original_ICorJitInfo->getReadonlyStaticFieldValue(field, buffer, bufferSize); } CORINFO_CLASS_HANDLE interceptor_ICJI::getStaticFieldCurrentClass( diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index e4d7658007676..fe6e7a4c7bc36 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -1510,10 +1510,10 @@ void* MyICJI::getFieldAddress(CORINFO_FIELD_HANDLE field, void** ppIndirection) return jitInstance->mc->repGetFieldAddress(field, ppIndirection); } -bool MyICJI::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint64_t* pValue) +bool MyICJI::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize) { jitInstance->mc->cr->AddCall("getReadonlyStaticFieldValue"); - return jitInstance->mc->repGetReadonlyStaticFieldValue(field, pValue); + return jitInstance->mc->repGetReadonlyStaticFieldValue(field, buffer, bufferSize); } // return the class handle for the current value of a static field diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index ce0d5d05f16ad..b158de4f5e3b0 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11814,7 +11814,7 @@ void* CEEJitInfo::getFieldAddress(CORINFO_FIELD_HANDLE fieldHnd, return result; } -bool CEEJitInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint64_t* pValue) +bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t* buffer, int bufferSize) { CONTRACTL { THROWS; @@ -11823,7 +11823,8 @@ bool CEEJitInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint } CONTRACTL_END; _ASSERT(fieldHnd != NULL); - _ASSERT(pValue != NULL); + _ASSERT(buffer != NULL); + _ASSERT(bufferSize == sizeof(uint64_t)); bool result = false; @@ -11851,13 +11852,14 @@ bool CEEJitInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint Object* obj = OBJECTREFToObject(fieldObj); if (GCHeapUtilities::GetGCHeap()->IsInFrozenSegment(obj)) { - *pValue = (uint64_t)obj; + intptr_t ptr = (intptr_t)obj; + memcpy(buffer, &ptr, sizeof(intptr_t)); result = true; } } else { - *pValue = 0; + memset(buffer, 0, sizeof(intptr_t)); result = true; } } @@ -11871,46 +11873,28 @@ bool CEEJitInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint switch (field->GetFieldType()) { case ELEMENT_TYPE_BOOLEAN: - *pValue = (uint64_t)*((uint8_t*)fldAddr); - break; - case ELEMENT_TYPE_CHAR: - *pValue = (uint64_t)*((uint16_t*)fldAddr); - break; case ELEMENT_TYPE_I1: - *pValue = (uint64_t)*((int8_t*)fldAddr); - break; case ELEMENT_TYPE_U1: - *pValue = (uint64_t)*((uint8_t*)fldAddr); + memcpy(buffer, fldAddr, sizeof(uint8_t)); break; + case ELEMENT_TYPE_CHAR: case ELEMENT_TYPE_I2: - *pValue = (uint64_t)*((int16_t*)fldAddr); - break; case ELEMENT_TYPE_U2: - *pValue = (uint64_t)*((uint16_t*)fldAddr); + memcpy(buffer, fldAddr, sizeof(uint16_t)); break; case ELEMENT_TYPE_I4: - *pValue = (uint64_t)*((int32_t*)fldAddr); - break; case ELEMENT_TYPE_U4: - *pValue = (uint64_t)*((uint32_t*)fldAddr); + case ELEMENT_TYPE_R4: + memcpy(buffer, fldAddr, sizeof(uint32_t)); break; case ELEMENT_TYPE_I8: - *pValue = (uint64_t)*((int32_t*)fldAddr); - break; case ELEMENT_TYPE_U8: - *pValue = (uint64_t)*((uint64_t*)fldAddr); - break; - case ELEMENT_TYPE_R4: - *pValue = (uint64_t)*((float*)fldAddr); - break; case ELEMENT_TYPE_R8: - *pValue = (uint64_t)*((double*)fldAddr); + memcpy(buffer, fldAddr, sizeof(uint64_t)); break; case ELEMENT_TYPE_I: - *pValue = (uint64_t)*((intptr_t*)fldAddr); - break; case ELEMENT_TYPE_U: - *pValue = (uint64_t)*((uintptr_t*)fldAddr); + memcpy(buffer, fldAddr, sizeof(intptr_t)); break; default: result = false; @@ -14467,12 +14451,6 @@ void* CEEInfo::getFieldAddress(CORINFO_FIELD_HANDLE fieldHnd, return result; } -bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint64_t* pValue) -{ - LIMITED_METHOD_CONTRACT; - UNREACHABLE(); // only called on derived class. -} - CORINFO_CLASS_HANDLE CEEInfo::getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE fieldHnd, bool* pIsSpeculative) { diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 3ffc6d774c586..9b517406ce4f1 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -925,7 +925,6 @@ class CEEJitInfo : public CEEInfo InfoAccessType constructStringLiteral(CORINFO_MODULE_HANDLE scopeHnd, mdToken metaTok, void **ppValue) override final; InfoAccessType emptyStringLiteral(void ** ppValue) override final; void* getFieldAddress(CORINFO_FIELD_HANDLE field, void **ppIndirection) override final; - bool getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint64_t *pValue) override final; CORINFO_CLASS_HANDLE getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, bool* pIsSpeculative) override final; void* getMethodSync(CORINFO_METHOD_HANDLE ftnHnd, void **ppIndirection) override final; From fd7e74211a6004b52170254070e785d57236d69b Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 24 Sep 2022 12:37:51 +0200 Subject: [PATCH 06/61] Address feedback --- src/coreclr/jit/importer.cpp | 2 +- .../tools/superpmi/superpmi-shared/agnostic.h | 1 - .../superpmi-shared/methodcontext.cpp | 76 +------------------ 3 files changed, 3 insertions(+), 76 deletions(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index baeed615943f5..cc1ea8435f36e 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -8157,7 +8157,7 @@ GenTree* Compiler::impImportStaticReadOnlyField(uint8_t* buffer, int bufferSize, case TYP_DOUBLE: { - float f64; + double f64; memcpy(&f64, buffer, sizeof(double)); tree = gtNewDconNode(f64); break; diff --git a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h index c9b67a1da8525..d2e9e8a3f4049 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h @@ -194,7 +194,6 @@ struct Agnostic_GetFieldAddress { DWORDLONG ppIndirection; DWORDLONG fieldAddress; - DWORD fieldValue; }; struct Agnostic_GetStaticFieldCurrentClass diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 294fab25b45b0..29cfc0e9693be 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -3581,70 +3581,13 @@ void MethodContext::recGetFieldAddress(CORINFO_FIELD_HANDLE field, void** ppIndi value.ppIndirection = CastPointer(*ppIndirection); value.fieldAddress = CastPointer(result); - value.fieldValue = (DWORD)-1; - - AssertCodeMsg(isReadyToRunCompilation != ReadyToRunCompilation::Uninitialized, EXCEPTIONCODE_MC, - "ReadyToRun flag should be initialized"); - - // Make an attempt at stashing a copy of the value, Jit can try to access - // a static readonly field value. - if (isReadyToRunCompilation == ReadyToRunCompilation::NotReadyToRun && - result > (void*)0xffff) - { - DWORDLONG scratch = 0x4242424242424242; - switch (cit) - { - case CORINFO_TYPE_BOOL: - case CORINFO_TYPE_BYTE: - case CORINFO_TYPE_UBYTE: - value.fieldValue = - (DWORD)GetFieldAddress->AddBuffer((unsigned char*)result, sizeof(BYTE), - true); // important to not merge two fields into one address - break; - case CORINFO_TYPE_CHAR: - case CORINFO_TYPE_SHORT: - case CORINFO_TYPE_USHORT: - value.fieldValue = - (DWORD)GetFieldAddress->AddBuffer((unsigned char*)result, sizeof(WORD), - true); // important to not merge two fields into one address - break; - case CORINFO_TYPE_INT: - case CORINFO_TYPE_UINT: - case CORINFO_TYPE_FLOAT: - value.fieldValue = - (DWORD)GetFieldAddress->AddBuffer((unsigned char*)result, sizeof(DWORD), - true); // important to not merge two fields into one address - break; - case CORINFO_TYPE_LONG: - case CORINFO_TYPE_ULONG: - case CORINFO_TYPE_DOUBLE: - value.fieldValue = - (DWORD)GetFieldAddress->AddBuffer((unsigned char*)result, sizeof(DWORDLONG), - true); // important to not merge two fields into one address - break; - case CORINFO_TYPE_NATIVEINT: - case CORINFO_TYPE_NATIVEUINT: - case CORINFO_TYPE_PTR: - value.fieldValue = - (DWORD)GetFieldAddress->AddBuffer((unsigned char*)result, sizeof(size_t), - true); // important to not merge two fields into one address - GetFieldAddress->AddBuffer((unsigned char*)&scratch, sizeof(DWORD)); // Padding out the data so we - // can read it back "safetly" - // on x64 - break; - default: - break; - } - } - DWORDLONG key = CastHandle(field); GetFieldAddress->Add(key, value); DEBUG_REC(dmpGetFieldAddress(key, value)); } void MethodContext::dmpGetFieldAddress(DWORDLONG key, const Agnostic_GetFieldAddress& value) { - printf("GetFieldAddress key fld-%016llX, value ppi-%016llX addr-%016llX val-%u", key, value.ppIndirection, - value.fieldAddress, value.fieldValue); + printf("GetFieldAddress key fld-%016llX, value ppi-%016llX addr-%016llX", key, value.ppIndirection, value.fieldAddress); } void* MethodContext::repGetFieldAddress(CORINFO_FIELD_HANDLE field, void** ppIndirection) { @@ -3654,26 +3597,11 @@ void* MethodContext::repGetFieldAddress(CORINFO_FIELD_HANDLE field, void** ppInd Agnostic_GetFieldAddress value = GetFieldAddress->Get(key); DEBUG_REP(dmpGetFieldAddress(key, value)); - AssertCodeMsg(isReadyToRunCompilation != ReadyToRunCompilation::Uninitialized, - EXCEPTIONCODE_MC, "isReadyToRunCompilation should be initialized"); - if (ppIndirection != nullptr) { *ppIndirection = (void*)value.ppIndirection; } - void* temp; - - if (value.fieldValue != (DWORD)-1) - { - temp = (void*)GetFieldAddress->GetBuffer(value.fieldValue); - cr->recAddressMap((void*)value.fieldAddress, temp, toCorInfoSize(repGetFieldType(field, nullptr, nullptr))); - } - else - { - temp = (void*)value.fieldAddress; - } - - return temp; + return (void*)value.fieldAddress; } void MethodContext::recGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize, bool result) From 75c40ae7d91a35cbb891ccc836c09f0e654e3c2c Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 24 Sep 2022 13:09:14 +0200 Subject: [PATCH 07/61] make jit-format happy --- src/coreclr/jit/importer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index cc1ea8435f36e..1c2620f072ca4 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -8167,7 +8167,7 @@ GenTree* Compiler::impImportStaticReadOnlyField(uint8_t* buffer, int bufferSize, { ssize_t ptr; memcpy(&ptr, buffer, sizeof(ssize_t)); - + if (ptr == 0) { tree = gtNewNull(); @@ -15269,8 +15269,8 @@ void Compiler::impImportBlockCode(BasicBlock* block) if ((aflags & CORINFO_ACCESS_GET) && (fieldInfo.fieldFlags & CORINFO_FLG_FIELD_FINAL) && !(fieldInfo.fieldFlags & CORINFO_FLG_FIELD_STATIC_IN_HEAP)) { - const int bufferSize = sizeof(uint64_t); - uint8_t buffer[bufferSize] = {0}; + const int bufferSize = sizeof(uint64_t); + uint8_t buffer[bufferSize] = {0}; if (info.compCompHnd->getReadonlyStaticFieldValue(resolvedToken.hField, buffer, bufferSize)) { GenTree* cnsValue = impImportStaticReadOnlyField(buffer, bufferSize, lclTyp); From 283b833f2ba72fcfc00321a980e8e4cfffd4c94d Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 24 Sep 2022 17:56:20 +0200 Subject: [PATCH 08/61] Fix FitsI32 assert --- src/coreclr/jit/gentree.cpp | 2 +- src/coreclr/jit/importer.cpp | 48 +++++++++++++++++++++++------------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index baa099d055c01..e278a3e288a3a 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -17581,7 +17581,7 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, b objClass = info.compCompHnd->getObjectType((void*)tree->AsIntCon()->IconValue()); if (objClass != NO_CLASS_HANDLE) { - // if we manage to get the class handle it's definitely not null + // if we managed to get a class handle it's definitely not null *pIsNonNull = true; } } diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 1c2620f072ca4..9a78431cc58da 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -8118,51 +8118,65 @@ GenTree* Compiler::impInitClass(CORINFO_RESOLVED_TOKEN* pResolvedToken) GenTree* Compiler::impImportStaticReadOnlyField(uint8_t* buffer, int bufferSize, var_types valueType) { - // We plan to support bigger values for structs, but for now it's always 64bit + // We plan to support larger values (for structs), for now let's keep it 64 bit assert(bufferSize == sizeof(INT64)); GenTree* tree = nullptr; switch (valueType) { +// Use memcpy to read from the buffer and create an Icon/Dcon tree +#define CreateTreeFromBuffer(type, treeFactory) \ + type v##type##; \ + memcpy(&v##type##, buffer, sizeof(type)); \ + tree = treeFactory(v##type##); + case TYP_BOOL: + { + CreateTreeFromBuffer(bool, gtNewIconNode); + break; + } case TYP_BYTE: + { + CreateTreeFromBuffer(int8_t, gtNewIconNode); + break; + } case TYP_UBYTE: + { + CreateTreeFromBuffer(uint8_t, gtNewIconNode); + break; + } case TYP_SHORT: + { + CreateTreeFromBuffer(int16_t, gtNewIconNode); + break; + } case TYP_USHORT: + { + CreateTreeFromBuffer(uint16_t, gtNewIconNode); + break; + } case TYP_UINT: case TYP_INT: { - ssize_t i32; - memcpy(&i32, buffer, sizeof(ssize_t)); - tree = gtNewIconNode(i32); + CreateTreeFromBuffer(int32_t, gtNewIconNode); break; } - case TYP_LONG: case TYP_ULONG: { - INT64 i64; - memcpy(&i64, buffer, sizeof(INT64)); - tree = gtNewLconNode(i64); + CreateTreeFromBuffer(int64_t, gtNewIconNode); break; } - case TYP_FLOAT: { - float f32; - memcpy(&f32, buffer, sizeof(float)); - tree = gtNewDconNode(f32); + CreateTreeFromBuffer(float, gtNewDconNode); break; } - case TYP_DOUBLE: { - double f64; - memcpy(&f64, buffer, sizeof(double)); - tree = gtNewDconNode(f64); + CreateTreeFromBuffer(double, gtNewDconNode); break; } - case TYP_REF: { ssize_t ptr; From 00e3e691bd7994411a400af2b9a4cb09e1ca5641 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 24 Sep 2022 18:17:59 +0200 Subject: [PATCH 09/61] clean up in methodcontext --- .../superpmi/superpmi-shared/methodcontext.cpp | 17 ----------------- .../superpmi/superpmi-shared/methodcontext.h | 11 ----------- 2 files changed, 28 deletions(-) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 29cfc0e9693be..b46094963bb95 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -30,7 +30,6 @@ MethodContext::MethodContext() cr = new CompileResult(); index = -1; - isReadyToRunCompilation = ReadyToRunCompilation::Uninitialized; } MethodContext::~MethodContext() @@ -1236,7 +1235,6 @@ void MethodContext::recGetJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes, DW // zero. GetJitFlags->Add(0, value); DEBUG_REC(dmpGetJitFlags(0, value)); - InitReadyToRunFlag(jitFlags); } void MethodContext::dmpGetJitFlags(DWORD key, DD value) { @@ -1261,7 +1259,6 @@ DWORD MethodContext::repGetJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes) CORJIT_FLAGS* resultFlags = (CORJIT_FLAGS*)GetJitFlags->GetBuffer(value.A); Assert(sizeInBytes >= value.B); memcpy(jitFlags, resultFlags, value.B); - InitReadyToRunFlag(resultFlags); return value.B; } @@ -7430,20 +7427,6 @@ bool MethodContext::IsStringContentEqual(LightWeightMap* prev, Lig } } -void MethodContext::InitReadyToRunFlag(const CORJIT_FLAGS* jitFlags) -{ - if (jitFlags->IsSet(CORJIT_FLAGS::CORJIT_FLAG_READYTORUN)) - { - isReadyToRunCompilation = ReadyToRunCompilation::ReadyToRun; - } - else - { - isReadyToRunCompilation = ReadyToRunCompilation::NotReadyToRun; - } - -} - - bool g_debugRec = false; bool g_debugRep = false; diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index 219b5573cd0e1..79f7b14365f87 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -900,17 +900,6 @@ class MethodContext bool IsEnvironmentHeaderEqual(const Environment& prevEnv); bool IsEnvironmentContentEqual(const Environment& prevEnv); - enum class ReadyToRunCompilation - { - Uninitialized, - ReadyToRun, - NotReadyToRun - }; - - ReadyToRunCompilation isReadyToRunCompilation; - - void InitReadyToRunFlag(const CORJIT_FLAGS* jitFlags); - template static bool AreLWMHeadersEqual(LightWeightMap* prev, LightWeightMap* curr); static bool IsIntConfigContentEqual(LightWeightMap* prev, From f7902d2e1a0e6e5e24ed634046f88485821b1fe9 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Sat, 24 Sep 2022 18:33:58 +0200 Subject: [PATCH 10/61] Update importer.cpp --- src/coreclr/jit/importer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 9a78431cc58da..ade399a4ef26d 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -8164,7 +8164,7 @@ GenTree* Compiler::impImportStaticReadOnlyField(uint8_t* buffer, int bufferSize, case TYP_LONG: case TYP_ULONG: { - CreateTreeFromBuffer(int64_t, gtNewIconNode); + CreateTreeFromBuffer(int64_t, gtNewLconNode); break; } case TYP_FLOAT: From bf7947f95f27e04d742066bdb176177fc9b105c6 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 24 Sep 2022 18:49:26 +0200 Subject: [PATCH 11/61] Implement getObjectType for ILC --- .../tools/Common/JitInterface/CorInfoImpl.cs | 8 +------- .../JitInterface/CorInfoImpl.ReadyToRun.cs | 5 +++++ .../JitInterface/CorInfoImpl.RyuJit.cs | 13 +++++++++++++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 6ef615b5ca1ab..d33d3256908c6 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -2347,16 +2347,10 @@ private CorInfoHelpFunc getUnBoxHelper(CORINFO_CLASS_STRUCT_* cls) private void* getRuntimeTypePointer(CORINFO_CLASS_STRUCT_* cls) #pragma warning restore CA1822 // Mark members as static { + // TODO: https://github.com/dotnet/runtime/pull/75573#issuecomment-1250824543 return (void*)IntPtr.Zero; } -#pragma warning disable CA1822 // Mark members as static - private CORINFO_CLASS_STRUCT_* getObjectType(void* typeObj) -#pragma warning restore CA1822 // Mark members as static - { - return (CORINFO_CLASS_STRUCT_*)IntPtr.Zero; - } - private byte* getHelperName(CorInfoHelpFunc helpFunc) { return (byte*)GetPin(StringToUTF8(helpFunc.ToString())); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index 7b89e36006e8f..f52e1d592e806 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -2992,5 +2992,10 @@ private int getExactClasses(CORINFO_CLASS_STRUCT_* baseType, int maxExactClasses // Not implemented for R2R yet return 0; } + + private CORINFO_CLASS_STRUCT_* getObjectType(void* objPtr) + { + return (CORINFO_CLASS_STRUCT_*)IntPtr.Zero; + } } } diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index efc9c60ac8cc0..35451576cc635 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2203,5 +2203,18 @@ private int getExactClasses(CORINFO_CLASS_STRUCT_* baseType, int maxExactClasses Debug.Assert(index <= maxExactClasses); return index; } + +#pragma warning disable CA1822 // Mark members as static + private CORINFO_CLASS_STRUCT_* getObjectType(void* objPtr) +#pragma warning restore CA1822 // Mark members as static + { + // only strings are passed here for now + object obj = HandleToObject((IntPtr)objPtr); + if (obj is string) + { + return ObjectToHandle(_compilation.TypeSystemContext.GetWellKnownType(WellKnownType.String)); + } + return (CORINFO_CLASS_STRUCT_*)IntPtr.Zero; + } } } From 5374beafac4ad53bba9472bdcd9883bbbd11f1a7 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Sat, 24 Sep 2022 19:09:50 +0200 Subject: [PATCH 12/61] fix clang/gcc --- src/coreclr/jit/importer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index ade399a4ef26d..4460576476419 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -8126,9 +8126,9 @@ GenTree* Compiler::impImportStaticReadOnlyField(uint8_t* buffer, int bufferSize, { // Use memcpy to read from the buffer and create an Icon/Dcon tree #define CreateTreeFromBuffer(type, treeFactory) \ - type v##type##; \ - memcpy(&v##type##, buffer, sizeof(type)); \ - tree = treeFactory(v##type##); + type v##type; \ + memcpy(&v##type, buffer, sizeof(type)); \ + tree = treeFactory(v##type); case TYP_BOOL: { From 548dc9c931ca5a4d71c6f5fa335463892f73e12f Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Sat, 24 Sep 2022 21:08:38 +0200 Subject: [PATCH 13/61] Update src/coreclr/vm/jitinterface.cpp Co-authored-by: Jan Kotas --- src/coreclr/vm/jitinterface.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index b158de4f5e3b0..013cb77c16cda 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -6028,8 +6028,6 @@ CORINFO_CLASS_HANDLE CEEInfo::getObjectType(void* typeObj) JIT_TO_EE_TRANSITION(); - if (typeObj != nullptr) - { GCX_COOP(); Object* obj = (Object*)typeObj; VALIDATEOBJECT(obj); From 1234e97bc17412aee96d228c2fad1348192253bc Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 24 Sep 2022 21:23:29 +0200 Subject: [PATCH 14/61] Address feedback --- .../JitInterface/CorInfoImpl.RyuJit.cs | 9 ++++----- src/coreclr/vm/jitinterface.cpp | 13 +++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 35451576cc635..7b05804079003 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2204,17 +2204,16 @@ private int getExactClasses(CORINFO_CLASS_STRUCT_* baseType, int maxExactClasses return index; } -#pragma warning disable CA1822 // Mark members as static private CORINFO_CLASS_STRUCT_* getObjectType(void* objPtr) -#pragma warning restore CA1822 // Mark members as static { - // only strings are passed here for now object obj = HandleToObject((IntPtr)objPtr); - if (obj is string) + if (obj is FrozenStringNode) { return ObjectToHandle(_compilation.TypeSystemContext.GetWellKnownType(WellKnownType.String)); } - return (CORINFO_CLASS_STRUCT_*)IntPtr.Zero; + + // For now only frozen strings can come here + throw new NotImplementedException($"Unexpected object in getObjectType: {obj}"); } } } diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 013cb77c16cda..91abd581c08f2 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -6016,7 +6016,7 @@ void* CEEInfo::getRuntimeTypePointer(CORINFO_CLASS_HANDLE clsHnd) } /***********************************************************************/ -CORINFO_CLASS_HANDLE CEEInfo::getObjectType(void* typeObj) +CORINFO_CLASS_HANDLE CEEInfo::getObjectType(void* objPtr) { CONTRACTL{ THROWS; @@ -6024,15 +6024,16 @@ CORINFO_CLASS_HANDLE CEEInfo::getObjectType(void* typeObj) MODE_PREEMPTIVE; } CONTRACTL_END; + _ASSERT(objPtr != nullptr); + CORINFO_CLASS_HANDLE handle = NULL; JIT_TO_EE_TRANSITION(); - GCX_COOP(); - Object* obj = (Object*)typeObj; - VALIDATEOBJECT(obj); - handle = (CORINFO_CLASS_HANDLE)obj->GetMethodTable(); - } + GCX_COOP(); + Object* obj = (Object*)objPtr; + VALIDATEOBJECT(obj); + handle = (CORINFO_CLASS_HANDLE)obj->GetMethodTable(); EE_TO_JIT_TRANSITION(); From 1c584a19e1b63a17d88db22e5f714931de719e04 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sun, 25 Sep 2022 22:29:47 +0200 Subject: [PATCH 15/61] Initial impl for NativeAOT --- src/coreclr/jit/importer.cpp | 2 +- .../tools/Common/JitInterface/CorInfoImpl.cs | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 4460576476419..d328b437d6f68 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -15278,6 +15278,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) usesHelper = true; break; + case CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER: case CORINFO_FIELD_STATIC_ADDRESS: // Replace static read-only fields with constant if possible if ((aflags & CORINFO_ACCESS_GET) && (fieldInfo.fieldFlags & CORINFO_FLG_FIELD_FINAL) && @@ -15298,7 +15299,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) FALLTHROUGH; case CORINFO_FIELD_STATIC_RVA_ADDRESS: - case CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER: case CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER: case CORINFO_FIELD_STATIC_READYTORUN_HELPER: op1 = impImportStaticFieldAccess(&resolvedToken, (CORINFO_ACCESS_FLAGS)aflags, &fieldInfo, diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index d33d3256908c6..0dca88957392a 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3308,9 +3308,26 @@ private uint getClassDomainID(CORINFO_CLASS_STRUCT_* cls, ref void* ppIndirectio } #pragma warning disable CA1822 // Mark members as static - private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* field, byte* buffer, int bufferSize) + private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byte* buffer, int bufferSize) #pragma warning restore CA1822 // Mark members as static { + /* + FieldDesc field = HandleToObject(fieldHandle); + if (field.IsStatic && !field.IsThreadStatic && field.IsInitOnly && !field.IsIntrinsic && !field.HasGCStaticBase && + !_compilation.HasLazyStaticConstructor(field.OwningType)) + { + switch (field.FieldType.Category) + { + case TypeFlags.Int32: + { + var baseAddress = _compilation.NodeFactory.TypeGCStaticsSymbol((MetadataType)field.OwningType); + *((int*)buffer) = 42; + return true; + } + break; + } + } + */ return false; } From 1fc50c72a577f51dcfbd372bc8f22f5574faff5c Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sun, 25 Sep 2022 23:56:47 +0200 Subject: [PATCH 16/61] Use PreinitializationInfo --- .../tools/Common/JitInterface/CorInfoImpl.cs | 28 +++++++++++++++---- .../Compiler/TypePreinit.cs | 18 ++++++++++++ 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 0dca88957392a..7adb17dd6c890 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3311,23 +3311,39 @@ private uint getClassDomainID(CORINFO_CLASS_STRUCT_* cls, ref void* ppIndirectio private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byte* buffer, int bufferSize) #pragma warning restore CA1822 // Mark members as static { - /* FieldDesc field = HandleToObject(fieldHandle); if (field.IsStatic && !field.IsThreadStatic && field.IsInitOnly && !field.IsIntrinsic && !field.HasGCStaticBase && - !_compilation.HasLazyStaticConstructor(field.OwningType)) + !_compilation.HasLazyStaticConstructor(field.OwningType) && field.OwningType is MetadataType owningType) { switch (field.FieldType.Category) { + case TypeFlags.Boolean: + case TypeFlags.Byte: + case TypeFlags.SByte: + case TypeFlags.Int16: + case TypeFlags.UInt16: + case TypeFlags.Char: case TypeFlags.Int32: + case TypeFlags.UInt32: + case TypeFlags.Int64: + case TypeFlags.UInt64: + case TypeFlags.Single: + case TypeFlags.Double: { - var baseAddress = _compilation.NodeFactory.TypeGCStaticsSymbol((MetadataType)field.OwningType); - *((int*)buffer) = 42; - return true; + PreinitializationManager preinitManager = _compilation.NodeFactory.PreinitializationManager; + if (preinitManager.IsPreinitialized(owningType)) + { + TypePreinit.ISerializableValue value = preinitManager + .GetPreinitializationInfo(owningType).GetFieldValue(field); + if (value.WriteFieldData(new Span(buffer, bufferSize))) + { + return true; + } + } } break; } } - */ return false; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs index 5d292226fbd72..600746ff3c6e0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs @@ -1704,6 +1704,8 @@ private enum StackValueKind public interface ISerializableValue { void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory factory); + + bool WriteFieldData(Span dest); } /// @@ -1767,6 +1769,11 @@ public virtual bool TryCreateByRef(out Value value) public abstract void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory factory); + public virtual bool WriteFieldData(Span dest) + { + return false; + } + private static T ThrowInvalidProgram() { ThrowHelper.ThrowInvalidProgramException(); @@ -1855,6 +1862,17 @@ public override void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory f builder.EmitBytes(InstanceBytes); } + public override bool WriteFieldData(Span dest) + { + byte[] data = InstanceBytes; + if (dest.Length < data.Length) + { + return false; + } + data.AsSpan().CopyTo(dest); + return true; + } + private byte[] AsExactByteCount(int size) { if (InstanceBytes.Length != size) From 600209fb2a90b971066a26cc80763b7c935010f9 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 26 Sep 2022 00:36:20 +0200 Subject: [PATCH 17/61] Handle strings --- .../tools/Common/JitInterface/CorInfoImpl.cs | 31 +++++++++++++++++-- .../Compiler/TypePreinit.cs | 20 ++++++------ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 7adb17dd6c890..a8240f5df0251 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3312,7 +3312,7 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt #pragma warning restore CA1822 // Mark members as static { FieldDesc field = HandleToObject(fieldHandle); - if (field.IsStatic && !field.IsThreadStatic && field.IsInitOnly && !field.IsIntrinsic && !field.HasGCStaticBase && + if (field.IsStatic && !field.IsThreadStatic && field.IsInitOnly && !field.IsIntrinsic && !_compilation.HasLazyStaticConstructor(field.OwningType) && field.OwningType is MetadataType owningType) { switch (field.FieldType.Category) @@ -3329,15 +3329,40 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt case TypeFlags.UInt64: case TypeFlags.Single: case TypeFlags.Double: + case TypeFlags.Class: { PreinitializationManager preinitManager = _compilation.NodeFactory.PreinitializationManager; if (preinitManager.IsPreinitialized(owningType)) { TypePreinit.ISerializableValue value = preinitManager .GetPreinitializationInfo(owningType).GetFieldValue(field); - if (value.WriteFieldData(new Span(buffer, bufferSize))) + + object data; + if (value.GetRawData(out data)) { - return true; + if (data is byte[] bytes && bytes.Length <= bufferSize) + { + Debug.Assert(!field.HasGCStaticBase); + bytes.AsSpan().CopyTo(new Span(buffer, bufferSize)); + return true; + } + + if (data is null) + { + Debug.Assert(field.FieldType.Category == TypeFlags.Class && field.HasGCStaticBase); + + *((nint*)buffer) = 0; + return true; + } + + if (data is string str) + { + Debug.Assert(field.FieldType.Category == TypeFlags.Class && field.HasGCStaticBase); + + FrozenStringNode stringObject = _compilation.NodeFactory.SerializedStringObject(str); + *((nint*)buffer) = ObjectToHandle(stringObject); + return true; + } } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs index 600746ff3c6e0..1758a6cf07973 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs @@ -1705,7 +1705,7 @@ public interface ISerializableValue { void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory factory); - bool WriteFieldData(Span dest); + bool GetRawData(out object data); } /// @@ -1769,8 +1769,9 @@ public virtual bool TryCreateByRef(out Value value) public abstract void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory factory); - public virtual bool WriteFieldData(Span dest) + public virtual bool GetRawData(out object data) { + data = null; return false; } @@ -1862,14 +1863,9 @@ public override void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory f builder.EmitBytes(InstanceBytes); } - public override bool WriteFieldData(Span dest) + public override bool GetRawData(out object data) { - byte[] data = InstanceBytes; - if (dest.Length < data.Length) - { - return false; - } - data.AsSpan().CopyTo(dest); + data = InstanceBytes; return true; } @@ -2243,6 +2239,12 @@ public override void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory f builder.EmitPointerReloc(factory.SerializedStringObject(_value)); } + public override bool GetRawData(out object data) + { + data = _value; + return true; + } + public override ReferenceTypeValue ToForeignInstance(int baseInstructionCounter) => this; } From 4cad20ac7901fbbc78949d18012ab93fac90f835 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Mon, 26 Sep 2022 00:36:45 +0200 Subject: [PATCH 18/61] Update src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs Co-authored-by: Jan Kotas --- src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 7adb17dd6c890..83ec239263562 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3307,7 +3307,6 @@ private uint getClassDomainID(CORINFO_CLASS_STRUCT_* cls, ref void* ppIndirectio } } -#pragma warning disable CA1822 // Mark members as static private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byte* buffer, int bufferSize) #pragma warning restore CA1822 // Mark members as static { From 28f2749acd5f4521cb86fb38356e41d261bd21cf Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Mon, 26 Sep 2022 00:37:08 +0200 Subject: [PATCH 19/61] Apply suggestions from code review Co-authored-by: Jan Kotas --- src/coreclr/jit/importer.cpp | 1 - src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index d328b437d6f68..8b508e9d9ee2a 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -15282,7 +15282,6 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CORINFO_FIELD_STATIC_ADDRESS: // Replace static read-only fields with constant if possible if ((aflags & CORINFO_ACCESS_GET) && (fieldInfo.fieldFlags & CORINFO_FLG_FIELD_FINAL) && - !(fieldInfo.fieldFlags & CORINFO_FLG_FIELD_STATIC_IN_HEAP)) { const int bufferSize = sizeof(uint64_t); uint8_t buffer[bufferSize] = {0}; diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 83ec239263562..7e0872a433796 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3308,11 +3308,10 @@ private uint getClassDomainID(CORINFO_CLASS_STRUCT_* cls, ref void* ppIndirectio } private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byte* buffer, int bufferSize) -#pragma warning restore CA1822 // Mark members as static { FieldDesc field = HandleToObject(fieldHandle); - if (field.IsStatic && !field.IsThreadStatic && field.IsInitOnly && !field.IsIntrinsic && !field.HasGCStaticBase && - !_compilation.HasLazyStaticConstructor(field.OwningType) && field.OwningType is MetadataType owningType) + if (field.IsStatic && !field.IsThreadStatic && field.IsInitOnly) + field.OwningType is MetadataType owningType) { switch (field.FieldType.Category) { From a07232dc30a68800701ab4e606fe04f41430d7ea Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 26 Sep 2022 00:48:44 +0200 Subject: [PATCH 20/61] clean up --- src/coreclr/jit/importer.cpp | 2 +- .../tools/Common/JitInterface/CorInfoImpl.cs | 21 +++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 8b508e9d9ee2a..df4c032b8f6fa 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -15281,7 +15281,7 @@ void Compiler::impImportBlockCode(BasicBlock* block) case CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER: case CORINFO_FIELD_STATIC_ADDRESS: // Replace static read-only fields with constant if possible - if ((aflags & CORINFO_ACCESS_GET) && (fieldInfo.fieldFlags & CORINFO_FLG_FIELD_FINAL) && + if ((aflags & CORINFO_ACCESS_GET) && (fieldInfo.fieldFlags & CORINFO_FLG_FIELD_FINAL)) { const int bufferSize = sizeof(uint64_t); uint8_t buffer[bufferSize] = {0}; diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 0e626ffc79d9f..13a75860ed5b8 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3308,11 +3308,9 @@ private uint getClassDomainID(CORINFO_CLASS_STRUCT_* cls, ref void* ppIndirectio } private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byte* buffer, int bufferSize) -#pragma warning restore CA1822 // Mark members as static { FieldDesc field = HandleToObject(fieldHandle); - if (field.IsStatic && !field.IsThreadStatic && field.IsInitOnly && !field.IsIntrinsic && - !_compilation.HasLazyStaticConstructor(field.OwningType) && field.OwningType is MetadataType owningType) + if (field.IsStatic && !field.IsThreadStatic && field.IsInitOnly && field.OwningType is MetadataType owningType) { switch (field.FieldType.Category) { @@ -3336,21 +3334,22 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt TypePreinit.ISerializableValue value = preinitManager .GetPreinitializationInfo(owningType).GetFieldValue(field); + if (value == null) + { + Debug.Assert(field.FieldType.Category == TypeFlags.Class && field.HasGCStaticBase); + + *((nint*)buffer) = 0; + return true; + } + object data; if (value.GetRawData(out data)) { if (data is byte[] bytes && bytes.Length <= bufferSize) { Debug.Assert(!field.HasGCStaticBase); - bytes.AsSpan().CopyTo(new Span(buffer, bufferSize)); - return true; - } - - if (data is null) - { - Debug.Assert(field.FieldType.Category == TypeFlags.Class && field.HasGCStaticBase); - *((nint*)buffer) = 0; + bytes.AsSpan().CopyTo(new Span(buffer, bufferSize)); return true; } From 0c6fe27d6df1b45623aa1ee8fa8fd07ed868db56 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 26 Sep 2022 01:05:56 +0200 Subject: [PATCH 21/61] Add a comment --- src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 13a75860ed5b8..d91bd23cd7b97 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3312,6 +3312,13 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt FieldDesc field = HandleToObject(fieldHandle); if (field.IsStatic && !field.IsThreadStatic && field.IsInitOnly && field.OwningType is MetadataType owningType) { + // Currently, jit is able to handle only these types of objects: + // * primitives + // * frozen strings + // * null + // + // To add support for mutable objects see https://github.com/dotnet/runtime/pull/76135#issuecomment-1257263126 + switch (field.FieldType.Category) { case TypeFlags.Boolean: From 271f44287ba68584a970437ce2b0f839ad554b02 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 26 Sep 2022 01:11:50 +0200 Subject: [PATCH 22/61] Fix build --- .../JitInterface/CorInfoImpl.ReadyToRun.cs | 5 ++ .../JitInterface/CorInfoImpl.RyuJit.cs | 70 +++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index f52e1d592e806..80e8359d2ffae 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -2993,6 +2993,11 @@ private int getExactClasses(CORINFO_CLASS_STRUCT_* baseType, int maxExactClasses return 0; } + private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byte* buffer, int bufferSize) + { + return false; + } + private CORINFO_CLASS_STRUCT_* getObjectType(void* objPtr) { return (CORINFO_CLASS_STRUCT_*)IntPtr.Zero; diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 7b05804079003..42df80b8daec6 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2204,6 +2204,76 @@ private int getExactClasses(CORINFO_CLASS_STRUCT_* baseType, int maxExactClasses return index; } + private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byte* buffer, int bufferSize) + { + FieldDesc field = HandleToObject(fieldHandle); + if (field.IsStatic && !field.IsThreadStatic && field.IsInitOnly && field.OwningType is MetadataType owningType) + { + // Currently, jit is able to handle only these types of objects: + // * primitives + // * frozen strings + // * null + // + // To add support for mutable objects see https://github.com/dotnet/runtime/pull/76135#issuecomment-1257263126 + + switch (field.FieldType.Category) + { + case TypeFlags.Boolean: + case TypeFlags.Byte: + case TypeFlags.SByte: + case TypeFlags.Int16: + case TypeFlags.UInt16: + case TypeFlags.Char: + case TypeFlags.Int32: + case TypeFlags.UInt32: + case TypeFlags.Int64: + case TypeFlags.UInt64: + case TypeFlags.Single: + case TypeFlags.Double: + case TypeFlags.Class: + { + PreinitializationManager preinitManager = _compilation.NodeFactory.PreinitializationManager; + if (preinitManager.IsPreinitialized(owningType)) + { + TypePreinit.ISerializableValue value = preinitManager + .GetPreinitializationInfo(owningType).GetFieldValue(field); + + if (value == null) + { + Debug.Assert(field.FieldType.Category == TypeFlags.Class && field.HasGCStaticBase); + + *((nint*)buffer) = 0; + return true; + } + + object data; + if (value.GetRawData(out data)) + { + if (data is byte[] bytes && bytes.Length <= bufferSize) + { + Debug.Assert(!field.HasGCStaticBase); + + bytes.AsSpan().CopyTo(new Span(buffer, bufferSize)); + return true; + } + + if (data is string str) + { + Debug.Assert(field.FieldType.Category == TypeFlags.Class && field.HasGCStaticBase); + + FrozenStringNode stringObject = _compilation.NodeFactory.SerializedStringObject(str); + *((nint*)buffer) = ObjectToHandle(stringObject); + return true; + } + } + } + } + break; + } + } + return false; + } + private CORINFO_CLASS_STRUCT_* getObjectType(void* objPtr) { object obj = HandleToObject((IntPtr)objPtr); From 76f6cdc812b5fef66fa633a9e45bff70957f9941 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 26 Sep 2022 01:13:58 +0200 Subject: [PATCH 23/61] Fix build --- .../tools/Common/JitInterface/CorInfoImpl.cs | 70 ------------------- 1 file changed, 70 deletions(-) diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index d91bd23cd7b97..06a29f75d91d0 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3307,76 +3307,6 @@ private uint getClassDomainID(CORINFO_CLASS_STRUCT_* cls, ref void* ppIndirectio } } - private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byte* buffer, int bufferSize) - { - FieldDesc field = HandleToObject(fieldHandle); - if (field.IsStatic && !field.IsThreadStatic && field.IsInitOnly && field.OwningType is MetadataType owningType) - { - // Currently, jit is able to handle only these types of objects: - // * primitives - // * frozen strings - // * null - // - // To add support for mutable objects see https://github.com/dotnet/runtime/pull/76135#issuecomment-1257263126 - - switch (field.FieldType.Category) - { - case TypeFlags.Boolean: - case TypeFlags.Byte: - case TypeFlags.SByte: - case TypeFlags.Int16: - case TypeFlags.UInt16: - case TypeFlags.Char: - case TypeFlags.Int32: - case TypeFlags.UInt32: - case TypeFlags.Int64: - case TypeFlags.UInt64: - case TypeFlags.Single: - case TypeFlags.Double: - case TypeFlags.Class: - { - PreinitializationManager preinitManager = _compilation.NodeFactory.PreinitializationManager; - if (preinitManager.IsPreinitialized(owningType)) - { - TypePreinit.ISerializableValue value = preinitManager - .GetPreinitializationInfo(owningType).GetFieldValue(field); - - if (value == null) - { - Debug.Assert(field.FieldType.Category == TypeFlags.Class && field.HasGCStaticBase); - - *((nint*)buffer) = 0; - return true; - } - - object data; - if (value.GetRawData(out data)) - { - if (data is byte[] bytes && bytes.Length <= bufferSize) - { - Debug.Assert(!field.HasGCStaticBase); - - bytes.AsSpan().CopyTo(new Span(buffer, bufferSize)); - return true; - } - - if (data is string str) - { - Debug.Assert(field.FieldType.Category == TypeFlags.Class && field.HasGCStaticBase); - - FrozenStringNode stringObject = _compilation.NodeFactory.SerializedStringObject(str); - *((nint*)buffer) = ObjectToHandle(stringObject); - return true; - } - } - } - } - break; - } - } - return false; - } - private CORINFO_CLASS_STRUCT_* getStaticFieldCurrentClass(CORINFO_FIELD_STRUCT_* field, byte* pIsSpeculative) { if (pIsSpeculative != null) From 133c2681ba3d7db04a9edf3f858ebebb62dcb046 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 26 Sep 2022 12:38:18 +0200 Subject: [PATCH 24/61] Address Michal's feedback --- .../Compiler/TypePreinit.cs | 16 ++-- .../JitInterface/CorInfoImpl.RyuJit.cs | 76 +++++-------------- 2 files changed, 32 insertions(+), 60 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs index 1758a6cf07973..8834f0be65718 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs @@ -1705,7 +1705,7 @@ public interface ISerializableValue { void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory factory); - bool GetRawData(out object data); + bool GetRawData(NodeFactory factory, out object data); } /// @@ -1769,7 +1769,7 @@ public virtual bool TryCreateByRef(out Value value) public abstract void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory factory); - public virtual bool GetRawData(out object data) + public virtual bool GetRawData(NodeFactory factory, out object data) { data = null; return false; @@ -1863,7 +1863,7 @@ public override void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory f builder.EmitBytes(InstanceBytes); } - public override bool GetRawData(out object data) + public override bool GetRawData(NodeFactory factory, out object data) { data = InstanceBytes; return true; @@ -2127,6 +2127,12 @@ public ArrayInstance(ArrayType type, int elementCount, AllocationSite allocation _data = new byte[elementCount * _elementSize]; } + public override bool GetRawData(NodeFactory factory, out object data) + { + data = null; + return false; + } + public bool TryInitialize(byte[] bytes) { if (bytes.Length != _data.Length) @@ -2239,9 +2245,9 @@ public override void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory f builder.EmitPointerReloc(factory.SerializedStringObject(_value)); } - public override bool GetRawData(out object data) + public override bool GetRawData(NodeFactory factory, out object data) { - data = _value; + data = factory.SerializedStringObject(_value); return true; } diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 42df80b8daec6..10db57a7048e6 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2209,66 +2209,32 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt FieldDesc field = HandleToObject(fieldHandle); if (field.IsStatic && !field.IsThreadStatic && field.IsInitOnly && field.OwningType is MetadataType owningType) { - // Currently, jit is able to handle only these types of objects: - // * primitives - // * frozen strings - // * null - // - // To add support for mutable objects see https://github.com/dotnet/runtime/pull/76135#issuecomment-1257263126 - - switch (field.FieldType.Category) + PreinitializationManager preinitManager = _compilation.NodeFactory.PreinitializationManager; + if (preinitManager.IsPreinitialized(owningType)) { - case TypeFlags.Boolean: - case TypeFlags.Byte: - case TypeFlags.SByte: - case TypeFlags.Int16: - case TypeFlags.UInt16: - case TypeFlags.Char: - case TypeFlags.Int32: - case TypeFlags.UInt32: - case TypeFlags.Int64: - case TypeFlags.UInt64: - case TypeFlags.Single: - case TypeFlags.Double: - case TypeFlags.Class: - { - PreinitializationManager preinitManager = _compilation.NodeFactory.PreinitializationManager; - if (preinitManager.IsPreinitialized(owningType)) - { - TypePreinit.ISerializableValue value = preinitManager - .GetPreinitializationInfo(owningType).GetFieldValue(field); + TypePreinit.ISerializableValue value = preinitManager + .GetPreinitializationInfo(owningType).GetFieldValue(field); - if (value == null) - { - Debug.Assert(field.FieldType.Category == TypeFlags.Class && field.HasGCStaticBase); + if (value == null) + { + *((nint*)buffer) = 0; + return true; + } - *((nint*)buffer) = 0; - return true; - } + object data; + if (value.GetRawData(_compilation.NodeFactory, out data)) + { + switch (data) + { + case byte[] bytes when bytes.Length <= bufferSize: + bytes.AsSpan().CopyTo(new Span(buffer, bufferSize)); + return true; - object data; - if (value.GetRawData(out data)) - { - if (data is byte[] bytes && bytes.Length <= bufferSize) - { - Debug.Assert(!field.HasGCStaticBase); - - bytes.AsSpan().CopyTo(new Span(buffer, bufferSize)); - return true; - } - - if (data is string str) - { - Debug.Assert(field.FieldType.Category == TypeFlags.Class && field.HasGCStaticBase); - - FrozenStringNode stringObject = _compilation.NodeFactory.SerializedStringObject(str); - *((nint*)buffer) = ObjectToHandle(stringObject); - return true; - } - } - } + case FrozenStringNode str: + *((nint*)buffer) = ObjectToHandle(str); + return true; } - break; + } } } return false; From 88809549d6445963801ca3946027c5eec504f28e Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 26 Sep 2022 12:48:08 +0200 Subject: [PATCH 25/61] Address Michal's feedback --- .../ILCompiler.Compiler/Compiler/TypePreinit.cs | 17 +++++++++++------ .../JitInterface/CorInfoImpl.RyuJit.cs | 10 ++++++++-- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs index 8834f0be65718..d063ffb541c05 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs @@ -2036,6 +2036,17 @@ public override ReferenceTypeValue ToForeignInstance(int baseInstructionCounter) Type, new AllocationSite(AllocationSite.OwningType, AllocationSite.InstructionCounter - baseInstructionCounter), this); + + public override bool GetRawData(NodeFactory factory, out object data) + { + if (this is ISerializableReference serializableRef) + { + data = factory.SerializedFrozenObject(AllocationSite.OwningType, AllocationSite.InstructionCounter, serializableRef); + return true; + } + data = null; + return false; + } } #pragma warning disable CA1852 @@ -2127,12 +2138,6 @@ public ArrayInstance(ArrayType type, int elementCount, AllocationSite allocation _data = new byte[elementCount * _elementSize]; } - public override bool GetRawData(NodeFactory factory, out object data) - { - data = null; - return false; - } - public bool TryInitialize(byte[] bytes) { if (bytes.Length != _data.Length) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 10db57a7048e6..b59aeee9bc127 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2233,6 +2233,10 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt case FrozenStringNode str: *((nint*)buffer) = ObjectToHandle(str); return true; + + case FrozenObjectNode node: + *((nint*)buffer) = ObjectToHandle(node); + return true; } } } @@ -2247,8 +2251,10 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt { return ObjectToHandle(_compilation.TypeSystemContext.GetWellKnownType(WellKnownType.String)); } - - // For now only frozen strings can come here + else if (obj is FrozenObjectNode) + { + return null; // TODO: how to implement properly? + } throw new NotImplementedException($"Unexpected object in getObjectType: {obj}"); } } From 63cd7cc22dd48c37f32a1a69ae557e7cde0253cf Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 26 Sep 2022 12:53:23 +0200 Subject: [PATCH 26/61] Simplify PM switch --- .../ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index b59aeee9bc127..63f5c3d672894 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2230,12 +2230,8 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt bytes.AsSpan().CopyTo(new Span(buffer, bufferSize)); return true; - case FrozenStringNode str: - *((nint*)buffer) = ObjectToHandle(str); - return true; - - case FrozenObjectNode node: - *((nint*)buffer) = ObjectToHandle(node); + case FrozenObjectNode or FrozenStringNode: + *(nint*)buffer = ObjectToHandle(data); return true; } } From 26567198faccd2b5148687fa0a995618df04be63 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 26 Sep 2022 14:46:00 +0200 Subject: [PATCH 27/61] Implement getObjectType for FrozenObjectNode --- .../DependencyAnalysis/FrozenObjectNode.cs | 2 ++ .../JitInterface/CorInfoImpl.RyuJit.cs | 20 +++++++++---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs index 7a1cf593a6ab3..a56c134e57abd 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs @@ -35,6 +35,8 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) public override bool StaticDependenciesAreComputed => true; + public MetadataType OwningType => _owningType; + int ISymbolNode.Offset => 0; int ISymbolDefinitionNode.Offset diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 63f5c3d672894..53b71cdaaa25a 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2221,8 +2221,7 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt return true; } - object data; - if (value.GetRawData(_compilation.NodeFactory, out data)) + if (value.GetRawData(_compilation.NodeFactory, out object data)) { switch (data) { @@ -2243,15 +2242,16 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt private CORINFO_CLASS_STRUCT_* getObjectType(void* objPtr) { object obj = HandleToObject((IntPtr)objPtr); - if (obj is FrozenStringNode) + return obj switch { - return ObjectToHandle(_compilation.TypeSystemContext.GetWellKnownType(WellKnownType.String)); - } - else if (obj is FrozenObjectNode) - { - return null; // TODO: how to implement properly? - } - throw new NotImplementedException($"Unexpected object in getObjectType: {obj}"); + // For now we only support frozen strings + FrozenStringNode => ObjectToHandle(_compilation.TypeSystemContext.GetWellKnownType(WellKnownType.String)), + + // and frozen objects like arrays + FrozenObjectNode frozenObj => ObjectToHandle(frozenObj.OwningType), + + _ => throw new NotImplementedException($"Unexpected object in getObjectType: {obj}") + }; } } } From 10065722c34279302f428f628775aaf07b39ffbd Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 26 Sep 2022 14:54:24 +0200 Subject: [PATCH 28/61] Address feedback --- .../Compiler/DependencyAnalysis/FrozenObjectNode.cs | 2 +- .../aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs index a56c134e57abd..ee3279e89c936 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs @@ -35,7 +35,7 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) public override bool StaticDependenciesAreComputed => true; - public MetadataType OwningType => _owningType; + public TypeDesc ObjectType => _data.Type; int ISymbolNode.Offset => 0; diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 53b71cdaaa25a..b9f47420f0b34 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2248,7 +2248,7 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt FrozenStringNode => ObjectToHandle(_compilation.TypeSystemContext.GetWellKnownType(WellKnownType.String)), // and frozen objects like arrays - FrozenObjectNode frozenObj => ObjectToHandle(frozenObj.OwningType), + FrozenObjectNode frozenObj => ObjectToHandle(frozenObj.ObjectType), _ => throw new NotImplementedException($"Unexpected object in getObjectType: {obj}") }; From 0d27470d0e9862388936d22af5cec5d699f1d2ae Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 26 Sep 2022 16:59:52 +0200 Subject: [PATCH 29/61] Add isObjectImmutable --- src/coreclr/inc/corinfo.h | 6 +- src/coreclr/inc/icorjitinfoimpl_generated.h | 5 +- src/coreclr/jit/ICorJitInfo_API_names.h | 1 + src/coreclr/jit/ICorJitInfo_API_wrapper.hpp | 13 +- src/coreclr/jit/gcinfo.cpp | 9 + .../tools/Common/JitInterface/CorInfoBase.cs | 244 ++++++++++-------- .../tools/Common/JitInterface/CorInfoImpl.cs | 8 - .../ThunkGenerator/ThunkInput.txt | 3 +- .../JitInterface/CorInfoImpl.ReadyToRun.cs | 12 +- .../JitInterface/CorInfoImpl.RyuJit.cs | 17 ++ .../tools/aot/jitinterface/jitinterface.h | 16 +- .../tools/superpmi/superpmi-shared/lwmlist.h | 1 + .../superpmi-shared/methodcontext.cpp | 31 ++- .../superpmi/superpmi-shared/methodcontext.h | 9 +- .../superpmi-shim-collector/icorjitinfo.cpp | 8 + .../superpmi-shim-counter/icorjitinfo.cpp | 11 +- .../superpmi-shim-simple/icorjitinfo.cpp | 10 +- .../tools/superpmi/superpmi/icorjitinfo.cpp | 11 +- src/coreclr/vm/jitinterface.cpp | 33 +++ 19 files changed, 305 insertions(+), 143 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 1b4befc32de34..c9ed71954e2a8 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -2486,8 +2486,12 @@ class ICorStaticInfo CORINFO_CLASS_HANDLE cls ) = 0; + virtual bool isObjectImmutable( + void* objPtr + ) = 0; + virtual CORINFO_CLASS_HANDLE getObjectType( - void* typeObj + void* objPtr ) = 0; virtual bool getReadyToRunHelper( diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 6a54465d383dc..b9d3378c4550c 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -288,8 +288,11 @@ CorInfoHelpFunc getUnBoxHelper( void* getRuntimeTypePointer( CORINFO_CLASS_HANDLE cls) override; +bool isObjectImmutable( + void* objPtr) override; + CORINFO_CLASS_HANDLE getObjectType( - void* typeObj) override; + void* objPtr) override; bool getReadyToRunHelper( CORINFO_RESOLVED_TOKEN* pResolvedToken, diff --git a/src/coreclr/jit/ICorJitInfo_API_names.h b/src/coreclr/jit/ICorJitInfo_API_names.h index 6e306d6b1e9e7..4ba98bdff84cd 100644 --- a/src/coreclr/jit/ICorJitInfo_API_names.h +++ b/src/coreclr/jit/ICorJitInfo_API_names.h @@ -72,6 +72,7 @@ DEF_CLR_API(getTypeForBox) DEF_CLR_API(getBoxHelper) DEF_CLR_API(getUnBoxHelper) DEF_CLR_API(getRuntimeTypePointer) +DEF_CLR_API(isObjectImmutable) DEF_CLR_API(getObjectType) DEF_CLR_API(getReadyToRunHelper) DEF_CLR_API(getReadyToRunDelegateCtorHelper) diff --git a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp index 4c2e2b95ef40f..431190d6bbf84 100644 --- a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp +++ b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp @@ -672,11 +672,20 @@ void* WrapICorJitInfo::getRuntimeTypePointer( return temp; } +bool WrapICorJitInfo::isObjectImmutable( + void* objPtr) +{ + API_ENTER(isObjectImmutable); + bool temp = wrapHnd->isObjectImmutable(objPtr); + API_LEAVE(isObjectImmutable); + return temp; +} + CORINFO_CLASS_HANDLE WrapICorJitInfo::getObjectType( - void* typeObj) + void* objPtr) { API_ENTER(getObjectType); - CORINFO_CLASS_HANDLE temp = wrapHnd->getObjectType(typeObj); + CORINFO_CLASS_HANDLE temp = wrapHnd->getObjectType(objPtr); API_LEAVE(getObjectType); return temp; } diff --git a/src/coreclr/jit/gcinfo.cpp b/src/coreclr/jit/gcinfo.cpp index ae7303435a68c..43f2acb5a0370 100644 --- a/src/coreclr/jit/gcinfo.cpp +++ b/src/coreclr/jit/gcinfo.cpp @@ -254,6 +254,15 @@ GCInfo::WriteBarrierForm GCInfo::gcIsWriteBarrierCandidate(GenTreeStoreInd* stor if (store->Data()->IsIconHandle(GTF_ICON_OBJ_HDL)) { +#ifdef TARGET_ARMARCH + const ssize_t handle = store->Data()->AsIntCon()->IconValue(); + if (!compiler->info.compCompHnd->isObjectImmutable(reinterpret_cast(handle))) + { + // See https://github.com/dotnet/runtime/pull/76135#issuecomment-1257258310 + store->gtFlags |= GTF_IND_VOLATILE; + } +#endif + // Ignore frozen objects return WBF_NoBarrier; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs index 47805909574f7..5c06bf7580f42 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs @@ -1018,12 +1018,27 @@ private static CorInfoHelpFunc _getUnBoxHelper(IntPtr thisHandle, IntPtr* ppExce } [UnmanagedCallersOnly] - private static CORINFO_CLASS_STRUCT_* _getObjectType(IntPtr thisHandle, IntPtr* ppException, void* typeObj) + private static byte _isObjectImmutable(IntPtr thisHandle, IntPtr* ppException, void* objPtr) { var _this = GetThis(thisHandle); try { - return _this.getObjectType(typeObj); + return _this.isObjectImmutable(objPtr) ? (byte)1 : (byte)0; + } + catch (Exception ex) + { + *ppException = _this.AllocException(ex); + return default; + } + } + + [UnmanagedCallersOnly] + private static CORINFO_CLASS_STRUCT_* _getObjectType(IntPtr thisHandle, IntPtr* ppException, void* objPtr) + { + var _this = GetThis(thisHandle); + try + { + return _this.getObjectType(objPtr); } catch (Exception ex) { @@ -2655,7 +2670,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)&_getMethodAttribs; @@ -2725,117 +2740,118 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[65] = (delegate* unmanaged)&_getBoxHelper; callbacks[66] = (delegate* unmanaged)&_getUnBoxHelper; callbacks[67] = (delegate* unmanaged)&_getRuntimeTypePointer; - callbacks[68] = (delegate* unmanaged)&_getObjectType; - callbacks[69] = (delegate* unmanaged)&_getReadyToRunHelper; - callbacks[70] = (delegate* unmanaged)&_getReadyToRunDelegateCtorHelper; - callbacks[71] = (delegate* unmanaged)&_getHelperName; - callbacks[72] = (delegate* unmanaged)&_initClass; - callbacks[73] = (delegate* unmanaged)&_classMustBeLoadedBeforeCodeIsRun; - callbacks[74] = (delegate* unmanaged)&_getBuiltinClass; - callbacks[75] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; - callbacks[76] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; - callbacks[77] = (delegate* unmanaged)&_canCast; - callbacks[78] = (delegate* unmanaged)&_areTypesEquivalent; - callbacks[79] = (delegate* unmanaged)&_compareTypesForCast; - callbacks[80] = (delegate* unmanaged)&_compareTypesForEquality; - callbacks[81] = (delegate* unmanaged)&_mergeClasses; - callbacks[82] = (delegate* unmanaged)&_isMoreSpecificType; - callbacks[83] = (delegate* unmanaged)&_getParentType; - callbacks[84] = (delegate* unmanaged)&_getChildType; - callbacks[85] = (delegate* unmanaged)&_satisfiesClassConstraints; - callbacks[86] = (delegate* unmanaged)&_isSDArray; - callbacks[87] = (delegate* unmanaged)&_getArrayRank; - callbacks[88] = (delegate* unmanaged)&_getArrayIntrinsicID; - callbacks[89] = (delegate* unmanaged)&_getArrayInitializationData; - callbacks[90] = (delegate* unmanaged)&_canAccessClass; - callbacks[91] = (delegate* unmanaged)&_getFieldName; - callbacks[92] = (delegate* unmanaged)&_getFieldClass; - callbacks[93] = (delegate* unmanaged)&_getFieldType; - callbacks[94] = (delegate* unmanaged)&_getFieldOffset; - callbacks[95] = (delegate* unmanaged)&_getFieldInfo; - callbacks[96] = (delegate* unmanaged)&_isFieldStatic; - callbacks[97] = (delegate* unmanaged)&_getBoundaries; - callbacks[98] = (delegate* unmanaged)&_setBoundaries; - callbacks[99] = (delegate* unmanaged)&_getVars; - callbacks[100] = (delegate* unmanaged)&_setVars; - callbacks[101] = (delegate* unmanaged)&_reportRichMappings; - callbacks[102] = (delegate* unmanaged)&_allocateArray; - callbacks[103] = (delegate* unmanaged)&_freeArray; - callbacks[104] = (delegate* unmanaged)&_getArgNext; - callbacks[105] = (delegate* unmanaged)&_getArgType; - callbacks[106] = (delegate* unmanaged)&_getExactClasses; - callbacks[107] = (delegate* unmanaged)&_getArgClass; - callbacks[108] = (delegate* unmanaged)&_getHFAType; - callbacks[109] = (delegate* unmanaged)&_GetErrorHRESULT; - callbacks[110] = (delegate* unmanaged)&_GetErrorMessage; - callbacks[111] = (delegate* unmanaged)&_FilterException; - callbacks[112] = (delegate* unmanaged)&_ThrowExceptionForJitResult; - callbacks[113] = (delegate* unmanaged)&_ThrowExceptionForHelper; - callbacks[114] = (delegate* unmanaged)&_runWithErrorTrap; - callbacks[115] = (delegate* unmanaged)&_runWithSPMIErrorTrap; - callbacks[116] = (delegate* unmanaged)&_getEEInfo; - callbacks[117] = (delegate* unmanaged)&_getJitTimeLogFilename; - callbacks[118] = (delegate* unmanaged)&_getMethodDefFromMethod; - callbacks[119] = (delegate* unmanaged)&_getMethodName; - callbacks[120] = (delegate* unmanaged)&_getMethodNameFromMetadata; - callbacks[121] = (delegate* unmanaged)&_getMethodHash; - callbacks[122] = (delegate* unmanaged)&_findNameOfToken; - callbacks[123] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; - callbacks[124] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; - callbacks[125] = (delegate* unmanaged)&_getThreadTLSIndex; - callbacks[126] = (delegate* unmanaged)&_getInlinedCallFrameVptr; - callbacks[127] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; - callbacks[128] = (delegate* unmanaged)&_getHelperFtn; - callbacks[129] = (delegate* unmanaged)&_getFunctionEntryPoint; - callbacks[130] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; - callbacks[131] = (delegate* unmanaged)&_getMethodSync; - callbacks[132] = (delegate* unmanaged)&_getLazyStringLiteralHelper; - callbacks[133] = (delegate* unmanaged)&_embedModuleHandle; - callbacks[134] = (delegate* unmanaged)&_embedClassHandle; - callbacks[135] = (delegate* unmanaged)&_embedMethodHandle; - callbacks[136] = (delegate* unmanaged)&_embedFieldHandle; - callbacks[137] = (delegate* unmanaged)&_embedGenericHandle; - callbacks[138] = (delegate* unmanaged)&_getLocationOfThisType; - callbacks[139] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; - callbacks[140] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; - callbacks[141] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; - callbacks[142] = (delegate* unmanaged)&_getJustMyCodeHandle; - callbacks[143] = (delegate* unmanaged)&_GetProfilingHandle; - callbacks[144] = (delegate* unmanaged)&_getCallInfo; - callbacks[145] = (delegate* unmanaged)&_canAccessFamily; - callbacks[146] = (delegate* unmanaged)&_isRIDClassDomainID; - callbacks[147] = (delegate* unmanaged)&_getClassDomainID; - callbacks[148] = (delegate* unmanaged)&_getFieldAddress; - callbacks[149] = (delegate* unmanaged)&_getReadonlyStaticFieldValue; - 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)&_addActiveDependency; - callbacks[157] = (delegate* unmanaged)&_GetDelegateCtor; - callbacks[158] = (delegate* unmanaged)&_MethodCompileComplete; - callbacks[159] = (delegate* unmanaged)&_getTailCallHelpers; - 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[68] = (delegate* unmanaged)&_isObjectImmutable; + callbacks[69] = (delegate* unmanaged)&_getObjectType; + callbacks[70] = (delegate* unmanaged)&_getReadyToRunHelper; + callbacks[71] = (delegate* unmanaged)&_getReadyToRunDelegateCtorHelper; + callbacks[72] = (delegate* unmanaged)&_getHelperName; + 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)&_areTypesEquivalent; + callbacks[80] = (delegate* unmanaged)&_compareTypesForCast; + callbacks[81] = (delegate* unmanaged)&_compareTypesForEquality; + callbacks[82] = (delegate* unmanaged)&_mergeClasses; + callbacks[83] = (delegate* unmanaged)&_isMoreSpecificType; + callbacks[84] = (delegate* unmanaged)&_getParentType; + callbacks[85] = (delegate* unmanaged)&_getChildType; + callbacks[86] = (delegate* unmanaged)&_satisfiesClassConstraints; + callbacks[87] = (delegate* unmanaged)&_isSDArray; + callbacks[88] = (delegate* unmanaged)&_getArrayRank; + callbacks[89] = (delegate* unmanaged)&_getArrayIntrinsicID; + callbacks[90] = (delegate* unmanaged)&_getArrayInitializationData; + callbacks[91] = (delegate* unmanaged)&_canAccessClass; + callbacks[92] = (delegate* unmanaged)&_getFieldName; + callbacks[93] = (delegate* unmanaged)&_getFieldClass; + callbacks[94] = (delegate* unmanaged)&_getFieldType; + callbacks[95] = (delegate* unmanaged)&_getFieldOffset; + callbacks[96] = (delegate* unmanaged)&_getFieldInfo; + callbacks[97] = (delegate* unmanaged)&_isFieldStatic; + callbacks[98] = (delegate* unmanaged)&_getBoundaries; + callbacks[99] = (delegate* unmanaged)&_setBoundaries; + callbacks[100] = (delegate* unmanaged)&_getVars; + callbacks[101] = (delegate* unmanaged)&_setVars; + callbacks[102] = (delegate* unmanaged)&_reportRichMappings; + callbacks[103] = (delegate* unmanaged)&_allocateArray; + callbacks[104] = (delegate* unmanaged)&_freeArray; + callbacks[105] = (delegate* unmanaged)&_getArgNext; + callbacks[106] = (delegate* unmanaged)&_getArgType; + callbacks[107] = (delegate* unmanaged)&_getExactClasses; + callbacks[108] = (delegate* unmanaged)&_getArgClass; + callbacks[109] = (delegate* unmanaged)&_getHFAType; + callbacks[110] = (delegate* unmanaged)&_GetErrorHRESULT; + callbacks[111] = (delegate* unmanaged)&_GetErrorMessage; + callbacks[112] = (delegate* unmanaged)&_FilterException; + callbacks[113] = (delegate* unmanaged)&_ThrowExceptionForJitResult; + callbacks[114] = (delegate* unmanaged)&_ThrowExceptionForHelper; + callbacks[115] = (delegate* unmanaged)&_runWithErrorTrap; + callbacks[116] = (delegate* unmanaged)&_runWithSPMIErrorTrap; + callbacks[117] = (delegate* unmanaged)&_getEEInfo; + callbacks[118] = (delegate* unmanaged)&_getJitTimeLogFilename; + callbacks[119] = (delegate* unmanaged)&_getMethodDefFromMethod; + callbacks[120] = (delegate* unmanaged)&_getMethodName; + callbacks[121] = (delegate* unmanaged)&_getMethodNameFromMetadata; + callbacks[122] = (delegate* unmanaged)&_getMethodHash; + callbacks[123] = (delegate* unmanaged)&_findNameOfToken; + callbacks[124] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; + callbacks[125] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; + callbacks[126] = (delegate* unmanaged)&_getThreadTLSIndex; + callbacks[127] = (delegate* unmanaged)&_getInlinedCallFrameVptr; + callbacks[128] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; + callbacks[129] = (delegate* unmanaged)&_getHelperFtn; + callbacks[130] = (delegate* unmanaged)&_getFunctionEntryPoint; + callbacks[131] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; + callbacks[132] = (delegate* unmanaged)&_getMethodSync; + callbacks[133] = (delegate* unmanaged)&_getLazyStringLiteralHelper; + callbacks[134] = (delegate* unmanaged)&_embedModuleHandle; + callbacks[135] = (delegate* unmanaged)&_embedClassHandle; + callbacks[136] = (delegate* unmanaged)&_embedMethodHandle; + callbacks[137] = (delegate* unmanaged)&_embedFieldHandle; + callbacks[138] = (delegate* unmanaged)&_embedGenericHandle; + callbacks[139] = (delegate* unmanaged)&_getLocationOfThisType; + callbacks[140] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; + callbacks[141] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; + callbacks[142] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; + callbacks[143] = (delegate* unmanaged)&_getJustMyCodeHandle; + callbacks[144] = (delegate* unmanaged)&_GetProfilingHandle; + callbacks[145] = (delegate* unmanaged)&_getCallInfo; + callbacks[146] = (delegate* unmanaged)&_canAccessFamily; + callbacks[147] = (delegate* unmanaged)&_isRIDClassDomainID; + callbacks[148] = (delegate* unmanaged)&_getClassDomainID; + callbacks[149] = (delegate* unmanaged)&_getFieldAddress; + callbacks[150] = (delegate* unmanaged)&_getReadonlyStaticFieldValue; + callbacks[151] = (delegate* unmanaged)&_getStaticFieldCurrentClass; + callbacks[152] = (delegate* unmanaged)&_getVarArgsHandle; + callbacks[153] = (delegate* unmanaged)&_canGetVarArgsHandle; + callbacks[154] = (delegate* unmanaged)&_constructStringLiteral; + callbacks[155] = (delegate* unmanaged)&_emptyStringLiteral; + callbacks[156] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; + callbacks[157] = (delegate* unmanaged)&_addActiveDependency; + callbacks[158] = (delegate* unmanaged)&_GetDelegateCtor; + callbacks[159] = (delegate* unmanaged)&_MethodCompileComplete; + callbacks[160] = (delegate* unmanaged)&_getTailCallHelpers; + callbacks[161] = (delegate* unmanaged)&_convertPInvokeCalliToCall; + callbacks[162] = (delegate* unmanaged)&_notifyInstructionSetUsage; + callbacks[163] = (delegate* unmanaged)&_updateEntryPointForTailCall; + callbacks[164] = (delegate* unmanaged)&_allocMem; + callbacks[165] = (delegate* unmanaged)&_reserveUnwindInfo; + callbacks[166] = (delegate* unmanaged)&_allocUnwindInfo; + callbacks[167] = (delegate* unmanaged)&_allocGCInfo; + callbacks[168] = (delegate* unmanaged)&_setEHcount; + callbacks[169] = (delegate* unmanaged)&_setEHinfo; + callbacks[170] = (delegate* unmanaged)&_logMsg; + callbacks[171] = (delegate* unmanaged)&_doAssert; + callbacks[172] = (delegate* unmanaged)&_reportFatalError; + callbacks[173] = (delegate* unmanaged)&_getPgoInstrumentationResults; + callbacks[174] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; + callbacks[175] = (delegate* unmanaged)&_recordCallSite; + callbacks[176] = (delegate* unmanaged)&_recordRelocation; + callbacks[177] = (delegate* unmanaged)&_getRelocTypeHint; + callbacks[178] = (delegate* unmanaged)&_getExpectedTargetArchitecture; + callbacks[179] = (delegate* unmanaged)&_getJitFlags; return (IntPtr)callbacks; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 06a29f75d91d0..433537b2072b7 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -2343,14 +2343,6 @@ private CorInfoHelpFunc getUnBoxHelper(CORINFO_CLASS_STRUCT_* cls) return type.IsNullable ? CorInfoHelpFunc.CORINFO_HELP_UNBOX_NULLABLE : CorInfoHelpFunc.CORINFO_HELP_UNBOX; } -#pragma warning disable CA1822 // Mark members as static - private void* getRuntimeTypePointer(CORINFO_CLASS_STRUCT_* cls) -#pragma warning restore CA1822 // Mark members as static - { - // TODO: https://github.com/dotnet/runtime/pull/75573#issuecomment-1250824543 - return (void*)IntPtr.Zero; - } - private byte* getHelperName(CorInfoHelpFunc helpFunc) { return (byte*)GetPin(StringToUTF8(helpFunc.ToString())); diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index 7ae8475d1506a..96b0e73b4dc06 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -223,7 +223,8 @@ FUNCTIONS CorInfoHelpFunc getBoxHelper(CORINFO_CLASS_HANDLE cls) CorInfoHelpFunc getUnBoxHelper(CORINFO_CLASS_HANDLE cls) void* getRuntimeTypePointer(CORINFO_CLASS_HANDLE cls) - CORINFO_CLASS_HANDLE getObjectType(void* typeObj) + bool isObjectImmutable(void* objPtr) + CORINFO_CLASS_HANDLE getObjectType(void* objPtr) bool getReadyToRunHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_LOOKUP_KIND * pGenericLookupKind, CorInfoHelpFunc id, CORINFO_CONST_LOOKUP *pLookup) void getReadyToRunDelegateCtorHelper(CORINFO_RESOLVED_TOKEN * pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, CORINFO_LOOKUP *pLookup) const char* getHelperName(CorInfoHelpFunc helpFunc) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index 80e8359d2ffae..aa95d302834a9 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -3000,7 +3000,17 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt private CORINFO_CLASS_STRUCT_* getObjectType(void* objPtr) { - return (CORINFO_CLASS_STRUCT_*)IntPtr.Zero; + throw new NotSupportedException(); + } + + private bool isObjectImmutable(void* objPtr) + { + throw new NotSupportedException(); + } + + private void* getRuntimeTypePointer(CORINFO_CLASS_STRUCT_* cls) + { + return null; } } } diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index b9f47420f0b34..f5526393b4323 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2253,5 +2253,22 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt _ => throw new NotImplementedException($"Unexpected object in getObjectType: {obj}") }; } + + private void* getRuntimeTypePointer(CORINFO_CLASS_STRUCT_* cls) + { + // TODO: https://github.com/dotnet/runtime/pull/75573#issuecomment-1250824543 + throw new NotImplementedException(); + } + + private bool isObjectImmutable(void* objPtr) + { + object obj = HandleToObject((IntPtr)objPtr); + return obj switch + { + FrozenStringNode => true, + FrozenObjectNode => false, + _ => throw new NotImplementedException($"Unexpected object in isObjectImmutable: {obj}") + }; + } } } diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface.h b/src/coreclr/tools/aot/jitinterface/jitinterface.h index b00339b2b4e95..f3e5b3445982a 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface.h @@ -79,7 +79,8 @@ struct JitInterfaceCallbacks CorInfoHelpFunc (* getBoxHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); CorInfoHelpFunc (* getUnBoxHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); void* (* getRuntimeTypePointer)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); - CORINFO_CLASS_HANDLE (* getObjectType)(void * thisHandle, CorInfoExceptionClass** ppException, void* typeObj); + bool (* isObjectImmutable)(void * thisHandle, CorInfoExceptionClass** ppException, void* objPtr); + CORINFO_CLASS_HANDLE (* getObjectType)(void * thisHandle, CorInfoExceptionClass** ppException, void* objPtr); bool (* getReadyToRunHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, CORINFO_CONST_LOOKUP* pLookup); void (* getReadyToRunDelegateCtorHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pTargetMethod, unsigned int targetConstraint, CORINFO_CLASS_HANDLE delegateType, CORINFO_LOOKUP* pLookup); const char* (* getHelperName)(void * thisHandle, CorInfoExceptionClass** ppException, CorInfoHelpFunc helpFunc); @@ -865,11 +866,20 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } + virtual bool isObjectImmutable( + void* objPtr) +{ + CorInfoExceptionClass* pException = nullptr; + bool temp = _callbacks->isObjectImmutable(_thisHandle, &pException, objPtr); + if (pException != nullptr) throw pException; + return temp; +} + virtual CORINFO_CLASS_HANDLE getObjectType( - void* typeObj) + void* objPtr) { CorInfoExceptionClass* pException = nullptr; - CORINFO_CLASS_HANDLE temp = _callbacks->getObjectType(_thisHandle, &pException, typeObj); + CORINFO_CLASS_HANDLE temp = _callbacks->getObjectType(_thisHandle, &pException, objPtr); 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 b0af2f1e3f250..a4ed23c57024c 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -140,6 +140,7 @@ LWM(GetTypeForPrimitiveNumericClass, DWORDLONG, DWORD) LWM(GetUnboxedEntry, DWORDLONG, DLD); LWM(GetUnBoxHelper, DWORDLONG, DWORD) LWM(GetRuntimeTypePointer, DWORDLONG, DWORDLONG) +LWM(IsObjectImmutable, DWORDLONG, DWORD) LWM(GetObjectType, DWORDLONG, DWORDLONG) LWM(GetVarArgsHandle, GetVarArgsHandleValue, DLDL) LWM(GetVars, DWORDLONG, Agnostic_GetVars) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index b46094963bb95..c2da94ac6f2aa 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -2207,12 +2207,35 @@ void* MethodContext::repGetRuntimeTypePointer(CORINFO_CLASS_HANDLE cls) return (void*)value; } -void MethodContext::recGetObjectType(void* typeObj, CORINFO_CLASS_HANDLE result) +void MethodContext::recIsObjectImmutable(void* objPtr, bool result) +{ + if (IsObjectImmutable == nullptr) + IsObjectImmutable = new LightWeightMap(); + + DWORDLONG key = (DWORDLONG)objPtr; + DWORD value = (DWORD)result; + IsObjectImmutable->Add(key, value); + DEBUG_REC(dmpIsObjectImmutable(key, value)); +} +void MethodContext::dmpIsObjectImmutable(DWORDLONG key, DWORD value) +{ + printf("IsObjectImmutable key obj-%016llX, value res-%u", key, value); +} +bool MethodContext::repIsObjectImmutable(void* objPtr) +{ + DWORDLONG key = (DWORDLONG)objPtr; + AssertMapAndKeyExist(IsObjectImmutable, key, ": key %016llX", key); + DWORD value = IsObjectImmutable->Get(key); + DEBUG_REP(dmpIsObjectImmutable(key, value)); + return (bool)value; +} + +void MethodContext::recGetObjectType(void* objPtr, CORINFO_CLASS_HANDLE result) { if (GetObjectType == nullptr) GetObjectType = new LightWeightMap(); - DWORDLONG key = (DWORDLONG)typeObj; + DWORDLONG key = (DWORDLONG)objPtr; DWORDLONG value = (DWORDLONG)result; GetObjectType->Add(key, value); DEBUG_REC(dmpGetObjectType(key, value)); @@ -2221,9 +2244,9 @@ void MethodContext::dmpGetObjectType(DWORDLONG key, DWORDLONG value) { printf("GetObjectType key obj-%016llX, value res-%016llX", key, value); } -CORINFO_CLASS_HANDLE MethodContext::repGetObjectType(void* typeObj) +CORINFO_CLASS_HANDLE MethodContext::repGetObjectType(void* objPtr) { - DWORDLONG key = (DWORDLONG)typeObj; + DWORDLONG key = (DWORDLONG)objPtr; AssertMapAndKeyExist(GetObjectType, key, ": key %016llX", key); DWORDLONG value = GetObjectType->Get(key); DEBUG_REP(dmpGetObjectType(key, value)); diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index 79f7b14365f87..e6aa9111a394a 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -314,9 +314,13 @@ class MethodContext void dmpGetRuntimeTypePointer(DWORDLONG key, DWORDLONG value); void* repGetRuntimeTypePointer(CORINFO_CLASS_HANDLE cls); - void recGetObjectType(void* typeObj, CORINFO_CLASS_HANDLE result); + void recIsObjectImmutable(void* objPtr, bool result); + void dmpIsObjectImmutable(DWORDLONG key, DWORD value); + bool repIsObjectImmutable(void* objPtr); + + void recGetObjectType(void* objPtr, CORINFO_CLASS_HANDLE result); void dmpGetObjectType(DWORDLONG key, DWORDLONG value); - CORINFO_CLASS_HANDLE repGetObjectType(void* typeObj); + CORINFO_CLASS_HANDLE repGetObjectType(void* objPtr); void recGetReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, @@ -1138,6 +1142,7 @@ enum mcPackets Packet_ObjectToString = 197, Packet_GetReadonlyStaticFieldValue = 198, Packet_GetObjectType = 199, + Packet_IsObjectImmutable = 200, }; 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 b90a955fa53ff..de0cefe9cf427 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -798,6 +798,14 @@ void* interceptor_ICJI::getRuntimeTypePointer(CORINFO_CLASS_HANDLE cls) return temp; } +bool interceptor_ICJI::isObjectImmutable(void* typeObj) +{ + mc->cr->AddCall("isObjectImmutable"); + bool temp = original_ICorJitInfo->isObjectImmutable(typeObj); + mc->recIsObjectImmutable(typeObj, temp); + return temp; +} + CORINFO_CLASS_HANDLE interceptor_ICJI::getObjectType(void* typeObj) { mc->cr->AddCall("getObjectType"); diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp index 1e86378f5155b..ebc3162218b85 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -551,11 +551,18 @@ void* interceptor_ICJI::getRuntimeTypePointer( return original_ICorJitInfo->getRuntimeTypePointer(cls); } +bool interceptor_ICJI::isObjectImmutable( + void* objPtr) +{ + mcs->AddCall("isObjectImmutable"); + return original_ICorJitInfo->isObjectImmutable(objPtr); +} + CORINFO_CLASS_HANDLE interceptor_ICJI::getObjectType( - void* typeObj) + void* objPtr) { mcs->AddCall("getObjectType"); - return original_ICorJitInfo->getObjectType(typeObj); + return original_ICorJitInfo->getObjectType(objPtr); } bool interceptor_ICJI::getReadyToRunHelper( diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp index 1058681597f71..fb9bb5f7063b3 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -483,10 +483,16 @@ void* interceptor_ICJI::getRuntimeTypePointer( return original_ICorJitInfo->getRuntimeTypePointer(cls); } +bool interceptor_ICJI::isObjectImmutable( + void* objPtr) +{ + return original_ICorJitInfo->isObjectImmutable(objPtr); +} + CORINFO_CLASS_HANDLE interceptor_ICJI::getObjectType( - void* typeObj) + void* objPtr) { - return original_ICorJitInfo->getObjectType(typeObj); + return original_ICorJitInfo->getObjectType(objPtr); } bool interceptor_ICJI::getReadyToRunHelper( diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index fe6e7a4c7bc36..b815f2b27bd89 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -679,10 +679,17 @@ void* MyICJI::getRuntimeTypePointer(CORINFO_CLASS_HANDLE cls) return result; } -CORINFO_CLASS_HANDLE MyICJI::getObjectType(void* typeObj) +bool MyICJI::isObjectImmutable(void* objPtr) +{ + jitInstance->mc->cr->AddCall("isObjectImmutable"); + bool result = jitInstance->mc->repIsObjectImmutable(objPtr); + return result; +} + +CORINFO_CLASS_HANDLE MyICJI::getObjectType(void* objPtr) { jitInstance->mc->cr->AddCall("getObjectType"); - CORINFO_CLASS_HANDLE result = jitInstance->mc->repGetObjectType(typeObj); + CORINFO_CLASS_HANDLE result = jitInstance->mc->repGetObjectType(objPtr); return result; } diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 91abd581c08f2..287455a0d5aeb 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -6015,6 +6015,39 @@ void* CEEInfo::getRuntimeTypePointer(CORINFO_CLASS_HANDLE clsHnd) return pointer; } + +/***********************************************************************/ +bool CEEInfo::isObjectImmutable(void* objPtr) +{ + CONTRACTL{ + THROWS; + GC_TRIGGERS; + MODE_PREEMPTIVE; + } CONTRACTL_END; + + bool isImmutable = false; + + JIT_TO_EE_TRANSITION(); + + GCX_COOP(); + Object* obj = (Object*)objPtr; + MethodTable* type = obj->GetMethodTable(); + + if (type->IsString() || type == g_pRuntimeTypeClass) + { + isImmutable = true; + } + else + { + // Unexpected type of object + UNREACHABLE(); + } + + EE_TO_JIT_TRANSITION(); + + return isImmutable; +} + /***********************************************************************/ CORINFO_CLASS_HANDLE CEEInfo::getObjectType(void* objPtr) { From 48343eed2d351562fdaceb38d6c2b7151fa9de36 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Mon, 26 Sep 2022 17:10:00 +0200 Subject: [PATCH 30/61] Update gcinfo.cpp --- src/coreclr/jit/gcinfo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/gcinfo.cpp b/src/coreclr/jit/gcinfo.cpp index 43f2acb5a0370..7b3cecc9b4f2b 100644 --- a/src/coreclr/jit/gcinfo.cpp +++ b/src/coreclr/jit/gcinfo.cpp @@ -254,7 +254,7 @@ GCInfo::WriteBarrierForm GCInfo::gcIsWriteBarrierCandidate(GenTreeStoreInd* stor if (store->Data()->IsIconHandle(GTF_ICON_OBJ_HDL)) { -#ifdef TARGET_ARMARCH +#ifndef TARGET_XARCH const ssize_t handle = store->Data()->AsIntCon()->IconValue(); if (!compiler->info.compCompHnd->isObjectImmutable(reinterpret_cast(handle))) { From 7264f67a1fe39a919764c4618163c88766b8a0e7 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 26 Sep 2022 18:05:20 +0200 Subject: [PATCH 31/61] fix getRuntimeTypePointer on NativeAOT --- .../aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index f5526393b4323..61ba6ecc307fa 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2257,7 +2257,7 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt private void* getRuntimeTypePointer(CORINFO_CLASS_STRUCT_* cls) { // TODO: https://github.com/dotnet/runtime/pull/75573#issuecomment-1250824543 - throw new NotImplementedException(); + return null; } private bool isObjectImmutable(void* objPtr) From 8d4048a083c0082d1926ebf2da4074a3d7d2afed Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 26 Sep 2022 18:39:08 +0200 Subject: [PATCH 32/61] fix getRuntimeTypePointer on NativeAOT --- .../aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 61ba6ecc307fa..9f87941d5cbe5 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2254,7 +2254,9 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt }; } +#pragma warning disable CA1822 // Mark members as static private void* getRuntimeTypePointer(CORINFO_CLASS_STRUCT_* cls) +#pragma warning restore CA1822 // Mark members as static { // TODO: https://github.com/dotnet/runtime/pull/75573#issuecomment-1250824543 return null; From 44a8fc612477b63fceb48b9e25360c7c3832a206 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Thu, 6 Oct 2022 19:17:06 +0200 Subject: [PATCH 33/61] Fix compilation --- .../aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 08183c876fbbe..e3ab92272c924 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2241,7 +2241,7 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt private CORINFO_CLASS_STRUCT_* getObjectType(void* objPtr) { - object obj = HandleToObject((IntPtr)objPtr); + object obj = HandleToObject(objPtr); return obj switch { // For now we only support frozen strings @@ -2264,7 +2264,7 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt private bool isObjectImmutable(void* objPtr) { - object obj = HandleToObject((IntPtr)objPtr); + object obj = HandleToObject(objPtr); return obj switch { FrozenStringNode => true, From 256bbd4179d9b9d85046c63911a84ba8a12223fa Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Thu, 6 Oct 2022 19:21:30 +0200 Subject: [PATCH 34/61] Apply suggestions from code review Co-authored-by: Jan Kotas --- .../JitInterface/CorInfoImpl.RyuJit.cs | 2 -- src/coreclr/vm/jitinterface.cpp | 17 +++++------------ 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index e3ab92272c924..e9319e2d9866b 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2244,10 +2244,8 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt object obj = HandleToObject(objPtr); return obj switch { - // For now we only support frozen strings FrozenStringNode => ObjectToHandle(_compilation.TypeSystemContext.GetWellKnownType(WellKnownType.String)), - // and frozen objects like arrays FrozenObjectNode frozenObj => ObjectToHandle(frozenObj.ObjectType), _ => throw new NotImplementedException($"Unexpected object in getObjectType: {obj}") diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index a80f1daeb8873..78f6ab4cbbb85 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -6038,27 +6038,20 @@ bool CEEInfo::isObjectImmutable(void* objPtr) MODE_PREEMPTIVE; } CONTRACTL_END; - bool isImmutable = false; - +#ifdef DEBUG JIT_TO_EE_TRANSITION(); GCX_COOP(); Object* obj = (Object*)objPtr; MethodTable* type = obj->GetMethodTable(); - if (type->IsString() || type == g_pRuntimeTypeClass) - { - isImmutable = true; - } - else - { - // Unexpected type of object - UNREACHABLE(); - } + _ASSERTE(type->IsString() || type == g_pRuntimeTypeClass); EE_TO_JIT_TRANSITION(); +#endif - return isImmutable; + // All currently allocated frozen objects can be treated as immutable + return true; } /***********************************************************************/ From fefbbe1a026c3ab64e68babd2ac2200ede9429db Mon Sep 17 00:00:00 2001 From: EgorBo Date: Thu, 6 Oct 2022 19:48:02 +0200 Subject: [PATCH 35/61] ILC: use correct TargetPtrSize --- .../JitInterface/CorInfoImpl.RyuJit.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index e9319e2d9866b..6074392cee47c 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2215,9 +2215,13 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt TypePreinit.ISerializableValue value = preinitManager .GetPreinitializationInfo(owningType).GetFieldValue(field); + int targetPtrSize = _compilation.TypeSystemContext.Target.PointerSize; + if (value == null) { - *((nint*)buffer) = 0; + // Write "null" to buffer + Debug.Assert(bufferSize >= targetPtrSize); + new Span(buffer, targetPtrSize).Clear(); return true; } @@ -2230,7 +2234,10 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt return true; case FrozenObjectNode or FrozenStringNode: - *(nint*)buffer = ObjectToHandle(data); + // save handle's value to buffer + nint handle = ObjectToHandle(data); + Debug.Assert(bufferSize >= targetPtrSize); + new Span(&handle, targetPtrSize).CopyTo(new Span(buffer, targetPtrSize)); return true; } } From 3d06a33a76eea10fa90884df37c43a831cb09b0d Mon Sep 17 00:00:00 2001 From: EgorBo Date: Thu, 6 Oct 2022 21:05:44 +0200 Subject: [PATCH 36/61] Address feedback --- .../Compiler/TypePreinit.cs | 24 +++++++++++++++---- .../JitInterface/CorInfoImpl.RyuJit.cs | 10 +++++--- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs index d063ffb541c05..3f6339e91e982 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs @@ -1769,11 +1769,7 @@ public virtual bool TryCreateByRef(out Value value) public abstract void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory factory); - public virtual bool GetRawData(NodeFactory factory, out object data) - { - data = null; - return false; - } + public abstract bool GetRawData(NodeFactory factory, out object data); private static T ThrowInvalidProgram() { @@ -1917,6 +1913,12 @@ public override void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory f { throw new NotSupportedException(); } + + public override bool GetRawData(NodeFactory factory, out object data) + { + data = null; + return false; + } } private sealed class MethodPointerValue : BaseValueTypeValue, IInternalModelingOnlyValue @@ -1944,6 +1946,12 @@ public override void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory f { throw new NotSupportedException(); } + + public override bool GetRawData(NodeFactory factory, out object data) + { + data = null; + return false; + } } private sealed class ByRefValue : Value, IHasInstanceFields @@ -1990,6 +1998,12 @@ public override void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory f // This would imply we have a byref-typed static field. The layout algorithm should have blocked this. throw new NotImplementedException(); } + + public override bool GetRawData(NodeFactory factory, out object data) + { + data = null; + return false; + } } private abstract class ReferenceTypeValue : Value diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 6074392cee47c..8edce45f28e63 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2219,8 +2219,9 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt if (value == null) { - // Write "null" to buffer Debug.Assert(bufferSize >= targetPtrSize); + + // Write "null" to buffer new Span(buffer, targetPtrSize).Clear(); return true; } @@ -2229,14 +2230,17 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt { switch (data) { - case byte[] bytes when bytes.Length <= bufferSize: + case byte[] bytes: + Debug.Assert(bufferSize >= bytes.Length); + bytes.AsSpan().CopyTo(new Span(buffer, bufferSize)); return true; case FrozenObjectNode or FrozenStringNode: + Debug.Assert(bufferSize >= targetPtrSize); + // save handle's value to buffer nint handle = ObjectToHandle(data); - Debug.Assert(bufferSize >= targetPtrSize); new Span(&handle, targetPtrSize).CopyTo(new Span(buffer, targetPtrSize)); return true; } From afefe442872705e6a413c391bec28541d82b8928 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Thu, 6 Oct 2022 21:35:03 +0200 Subject: [PATCH 37/61] Add support for delegates, empty arrays and objects without fields --- .../Compiler/DependencyAnalysis/FrozenObjectNode.cs | 2 ++ .../tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs | 7 +++++++ .../ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs | 4 +--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs index ee3279e89c936..18ff65d55f37e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs @@ -37,6 +37,8 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) public TypeDesc ObjectType => _data.Type; + public bool IsKnownImmutable => _data.IsKnownImmutable; + int ISymbolNode.Offset => 0; int ISymbolDefinitionNode.Offset diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs index 3f6339e91e982..6ba34016e7852 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs @@ -1715,6 +1715,7 @@ public interface ISerializableReference : ISerializableValue { TypeDesc Type { get; } void WriteContent(ref ObjectDataBuilder builder, ISymbolNode thisNode, NodeFactory factory); + bool IsKnownImmutable { get; } } /// @@ -2134,6 +2135,8 @@ public override void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory f { builder.EmitPointerReloc(factory.SerializedFrozenObject(AllocationSite.OwningType, AllocationSite.InstructionCounter, this)); } + + public bool IsKnownImmutable => true; } #pragma warning disable CA1852 @@ -2222,6 +2225,8 @@ public virtual void WriteContent(ref ObjectDataBuilder builder, ISymbolNode this builder.EmitBytes(_data); } + + public bool IsKnownImmutable => _elementCount == 0; } private sealed class ForeignTypeInstance : AllocatedReferenceTypeValue @@ -2341,6 +2346,8 @@ public virtual void WriteContent(ref ObjectDataBuilder builder, ISymbolNode this int pointerSize = factory.Target.PointerSize; builder.EmitBytes(_data, pointerSize, _data.Length - pointerSize); } + + public bool IsKnownImmutable => !Type.GetFields().GetEnumerator().MoveNext(); } private struct FieldAccessor diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 8edce45f28e63..9f48f080b5b2f 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2256,9 +2256,7 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt return obj switch { FrozenStringNode => ObjectToHandle(_compilation.TypeSystemContext.GetWellKnownType(WellKnownType.String)), - FrozenObjectNode frozenObj => ObjectToHandle(frozenObj.ObjectType), - _ => throw new NotImplementedException($"Unexpected object in getObjectType: {obj}") }; } @@ -2277,7 +2275,7 @@ private bool isObjectImmutable(void* objPtr) return obj switch { FrozenStringNode => true, - FrozenObjectNode => false, + FrozenObjectNode frozenObj => frozenObj.IsKnownImmutable, _ => throw new NotImplementedException($"Unexpected object in isObjectImmutable: {obj}") }; } From eece561f856a8e650cc915f901522b100e5c61c3 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Thu, 6 Oct 2022 21:50:18 +0200 Subject: [PATCH 38/61] Add some comments --- src/coreclr/inc/corinfo.h | 43 ++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 509acbd00a077..dede4ad2f8858 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -2503,10 +2503,28 @@ class ICorStaticInfo CORINFO_CLASS_HANDLE cls ) = 0; + //------------------------------------------------------------------------------ + // isObjectImmutable: checks whether given object is known to be immutable or not + // + // Arguments: + // objPtr - Direct object handle + // + // Return Value: + // Returns true if object is known to be immutable + // virtual bool isObjectImmutable( void* objPtr ) = 0; + //------------------------------------------------------------------------------ + // getObjectType: obtains type handle for given object + // + // Arguments: + // objPtr - Direct object handle + // + // Return Value: + // Returns CORINFO_CLASS_HANDLE handle that represents given object's type + // virtual CORINFO_CLASS_HANDLE getObjectType( void* objPtr ) = 0; @@ -3175,11 +3193,26 @@ class ICorDynamicInfo : public ICorStaticInfo void **ppIndirection = NULL ) = 0; - // Returns true if the given field is "static readonly" and its value will never change - // also, returns its actual value via pValue argument. For now, it's either: - // * integer/floating point primitive - // * null - // * frozen object + //------------------------------------------------------------------------------ + // getReadonlyStaticFieldValue: returns true and the actual field's value if the given + // field represents a statically initialized readonly field of any type, it might be: + // * integer/floating point primitive + // * null + // * frozen object which in turn can be: + // * string + // * RuntimeType (CoreCLR only) + // * Array (NativeAOT only) + // * Delegate (NativeAOT only) + // * Object wihtout fields (NativeAOT only) + // + // Arguments: + // field - field handle + // buffer - buffer field's value will be stored to + // bufferSize - size of buffer + // + // Return Value: + // Returns true if field's constant value was succesfully copied to buffer + // virtual bool getReadonlyStaticFieldValue( CORINFO_FIELD_HANDLE field, uint8_t *buffer, From e2ae1178b7354654148a07be3c874424e087e2eb Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Thu, 6 Oct 2022 21:55:45 +0200 Subject: [PATCH 39/61] Update src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs Co-authored-by: Jan Kotas --- .../tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs index 6ba34016e7852..24cfdac46c01a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs @@ -2136,7 +2136,7 @@ public override void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory f builder.EmitPointerReloc(factory.SerializedFrozenObject(AllocationSite.OwningType, AllocationSite.InstructionCounter, this)); } - public bool IsKnownImmutable => true; + public bool IsKnownImmutable => _methodPointed.Signature.IsStatic; } #pragma warning disable CA1852 From 34b39cb7ecd4e0e6b88c0e02898e862a9633a0c8 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Thu, 6 Oct 2022 22:02:27 +0200 Subject: [PATCH 40/61] Apply suggestions from code review Co-authored-by: Jan Kotas --- src/coreclr/inc/corinfo.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index dede4ad2f8858..c6135b8ed173a 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -3198,12 +3198,7 @@ class ICorDynamicInfo : public ICorStaticInfo // field represents a statically initialized readonly field of any type, it might be: // * integer/floating point primitive // * null - // * frozen object which in turn can be: - // * string - // * RuntimeType (CoreCLR only) - // * Array (NativeAOT only) - // * Delegate (NativeAOT only) - // * Object wihtout fields (NativeAOT only) + // * frozen object reference (string, array or object) // // Arguments: // field - field handle @@ -3211,7 +3206,7 @@ class ICorDynamicInfo : public ICorStaticInfo // bufferSize - size of buffer // // Return Value: - // Returns true if field's constant value was succesfully copied to buffer + // Returns true if field's constant value was available and successfully copied to buffer // virtual bool getReadonlyStaticFieldValue( CORINFO_FIELD_HANDLE field, From 22baa4325e5147dbcf27b048ecb4f8478ba3a201 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Thu, 6 Oct 2022 22:53:25 +0200 Subject: [PATCH 41/61] Ah, actually we need that condition, it can be a struct --- .../aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 9f48f080b5b2f..86b0a5d59da4b 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2230,9 +2230,8 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt { switch (data) { - case byte[] bytes: - Debug.Assert(bufferSize >= bytes.Length); - + case byte[] bytes when bufferSize >= bytes.Length: + // Ensure we have enough room in the buffer, it can be a large struct bytes.AsSpan().CopyTo(new Span(buffer, bufferSize)); return true; From 47523545d3965c90b5e08c4773a100ed4253e912 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 7 Oct 2022 14:46:40 +0200 Subject: [PATCH 42/61] Address Jakob's feedback --- src/coreclr/jit/gcinfo.cpp | 8 ++++- .../superpmi-shared/methodcontext.cpp | 2 +- src/coreclr/vm/jitinterface.cpp | 31 +++++++++++++------ 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/coreclr/jit/gcinfo.cpp b/src/coreclr/jit/gcinfo.cpp index 7b3cecc9b4f2b..732075b876a50 100644 --- a/src/coreclr/jit/gcinfo.cpp +++ b/src/coreclr/jit/gcinfo.cpp @@ -252,13 +252,19 @@ GCInfo::WriteBarrierForm GCInfo::gcIsWriteBarrierCandidate(GenTreeStoreInd* stor return WBF_NoBarrier; } + // Write-barriers are no-op for frozen objects (as values) if (store->Data()->IsIconHandle(GTF_ICON_OBJ_HDL)) { #ifndef TARGET_XARCH const ssize_t handle = store->Data()->AsIntCon()->IconValue(); if (!compiler->info.compCompHnd->isObjectImmutable(reinterpret_cast(handle))) { - // See https://github.com/dotnet/runtime/pull/76135#issuecomment-1257258310 + // On platforms with weaker memory model we need to make sure we use a store with the release semantic + // when we publish a potentially mutable object + // See relevant discussions https://github.com/dotnet/runtime/pull/76135#issuecomment-1257258310 and + // https://github.com/dotnet/runtime/pull/76112#discussion_r980639782 + + // This can be relaxed to "just make sure to use stlr/memory barrier" if needed store->gtFlags |= GTF_IND_VOLATILE; } #endif diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index dd8062b8bed17..ae9cc6da3ec2d 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -3664,7 +3664,7 @@ bool MethodContext::repGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, u int itemIndex = GetReadonlyStaticFieldValue->GetIndex(key); if (itemIndex < 0) { - return false; + LogException(EXCEPTIONCODE_MC, "repGetReadonlyStaticFieldValue: didn't find buffer for {fld-%016llX, %d}", field, bufferSize); } else { diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 78f6ab4cbbb85..db8cd5542d4b2 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11889,6 +11889,19 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t JIT_TO_EE_TRANSITION(); + auto setResult = [&](void* data, int size) + { + if (size > bufferSize) + { + result = false; + } + else + { + memcpy(buffer, data, size); + result = true; + } + }; + FieldDesc* field = (FieldDesc*)fieldHnd; if (field->IsStatic() && !field->IsThreadStatic()) { @@ -11911,15 +11924,13 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t Object* obj = OBJECTREFToObject(fieldObj); if (GCHeapUtilities::GetGCHeap()->IsInFrozenSegment(obj)) { - intptr_t ptr = (intptr_t)obj; - memcpy(buffer, &ptr, sizeof(intptr_t)); - result = true; + setResult(&obj, sizeof(intptr_t)); } } else { - memset(buffer, 0, sizeof(intptr_t)); - result = true; + intptr_t zero = 0; + setResult(&zero, sizeof(intptr_t)); } } else @@ -11934,26 +11945,26 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t case ELEMENT_TYPE_BOOLEAN: case ELEMENT_TYPE_I1: case ELEMENT_TYPE_U1: - memcpy(buffer, fldAddr, sizeof(uint8_t)); + setResult(fldAddr, sizeof(uint8_t)); break; case ELEMENT_TYPE_CHAR: case ELEMENT_TYPE_I2: case ELEMENT_TYPE_U2: - memcpy(buffer, fldAddr, sizeof(uint16_t)); + setResult(fldAddr, sizeof(uint16_t)); break; case ELEMENT_TYPE_I4: case ELEMENT_TYPE_U4: case ELEMENT_TYPE_R4: - memcpy(buffer, fldAddr, sizeof(uint32_t)); + setResult(fldAddr, sizeof(uint32_t)); break; case ELEMENT_TYPE_I8: case ELEMENT_TYPE_U8: case ELEMENT_TYPE_R8: - memcpy(buffer, fldAddr, sizeof(uint64_t)); + setResult(fldAddr, sizeof(uint64_t)); break; case ELEMENT_TYPE_I: case ELEMENT_TYPE_U: - memcpy(buffer, fldAddr, sizeof(intptr_t)); + setResult(fldAddr, sizeof(intptr_t)); break; default: result = false; From 49ab02390695d2d6bf86ddc313d985410ef79143 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 7 Oct 2022 15:07:17 +0200 Subject: [PATCH 43/61] fix compilation --- .../Compiler/DependencyAnalysis/FrozenObjectNode.cs | 2 ++ src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp | 1 + 2 files changed, 3 insertions(+) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs index 18ff65d55f37e..bc863631e8818 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs @@ -105,5 +105,7 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer return _allocationSiteId.CompareTo(otherFrozenObjectNode._allocationSiteId); } + + public override string ToString() => $"Frozen {_data.Type.GetDisplayNameWithoutNamespace()} object"; } } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index ae9cc6da3ec2d..e50a507cf5423 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -3665,6 +3665,7 @@ bool MethodContext::repGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, u if (itemIndex < 0) { LogException(EXCEPTIONCODE_MC, "repGetReadonlyStaticFieldValue: didn't find buffer for {fld-%016llX, %d}", field, bufferSize); + return false; } else { From 08d59f5123ecc7638f405ac927462171fe43e987 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 7 Oct 2022 15:14:26 +0200 Subject: [PATCH 44/61] Use AssertMapExistsNoMessage --- .../superpmi-shared/methodcontext.cpp | 28 ++++++------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index e50a507cf5423..6d81457151190 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -3653,32 +3653,22 @@ void MethodContext::dmpGetReadonlyStaticFieldValue(DLD key, DD value) } bool MethodContext::repGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize) { - if (GetReadonlyStaticFieldValue == nullptr) - return false; - DLD key; ZeroMemory(&key, sizeof(key)); key.A = CastHandle(field); key.B = (DWORD)bufferSize; - int itemIndex = GetReadonlyStaticFieldValue->GetIndex(key); - if (itemIndex < 0) - { - LogException(EXCEPTIONCODE_MC, "repGetReadonlyStaticFieldValue: didn't find buffer for {fld-%016llX, %d}", field, bufferSize); - return false; - } - else + AssertMapExistsNoMessage(GetReadonlyStaticFieldValue, key); + + DD value = GetReadonlyStaticFieldValue->Get(key); + DEBUG_REP(dmpGetReadonlyStaticFieldValue(key, value)); + if (buffer != nullptr && (bool)value.A) { - DD value = GetReadonlyStaticFieldValue->Get(key); - DEBUG_REP(dmpGetReadonlyStaticFieldValue(key, value)); - if (buffer != nullptr && (bool)value.A) - { - uint8_t* srcBuffer = (uint8_t*)GetReadonlyStaticFieldValue->GetBuffer(value.B); - Assert(srcBuffer != nullptr); - memcpy(buffer, srcBuffer, bufferSize); - } - return (bool)value.A; + uint8_t* srcBuffer = (uint8_t*)GetReadonlyStaticFieldValue->GetBuffer(value.B); + Assert(srcBuffer != nullptr); + memcpy(buffer, srcBuffer, bufferSize); } + return (bool)value.A; } void MethodContext::recGetStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, From 45cd02b2262f1443db9aef6ae552eef6a4e77689 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 7 Oct 2022 16:14:22 +0200 Subject: [PATCH 45/61] Address feedback --- src/coreclr/jit/gcinfo.cpp | 14 ----- src/coreclr/jit/importer.cpp | 15 +++-- src/coreclr/jit/lower.cpp | 17 ++++++ .../JitInterface/CorInfoImpl.RyuJit.cs | 8 ++- .../superpmi-shared/methodcontext.cpp | 2 +- src/coreclr/vm/jitinterface.cpp | 57 ++++--------------- 6 files changed, 45 insertions(+), 68 deletions(-) diff --git a/src/coreclr/jit/gcinfo.cpp b/src/coreclr/jit/gcinfo.cpp index 732075b876a50..6ee757a7238bc 100644 --- a/src/coreclr/jit/gcinfo.cpp +++ b/src/coreclr/jit/gcinfo.cpp @@ -255,20 +255,6 @@ GCInfo::WriteBarrierForm GCInfo::gcIsWriteBarrierCandidate(GenTreeStoreInd* stor // Write-barriers are no-op for frozen objects (as values) if (store->Data()->IsIconHandle(GTF_ICON_OBJ_HDL)) { -#ifndef TARGET_XARCH - const ssize_t handle = store->Data()->AsIntCon()->IconValue(); - if (!compiler->info.compCompHnd->isObjectImmutable(reinterpret_cast(handle))) - { - // On platforms with weaker memory model we need to make sure we use a store with the release semantic - // when we publish a potentially mutable object - // See relevant discussions https://github.com/dotnet/runtime/pull/76135#issuecomment-1257258310 and - // https://github.com/dotnet/runtime/pull/76112#discussion_r980639782 - - // This can be relaxed to "just make sure to use stlr/memory barrier" if needed - store->gtFlags |= GTF_IND_VOLATILE; - } -#endif - // Ignore frozen objects return WBF_NoBarrier; } diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 7d490c5a88fe2..586d6dc34ae39 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -15291,13 +15291,18 @@ void Compiler::impImportBlockCode(BasicBlock* block) { const int bufferSize = sizeof(uint64_t); uint8_t buffer[bufferSize] = {0}; - if (info.compCompHnd->getReadonlyStaticFieldValue(resolvedToken.hField, buffer, bufferSize)) + if (varTypeIsIntegral(lclTyp) || varTypeIsFloating(lclTyp) || (lclTyp == TYP_REF)) { - GenTree* cnsValue = impImportStaticReadOnlyField(buffer, bufferSize, lclTyp); - if (cnsValue != nullptr) + assert(bufferSize >= genTypeSize(lclTyp)); + if (info.compCompHnd->getReadonlyStaticFieldValue(resolvedToken.hField, buffer, + genTypeSize(lclTyp))) { - op1 = cnsValue; - goto FIELD_DONE; + GenTree* cnsValue = impImportStaticReadOnlyField(buffer, bufferSize, lclTyp); + if (cnsValue != nullptr) + { + op1 = cnsValue; + goto FIELD_DONE; + } } } } diff --git a/src/coreclr/jit/lower.cpp b/src/coreclr/jit/lower.cpp index 5611761daabab..c9b047438ac56 100644 --- a/src/coreclr/jit/lower.cpp +++ b/src/coreclr/jit/lower.cpp @@ -7108,6 +7108,23 @@ void Lowering::LowerStoreIndirCommon(GenTreeStoreInd* ind) if (!comp->codeGen->gcInfo.gcIsWriteBarrierStoreIndNode(ind)) { +#ifndef TARGET_XARCH + if (ind->Data()->IsIconHandle(GTF_ICON_OBJ_HDL)) + { + const ssize_t handle = ind->Data()->AsIntCon()->IconValue(); + if (!comp->info.compCompHnd->isObjectImmutable(reinterpret_cast(handle))) + { + // On platforms with weaker memory model we need to make sure we use a store with the release semantic + // when we publish a potentially mutable object + // See relevant discussions https://github.com/dotnet/runtime/pull/76135#issuecomment-1257258310 and + // https://github.com/dotnet/runtime/pull/76112#discussion_r980639782 + + // This can be relaxed to "just make sure to use stlr/memory barrier" if needed + ind->gtFlags |= GTF_IND_VOLATILE; + } + } +#endif + if (varTypeIsFloating(ind) && ind->Data()->IsCnsFltOrDbl()) { // Optimize *x = DCON to *x = ICON which can be slightly faster and/or smaller. diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 86b0a5d59da4b..4d82e7b0e3536 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2206,6 +2206,10 @@ private int getExactClasses(CORINFO_CLASS_STRUCT_* baseType, int maxExactClasses private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byte* buffer, int bufferSize) { + Debug.Assert(fieldHandle != null); + Debug.Assert(buffer != null); + Debug.Assert(bufferSize > 0); + FieldDesc field = HandleToObject(fieldHandle); if (field.IsStatic && !field.IsThreadStatic && field.IsInitOnly && field.OwningType is MetadataType owningType) { @@ -2230,7 +2234,9 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt { switch (data) { - case byte[] bytes when bufferSize >= bytes.Length: + case byte[] bytes: + Debug.Assert(bufferSize >= bytes.Length); + // Ensure we have enough room in the buffer, it can be a large struct bytes.AsSpan().CopyTo(new Span(buffer, bufferSize)); return true; diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 6d81457151190..8863efa420b4e 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -3658,7 +3658,7 @@ bool MethodContext::repGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, u key.A = CastHandle(field); key.B = (DWORD)bufferSize; - AssertMapExistsNoMessage(GetReadonlyStaticFieldValue, key); + AssertMapExistsNoMessage(GetReadonlyStaticFieldValue); DD value = GetReadonlyStaticFieldValue->Get(key); DEBUG_REP(dmpGetReadonlyStaticFieldValue(key, value)); diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index db8cd5542d4b2..8ea37d517a04b 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11883,25 +11883,12 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t _ASSERT(fieldHnd != NULL); _ASSERT(buffer != NULL); - _ASSERT(bufferSize == sizeof(uint64_t)); + _ASSERT(bufferSize > 0); bool result = false; JIT_TO_EE_TRANSITION(); - auto setResult = [&](void* data, int size) - { - if (size > bufferSize) - { - result = false; - } - else - { - memcpy(buffer, data, size); - result = true; - } - }; - FieldDesc* field = (FieldDesc*)fieldHnd; if (field->IsStatic() && !field->IsThreadStatic()) { @@ -11918,19 +11905,23 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t { if (field->IsObjRef()) { + _ASSERT(bufferSize >= sizeof(intptr_t)); + OBJECTREF fieldObj = field->GetStaticOBJECTREF(); if (fieldObj != NULL) { Object* obj = OBJECTREFToObject(fieldObj); if (GCHeapUtilities::GetGCHeap()->IsInFrozenSegment(obj)) { - setResult(&obj, sizeof(intptr_t)); + intptr_t ptr = (intptr_t)obj; + memcpy(buffer, &ptr, sizeof(intptr_t)); + result = true; } } else { - intptr_t zero = 0; - setResult(&zero, sizeof(intptr_t)); + memset(buffer, 0, sizeof(intptr_t)); + result = true; } } else @@ -11938,38 +11929,10 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t void* fldAddr = field->GetStaticAddressHandle(field->IsRVA() ? nullptr : (void*)field->GetBase()); if (fldAddr != nullptr) { + _ASSERT((unsigned)bufferSize >= field->GetSize()); _ASSERTE(!pEnclosingMT->ContainsGenericVariables()); + memcpy(fldAddr, fldAddr, field->GetSize()); result = true; - switch (field->GetFieldType()) - { - case ELEMENT_TYPE_BOOLEAN: - case ELEMENT_TYPE_I1: - case ELEMENT_TYPE_U1: - setResult(fldAddr, sizeof(uint8_t)); - break; - case ELEMENT_TYPE_CHAR: - case ELEMENT_TYPE_I2: - case ELEMENT_TYPE_U2: - setResult(fldAddr, sizeof(uint16_t)); - break; - case ELEMENT_TYPE_I4: - case ELEMENT_TYPE_U4: - case ELEMENT_TYPE_R4: - setResult(fldAddr, sizeof(uint32_t)); - break; - case ELEMENT_TYPE_I8: - case ELEMENT_TYPE_U8: - case ELEMENT_TYPE_R8: - setResult(fldAddr, sizeof(uint64_t)); - break; - case ELEMENT_TYPE_I: - case ELEMENT_TYPE_U: - setResult(fldAddr, sizeof(intptr_t)); - break; - default: - result = false; - break; - } } } } From b578780fc3e5f1580d30045de5762351c8e2eaec Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Fri, 7 Oct 2022 16:57:51 +0200 Subject: [PATCH 46/61] Update src/coreclr/vm/jitinterface.cpp Co-authored-by: Jakob Botsch Nielsen --- src/coreclr/vm/jitinterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 8ea37d517a04b..995e88f58ff9d 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11890,7 +11890,7 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t JIT_TO_EE_TRANSITION(); FieldDesc* field = (FieldDesc*)fieldHnd; - if (field->IsStatic() && !field->IsThreadStatic()) + if (field->IsStatic() && !field->IsThreadStatic() && (bufferSize == field->GetSize())) { MethodTable* pEnclosingMT = field->GetEnclosingMethodTable(); if (!pEnclosingMT->IsSharedByGenericInstantiations()) From 84de4d2ce5f7aa5dabd05a2a1a84e967059cc4c3 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 7 Oct 2022 17:01:57 +0200 Subject: [PATCH 47/61] Address feedback --- src/coreclr/jit/importer.cpp | 4 ++-- src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp | 2 +- src/coreclr/vm/jitinterface.cpp | 3 --- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 586d6dc34ae39..f4e92d2163324 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -8179,7 +8179,7 @@ GenTree* Compiler::impImportStaticReadOnlyField(uint8_t* buffer, int bufferSize, } case TYP_REF: { - ssize_t ptr; + void* ptr; memcpy(&ptr, buffer, sizeof(ssize_t)); if (ptr == 0) @@ -8189,7 +8189,7 @@ GenTree* Compiler::impImportStaticReadOnlyField(uint8_t* buffer, int bufferSize, else { setMethodHasFrozenObjects(); - tree = gtNewIconEmbHndNode((void*)ptr, nullptr, GTF_ICON_OBJ_HDL, nullptr); + tree = gtNewIconEmbHndNode(ptr, nullptr, GTF_ICON_OBJ_HDL, nullptr); tree->gtType = TYP_REF; INDEBUG(tree->AsIntCon()->gtTargetHandle = (size_t)ptr); } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 8863efa420b4e..5534c4617769d 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -3658,7 +3658,7 @@ bool MethodContext::repGetReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE field, u key.A = CastHandle(field); key.B = (DWORD)bufferSize; - AssertMapExistsNoMessage(GetReadonlyStaticFieldValue); + AssertMapAndKeyExist(GetReadonlyStaticFieldValue, key, ": key %016llX", key.A); DD value = GetReadonlyStaticFieldValue->Get(key); DEBUG_REP(dmpGetReadonlyStaticFieldValue(key, value)); diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 995e88f58ff9d..c22e195c994ff 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11905,8 +11905,6 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t { if (field->IsObjRef()) { - _ASSERT(bufferSize >= sizeof(intptr_t)); - OBJECTREF fieldObj = field->GetStaticOBJECTREF(); if (fieldObj != NULL) { @@ -11929,7 +11927,6 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t void* fldAddr = field->GetStaticAddressHandle(field->IsRVA() ? nullptr : (void*)field->GetBase()); if (fldAddr != nullptr) { - _ASSERT((unsigned)bufferSize >= field->GetSize()); _ASSERTE(!pEnclosingMT->ContainsGenericVariables()); memcpy(fldAddr, fldAddr, field->GetSize()); result = true; From 05e263972ca5a5f5a32485d537d286b89ce0bd50 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 7 Oct 2022 17:07:43 +0200 Subject: [PATCH 48/61] fix compilation --- src/coreclr/vm/jitinterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index c22e195c994ff..8b04d234be866 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11890,7 +11890,7 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t JIT_TO_EE_TRANSITION(); FieldDesc* field = (FieldDesc*)fieldHnd; - if (field->IsStatic() && !field->IsThreadStatic() && (bufferSize == field->GetSize())) + if (field->IsStatic() && !field->IsThreadStatic() && ((unsigned)bufferSize == field->GetSize())) { MethodTable* pEnclosingMT = field->GetEnclosingMethodTable(); if (!pEnclosingMT->IsSharedByGenericInstantiations()) From 771fd6adcb63c087263a681873feec09d3ea9b05 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Fri, 7 Oct 2022 18:25:57 +0200 Subject: [PATCH 49/61] Update src/coreclr/vm/jitinterface.cpp Co-authored-by: Jan Kotas --- src/coreclr/vm/jitinterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 8b04d234be866..9c1ee178c7ca4 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11928,7 +11928,7 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t if (fldAddr != nullptr) { _ASSERTE(!pEnclosingMT->ContainsGenericVariables()); - memcpy(fldAddr, fldAddr, field->GetSize()); + memcpy(buffer, fldAddr, bufferSize); result = true; } } From 1acf664ba4261edcb8d5528c2255af87dffb22cd Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Fri, 7 Oct 2022 18:26:15 +0200 Subject: [PATCH 50/61] Update src/coreclr/vm/jitinterface.cpp Co-authored-by: Jan Kotas --- src/coreclr/vm/jitinterface.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 9c1ee178c7ca4..268137a4641c6 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11925,8 +11925,7 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t else { void* fldAddr = field->GetStaticAddressHandle(field->IsRVA() ? nullptr : (void*)field->GetBase()); - if (fldAddr != nullptr) - { + _ASSERTE(fldAddr != nullptr); _ASSERTE(!pEnclosingMT->ContainsGenericVariables()); memcpy(buffer, fldAddr, bufferSize); result = true; From 806e985b664ed27e9086cea6ae3d5170c599ee77 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 7 Oct 2022 18:31:40 +0200 Subject: [PATCH 51/61] Address feedback --- src/coreclr/vm/jitinterface.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 268137a4641c6..e161c44d3ed01 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11926,10 +11926,9 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t { void* fldAddr = field->GetStaticAddressHandle(field->IsRVA() ? nullptr : (void*)field->GetBase()); _ASSERTE(fldAddr != nullptr); - _ASSERTE(!pEnclosingMT->ContainsGenericVariables()); - memcpy(buffer, fldAddr, bufferSize); - result = true; - } + _ASSERTE(!pEnclosingMT->ContainsGenericVariables()); + memcpy(buffer, fldAddr, bufferSize); + result = true; } } } From 2a0fc8840acee10cedde12b5f55735198a49932b Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 7 Oct 2022 18:39:19 +0200 Subject: [PATCH 52/61] add assert --- src/coreclr/vm/jitinterface.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index e161c44d3ed01..9f8f5b641763a 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11924,6 +11924,8 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t } else { + // GetStaticAddressHandle doesn't work for structs + _ASSERT(field->GetFieldType() != ELEMENT_TYPE_VALUETYPE); void* fldAddr = field->GetStaticAddressHandle(field->IsRVA() ? nullptr : (void*)field->GetBase()); _ASSERTE(fldAddr != nullptr); _ASSERTE(!pEnclosingMT->ContainsGenericVariables()); From fe169c679205338744cd84e8a0f3f24cb17653e9 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 7 Oct 2022 18:45:00 +0200 Subject: [PATCH 53/61] limit to primitives and objects on llc side --- .../aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 4d82e7b0e3536..c34d2655c1705 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2211,7 +2211,8 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt Debug.Assert(bufferSize > 0); FieldDesc field = HandleToObject(fieldHandle); - if (field.IsStatic && !field.IsThreadStatic && field.IsInitOnly && field.OwningType is MetadataType owningType) + if (field.IsStatic && !field.IsThreadStatic && field.IsInitOnly && field.OwningType is MetadataType owningType && + ((field.FieldType.IsPrimitive) || field.FieldType.IsObject)) { PreinitializationManager preinitManager = _compilation.NodeFactory.PreinitializationManager; if (preinitManager.IsPreinitialized(owningType)) From 30fbd2170fb9d85126e170d874443352f8dc1f94 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Fri, 7 Oct 2022 18:56:56 +0200 Subject: [PATCH 54/61] fix check --- .../JitInterface/CorInfoImpl.RyuJit.cs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index c34d2655c1705..23d02734779b3 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2211,11 +2211,23 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt Debug.Assert(bufferSize > 0); FieldDesc field = HandleToObject(fieldHandle); - if (field.IsStatic && !field.IsThreadStatic && field.IsInitOnly && field.OwningType is MetadataType owningType && - ((field.FieldType.IsPrimitive) || field.FieldType.IsObject)) + if (field.IsStatic && !field.IsThreadStatic && field.IsInitOnly && field.OwningType is MetadataType owningType) { + bool supportedType = field.FieldType.Category switch + { + TypeFlags.Enum or + TypeFlags.Class or + TypeFlags.Interface or + TypeFlags.Array or + TypeFlags.SzArray or + TypeFlags.Pointer or + TypeFlags.FunctionPointer => true, + + _ => field.FieldType.IsPrimitive + }; + PreinitializationManager preinitManager = _compilation.NodeFactory.PreinitializationManager; - if (preinitManager.IsPreinitialized(owningType)) + if (supportedType && preinitManager.IsPreinitialized(owningType)) { TypePreinit.ISerializableValue value = preinitManager .GetPreinitializationInfo(owningType).GetFieldValue(field); From 7c2d8dc02c23124b1e3ebce5281e4589c9a0014c Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Sat, 8 Oct 2022 04:55:36 +0200 Subject: [PATCH 55/61] Apply suggestions from code review Co-authored-by: Jan Kotas --- src/coreclr/vm/jitinterface.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 9f8f5b641763a..d77228bad1350 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11890,7 +11890,8 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t JIT_TO_EE_TRANSITION(); FieldDesc* field = (FieldDesc*)fieldHnd; - if (field->IsStatic() && !field->IsThreadStatic() && ((unsigned)bufferSize == field->GetSize())) + _ASSERTE(field->IsStatic() && !field->IsThreadStatic()); + _ASSERTE((unsigned)bufferSize == field->GetSize()); { MethodTable* pEnclosingMT = field->GetEnclosingMethodTable(); if (!pEnclosingMT->IsSharedByGenericInstantiations()) @@ -11924,9 +11925,7 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t } else { - // GetStaticAddressHandle doesn't work for structs - _ASSERT(field->GetFieldType() != ELEMENT_TYPE_VALUETYPE); - void* fldAddr = field->GetStaticAddressHandle(field->IsRVA() ? nullptr : (void*)field->GetBase()); + void* fldAddr = field->GetCurrentStaticAddress(); _ASSERTE(fldAddr != nullptr); _ASSERTE(!pEnclosingMT->ContainsGenericVariables()); memcpy(buffer, fldAddr, bufferSize); From be7c16f68a550e6b29e06a3208b1199a6fc5d10f Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 8 Oct 2022 04:58:39 +0200 Subject: [PATCH 56/61] Fix indention since "if" was removed --- src/coreclr/vm/jitinterface.cpp | 53 ++++++++++++++++----------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index d77228bad1350..951109777d13e 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11892,46 +11892,45 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t FieldDesc* field = (FieldDesc*)fieldHnd; _ASSERTE(field->IsStatic() && !field->IsThreadStatic()); _ASSERTE((unsigned)bufferSize == field->GetSize()); + + MethodTable* pEnclosingMT = field->GetEnclosingMethodTable(); + if (!pEnclosingMT->IsSharedByGenericInstantiations()) { - MethodTable* pEnclosingMT = field->GetEnclosingMethodTable(); - if (!pEnclosingMT->IsSharedByGenericInstantiations()) - { - // Allocate space for the local class if necessary, but don't trigger - // class construction. - DomainLocalModule* pLocalModule = pEnclosingMT->GetDomainLocalModule(); - pLocalModule->PopulateClass(pEnclosingMT); + // Allocate space for the local class if necessary, but don't trigger + // class construction. + DomainLocalModule* pLocalModule = pEnclosingMT->GetDomainLocalModule(); + pLocalModule->PopulateClass(pEnclosingMT); - GCX_COOP(); - if (pEnclosingMT->IsClassInited() && IsFdInitOnly(field->GetAttributes())) + GCX_COOP(); + if (pEnclosingMT->IsClassInited() && IsFdInitOnly(field->GetAttributes())) + { + if (field->IsObjRef()) { - if (field->IsObjRef()) + OBJECTREF fieldObj = field->GetStaticOBJECTREF(); + if (fieldObj != NULL) { - OBJECTREF fieldObj = field->GetStaticOBJECTREF(); - if (fieldObj != NULL) + Object* obj = OBJECTREFToObject(fieldObj); + if (GCHeapUtilities::GetGCHeap()->IsInFrozenSegment(obj)) { - Object* obj = OBJECTREFToObject(fieldObj); - if (GCHeapUtilities::GetGCHeap()->IsInFrozenSegment(obj)) - { - intptr_t ptr = (intptr_t)obj; - memcpy(buffer, &ptr, sizeof(intptr_t)); - result = true; - } - } - else - { - memset(buffer, 0, sizeof(intptr_t)); + intptr_t ptr = (intptr_t)obj; + memcpy(buffer, &ptr, sizeof(intptr_t)); result = true; } } else { - void* fldAddr = field->GetCurrentStaticAddress(); - _ASSERTE(fldAddr != nullptr); - _ASSERTE(!pEnclosingMT->ContainsGenericVariables()); - memcpy(buffer, fldAddr, bufferSize); + memset(buffer, 0, sizeof(intptr_t)); result = true; } } + else + { + void* fldAddr = field->GetCurrentStaticAddress(); + _ASSERTE(fldAddr != nullptr); + _ASSERTE(!pEnclosingMT->ContainsGenericVariables()); + memcpy(buffer, fldAddr, bufferSize); + result = true; + } } } From 5fbe665e50a9a50782a9801a1028138f378fd2a6 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Sat, 8 Oct 2022 05:11:20 +0200 Subject: [PATCH 57/61] Apply suggestions from code review Co-authored-by: Jan Kotas --- .../aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs | 4 ++-- src/coreclr/vm/jitinterface.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 23d02734779b3..f7b4d3fd9c936 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2248,14 +2248,14 @@ TypeFlags.Pointer or switch (data) { case byte[] bytes: - Debug.Assert(bufferSize >= bytes.Length); + Debug.Assert(bufferSize == bytes.Length); // Ensure we have enough room in the buffer, it can be a large struct bytes.AsSpan().CopyTo(new Span(buffer, bufferSize)); return true; case FrozenObjectNode or FrozenStringNode: - Debug.Assert(bufferSize >= targetPtrSize); + Debug.Assert(bufferSize == targetPtrSize); // save handle's value to buffer nint handle = ObjectToHandle(data); diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 951109777d13e..a40f87537da14 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11894,7 +11894,8 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t _ASSERTE((unsigned)bufferSize == field->GetSize()); MethodTable* pEnclosingMT = field->GetEnclosingMethodTable(); - if (!pEnclosingMT->IsSharedByGenericInstantiations()) + _ASSERTE(!pEnclosingMT->IsSharedByGenericInstantiations()); + _ASSERTE(!pEnclosingMT->ContainsGenericVariables()); { // Allocate space for the local class if necessary, but don't trigger // class construction. @@ -11927,7 +11928,6 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t { void* fldAddr = field->GetCurrentStaticAddress(); _ASSERTE(fldAddr != nullptr); - _ASSERTE(!pEnclosingMT->ContainsGenericVariables()); memcpy(buffer, fldAddr, bufferSize); result = true; } From 56908b08f97c5cd4fdd1bb2e503b93274d7220e5 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 8 Oct 2022 05:16:58 +0200 Subject: [PATCH 58/61] Address feedback, align NativeAOT logic with CoreCLR --- .../JitInterface/CorInfoImpl.RyuJit.cs | 22 +++------ src/coreclr/vm/jitinterface.cpp | 47 +++++++++---------- 2 files changed, 29 insertions(+), 40 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index f7b4d3fd9c936..34ece05ba5afa 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2211,23 +2211,13 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt Debug.Assert(bufferSize > 0); FieldDesc field = HandleToObject(fieldHandle); - if (field.IsStatic && !field.IsThreadStatic && field.IsInitOnly && field.OwningType is MetadataType owningType) - { - bool supportedType = field.FieldType.Category switch - { - TypeFlags.Enum or - TypeFlags.Class or - TypeFlags.Interface or - TypeFlags.Array or - TypeFlags.SzArray or - TypeFlags.Pointer or - TypeFlags.FunctionPointer => true, - - _ => field.FieldType.IsPrimitive - }; + Debug.Assert(field.IsStatic && !field.IsThreadStatic); + Debug.Assert(field.FieldType.GetElementSize().AsInt == bufferSize); + if (field.IsInitOnly && field.OwningType is MetadataType owningType) + { PreinitializationManager preinitManager = _compilation.NodeFactory.PreinitializationManager; - if (supportedType && preinitManager.IsPreinitialized(owningType)) + if (preinitManager.IsPreinitialized(owningType)) { TypePreinit.ISerializableValue value = preinitManager .GetPreinitializationInfo(owningType).GetFieldValue(field); @@ -2236,7 +2226,7 @@ TypeFlags.Pointer or if (value == null) { - Debug.Assert(bufferSize >= targetPtrSize); + Debug.Assert(bufferSize == targetPtrSize); // Write "null" to buffer new Span(buffer, targetPtrSize).Clear(); diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index a40f87537da14..1dd60201f4198 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11896,42 +11896,41 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t MethodTable* pEnclosingMT = field->GetEnclosingMethodTable(); _ASSERTE(!pEnclosingMT->IsSharedByGenericInstantiations()); _ASSERTE(!pEnclosingMT->ContainsGenericVariables()); - { - // Allocate space for the local class if necessary, but don't trigger - // class construction. - DomainLocalModule* pLocalModule = pEnclosingMT->GetDomainLocalModule(); - pLocalModule->PopulateClass(pEnclosingMT); - GCX_COOP(); - if (pEnclosingMT->IsClassInited() && IsFdInitOnly(field->GetAttributes())) + // Allocate space for the local class if necessary, but don't trigger + // class construction. + DomainLocalModule* pLocalModule = pEnclosingMT->GetDomainLocalModule(); + pLocalModule->PopulateClass(pEnclosingMT); + + GCX_COOP(); + if (pEnclosingMT->IsClassInited() && IsFdInitOnly(field->GetAttributes())) + { + if (field->IsObjRef()) { - if (field->IsObjRef()) + OBJECTREF fieldObj = field->GetStaticOBJECTREF(); + if (fieldObj != NULL) { - OBJECTREF fieldObj = field->GetStaticOBJECTREF(); - if (fieldObj != NULL) + Object* obj = OBJECTREFToObject(fieldObj); + if (GCHeapUtilities::GetGCHeap()->IsInFrozenSegment(obj)) { - Object* obj = OBJECTREFToObject(fieldObj); - if (GCHeapUtilities::GetGCHeap()->IsInFrozenSegment(obj)) - { - intptr_t ptr = (intptr_t)obj; - memcpy(buffer, &ptr, sizeof(intptr_t)); - result = true; - } - } - else - { - memset(buffer, 0, sizeof(intptr_t)); + intptr_t ptr = (intptr_t)obj; + memcpy(buffer, &ptr, sizeof(intptr_t)); result = true; } } else { - void* fldAddr = field->GetCurrentStaticAddress(); - _ASSERTE(fldAddr != nullptr); - memcpy(buffer, fldAddr, bufferSize); + memset(buffer, 0, sizeof(intptr_t)); result = true; } } + else + { + void* fldAddr = field->GetCurrentStaticAddress(); + _ASSERTE(fldAddr != nullptr); + memcpy(buffer, fldAddr, bufferSize); + result = true; + } } EE_TO_JIT_TRANSITION(); From cbe5cd0238087191dc47ad78bc5d5b0e0cd9e7a5 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Sat, 8 Oct 2022 05:21:10 +0200 Subject: [PATCH 59/61] Update src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs Co-authored-by: Jan Kotas --- .../aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index 34ece05ba5afa..e287f66070524 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2212,7 +2212,6 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt FieldDesc field = HandleToObject(fieldHandle); Debug.Assert(field.IsStatic && !field.IsThreadStatic); - Debug.Assert(field.FieldType.GetElementSize().AsInt == bufferSize); if (field.IsInitOnly && field.OwningType is MetadataType owningType) { From 76a72d845c8fd607be2298ad15a25032807d2208 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Fri, 7 Oct 2022 20:24:54 -0700 Subject: [PATCH 60/61] Update src/coreclr/vm/jitinterface.cpp --- src/coreclr/vm/jitinterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 1dd60201f4198..70ffd2cb832d5 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11902,9 +11902,9 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t DomainLocalModule* pLocalModule = pEnclosingMT->GetDomainLocalModule(); pLocalModule->PopulateClass(pEnclosingMT); - GCX_COOP(); if (pEnclosingMT->IsClassInited() && IsFdInitOnly(field->GetAttributes())) { + GCX_COOP(); if (field->IsObjRef()) { OBJECTREF fieldObj = field->GetStaticOBJECTREF(); From aa5be5107517545d53efd6c7190f82c133514bbf Mon Sep 17 00:00:00 2001 From: EgorBo Date: Sat, 8 Oct 2022 05:36:01 +0200 Subject: [PATCH 61/61] Keep IsThreadStatic on vm side --- .../aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs | 4 ++-- src/coreclr/vm/jitinterface.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs index e287f66070524..72ee00ccd76da 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2211,9 +2211,9 @@ private bool getReadonlyStaticFieldValue(CORINFO_FIELD_STRUCT_* fieldHandle, byt Debug.Assert(bufferSize > 0); FieldDesc field = HandleToObject(fieldHandle); - Debug.Assert(field.IsStatic && !field.IsThreadStatic); + Debug.Assert(field.IsStatic); - if (field.IsInitOnly && field.OwningType is MetadataType owningType) + if (!field.IsThreadStatic && field.IsInitOnly && field.OwningType is MetadataType owningType) { PreinitializationManager preinitManager = _compilation.NodeFactory.PreinitializationManager; if (preinitManager.IsPreinitialized(owningType)) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 70ffd2cb832d5..7f9eb04892604 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11890,7 +11890,7 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t JIT_TO_EE_TRANSITION(); FieldDesc* field = (FieldDesc*)fieldHnd; - _ASSERTE(field->IsStatic() && !field->IsThreadStatic()); + _ASSERTE(field->IsStatic()); _ASSERTE((unsigned)bufferSize == field->GetSize()); MethodTable* pEnclosingMT = field->GetEnclosingMethodTable(); @@ -11902,7 +11902,7 @@ bool CEEInfo::getReadonlyStaticFieldValue(CORINFO_FIELD_HANDLE fieldHnd, uint8_t DomainLocalModule* pLocalModule = pEnclosingMT->GetDomainLocalModule(); pLocalModule->PopulateClass(pEnclosingMT); - if (pEnclosingMT->IsClassInited() && IsFdInitOnly(field->GetAttributes())) + if (!field->IsThreadStatic() && pEnclosingMT->IsClassInited() && IsFdInitOnly(field->GetAttributes())) { GCX_COOP(); if (field->IsObjRef())