From 2cd11d437a68cb6e4ad105fcd97f67eff5e45eca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Petryka?= Date: Sun, 10 Nov 2024 04:32:48 +0100 Subject: [PATCH 01/12] Non-PGO calli/delegate call transformation --- src/coreclr/inc/corinfo.h | 8 +- src/coreclr/inc/icorjitinfoimpl_generated.h | 4 + src/coreclr/inc/jiteeversionguid.h | 10 +- src/coreclr/jit/ICorJitInfo_names_generated.h | 1 + .../jit/ICorJitInfo_wrapper_generated.hpp | 10 + src/coreclr/jit/compiler.h | 7 +- src/coreclr/jit/importercalls.cpp | 312 +++++++++++++++++- .../tools/Common/JitInterface/CorInfoImpl.cs | 13 + .../JitInterface/CorInfoImpl_generated.cs | 220 ++++++------ .../ThunkGenerator/ThunkInput.txt | 1 + .../aot/jitinterface/jitinterface_generated.h | 11 + .../tools/superpmi/superpmi-shared/lwmlist.h | 1 + .../superpmi-shared/methodcontext.cpp | 38 ++- .../superpmi/superpmi-shared/methodcontext.h | 11 +- .../superpmi-shim-collector/icorjitinfo.cpp | 9 + .../icorjitinfo_generated.cpp | 8 + .../icorjitinfo_generated.cpp | 7 + .../tools/superpmi/superpmi/icorjitinfo.cpp | 7 + src/coreclr/vm/comdelegate.cpp | 5 +- src/coreclr/vm/jitinterface.cpp | 68 ++++ 20 files changed, 622 insertions(+), 129 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 93778cc0925910..bef324643a857c 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -2326,7 +2326,7 @@ class ICorStaticInfo CORINFO_CLASS_HANDLE cls ) = 0; - // Returns the assembly name of the class "cls", or nullptr if there is none. + // Returns the assembly name of the class "cls", or nullptr if there is none. virtual const char* getClassAssemblyName ( CORINFO_CLASS_HANDLE cls ) = 0; @@ -2611,6 +2611,12 @@ class ICorStaticInfo CorInfoClassId classId ) = 0; + // returns the class handle for the special builtin classes + virtual CORINFO_METHOD_HANDLE getMethodFromDelegate ( + void* address, + bool pinned + ) = 0; + // "System.Int32" ==> CORINFO_TYPE_INT.. virtual CorInfoType getTypeForPrimitiveValueClass( CORINFO_CLASS_HANDLE cls diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 1744b5dcf20380..7b4f43f5ed02d0 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -329,6 +329,10 @@ void classMustBeLoadedBeforeCodeIsRun( CORINFO_CLASS_HANDLE getBuiltinClass( CorInfoClassId classId) override; +CORINFO_METHOD_HANDLE getMethodFromDelegate( + void* address, + bool pinned) override; + CorInfoType getTypeForPrimitiveValueClass( CORINFO_CLASS_HANDLE cls) override; diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 07e246cd3fa13e..fd59df8ad8e9ab 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 = { /* 04021b93-e969-41ed-96cd-4c583673b9ab */ - 0x04021b93, - 0xe969, - 0x41ed, - {0x96, 0xcd, 0x4c, 0x58, 0x36, 0x73, 0xb9, 0xab} +constexpr GUID JITEEVersionIdentifier = { /* 836ac5db-120c-4d01-9eb0-950dbe7962a2 */ + 0x836ac5db, + 0x120c, + 0x4d01, + {0x9e, 0xb0, 0x95, 0x0d, 0xbe, 0x79, 0x62, 0xa2} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/jit/ICorJitInfo_names_generated.h b/src/coreclr/jit/ICorJitInfo_names_generated.h index b903dcb19709f4..fdfcd273f547dd 100644 --- a/src/coreclr/jit/ICorJitInfo_names_generated.h +++ b/src/coreclr/jit/ICorJitInfo_names_generated.h @@ -81,6 +81,7 @@ DEF_CLR_API(getReadyToRunDelegateCtorHelper) DEF_CLR_API(initClass) DEF_CLR_API(classMustBeLoadedBeforeCodeIsRun) DEF_CLR_API(getBuiltinClass) +DEF_CLR_API(getMethodFromDelegate) DEF_CLR_API(getTypeForPrimitiveValueClass) DEF_CLR_API(getTypeForPrimitiveNumericClass) DEF_CLR_API(canCast) diff --git a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp index 70f4ec545e8d7e..bdd19fb95536d2 100644 --- a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp +++ b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp @@ -765,6 +765,16 @@ CORINFO_CLASS_HANDLE WrapICorJitInfo::getBuiltinClass( return temp; } +CORINFO_METHOD_HANDLE WrapICorJitInfo::getMethodFromDelegate( + void* address, + bool pinned) +{ + API_ENTER(getMethodFromDelegate); + CORINFO_METHOD_HANDLE temp = wrapHnd->getMethodFromDelegate(address, pinned); + API_LEAVE(getMethodFromDelegate); + return temp; +} + CorInfoType WrapICorJitInfo::getTypeForPrimitiveValueClass( CORINFO_CLASS_HANDLE cls) { diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 68a4c29f3c3f7f..95104dc8f14f7e 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -3919,7 +3919,7 @@ class Compiler // false: we can add new tracked variables. // true: We cannot add new 'tracked' variable - bool lvaTrackedFixed = false; + bool lvaTrackedFixed = false; unsigned lvaCount; // total number of locals, which includes function arguments, // special arguments, IL local variables, and JIT temporary variables @@ -4559,6 +4559,7 @@ class Compiler void impPopArgsForUnmanagedCall(GenTreeCall* call, CORINFO_SIG_INFO* sig, GenTree** swiftErrorNode); void impPopArgsForSwiftCall(GenTreeCall* call, CORINFO_SIG_INFO* sig, GenTree** swiftErrorNode); void impRetypeUnmanagedCallArgs(GenTreeCall* call); + bool impCanSubstituteSig(CORINFO_SIG_INFO* sourceSig, CORINFO_SIG_INFO* targetSig, bool* removeInstance); #ifdef SWIFT_SUPPORT void impAppendSwiftErrorStore(GenTree* const swiftErrorNode); @@ -6869,7 +6870,7 @@ class Compiler unsigned acdCount = 0; // Get the index to use as part of the AddCodeDsc key for sharing throw blocks - unsigned bbThrowIndex(BasicBlock* blk, AcdKeyDesignator* dsg); + unsigned bbThrowIndex(BasicBlock* blk, AcdKeyDesignator* dsg); struct AddCodeDscKey { @@ -6877,7 +6878,7 @@ class Compiler AddCodeDscKey(): acdKind(SCK_NONE), acdData(0) {} AddCodeDscKey(SpecialCodeKind kind, BasicBlock* block, Compiler* comp); AddCodeDscKey(AddCodeDsc* add); - + static bool Equals(const AddCodeDscKey& x, const AddCodeDscKey& y) { return (x.acdData == y.acdData) && (x.acdKind == y.acdKind); diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 4251b7c0c6cf19..280959fa6aeed2 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -95,17 +95,20 @@ var_types Compiler::impImportCall(OPCODE opcode, bool checkForSmallType = false; bool bIntrinsicImported = false; - CORINFO_SIG_INFO calliSig; + CORINFO_SIG_INFO originalSig = {}; NewCallArg extraArg; // Swift calls that might throw use a SwiftError* arg that requires additional IR to handle, // so if we're importing a Swift call, look for this type in the signature GenTree* swiftErrorNode = nullptr; - /*------------------------------------------------------------------------- - * First create the call node - */ + // prepare data for calli/delegate call replacement + bool optimizedOrInstrumented = opts.OptimizationEnabled() || opts.IsInstrumented(); + CORINFO_METHOD_HANDLE replacementMethod = nullptr; // real method called by the calli/delegate + GenTree* newThis = nullptr; // new instance for the delegate call + int firstArgPos = -1; // position of the first arg after delegate + // handle special import cases if (opcode == CEE_CALLI) { if (IsTargetAbi(CORINFO_NATIVEAOT_ABI)) @@ -120,25 +123,191 @@ var_types Compiler::impImportCall(OPCODE opcode, } /* Get the call site sig */ - eeGetSig(pResolvedToken->token, pResolvedToken->tokenScope, pResolvedToken->tokenContext, &calliSig); + eeGetSig(pResolvedToken->token, pResolvedToken->tokenScope, pResolvedToken->tokenContext, &originalSig); + + if (!optimizedOrInstrumented) + { + // ignore + } + else if (originalSig.getCallConv() == CORINFO_CALLCONV_DEFAULT) + { + JITDUMP("\n\nimpImportCall trying to import calli as call\n"); + // TODO-Perf: Add an importer forward substitution to handle more cases here. + GenTree* fptr = impStackTop().val; + + // We can only handle known valid pointers here since the VM crashes + // when querying invalid method addresses. + // As such, we can't handle static readonly function pointers here. + if (fptr->OperIs(GT_FTN_ADDR)) + { + // Ldftn should never point to a method from another unloadable context + replacementMethod = fptr->AsFptrVal()->gtFptrMethod; + } + else + { + JITDUMP("impImportCall failed to import calli as call - address node not found\n"); + } + } + else + { + JITDUMP("\n\nimpImportCall failed to import calli as call - call conv %u is not managed\n", + originalSig.getCallConv()); + } + } + else if (optimizedOrInstrumented && callInfo->methodFlags & CORINFO_FLG_DELEGATE_INVOKE) + { + JITDUMP("\n\nimpImportCall trying to transform delegate - checking delegate call\n"); + + CORINFO_CLASS_HANDLE delegateClass = info.compCompHnd->getMethodClass(callInfo->hMethod); + info.compCompHnd->getMethodSig(callInfo->hMethod, &originalSig, delegateClass); + + // TODO-Perf: Add an importer forward substitution to handle more cases here. + GenTree* instance = impStackTop(originalSig.numArgs).val; + bool pinned = false; + void* object = nullptr; + + if (instance->IsIconHandle(GTF_ICON_OBJ_HDL)) + { + // Frozen delegates should never point to collectible contexts. + pinned = true; + object = (void*)instance->AsIntCon()->gtIconVal; + JITDUMP("impImportCall trying to transform delegate - found frozen\n"); + } + else if (instance->OperIs(GT_IND)) + { + GenTree* address = instance->AsIndir()->gtOp1; + if (address->IsIconHandle(GTF_ICON_CONST_PTR)) + { + // Const static addresses only exist in non-unloadable contexts, + // such context will keep the delegate permanently alive so even + // if it points to an unloadable method, we can still handle it safely. + // This lets us inline DynamicMethods. + object = (void*)address->AsIntCon()->gtIconVal; + JITDUMP("impImportCall trying to transform delegate - found static readonly\n"); + } + } + // TODO-Perf: Handle unloadable delegates in same context. + + if (object != nullptr) + { + JITDUMP("impImportCall trying to transform delegate - found delegate at 0x%llx, pinned: %d\n", object, pinned ? 1 : 0); + replacementMethod = info.compCompHnd->getMethodFromDelegate(object, pinned); + + if (replacementMethod != NO_METHOD_HANDLE) + { + firstArgPos = (int)(stackState.esStackDepth - originalSig.numArgs); + assert(firstArgPos >= 0); + newThis = + gtNewIndir(TYP_REF, + gtNewOperNode(GT_ADD, TYP_BYREF, instance, + gtNewIconNode(eeGetEEInfo()->offsetOfDelegateFirstTarget, TYP_I_IMPL)), + GTF_IND_INVARIANT | GTF_IND_NONNULL | GTF_IND_NONFAULTING); + } + } + } + + if (replacementMethod != NO_METHOD_HANDLE) + { + JITDUMP("impImportCall trying to transform call - found target method %s\n", + eeGetMethodName(replacementMethod)); + CORINFO_SIG_INFO methodSig; + CORINFO_CLASS_HANDLE targetClass = info.compCompHnd->getMethodClass(replacementMethod); + info.compCompHnd->getMethodSig(replacementMethod, &methodSig, targetClass); + + bool removeInstance = false; + unsigned replacementFlags = info.compCompHnd->getMethodAttribs(replacementMethod); + + if ((replacementFlags & CORINFO_FLG_PINVOKE) != 0) + { + JITDUMP("impImportCall aborting transformation - found PInvoke\n"); + } + else if (methodSig.hasImplicitThis() && eeIsValueClass(targetClass)) + { + JITDUMP("impImportCall aborting transformation - valuetype instance methods are not supported\n"); + } + else if (!impCanSubstituteSig(&originalSig, &methodSig, &removeInstance)) + { + JITDUMP("impImportCall aborting transformation - incompatible signature\n"); + } + else if (removeInstance && firstArgPos < 0) + { + JITDUMP("impImportCall aborting transformation - invalid function pointer\n"); + } + else + { + if (firstArgPos >= 0) + { + // check if we are at a valid position and + // had a valid delegate instance beforehand. + assert(&stackState.esStack[firstArgPos - 1] >= stackState.esStack); + assert(stackState.esStack[firstArgPos - 1].seTypeInfo.GetType() == TYP_REF); + assert(newThis->TypeGet() == TYP_REF); + assert(removeInstance || !eeIsValueClass(targetClass)); + } + + if (removeInstance || firstArgPos < 0) + { + // shift args if needed + if (firstArgPos > 0) + { + memmove(&stackState.esStack[firstArgPos - 1], &stackState.esStack[firstArgPos], + (stackState.esStackDepth - firstArgPos) * sizeof(StackEntry)); + } + // we can just pop the top arg after shifting + impPopStack(); + } + else + { + // replace delegate instance with the new this + stackState.esStack[firstArgPos - 1].seTypeInfo = typeInfo(targetClass); + stackState.esStack[firstArgPos - 1].val = newThis; + } + + JITDUMP("impImportCall transforming call\n"); + + // we need to update the token and info to the real method + pResolvedToken->tokenContext = impTokenLookupContextHandle; + pResolvedToken->tokenScope = info.compScopeHnd; + pResolvedToken->token = methodSig.token; + pResolvedToken->tokenType = CORINFO_TOKENKIND_Method; + pResolvedToken->hMethod = replacementMethod; + pResolvedToken->hClass = targetClass; + + eeGetCallInfo(pResolvedToken, nullptr, CORINFO_CALLINFO_ALLOWINSTPARAM, callInfo); + callInfo->sig = methodSig; + callInfo->hMethod = replacementMethod; + callInfo->methodFlags = replacementFlags; + callInfo->classFlags = info.compCompHnd->getClassAttribs(targetClass); + callInfo->nullInstanceCheck = false; + callInfo->accessAllowed = CORINFO_ACCESS_ALLOWED; + + return impImportCall(CEE_CALL, pResolvedToken, nullptr, nullptr, prefixFlags, callInfo, rawILOffset); + } + } - callRetTyp = JITtype2varType(calliSig.retType); + /*------------------------------------------------------------------------- + * First create the call node + */ - call = impImportIndirectCall(&calliSig, di); + if (opcode == CEE_CALLI) + { + callRetTyp = JITtype2varType(originalSig.retType); + + call = impImportIndirectCall(&originalSig, di); // We don't know the target method, so we have to infer the flags, or // assume the worst-case. - mflags = (calliSig.callConv & CORINFO_CALLCONV_HASTHIS) ? 0 : CORINFO_FLG_STATIC; + mflags = (originalSig.callConv & CORINFO_CALLCONV_HASTHIS) ? 0 : CORINFO_FLG_STATIC; #ifdef DEBUG if (verbose) { - unsigned structSize = (callRetTyp == TYP_STRUCT) ? eeTryGetClassSize(calliSig.retTypeSigClass) : 0; + unsigned structSize = (callRetTyp == TYP_STRUCT) ? eeTryGetClassSize(originalSig.retTypeSigClass) : 0; printf("\nIn Compiler::impImportCall: opcode is %s, kind=%d, callRetType is %s, structSize is %u\n", opcodeNames[opcode], callInfo->kind, varTypeName(callRetTyp), structSize); } #endif - sig = &calliSig; + sig = &originalSig; } else // (opcode != CEE_CALLI) { @@ -1927,6 +2096,129 @@ GenTree* Compiler::impFixupCallStructReturn(GenTreeCall* call, CORINFO_CLASS_HAN #endif // FEATURE_MULTIREG_RET } +//----------------------------------------------------------------------------------- +// impCanSubstituteSig: Checks whether it's safe to replace a call with another one. +// This DOES NOT check if the calls are actually compatible, it only checks if their trees are. +// Use ONLY when code will call the method with target sig anyway. +// +// Arguments: +// sourceSig - original call signature +// targetSig - new call signature +// removeInstance - is removal of original instance needed +// +// Return Value: +// Whether it's safe to change the IR to call the target method +// +bool Compiler::impCanSubstituteSig(CORINFO_SIG_INFO* sourceSig, + CORINFO_SIG_INFO* targetSig, bool* removeInstance) +{ + if (sourceSig->getCallConv() != targetSig->getCallConv()) + { + JITDUMP("impCanSubstituteSig returning false - call conv %u != %u\n", sourceSig->callConv, targetSig->callConv); + return false; + } + + bool removedInstance = false; + + unsigned sourceArgCount = sourceSig->totalILArgs(); + unsigned targetArgCount = targetSig->totalILArgs(); + if ((sourceArgCount == targetArgCount + 1) && sourceSig->hasImplicitThis()) + { + removedInstance = true; + sourceArgCount--; + } + else if (sourceArgCount != targetArgCount) + { + JITDUMP("impCanSubstituteSig returning false - args count %u != %u\n", sourceArgCount, + targetSig->totalILArgs()); + return false; + } + + if (sourceSig->retType != targetSig->retType) + { + JITDUMP("impCanSubstituteSig returning false - return type %u != %u\n", (unsigned)sourceSig->retType, + (unsigned)targetSig->retType); + return false; + } + + if (sourceSig->retType == CORINFO_TYPE_VALUECLASS || sourceSig->retType == CORINFO_TYPE_REFANY) + { + ClassLayout* layoutRetSource = typGetObjLayout(sourceSig->retTypeClass); + ClassLayout* layoutRetTarget = typGetObjLayout(targetSig->retTypeClass); + + if (!ClassLayout::AreCompatible(layoutRetSource, layoutRetTarget)) + { + JITDUMP("impCanSubstituteSig returning false - return type %s is incompatible with %s\n", + eeGetClassName(targetSig->retTypeClass), eeGetClassName(sourceSig->retTypeClass)); + return false; + } + } + + CORINFO_ARG_LIST_HANDLE sourceArg = sourceSig->args; + CORINFO_ARG_LIST_HANDLE targetArg = targetSig->args; + + assert(targetArgCount == sourceArgCount); + for (unsigned i = 0; i < targetArgCount; i++) + { + var_types sourceType; + var_types targetType; + + ClassLayout* sourceLayout = nullptr; + ClassLayout* targetLayout = nullptr; + if (i == 0 && !removeInstance && sourceSig->hasImplicitThis()) + { + // assume ref type on implicit this + sourceType = TYP_REF; + } + else + { + sourceType = eeGetArgType(sourceArg, sourceSig); + if (varTypeIsStruct(sourceType)) + { + CORINFO_CLASS_HANDLE sourceClassHnd = NO_CLASS_HANDLE; + info.compCompHnd->getArgType(sourceSig, sourceArg, &sourceClassHnd); + sourceLayout = typGetObjLayout(sourceClassHnd); + } + sourceArg = info.compCompHnd->getArgNext(sourceArg); + } + + if (i == 0 && targetSig->hasImplicitThis()) + { + // assume ref type on implicit this + targetType = TYP_REF; + } + else + { + targetType = eeGetArgType(targetArg, targetSig); + if (varTypeIsStruct(targetType)) + { + CORINFO_CLASS_HANDLE targetClassHnd = NO_CLASS_HANDLE; + info.compCompHnd->getArgType(targetSig, targetArg, &targetClassHnd); + targetLayout = typGetObjLayout(targetClassHnd); + } + targetArg = info.compCompHnd->getArgNext(targetArg); + } + + if (sourceType != targetType) + { + JITDUMP("impCanSubstituteSig returning false - parameter %u type %s != %s\n", i, varTypeName(sourceType), + varTypeName(targetType)); + return false; + } + + assert((sourceLayout == nullptr) == (targetLayout == nullptr)); + if ((sourceLayout != nullptr) && !ClassLayout::AreCompatible(sourceLayout, targetLayout)) + { + JITDUMP("impCanSubstituteSig returning false - parameter %u type %s is incompatible with %s\n", i, + varTypeName(sourceType), varTypeName(targetType)); + return false; + } + } + + *removeInstance = removedInstance; + return true; +} + GenTreeCall* Compiler::impImportIndirectCall(CORINFO_SIG_INFO* sig, const DebugInfo& di) { var_types callRetTyp = JITtype2varType(sig->retType); diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 08e0e5df8e8fd0..da6be5173165ea 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -2809,6 +2809,19 @@ private CorInfoInitClassResult initClass(CORINFO_FIELD_STRUCT_* field, CORINFO_M } } +#pragma warning disable CA1822 // Mark members as static + private CORINFO_METHOD_STRUCT_* getMethodFromDelegate(void* address, bool pinned) +#pragma warning restore CA1822 // Mark members as static + { + Debug.Assert(address != null); + + // it should be impossible to see unpinned delegates during AOT + Debug.Assert(pinned); + + // TODO-Perf: implement this for NativeAOT + return null; + } + private CorInfoType getTypeForPrimitiveValueClass(CORINFO_CLASS_STRUCT_* cls) { var type = HandleToObject(cls); diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index ddf080c72b4457..3e48cbb430c3f9 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -1150,6 +1150,21 @@ private static void _classMustBeLoadedBeforeCodeIsRun(IntPtr thisHandle, IntPtr* } } + [UnmanagedCallersOnly] + private static CORINFO_METHOD_STRUCT_* _getMethodFromDelegate(IntPtr thisHandle, IntPtr* ppException, void* address, byte pinned) + { + var _this = GetThis(thisHandle); + try + { + return _this.getMethodFromDelegate(address, pinned != 0); + } + catch (Exception ex) + { + *ppException = _this.AllocException(ex); + return default; + } + } + [UnmanagedCallersOnly] private static CorInfoType _getTypeForPrimitiveValueClass(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls) { @@ -2638,7 +2653,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)&_notifyMethodInfoUsage; @@ -2717,107 +2732,108 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[74] = (delegate* unmanaged)&_initClass; callbacks[75] = (delegate* unmanaged)&_classMustBeLoadedBeforeCodeIsRun; callbacks[76] = (delegate* unmanaged)&_getBuiltinClass; - callbacks[77] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; - callbacks[78] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; - callbacks[79] = (delegate* unmanaged)&_canCast; - callbacks[80] = (delegate* unmanaged)&_compareTypesForCast; - callbacks[81] = (delegate* unmanaged)&_compareTypesForEquality; - callbacks[82] = (delegate* unmanaged)&_isMoreSpecificType; - callbacks[83] = (delegate* unmanaged)&_isExactType; - callbacks[84] = (delegate* unmanaged)&_isGenericType; - callbacks[85] = (delegate* unmanaged)&_isNullableType; - callbacks[86] = (delegate* unmanaged)&_isEnum; - callbacks[87] = (delegate* unmanaged)&_getParentType; - callbacks[88] = (delegate* unmanaged)&_getChildType; - callbacks[89] = (delegate* unmanaged)&_isSDArray; - callbacks[90] = (delegate* unmanaged)&_getArrayRank; - callbacks[91] = (delegate* unmanaged)&_getArrayIntrinsicID; - callbacks[92] = (delegate* unmanaged)&_getArrayInitializationData; - callbacks[93] = (delegate* unmanaged)&_canAccessClass; - callbacks[94] = (delegate* unmanaged)&_printFieldName; - callbacks[95] = (delegate* unmanaged)&_getFieldClass; - callbacks[96] = (delegate* unmanaged)&_getFieldType; - callbacks[97] = (delegate* unmanaged)&_getFieldOffset; - callbacks[98] = (delegate* unmanaged)&_getFieldInfo; - callbacks[99] = (delegate* unmanaged)&_getThreadLocalFieldInfo; - callbacks[100] = (delegate* unmanaged)&_getThreadLocalStaticBlocksInfo; - callbacks[101] = (delegate* unmanaged)&_getThreadLocalStaticInfo_NativeAOT; - callbacks[102] = (delegate* unmanaged)&_isFieldStatic; - callbacks[103] = (delegate* unmanaged)&_getArrayOrStringLength; - callbacks[104] = (delegate* unmanaged)&_getBoundaries; - callbacks[105] = (delegate* unmanaged)&_setBoundaries; - callbacks[106] = (delegate* unmanaged)&_getVars; - callbacks[107] = (delegate* unmanaged)&_setVars; - callbacks[108] = (delegate* unmanaged)&_reportRichMappings; - callbacks[109] = (delegate* unmanaged)&_reportMetadata; - callbacks[110] = (delegate* unmanaged)&_allocateArray; - callbacks[111] = (delegate* unmanaged)&_freeArray; - callbacks[112] = (delegate* unmanaged)&_getArgNext; - callbacks[113] = (delegate* unmanaged)&_getArgType; - callbacks[114] = (delegate* unmanaged)&_getExactClasses; - callbacks[115] = (delegate* unmanaged)&_getArgClass; - callbacks[116] = (delegate* unmanaged)&_getHFAType; - callbacks[117] = (delegate* unmanaged)&_runWithErrorTrap; - callbacks[118] = (delegate* unmanaged)&_runWithSPMIErrorTrap; - callbacks[119] = (delegate* unmanaged)&_getEEInfo; - callbacks[120] = (delegate* unmanaged)&_getJitTimeLogFilename; - callbacks[121] = (delegate* unmanaged)&_getMethodDefFromMethod; - callbacks[122] = (delegate* unmanaged)&_printMethodName; - callbacks[123] = (delegate* unmanaged)&_getMethodNameFromMetadata; - callbacks[124] = (delegate* unmanaged)&_getMethodHash; - callbacks[125] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; - callbacks[126] = (delegate* unmanaged)&_getSwiftLowering; - callbacks[127] = (delegate* unmanaged)&_getFpStructLowering; - callbacks[128] = (delegate* unmanaged)&_getThreadTLSIndex; - callbacks[129] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; - callbacks[130] = (delegate* unmanaged)&_getHelperFtn; - callbacks[131] = (delegate* unmanaged)&_getFunctionEntryPoint; - callbacks[132] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; - callbacks[133] = (delegate* unmanaged)&_getMethodSync; - callbacks[134] = (delegate* unmanaged)&_getLazyStringLiteralHelper; - callbacks[135] = (delegate* unmanaged)&_embedModuleHandle; - callbacks[136] = (delegate* unmanaged)&_embedClassHandle; - callbacks[137] = (delegate* unmanaged)&_embedMethodHandle; - callbacks[138] = (delegate* unmanaged)&_embedFieldHandle; - callbacks[139] = (delegate* unmanaged)&_embedGenericHandle; - callbacks[140] = (delegate* unmanaged)&_getLocationOfThisType; - callbacks[141] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; - callbacks[142] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; - callbacks[143] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; - callbacks[144] = (delegate* unmanaged)&_getJustMyCodeHandle; - callbacks[145] = (delegate* unmanaged)&_GetProfilingHandle; - callbacks[146] = (delegate* unmanaged)&_getCallInfo; - callbacks[147] = (delegate* unmanaged)&_getStaticFieldContent; - callbacks[148] = (delegate* unmanaged)&_getObjectContent; - callbacks[149] = (delegate* unmanaged)&_getStaticFieldCurrentClass; - callbacks[150] = (delegate* unmanaged)&_getVarArgsHandle; - callbacks[151] = (delegate* unmanaged)&_canGetVarArgsHandle; - callbacks[152] = (delegate* unmanaged)&_constructStringLiteral; - callbacks[153] = (delegate* unmanaged)&_emptyStringLiteral; - callbacks[154] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; - callbacks[155] = (delegate* unmanaged)&_GetDelegateCtor; - callbacks[156] = (delegate* unmanaged)&_MethodCompileComplete; - callbacks[157] = (delegate* unmanaged)&_getTailCallHelpers; - callbacks[158] = (delegate* unmanaged)&_convertPInvokeCalliToCall; - callbacks[159] = (delegate* unmanaged)&_notifyInstructionSetUsage; - callbacks[160] = (delegate* unmanaged)&_updateEntryPointForTailCall; - callbacks[161] = (delegate* unmanaged)&_allocMem; - callbacks[162] = (delegate* unmanaged)&_reserveUnwindInfo; - callbacks[163] = (delegate* unmanaged)&_allocUnwindInfo; - callbacks[164] = (delegate* unmanaged)&_allocGCInfo; - callbacks[165] = (delegate* unmanaged)&_setEHcount; - callbacks[166] = (delegate* unmanaged)&_setEHinfo; - callbacks[167] = (delegate* unmanaged)&_logMsg; - callbacks[168] = (delegate* unmanaged)&_doAssert; - callbacks[169] = (delegate* unmanaged)&_reportFatalError; - callbacks[170] = (delegate* unmanaged)&_getPgoInstrumentationResults; - callbacks[171] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; - callbacks[172] = (delegate* unmanaged)&_recordCallSite; - callbacks[173] = (delegate* unmanaged)&_recordRelocation; - callbacks[174] = (delegate* unmanaged)&_getRelocTypeHint; - callbacks[175] = (delegate* unmanaged)&_getExpectedTargetArchitecture; - callbacks[176] = (delegate* unmanaged)&_getJitFlags; - callbacks[177] = (delegate* unmanaged)&_getSpecialCopyHelper; + callbacks[77] = (delegate* unmanaged)&_getMethodFromDelegate; + callbacks[78] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; + callbacks[79] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; + callbacks[80] = (delegate* unmanaged)&_canCast; + callbacks[81] = (delegate* unmanaged)&_compareTypesForCast; + callbacks[82] = (delegate* unmanaged)&_compareTypesForEquality; + callbacks[83] = (delegate* unmanaged)&_isMoreSpecificType; + callbacks[84] = (delegate* unmanaged)&_isExactType; + callbacks[85] = (delegate* unmanaged)&_isGenericType; + callbacks[86] = (delegate* unmanaged)&_isNullableType; + callbacks[87] = (delegate* unmanaged)&_isEnum; + callbacks[88] = (delegate* unmanaged)&_getParentType; + callbacks[89] = (delegate* unmanaged)&_getChildType; + callbacks[90] = (delegate* unmanaged)&_isSDArray; + callbacks[91] = (delegate* unmanaged)&_getArrayRank; + callbacks[92] = (delegate* unmanaged)&_getArrayIntrinsicID; + callbacks[93] = (delegate* unmanaged)&_getArrayInitializationData; + callbacks[94] = (delegate* unmanaged)&_canAccessClass; + callbacks[95] = (delegate* unmanaged)&_printFieldName; + callbacks[96] = (delegate* unmanaged)&_getFieldClass; + callbacks[97] = (delegate* unmanaged)&_getFieldType; + callbacks[98] = (delegate* unmanaged)&_getFieldOffset; + callbacks[99] = (delegate* unmanaged)&_getFieldInfo; + callbacks[100] = (delegate* unmanaged)&_getThreadLocalFieldInfo; + callbacks[101] = (delegate* unmanaged)&_getThreadLocalStaticBlocksInfo; + callbacks[102] = (delegate* unmanaged)&_getThreadLocalStaticInfo_NativeAOT; + callbacks[103] = (delegate* unmanaged)&_isFieldStatic; + callbacks[104] = (delegate* unmanaged)&_getArrayOrStringLength; + callbacks[105] = (delegate* unmanaged)&_getBoundaries; + callbacks[106] = (delegate* unmanaged)&_setBoundaries; + callbacks[107] = (delegate* unmanaged)&_getVars; + callbacks[108] = (delegate* unmanaged)&_setVars; + callbacks[109] = (delegate* unmanaged)&_reportRichMappings; + callbacks[110] = (delegate* unmanaged)&_reportMetadata; + callbacks[111] = (delegate* unmanaged)&_allocateArray; + callbacks[112] = (delegate* unmanaged)&_freeArray; + callbacks[113] = (delegate* unmanaged)&_getArgNext; + callbacks[114] = (delegate* unmanaged)&_getArgType; + callbacks[115] = (delegate* unmanaged)&_getExactClasses; + callbacks[116] = (delegate* unmanaged)&_getArgClass; + callbacks[117] = (delegate* unmanaged)&_getHFAType; + callbacks[118] = (delegate* unmanaged)&_runWithErrorTrap; + callbacks[119] = (delegate* unmanaged)&_runWithSPMIErrorTrap; + callbacks[120] = (delegate* unmanaged)&_getEEInfo; + callbacks[121] = (delegate* unmanaged)&_getJitTimeLogFilename; + callbacks[122] = (delegate* unmanaged)&_getMethodDefFromMethod; + callbacks[123] = (delegate* unmanaged)&_printMethodName; + callbacks[124] = (delegate* unmanaged)&_getMethodNameFromMetadata; + callbacks[125] = (delegate* unmanaged)&_getMethodHash; + callbacks[126] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; + callbacks[127] = (delegate* unmanaged)&_getSwiftLowering; + callbacks[128] = (delegate* unmanaged)&_getFpStructLowering; + callbacks[129] = (delegate* unmanaged)&_getThreadTLSIndex; + callbacks[130] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; + callbacks[131] = (delegate* unmanaged)&_getHelperFtn; + callbacks[132] = (delegate* unmanaged)&_getFunctionEntryPoint; + callbacks[133] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; + callbacks[134] = (delegate* unmanaged)&_getMethodSync; + callbacks[135] = (delegate* unmanaged)&_getLazyStringLiteralHelper; + callbacks[136] = (delegate* unmanaged)&_embedModuleHandle; + callbacks[137] = (delegate* unmanaged)&_embedClassHandle; + callbacks[138] = (delegate* unmanaged)&_embedMethodHandle; + callbacks[139] = (delegate* unmanaged)&_embedFieldHandle; + callbacks[140] = (delegate* unmanaged)&_embedGenericHandle; + callbacks[141] = (delegate* unmanaged)&_getLocationOfThisType; + callbacks[142] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; + callbacks[143] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; + callbacks[144] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; + callbacks[145] = (delegate* unmanaged)&_getJustMyCodeHandle; + callbacks[146] = (delegate* unmanaged)&_GetProfilingHandle; + callbacks[147] = (delegate* unmanaged)&_getCallInfo; + callbacks[148] = (delegate* unmanaged)&_getStaticFieldContent; + callbacks[149] = (delegate* unmanaged)&_getObjectContent; + callbacks[150] = (delegate* unmanaged)&_getStaticFieldCurrentClass; + callbacks[151] = (delegate* unmanaged)&_getVarArgsHandle; + callbacks[152] = (delegate* unmanaged)&_canGetVarArgsHandle; + callbacks[153] = (delegate* unmanaged)&_constructStringLiteral; + callbacks[154] = (delegate* unmanaged)&_emptyStringLiteral; + callbacks[155] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; + callbacks[156] = (delegate* unmanaged)&_GetDelegateCtor; + callbacks[157] = (delegate* unmanaged)&_MethodCompileComplete; + callbacks[158] = (delegate* unmanaged)&_getTailCallHelpers; + callbacks[159] = (delegate* unmanaged)&_convertPInvokeCalliToCall; + callbacks[160] = (delegate* unmanaged)&_notifyInstructionSetUsage; + callbacks[161] = (delegate* unmanaged)&_updateEntryPointForTailCall; + callbacks[162] = (delegate* unmanaged)&_allocMem; + callbacks[163] = (delegate* unmanaged)&_reserveUnwindInfo; + callbacks[164] = (delegate* unmanaged)&_allocUnwindInfo; + callbacks[165] = (delegate* unmanaged)&_allocGCInfo; + callbacks[166] = (delegate* unmanaged)&_setEHcount; + callbacks[167] = (delegate* unmanaged)&_setEHinfo; + callbacks[168] = (delegate* unmanaged)&_logMsg; + callbacks[169] = (delegate* unmanaged)&_doAssert; + callbacks[170] = (delegate* unmanaged)&_reportFatalError; + callbacks[171] = (delegate* unmanaged)&_getPgoInstrumentationResults; + callbacks[172] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; + callbacks[173] = (delegate* unmanaged)&_recordCallSite; + callbacks[174] = (delegate* unmanaged)&_recordRelocation; + callbacks[175] = (delegate* unmanaged)&_getRelocTypeHint; + callbacks[176] = (delegate* unmanaged)&_getExpectedTargetArchitecture; + callbacks[177] = (delegate* unmanaged)&_getJitFlags; + callbacks[178] = (delegate* unmanaged)&_getSpecialCopyHelper; return (IntPtr)callbacks; } diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index f964d4d4a22d42..732fd16742f757 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -241,6 +241,7 @@ FUNCTIONS CorInfoInitClassResult initClass(CORINFO_FIELD_HANDLE field, CORINFO_METHOD_HANDLE method, CORINFO_CONTEXT_HANDLE context) void classMustBeLoadedBeforeCodeIsRun(CORINFO_CLASS_HANDLE cls) CORINFO_CLASS_HANDLE getBuiltinClass(CorInfoClassId classId) + CORINFO_METHOD_HANDLE getMethodFromDelegate(void* address, bool pinned) CorInfoType getTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls) CorInfoType getTypeForPrimitiveNumericClass(CORINFO_CLASS_HANDLE cls) bool canCast(CORINFO_CLASS_HANDLE child, CORINFO_CLASS_HANDLE parent) diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h index 356920821be8ae..4e413c23e657c6 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h @@ -88,6 +88,7 @@ struct JitInterfaceCallbacks CorInfoInitClassResult (* initClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, CORINFO_METHOD_HANDLE method, CORINFO_CONTEXT_HANDLE context); void (* classMustBeLoadedBeforeCodeIsRun)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); CORINFO_CLASS_HANDLE (* getBuiltinClass)(void * thisHandle, CorInfoExceptionClass** ppException, CorInfoClassId classId); + CORINFO_METHOD_HANDLE (* getMethodFromDelegate)(void * thisHandle, CorInfoExceptionClass** ppException, void* address, bool pinned); CorInfoType (* getTypeForPrimitiveValueClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); CorInfoType (* getTypeForPrimitiveNumericClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); bool (* canCast)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE child, CORINFO_CLASS_HANDLE parent); @@ -957,6 +958,16 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } + virtual CORINFO_METHOD_HANDLE getMethodFromDelegate( + void* address, + bool pinned) +{ + CorInfoExceptionClass* pException = nullptr; + CORINFO_METHOD_HANDLE temp = _callbacks->getMethodFromDelegate(_thisHandle, &pException, address, pinned); + if (pException != nullptr) throw pException; + return temp; +} + virtual CorInfoType getTypeForPrimitiveValueClass( CORINFO_CLASS_HANDLE cls) { diff --git a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h index b1a9ee644077fe..3ef6f19e65bb00 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -136,6 +136,7 @@ LWM(GetThreadTLSIndex, DWORD, DLD) LWM(GetTokenTypeAsHandle, GetTokenTypeAsHandleValue, DWORDLONG) LWM(GetTypeForBox, DWORDLONG, DWORDLONG) LWM(GetTypeForBoxOnStack, DWORDLONG, DWORDLONG) +LWM(GetMethodFromDelegate, DLD, DWORDLONG) LWM(GetTypeForPrimitiveValueClass, DWORDLONG, DWORD) LWM(GetTypeForPrimitiveNumericClass, DWORDLONG, DWORD) LWM(GetUnboxedEntry, DWORDLONG, DLD); diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index c54241ef46b536..37d30b2bdf4227 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -1987,6 +1987,38 @@ CORINFO_CLASS_HANDLE MethodContext::repGetBuiltinClass(CorInfoClassId classId) return result; } +void MethodContext::recGetMethodFromDelegate(void* address, bool pinned, CORINFO_METHOD_HANDLE method) +{ + if (GetMethodFromDelegate == nullptr) + GetMethodFromDelegate = new LightWeightMap(); + + DLD key; + ZeroMemory(&key, sizeof(key)); + key.A = (DWORDLONG)address; + key.B = pinned ? 1 : 0; + + DWORDLONG value = CastHandle(method); + + GetMethodFromDelegate->Add(key, value); + DEBUG_REC(dmpGetMethodFromDelegate(key, value)); +} +void MethodContext::dmpGetMethodFromDelegate(DLD key, DWORDLONG value) +{ + printf("GetMethodFromDelegate key address-%llx pinned-%u, value method-%llx", + key.A, key.B, value); +} +CORINFO_METHOD_HANDLE MethodContext::repGetMethodFromDelegate(void* address, bool pinned) +{ + DLD key; + ZeroMemory(&key, sizeof(key)); + key.A = (DWORDLONG)address; + key.B = pinned ? 1 : 0; + + DWORDLONG value = LookupByKeyOrMiss(GetMethodFromDelegate, key, ": key address-%llx pinned-%u", key.A, key.B); + DEBUG_REP(dmpGetMethodFromDelegate(key, value)); + return (CORINFO_METHOD_HANDLE)value; +} + void MethodContext::recGetTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls, CorInfoType result) { if (GetTypeForPrimitiveValueClass == nullptr) @@ -4589,7 +4621,7 @@ size_t MethodContext::repGetClassModuleIdForStatics(CORINFO_CLASS_HANDLE cls, DWORDLONG key = CastHandle(cls); Agnostic_GetClassModuleIdForStatics value = LookupByKeyOrMiss(GetClassModuleIdForStatics, key, ": key %016" PRIX64 "", key); - DEBUG_REP(dmpGetClassModuleIdForStatics(key, value)); + DEBUG_REP(dmpGetClassModuleIdForStatics(key, value)); if (pModule != nullptr) *pModule = (CORINFO_MODULE_HANDLE)value.Module; @@ -4689,7 +4721,7 @@ DWORD MethodContext::repGetThreadTLSIndex(void** ppIndirection) { DLD value = LookupByKeyOrMissNoMessage(GetThreadTLSIndex, 0); - DEBUG_REP(dmpGetThreadTLSIndex(0, value)); + DEBUG_REP(dmpGetThreadTLSIndex(0, value)); if (ppIndirection != nullptr) *ppIndirection = (void*)value.A; @@ -4814,7 +4846,7 @@ void MethodContext::repGetLocationOfThisType(CORINFO_METHOD_HANDLE context, CORI { DWORDLONG key = CastHandle(context); Agnostic_CORINFO_LOOKUP_KIND value = LookupByKeyOrMiss(GetLocationOfThisType, key, ": key %016" PRIX64 "", key); - DEBUG_REP(dmpGetLocationOfThisType(key, value)); + DEBUG_REP(dmpGetLocationOfThisType(key, value)); *pLookupKind = SpmiRecordsHelper::RestoreCORINFO_LOOKUP_KIND(value); } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index 109d3ba9854fc3..1b97242d1606ae 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -254,6 +254,10 @@ class MethodContext void dmpGetBuiltinClass(DWORD key, DWORDLONG value); CORINFO_CLASS_HANDLE repGetBuiltinClass(CorInfoClassId classId); + void recGetMethodFromDelegate(void* address, bool pinned, CORINFO_METHOD_HANDLE method); + void dmpGetMethodFromDelegate(DLD key, DWORDLONG value); + CORINFO_METHOD_HANDLE repGetMethodFromDelegate(void* address, bool pinned); + void recGetTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls, CorInfoType result); void dmpGetTypeForPrimitiveValueClass(DWORDLONG key, DWORD value); CorInfoType repGetTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls); @@ -460,13 +464,13 @@ class MethodContext void dmpGetUnboxedEntry(DWORDLONG key, DLD value); CORINFO_METHOD_HANDLE repGetUnboxedEntry(CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg); - void recGetInstantiatedEntry(CORINFO_METHOD_HANDLE ftn, + void recGetInstantiatedEntry(CORINFO_METHOD_HANDLE ftn, CORINFO_METHOD_HANDLE methodHandle, CORINFO_CLASS_HANDLE classHandle, CORINFO_METHOD_HANDLE result); void dmpGetInstantiatedEntry(DWORDLONG key, const Agnostic_GetInstantiatedEntryResult& value); - CORINFO_METHOD_HANDLE repGetInstantiatedEntry(CORINFO_METHOD_HANDLE ftn, - CORINFO_METHOD_HANDLE* methodHandle, + CORINFO_METHOD_HANDLE repGetInstantiatedEntry(CORINFO_METHOD_HANDLE ftn, + CORINFO_METHOD_HANDLE* methodHandle, CORINFO_CLASS_HANDLE* classHandle); void recGetDefaultComparerClass(CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE result); @@ -1207,6 +1211,7 @@ enum mcPackets Packet_GetSZArrayHelperEnumeratorClass = 226, Packet_GetMethodInstantiationArgument = 227, Packet_GetInstantiatedEntry = 228, + Packet_GetMethodFromDelegate = 229, }; 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 a39adab7a9bffc..958a47510e8e36 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -865,6 +865,15 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getBuiltinClass(CorInfoClassId classId) return temp; } +// returns the class handle for the special builtin classes +CORINFO_METHOD_HANDLE interceptor_ICJI::getMethodFromDelegate(void* address, bool pinned) +{ + mc->cr->AddCall("getMethodFromDelegate"); + CORINFO_METHOD_HANDLE temp = original_ICorJitInfo->getMethodFromDelegate(address, pinned); + mc->recGetMethodFromDelegate(address, pinned, temp); + return temp; +} + // "System.Int32" ==> CORINFO_TYPE_INT.. CorInfoType interceptor_ICJI::getTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls) { diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp index 1f6d8a0530b201..fda3e22fb0e8af 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp @@ -628,6 +628,14 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getBuiltinClass( return original_ICorJitInfo->getBuiltinClass(classId); } +CORINFO_METHOD_HANDLE interceptor_ICJI::getMethodFromDelegate( + void* address, + bool pinned) +{ + mcs->AddCall("getMethodFromDelegate"); + return original_ICorJitInfo->getMethodFromDelegate(address, pinned); +} + CorInfoType interceptor_ICJI::getTypeForPrimitiveValueClass( CORINFO_CLASS_HANDLE cls) { diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp index 8df26208b464fa..1cf787103c1f36 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp @@ -551,6 +551,13 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getBuiltinClass( return original_ICorJitInfo->getBuiltinClass(classId); } +CORINFO_METHOD_HANDLE interceptor_ICJI::getMethodFromDelegate( + void* address, + bool pinned) +{ + return original_ICorJitInfo->getMethodFromDelegate(address, pinned); +} + CorInfoType interceptor_ICJI::getTypeForPrimitiveValueClass( CORINFO_CLASS_HANDLE cls) { diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index c8b36d5203e0c0..4697138e39c5be 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -730,6 +730,13 @@ CORINFO_CLASS_HANDLE MyICJI::getBuiltinClass(CorInfoClassId classId) return jitInstance->mc->repGetBuiltinClass(classId); } +// returns the class handle for the special builtin classes +CORINFO_METHOD_HANDLE MyICJI::getMethodFromDelegate(void* address, bool pinned) +{ + jitInstance->mc->cr->AddCall("getMethodFromDelegate"); + return jitInstance->mc->repGetMethodFromDelegate(address, pinned); +} + // "System.Int32" ==> CORINFO_TYPE_INT.. CorInfoType MyICJI::getTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls) { diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 205c5105d5a2d8..166f4ed0b76806 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1814,8 +1814,9 @@ MethodDesc *COMDelegate::GetMethodDesc(OBJECTREF orDelegate) } CONTRACTL_END; - // If you modify this logic, please update DacDbiInterfaceImpl::GetDelegateType, DacDbiInterfaceImpl::GetDelegateType, - // DacDbiInterfaceImpl::GetDelegateFunctionData, and DacDbiInterfaceImpl::GetDelegateTargetObject. + // If you modify this logic, please update getMethodFromDelegateHelper, DacDbiInterfaceImpl::GetDelegateType, + // DacDbiInterfaceImpl::GetDelegateType, DacDbiInterfaceImpl::GetDelegateFunctionData, + // and DacDbiInterfaceImpl::GetDelegateTargetObject. MethodDesc *pMethodHandle = NULL; diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index c447ab3303faf0..3bc9c26903206c 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -3985,7 +3985,75 @@ CORINFO_CLASS_HANDLE CEEInfo::getBuiltinClass(CorInfoClassId classId) return result; } +/*********************************************************************/ +CORINFO_METHOD_HANDLE getMethodFromDelegateHelper(DelegateObject* delegate) +{ + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } CONTRACTL_END; + + // If you modify this logic, please update COMDelegate::GetMethodDesc, DacDbiInterfaceImpl::GetDelegateType, + // DacDbiInterfaceImpl::GetDelegateType, DacDbiInterfaceImpl::GetDelegateFunctionData, + // and DacDbiInterfaceImpl::GetDelegateTargetObject. + + if (delegate->GetInvocationCount() != 0) + return 0; + + PCODE code = delegate->GetMethodPtrAux(); + + if (code != (PCODE)NULL) + { + // Note that MethodTable::GetMethodDescForSlotAddress is significantly faster than Entry2MethodDesc + return (CORINFO_METHOD_HANDLE)MethodTable::GetMethodDescForSlotAddress(code); + } + + // Must be a normal delegate + code = delegate->GetMethodPtr(); + + MethodTable* pMT = NULL; + + OBJECTREF orThis = delegate->GetTarget(); + if (orThis != NULL) + { + pMT = orThis->GetMethodTable(); + } + + return (CORINFO_METHOD_HANDLE)Entry2MethodDesc(code, pMT); +} + +/*********************************************************************/ +CORINFO_METHOD_HANDLE CEEInfo::getMethodFromDelegate(void* address, bool pinned) +{ + CONTRACTL { + NOTHROW; + GC_NOTRIGGER; + MODE_PREEMPTIVE; + } CONTRACTL_END; + + CORINFO_METHOD_HANDLE result = 0; + + JIT_TO_EE_TRANSITION(); + + _ASSERTE (address != nullptr); + if (pinned) + { + // For frozen delegates we don't need to worry about the GC. + result = getMethodFromDelegateHelper((DelegateObject*)address); + } + else + { + // For normal objects in static readonlys, we need to ensure that + // the GC doesn't run while we're reading from the object. + GCX_COOP(); + result = getMethodFromDelegateHelper(*(DelegateObject**)address); + } + EE_TO_JIT_TRANSITION(); + + return result; +} /*********************************************************************/ CorInfoType CEEInfo::getTypeForPrimitiveValueClass( From 1bf83c69188dd92fd9ae7a9ebb33bde8e835794b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Petryka?= Date: Sun, 10 Nov 2024 05:08:48 +0100 Subject: [PATCH 02/12] Fix POSIX build errors --- src/coreclr/jit/importercalls.cpp | 12 ++++++------ .../tools/superpmi/superpmi-shared/methodcontext.cpp | 5 +++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 280959fa6aeed2..ab82202be0fec2 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -190,7 +190,8 @@ var_types Compiler::impImportCall(OPCODE opcode, if (object != nullptr) { - JITDUMP("impImportCall trying to transform delegate - found delegate at 0x%llx, pinned: %d\n", object, pinned ? 1 : 0); + JITDUMP("impImportCall trying to transform delegate - found delegate at 0x%llx, pinned: %d\n", object, + pinned ? 1 : 0); replacementMethod = info.compCompHnd->getMethodFromDelegate(object, pinned); if (replacementMethod != NO_METHOD_HANDLE) @@ -200,8 +201,8 @@ var_types Compiler::impImportCall(OPCODE opcode, newThis = gtNewIndir(TYP_REF, gtNewOperNode(GT_ADD, TYP_BYREF, instance, - gtNewIconNode(eeGetEEInfo()->offsetOfDelegateFirstTarget, TYP_I_IMPL)), - GTF_IND_INVARIANT | GTF_IND_NONNULL | GTF_IND_NONFAULTING); + gtNewIconNode(eeGetEEInfo()->offsetOfDelegateFirstTarget, TYP_I_IMPL)), + GTF_IND_INVARIANT | GTF_IND_NONNULL | GTF_IND_NONFAULTING); } } } @@ -2109,8 +2110,7 @@ GenTree* Compiler::impFixupCallStructReturn(GenTreeCall* call, CORINFO_CLASS_HAN // Return Value: // Whether it's safe to change the IR to call the target method // -bool Compiler::impCanSubstituteSig(CORINFO_SIG_INFO* sourceSig, - CORINFO_SIG_INFO* targetSig, bool* removeInstance) +bool Compiler::impCanSubstituteSig(CORINFO_SIG_INFO* sourceSig, CORINFO_SIG_INFO* targetSig, bool* removeInstance) { if (sourceSig->getCallConv() != targetSig->getCallConv()) { @@ -2210,7 +2210,7 @@ bool Compiler::impCanSubstituteSig(CORINFO_SIG_INFO* sourceSig, if ((sourceLayout != nullptr) && !ClassLayout::AreCompatible(sourceLayout, targetLayout)) { JITDUMP("impCanSubstituteSig returning false - parameter %u type %s is incompatible with %s\n", i, - varTypeName(sourceType), varTypeName(targetType)); + varTypeName(sourceType), varTypeName(targetType)); return false; } } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 37d30b2bdf4227..a95e51fe4c587a 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -2004,7 +2004,7 @@ void MethodContext::recGetMethodFromDelegate(void* address, bool pinned, CORINFO } void MethodContext::dmpGetMethodFromDelegate(DLD key, DWORDLONG value) { - printf("GetMethodFromDelegate key address-%llx pinned-%u, value method-%llx", + printf("GetMethodFromDelegate key address-%016" PRIX64 " pinned-%lu, value method-%016" PRIX64 "", key.A, key.B, value); } CORINFO_METHOD_HANDLE MethodContext::repGetMethodFromDelegate(void* address, bool pinned) @@ -2014,7 +2014,8 @@ CORINFO_METHOD_HANDLE MethodContext::repGetMethodFromDelegate(void* address, boo key.A = (DWORDLONG)address; key.B = pinned ? 1 : 0; - DWORDLONG value = LookupByKeyOrMiss(GetMethodFromDelegate, key, ": key address-%llx pinned-%u", key.A, key.B); + DWORDLONG value = + LookupByKeyOrMiss(GetMethodFromDelegate, key, ": key address-%016" PRIX64 " pinned-%lu", key.A, key.B); DEBUG_REP(dmpGetMethodFromDelegate(key, value)); return (CORINFO_METHOD_HANDLE)value; } From 7d956cf2dc1e4a1e599dd1f4bb37b0b109e7a07d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Petryka?= <35800402+MichalPetryka@users.noreply.github.com> Date: Sun, 10 Nov 2024 05:28:04 +0100 Subject: [PATCH 03/12] I love C long --- src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index a95e51fe4c587a..9f836410d2652f 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -2004,7 +2004,7 @@ void MethodContext::recGetMethodFromDelegate(void* address, bool pinned, CORINFO } void MethodContext::dmpGetMethodFromDelegate(DLD key, DWORDLONG value) { - printf("GetMethodFromDelegate key address-%016" PRIX64 " pinned-%lu, value method-%016" PRIX64 "", + printf("GetMethodFromDelegate key address-%016" PRIX64 " pinned-%u, value method-%016" PRIX64 "", key.A, key.B, value); } CORINFO_METHOD_HANDLE MethodContext::repGetMethodFromDelegate(void* address, bool pinned) @@ -2015,7 +2015,7 @@ CORINFO_METHOD_HANDLE MethodContext::repGetMethodFromDelegate(void* address, boo key.B = pinned ? 1 : 0; DWORDLONG value = - LookupByKeyOrMiss(GetMethodFromDelegate, key, ": key address-%016" PRIX64 " pinned-%lu", key.A, key.B); + LookupByKeyOrMiss(GetMethodFromDelegate, key, ": key address-%016" PRIX64 " pinned-%u", key.A, key.B); DEBUG_REP(dmpGetMethodFromDelegate(key, value)); return (CORINFO_METHOD_HANDLE)value; } From f712508af392c62615dae3775fc892c1c2b9a4a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Petryka?= <35800402+MichalPetryka@users.noreply.github.com> Date: Sun, 10 Nov 2024 05:39:31 +0100 Subject: [PATCH 04/12] Fix contract --- src/coreclr/vm/jitinterface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 3bc9c26903206c..924b8faa14ca44 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -3989,7 +3989,7 @@ CORINFO_CLASS_HANDLE CEEInfo::getBuiltinClass(CorInfoClassId classId) CORINFO_METHOD_HANDLE getMethodFromDelegateHelper(DelegateObject* delegate) { CONTRACTL { - NOTHROW; + THROWS; GC_NOTRIGGER; MODE_ANY; } CONTRACTL_END; @@ -4027,7 +4027,7 @@ CORINFO_METHOD_HANDLE getMethodFromDelegateHelper(DelegateObject* delegate) CORINFO_METHOD_HANDLE CEEInfo::getMethodFromDelegate(void* address, bool pinned) { CONTRACTL { - NOTHROW; + THROWS; GC_NOTRIGGER; MODE_PREEMPTIVE; } CONTRACTL_END; From aee504f861176dd5607674231bff8cd3309c56a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Petryka?= Date: Mon, 11 Nov 2024 04:40:05 +0100 Subject: [PATCH 05/12] Fix asserts --- src/coreclr/inc/corinfo.h | 2 +- src/coreclr/inc/icorjitinfoimpl_generated.h | 2 +- src/coreclr/inc/jiteeversionguid.h | 10 +-- .../jit/ICorJitInfo_wrapper_generated.hpp | 4 +- src/coreclr/jit/importercalls.cpp | 17 +++-- .../tools/Common/JitInterface/CorInfoImpl.cs | 4 +- .../JitInterface/CorInfoImpl_generated.cs | 4 +- .../ThunkGenerator/ThunkInput.txt | 2 +- .../aot/jitinterface/jitinterface_generated.h | 6 +- .../superpmi-shared/methodcontext.cpp | 12 ++-- .../superpmi/superpmi-shared/methodcontext.h | 4 +- .../superpmi-shim-collector/icorjitinfo.cpp | 6 +- .../icorjitinfo_generated.cpp | 4 +- .../icorjitinfo_generated.cpp | 4 +- .../tools/superpmi/superpmi/icorjitinfo.cpp | 4 +- src/coreclr/vm/comdelegate.cpp | 5 +- src/coreclr/vm/jitinterface.cpp | 71 ++++++------------- 17 files changed, 66 insertions(+), 95 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index bef324643a857c..53b80beac13a3d 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -2614,7 +2614,7 @@ class ICorStaticInfo // returns the class handle for the special builtin classes virtual CORINFO_METHOD_HANDLE getMethodFromDelegate ( void* address, - bool pinned + bool indirect ) = 0; // "System.Int32" ==> CORINFO_TYPE_INT.. diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 7b4f43f5ed02d0..3794fde144ffc1 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -331,7 +331,7 @@ CORINFO_CLASS_HANDLE getBuiltinClass( CORINFO_METHOD_HANDLE getMethodFromDelegate( void* address, - bool pinned) override; + bool indirect) override; CorInfoType getTypeForPrimitiveValueClass( CORINFO_CLASS_HANDLE cls) override; diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index fd59df8ad8e9ab..5455d2a9c76265 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 = { /* 836ac5db-120c-4d01-9eb0-950dbe7962a2 */ - 0x836ac5db, - 0x120c, - 0x4d01, - {0x9e, 0xb0, 0x95, 0x0d, 0xbe, 0x79, 0x62, 0xa2} +constexpr GUID JITEEVersionIdentifier = { /* 6ae7037f-e94a-4d63-ba3e-869778a1197b */ + 0x6ae7037f, + 0xe94a, + 0x4d63, + {0xba, 0x3e, 0x86, 0x97, 0x78, 0xa1, 0x19, 0x7b} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp index bdd19fb95536d2..0c408c2c26f319 100644 --- a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp +++ b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp @@ -767,10 +767,10 @@ CORINFO_CLASS_HANDLE WrapICorJitInfo::getBuiltinClass( CORINFO_METHOD_HANDLE WrapICorJitInfo::getMethodFromDelegate( void* address, - bool pinned) + bool indirect) { API_ENTER(getMethodFromDelegate); - CORINFO_METHOD_HANDLE temp = wrapHnd->getMethodFromDelegate(address, pinned); + CORINFO_METHOD_HANDLE temp = wrapHnd->getMethodFromDelegate(address, indirect); API_LEAVE(getMethodFromDelegate); return temp; } diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index ab82202be0fec2..6337360261c836 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -163,13 +163,12 @@ var_types Compiler::impImportCall(OPCODE opcode, // TODO-Perf: Add an importer forward substitution to handle more cases here. GenTree* instance = impStackTop(originalSig.numArgs).val; - bool pinned = false; + bool indirect = false; void* object = nullptr; if (instance->IsIconHandle(GTF_ICON_OBJ_HDL)) { // Frozen delegates should never point to collectible contexts. - pinned = true; object = (void*)instance->AsIntCon()->gtIconVal; JITDUMP("impImportCall trying to transform delegate - found frozen\n"); } @@ -182,17 +181,18 @@ var_types Compiler::impImportCall(OPCODE opcode, // such context will keep the delegate permanently alive so even // if it points to an unloadable method, we can still handle it safely. // This lets us inline DynamicMethods. + indirect = true; object = (void*)address->AsIntCon()->gtIconVal; JITDUMP("impImportCall trying to transform delegate - found static readonly\n"); } } - // TODO-Perf: Handle unloadable delegates in same context. + // TODO-Perf: Handle unloadable delegates in the same context. if (object != nullptr) { - JITDUMP("impImportCall trying to transform delegate - found delegate at 0x%llx, pinned: %d\n", object, - pinned ? 1 : 0); - replacementMethod = info.compCompHnd->getMethodFromDelegate(object, pinned); + JITDUMP("impImportCall trying to transform delegate - found delegate at 0x%llx, indirect: %d\n", object, + indirect ? 1 : 0); + replacementMethod = info.compCompHnd->getMethodFromDelegate(object, indirect); if (replacementMethod != NO_METHOD_HANDLE) { @@ -2129,8 +2129,7 @@ bool Compiler::impCanSubstituteSig(CORINFO_SIG_INFO* sourceSig, CORINFO_SIG_INFO } else if (sourceArgCount != targetArgCount) { - JITDUMP("impCanSubstituteSig returning false - args count %u != %u\n", sourceArgCount, - targetSig->totalILArgs()); + JITDUMP("impCanSubstituteSig returning false - args count %u != %u\n", sourceArgCount, targetArgCount); return false; } @@ -2165,7 +2164,7 @@ bool Compiler::impCanSubstituteSig(CORINFO_SIG_INFO* sourceSig, CORINFO_SIG_INFO ClassLayout* sourceLayout = nullptr; ClassLayout* targetLayout = nullptr; - if (i == 0 && !removeInstance && sourceSig->hasImplicitThis()) + if (i == 0 && !removedInstance && sourceSig->hasImplicitThis()) { // assume ref type on implicit this sourceType = TYP_REF; diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index da6be5173165ea..6bc48cfde24749 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -2810,13 +2810,13 @@ private CorInfoInitClassResult initClass(CORINFO_FIELD_STRUCT_* field, CORINFO_M } #pragma warning disable CA1822 // Mark members as static - private CORINFO_METHOD_STRUCT_* getMethodFromDelegate(void* address, bool pinned) + private CORINFO_METHOD_STRUCT_* getMethodFromDelegate(void* address, bool indirect) #pragma warning restore CA1822 // Mark members as static { Debug.Assert(address != null); // it should be impossible to see unpinned delegates during AOT - Debug.Assert(pinned); + Debug.Assert(!indirect); // TODO-Perf: implement this for NativeAOT return null; diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index 3e48cbb430c3f9..e24b1a3e5f4614 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -1151,12 +1151,12 @@ private static void _classMustBeLoadedBeforeCodeIsRun(IntPtr thisHandle, IntPtr* } [UnmanagedCallersOnly] - private static CORINFO_METHOD_STRUCT_* _getMethodFromDelegate(IntPtr thisHandle, IntPtr* ppException, void* address, byte pinned) + private static CORINFO_METHOD_STRUCT_* _getMethodFromDelegate(IntPtr thisHandle, IntPtr* ppException, void* address, byte indirect) { var _this = GetThis(thisHandle); try { - return _this.getMethodFromDelegate(address, pinned != 0); + return _this.getMethodFromDelegate(address, indirect != 0); } catch (Exception ex) { diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index 732fd16742f757..5ceac9ba1c276b 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -241,7 +241,7 @@ FUNCTIONS CorInfoInitClassResult initClass(CORINFO_FIELD_HANDLE field, CORINFO_METHOD_HANDLE method, CORINFO_CONTEXT_HANDLE context) void classMustBeLoadedBeforeCodeIsRun(CORINFO_CLASS_HANDLE cls) CORINFO_CLASS_HANDLE getBuiltinClass(CorInfoClassId classId) - CORINFO_METHOD_HANDLE getMethodFromDelegate(void* address, bool pinned) + CORINFO_METHOD_HANDLE getMethodFromDelegate(void* address, bool indirect) CorInfoType getTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls) CorInfoType getTypeForPrimitiveNumericClass(CORINFO_CLASS_HANDLE cls) bool canCast(CORINFO_CLASS_HANDLE child, CORINFO_CLASS_HANDLE parent) diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h index 4e413c23e657c6..9428f9cc94a917 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h @@ -88,7 +88,7 @@ struct JitInterfaceCallbacks CorInfoInitClassResult (* initClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, CORINFO_METHOD_HANDLE method, CORINFO_CONTEXT_HANDLE context); void (* classMustBeLoadedBeforeCodeIsRun)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); CORINFO_CLASS_HANDLE (* getBuiltinClass)(void * thisHandle, CorInfoExceptionClass** ppException, CorInfoClassId classId); - CORINFO_METHOD_HANDLE (* getMethodFromDelegate)(void * thisHandle, CorInfoExceptionClass** ppException, void* address, bool pinned); + CORINFO_METHOD_HANDLE (* getMethodFromDelegate)(void * thisHandle, CorInfoExceptionClass** ppException, void* address, bool indirect); CorInfoType (* getTypeForPrimitiveValueClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); CorInfoType (* getTypeForPrimitiveNumericClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); bool (* canCast)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE child, CORINFO_CLASS_HANDLE parent); @@ -960,10 +960,10 @@ class JitInterfaceWrapper : public ICorJitInfo virtual CORINFO_METHOD_HANDLE getMethodFromDelegate( void* address, - bool pinned) + bool indirect) { CorInfoExceptionClass* pException = nullptr; - CORINFO_METHOD_HANDLE temp = _callbacks->getMethodFromDelegate(_thisHandle, &pException, address, pinned); + CORINFO_METHOD_HANDLE temp = _callbacks->getMethodFromDelegate(_thisHandle, &pException, address, indirect); if (pException != nullptr) throw pException; return temp; } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 9f836410d2652f..162de936996ec3 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -1987,7 +1987,7 @@ CORINFO_CLASS_HANDLE MethodContext::repGetBuiltinClass(CorInfoClassId classId) return result; } -void MethodContext::recGetMethodFromDelegate(void* address, bool pinned, CORINFO_METHOD_HANDLE method) +void MethodContext::recGetMethodFromDelegate(void* address, bool indirect, CORINFO_METHOD_HANDLE method) { if (GetMethodFromDelegate == nullptr) GetMethodFromDelegate = new LightWeightMap(); @@ -1995,7 +1995,7 @@ void MethodContext::recGetMethodFromDelegate(void* address, bool pinned, CORINFO DLD key; ZeroMemory(&key, sizeof(key)); key.A = (DWORDLONG)address; - key.B = pinned ? 1 : 0; + key.B = indirect ? 1 : 0; DWORDLONG value = CastHandle(method); @@ -2004,18 +2004,18 @@ void MethodContext::recGetMethodFromDelegate(void* address, bool pinned, CORINFO } void MethodContext::dmpGetMethodFromDelegate(DLD key, DWORDLONG value) { - printf("GetMethodFromDelegate key address-%016" PRIX64 " pinned-%u, value method-%016" PRIX64 "", + printf("GetMethodFromDelegate key address-%016" PRIX64 " indirect-%u, value method-%016" PRIX64 "", key.A, key.B, value); } -CORINFO_METHOD_HANDLE MethodContext::repGetMethodFromDelegate(void* address, bool pinned) +CORINFO_METHOD_HANDLE MethodContext::repGetMethodFromDelegate(void* address, bool indirect) { DLD key; ZeroMemory(&key, sizeof(key)); key.A = (DWORDLONG)address; - key.B = pinned ? 1 : 0; + key.B = indirect ? 1 : 0; DWORDLONG value = - LookupByKeyOrMiss(GetMethodFromDelegate, key, ": key address-%016" PRIX64 " pinned-%u", key.A, key.B); + LookupByKeyOrMiss(GetMethodFromDelegate, key, ": key address-%016" PRIX64 " indirect-%u", key.A, key.B); DEBUG_REP(dmpGetMethodFromDelegate(key, value)); return (CORINFO_METHOD_HANDLE)value; } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index 1b97242d1606ae..0b20b46daefb64 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -254,9 +254,9 @@ class MethodContext void dmpGetBuiltinClass(DWORD key, DWORDLONG value); CORINFO_CLASS_HANDLE repGetBuiltinClass(CorInfoClassId classId); - void recGetMethodFromDelegate(void* address, bool pinned, CORINFO_METHOD_HANDLE method); + void recGetMethodFromDelegate(void* address, bool indirect, CORINFO_METHOD_HANDLE method); void dmpGetMethodFromDelegate(DLD key, DWORDLONG value); - CORINFO_METHOD_HANDLE repGetMethodFromDelegate(void* address, bool pinned); + CORINFO_METHOD_HANDLE repGetMethodFromDelegate(void* address, bool indirect); void recGetTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls, CorInfoType result); void dmpGetTypeForPrimitiveValueClass(DWORDLONG key, DWORD value); diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index 958a47510e8e36..c89a4254c614ee 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -866,11 +866,11 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getBuiltinClass(CorInfoClassId classId) } // returns the class handle for the special builtin classes -CORINFO_METHOD_HANDLE interceptor_ICJI::getMethodFromDelegate(void* address, bool pinned) +CORINFO_METHOD_HANDLE interceptor_ICJI::getMethodFromDelegate(void* address, bool indirect) { mc->cr->AddCall("getMethodFromDelegate"); - CORINFO_METHOD_HANDLE temp = original_ICorJitInfo->getMethodFromDelegate(address, pinned); - mc->recGetMethodFromDelegate(address, pinned, temp); + CORINFO_METHOD_HANDLE temp = original_ICorJitInfo->getMethodFromDelegate(address, indirect); + mc->recGetMethodFromDelegate(address, indirect, temp); return temp; } diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp index fda3e22fb0e8af..f399580bf0ca56 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp @@ -630,10 +630,10 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getBuiltinClass( CORINFO_METHOD_HANDLE interceptor_ICJI::getMethodFromDelegate( void* address, - bool pinned) + bool indirect) { mcs->AddCall("getMethodFromDelegate"); - return original_ICorJitInfo->getMethodFromDelegate(address, pinned); + return original_ICorJitInfo->getMethodFromDelegate(address, indirect); } CorInfoType interceptor_ICJI::getTypeForPrimitiveValueClass( diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp index 1cf787103c1f36..6030b75363e7e1 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp @@ -553,9 +553,9 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getBuiltinClass( CORINFO_METHOD_HANDLE interceptor_ICJI::getMethodFromDelegate( void* address, - bool pinned) + bool indirect) { - return original_ICorJitInfo->getMethodFromDelegate(address, pinned); + return original_ICorJitInfo->getMethodFromDelegate(address, indirect); } CorInfoType interceptor_ICJI::getTypeForPrimitiveValueClass( diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index 4697138e39c5be..170557103b4e2b 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -731,10 +731,10 @@ CORINFO_CLASS_HANDLE MyICJI::getBuiltinClass(CorInfoClassId classId) } // returns the class handle for the special builtin classes -CORINFO_METHOD_HANDLE MyICJI::getMethodFromDelegate(void* address, bool pinned) +CORINFO_METHOD_HANDLE MyICJI::getMethodFromDelegate(void* address, bool indirect) { jitInstance->mc->cr->AddCall("getMethodFromDelegate"); - return jitInstance->mc->repGetMethodFromDelegate(address, pinned); + return jitInstance->mc->repGetMethodFromDelegate(address, indirect); } // "System.Int32" ==> CORINFO_TYPE_INT.. diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 166f4ed0b76806..205c5105d5a2d8 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1814,9 +1814,8 @@ MethodDesc *COMDelegate::GetMethodDesc(OBJECTREF orDelegate) } CONTRACTL_END; - // If you modify this logic, please update getMethodFromDelegateHelper, DacDbiInterfaceImpl::GetDelegateType, - // DacDbiInterfaceImpl::GetDelegateType, DacDbiInterfaceImpl::GetDelegateFunctionData, - // and DacDbiInterfaceImpl::GetDelegateTargetObject. + // If you modify this logic, please update DacDbiInterfaceImpl::GetDelegateType, DacDbiInterfaceImpl::GetDelegateType, + // DacDbiInterfaceImpl::GetDelegateFunctionData, and DacDbiInterfaceImpl::GetDelegateTargetObject. MethodDesc *pMethodHandle = NULL; diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 924b8faa14ca44..95f310b70cb115 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -3986,49 +3986,11 @@ CORINFO_CLASS_HANDLE CEEInfo::getBuiltinClass(CorInfoClassId classId) } /*********************************************************************/ -CORINFO_METHOD_HANDLE getMethodFromDelegateHelper(DelegateObject* delegate) +CORINFO_METHOD_HANDLE CEEInfo::getMethodFromDelegate(void* address, bool indirect) { CONTRACTL { THROWS; - GC_NOTRIGGER; - MODE_ANY; - } CONTRACTL_END; - - // If you modify this logic, please update COMDelegate::GetMethodDesc, DacDbiInterfaceImpl::GetDelegateType, - // DacDbiInterfaceImpl::GetDelegateType, DacDbiInterfaceImpl::GetDelegateFunctionData, - // and DacDbiInterfaceImpl::GetDelegateTargetObject. - - if (delegate->GetInvocationCount() != 0) - return 0; - - PCODE code = delegate->GetMethodPtrAux(); - - if (code != (PCODE)NULL) - { - // Note that MethodTable::GetMethodDescForSlotAddress is significantly faster than Entry2MethodDesc - return (CORINFO_METHOD_HANDLE)MethodTable::GetMethodDescForSlotAddress(code); - } - - // Must be a normal delegate - code = delegate->GetMethodPtr(); - - MethodTable* pMT = NULL; - - OBJECTREF orThis = delegate->GetTarget(); - if (orThis != NULL) - { - pMT = orThis->GetMethodTable(); - } - - return (CORINFO_METHOD_HANDLE)Entry2MethodDesc(code, pMT); -} - -/*********************************************************************/ -CORINFO_METHOD_HANDLE CEEInfo::getMethodFromDelegate(void* address, bool pinned) -{ - CONTRACTL { - THROWS; - GC_NOTRIGGER; + GC_TRIGGERS; MODE_PREEMPTIVE; } CONTRACTL_END; @@ -4038,18 +4000,29 @@ CORINFO_METHOD_HANDLE CEEInfo::getMethodFromDelegate(void* address, bool pinned) _ASSERTE (address != nullptr); - if (pinned) - { - // For frozen delegates we don't need to worry about the GC. - result = getMethodFromDelegateHelper((DelegateObject*)address); - } - else { - // For normal objects in static readonlys, we need to ensure that - // the GC doesn't run while we're reading from the object. + // We get a direct pointer for frozen delegates + // and a pointer to a static location for normal ones. + // As such we need to deref the pointer if needed. + // We technically don't need to care about the GC + // for frozen delegates, but APIs used here require COOP. GCX_COOP(); - result = getMethodFromDelegateHelper(*(DelegateObject**)address); + DELEGATEREF delegate; + { + GCX_NOTRIGGER(); + delegate = (DELEGATEREF)ObjectToOBJECTREF(indirect ? + *(DelegateObject**)address : (DelegateObject*)address); + _ASSERTE (delegate != nullptr); + } + + { + GCPROTECT_BEGIN(delegate); + if (delegate->GetInvocationCount() == 0) + result = (CORINFO_METHOD_HANDLE)COMDelegate::GetMethodDesc(delegate); + GCPROTECT_END(); + } } + EE_TO_JIT_TRANSITION(); return result; From 7b9a565bda3060212949d5f3986873b52627b7b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Petryka?= Date: Mon, 11 Nov 2024 20:36:56 +0100 Subject: [PATCH 06/12] Fix asserts --- src/coreclr/jit/importercalls.cpp | 6 +++--- src/coreclr/vm/jitinterface.cpp | 22 ++++++++-------------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 6337360261c836..a7639b0a22626a 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -182,7 +182,7 @@ var_types Compiler::impImportCall(OPCODE opcode, // if it points to an unloadable method, we can still handle it safely. // This lets us inline DynamicMethods. indirect = true; - object = (void*)address->AsIntCon()->gtIconVal; + object = (void*)address->AsIntCon()->gtIconVal; JITDUMP("impImportCall trying to transform delegate - found static readonly\n"); } } @@ -209,10 +209,10 @@ var_types Compiler::impImportCall(OPCODE opcode, if (replacementMethod != NO_METHOD_HANDLE) { - JITDUMP("impImportCall trying to transform call - found target method %s\n", - eeGetMethodName(replacementMethod)); CORINFO_SIG_INFO methodSig; CORINFO_CLASS_HANDLE targetClass = info.compCompHnd->getMethodClass(replacementMethod); + JITDUMP("impImportCall trying to transform call - found target method %s:%s\n", eeGetClassName(targetClass), + eeGetMethodName(replacementMethod)); info.compCompHnd->getMethodSig(replacementMethod, &methodSig, targetClass); bool removeInstance = false; diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 95f310b70cb115..bccdf84b19f589 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -4007,20 +4007,14 @@ CORINFO_METHOD_HANDLE CEEInfo::getMethodFromDelegate(void* address, bool indirec // We technically don't need to care about the GC // for frozen delegates, but APIs used here require COOP. GCX_COOP(); - DELEGATEREF delegate; - { - GCX_NOTRIGGER(); - delegate = (DELEGATEREF)ObjectToOBJECTREF(indirect ? - *(DelegateObject**)address : (DelegateObject*)address); - _ASSERTE (delegate != nullptr); - } + DELEGATEREF delegate = (DELEGATEREF)ObjectToOBJECTREF(indirect ? + *(DelegateObject**)address : (DelegateObject*)address); + _ASSERTE (delegate != nullptr); - { - GCPROTECT_BEGIN(delegate); - if (delegate->GetInvocationCount() == 0) - result = (CORINFO_METHOD_HANDLE)COMDelegate::GetMethodDesc(delegate); - GCPROTECT_END(); - } + GCPROTECT_BEGIN(delegate); + if (delegate->GetInvocationCount() == 0) + result = (CORINFO_METHOD_HANDLE)COMDelegate::GetMethodDesc(delegate); + GCPROTECT_END(); } EE_TO_JIT_TRANSITION(); @@ -5107,7 +5101,7 @@ void CEEInfo::getCallInfo( } else { - if (!exactType.IsTypeDesc() && !pTargetMD->IsArray()) + if (!exactType.IsTypeDesc() && !pTargetMD->IsArray() && !pTargetMD->IsDynamicMethod()) { // Because of .NET's notion of base calls, exactType may point to a sub-class // of the actual class that defines pTargetMD. If the JIT decides to inline, it is From 9c2b6c9ab9336f79e4c57d8db98dfe283f4bdbb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Petryka?= Date: Mon, 11 Nov 2024 21:28:41 +0100 Subject: [PATCH 07/12] Add NativeAOT support --- .../tools/Common/JitInterface/CorInfoImpl.cs | 13 ------------- .../DependencyAnalysis/FrozenObjectNode.cs | 1 + .../DependencyAnalysis/FrozenRuntimeTypeNode.cs | 1 + .../DependencyAnalysis/FrozenStringNode.cs | 1 + .../SerializedFrozenObjectNode.cs | 2 ++ .../ILCompiler.Compiler/Compiler/TypePreinit.cs | 16 ++++++++++------ .../JitInterface/CorInfoImpl.ReadyToRun.cs | 7 ++++++- .../JitInterface/CorInfoImpl.RyuJit.cs | 10 ++++++++++ 8 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 6bc48cfde24749..08e0e5df8e8fd0 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -2809,19 +2809,6 @@ private CorInfoInitClassResult initClass(CORINFO_FIELD_STRUCT_* field, CORINFO_M } } -#pragma warning disable CA1822 // Mark members as static - private CORINFO_METHOD_STRUCT_* getMethodFromDelegate(void* address, bool indirect) -#pragma warning restore CA1822 // Mark members as static - { - Debug.Assert(address != null); - - // it should be impossible to see unpinned delegates during AOT - Debug.Assert(!indirect); - - // TODO-Perf: implement this for NativeAOT - return null; - } - private CorInfoType getTypeForPrimitiveValueClass(CORINFO_CLASS_STRUCT_* cls) { var type = HandleToObject(cls); 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 2d1bcefd4fd56f..b2d2f162db2630 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs @@ -26,6 +26,7 @@ int ISymbolDefinitionNode.Offset public abstract TypeDesc ObjectType { get; } public abstract int? ArrayLength { get; } + public abstract MethodDesc DelegateMethod { get; } public abstract bool IsKnownImmutable { get; } public int Size => ObjectType.Context.Target.PointerSize + ContentSize; // SyncBlock + size of contents protected abstract int ContentSize { get; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenRuntimeTypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenRuntimeTypeNode.cs index df38758e7deeed..f040975ee61d60 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenRuntimeTypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenRuntimeTypeNode.cs @@ -49,6 +49,7 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer } public override int? ArrayLength => null; + public override MethodDesc DelegateMethod => null; public override bool IsKnownImmutable => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs index a115db34764baa..2f1633820ba054 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs @@ -51,6 +51,7 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer public string Data => _data; public override int? ArrayLength => _data.Length; + public override MethodDesc DelegateMethod => null; public override bool IsKnownImmutable => true; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs index fbe021414800bc..a457b9b33db4e5 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs @@ -48,6 +48,8 @@ protected override int ContentSize public override int? ArrayLength => _data.Type.IsArray ? _data.ArrayLength : null; + public override MethodDesc DelegateMethod => _data.Type.IsDelegate ? _data.DelegateMethod : null; + public override void EncodeContents(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { // byte contents diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs index a5851aba72f2fe..70f76b3c3f4e7c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs @@ -2210,6 +2210,7 @@ public interface ISerializableReference : ISerializableValue void GetConditionalDependencies(ref CombinedDependencyList dependencies, NodeFactory factory); bool IsKnownImmutable { get; } int ArrayLength { get; } + MethodDesc DelegateMethod { get; } } /// @@ -2767,20 +2768,20 @@ public virtual void GetConditionalDependencies(ref CombinedDependencyList depend private sealed class DelegateInstance : AllocatedReferenceTypeValue, ISerializableReference { - private readonly MethodDesc _methodPointed; + public MethodDesc DelegateMethod { get; } private readonly ReferenceTypeValue _firstParameter; public DelegateInstance(TypeDesc delegateType, MethodDesc methodPointed, ReferenceTypeValue firstParameter, AllocationSite allocationSite) : base(delegateType, allocationSite) { - _methodPointed = methodPointed; + DelegateMethod = methodPointed; _firstParameter = firstParameter; } private DelegateCreationInfo GetDelegateCreationInfo(NodeFactory factory) => DelegateCreationInfo.Create( Type.ConvertToCanonForm(CanonicalFormKind.Specific), - _methodPointed, + DelegateMethod, constrainedType: null, factory, followVirtualDispatch: false); @@ -2799,7 +2800,7 @@ public override void GetConditionalDependencies(ref CombinedDependencyList depen public void WriteContent(ref ObjectDataBuilder builder, ISymbolNode thisNode, NodeFactory factory) { - Debug.Assert(_methodPointed.Signature.IsStatic == (_firstParameter == null)); + Debug.Assert(DelegateMethod.Signature.IsStatic == (_firstParameter == null)); DelegateCreationInfo creationInfo = GetDelegateCreationInfo(factory); @@ -2810,7 +2811,7 @@ public void WriteContent(ref ObjectDataBuilder builder, ISymbolNode thisNode, No Debug.Assert(!node.RepresentsIndirectionCell); // Shouldn't have allowed this builder.EmitPointerReloc(node); - if (_methodPointed.Signature.IsStatic) + if (DelegateMethod.Signature.IsStatic) { Debug.Assert(creationInfo.Constructor.Method.Name == "InitializeOpenStaticThunk"); @@ -2850,7 +2851,7 @@ public override void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory f builder.EmitPointerReloc(factory.SerializedFrozenObject(AllocationSite.OwningType, AllocationSite.InstructionCounter, this)); } - public bool IsKnownImmutable => _methodPointed.Signature.IsStatic; + public bool IsKnownImmutable => DelegateMethod.Signature.IsStatic; public int ArrayLength => throw new NotSupportedException(); } @@ -2954,6 +2955,8 @@ public bool TryGetReadOnlySpan(out ReadOnlySpanValue value) public bool IsKnownImmutable => _elementCount == 0; public int ArrayLength => Length; + + public MethodDesc DelegateMethod => throw new NotSupportedException(); } private sealed class ForeignTypeInstance : AllocatedReferenceTypeValue @@ -3121,6 +3124,7 @@ public void WriteContent(ref ObjectDataBuilder builder, ISymbolNode thisNode, No public bool IsKnownImmutable => !Type.GetFields().GetEnumerator().MoveNext(); public int ArrayLength => throw new NotSupportedException(); + public MethodDesc DelegateMethod => throw new NotSupportedException(); } private struct FieldAccessor 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 500863a90d9347..95e82aba876ba7 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -2111,7 +2111,7 @@ private void ceeInfoGetCallInfo( // of shared generic code calling a shared generic implementation method, which should be rare. // // An alternative design would be to add a new generic dictionary entry kind to hold the MethodDesc - // of the constrained target instead, and use that in some circumstances; however, implementation of + // of the constrained target instead, and use that in some circumstances; however, implementation of // that design requires refactoring variuos parts of the JIT interface as well as // TryResolveConstraintMethodApprox. In particular we would need to be abled to embed a constrained lookup // via EmbedGenericHandle, as well as decide in TryResolveConstraintMethodApprox if the call can be made @@ -3301,6 +3301,11 @@ private bool getObjectContent(CORINFO_OBJECT_STRUCT_* obj, byte* buffer, int buf throw new NotSupportedException(); } + private CORINFO_METHOD_STRUCT_* getMethodFromDelegate(void* address, bool indirect) + { + throw new NotSupportedException(); + } + private bool isObjectImmutable(CORINFO_OBJECT_STRUCT_* objPtr) { throw new NotSupportedException(); 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 34c5a1a3b16cc0..bd7faeb432b383 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2401,6 +2401,16 @@ private bool getObjectContent(CORINFO_OBJECT_STRUCT_* objPtr, byte* buffer, int return ObjectToHandle(HandleToObject(objPtr).ObjectType); } + private CORINFO_METHOD_STRUCT_* getMethodFromDelegate(void* address, bool indirect) + { + Debug.Assert(address != null); + + // it should be impossible to see unpinned delegates during AOT + Debug.Assert(!indirect); + + return ObjectToHandle(HandleToObject((CORINFO_OBJECT_STRUCT_*)address).DelegateMethod); + } + private CORINFO_OBJECT_STRUCT_* getRuntimeTypePointer(CORINFO_CLASS_STRUCT_* cls) { TypeDesc type = HandleToObject(cls); From 6c15c694d0932f9d1fcbf70c419fc6a925af1a96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Petryka?= Date: Mon, 18 Nov 2024 22:24:14 +0100 Subject: [PATCH 08/12] Fix merge --- src/coreclr/inc/jiteeversionguid.h | 10 +- .../JitInterface/CorInfoImpl_generated.cs | 224 +++++------------- 2 files changed, 63 insertions(+), 171 deletions(-) diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 7a6479c81e5ae1..74e62fb4aeacae 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 = { /* 381fc250-b8f3-4cee-834e-b0bc682a09f2 */ - 0x381fc250, - 0xb8f3, - 0x4cee, - {0x83, 0x4e, 0xb0, 0xbc, 0x68, 0x2a, 0x09, 0xf2} +constexpr GUID JITEEVersionIdentifier = { /* 2f665052-b021-494e-af81-3dc8ea6b7e1b */ + 0x2f665052, + 0xb021, + 0x494e, + {0xaf, 0x81, 0x3d, 0xc8, 0xea, 0x6b, 0x7e, 0x1b} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index 68a85860e20c0e..e43d197fa2081c 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -2638,11 +2638,7 @@ private static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, CORJIT_ private static IntPtr GetUnmanagedCallbacks() { -<<<<<<< HEAD - void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 179); -======= - void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 177); ->>>>>>> upstream/main + void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 178); callbacks[0] = (delegate* unmanaged)&_isIntrinsic; callbacks[1] = (delegate* unmanaged)&_notifyMethodInfoUsage; @@ -2721,7 +2717,6 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[74] = (delegate* unmanaged)&_initClass; callbacks[75] = (delegate* unmanaged)&_classMustBeLoadedBeforeCodeIsRun; callbacks[76] = (delegate* unmanaged)&_getBuiltinClass; -<<<<<<< HEAD callbacks[77] = (delegate* unmanaged)&_getMethodFromDelegate; callbacks[78] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; callbacks[79] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; @@ -2766,166 +2761,63 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[118] = (delegate* unmanaged)&_runWithErrorTrap; callbacks[119] = (delegate* unmanaged)&_runWithSPMIErrorTrap; callbacks[120] = (delegate* unmanaged)&_getEEInfo; - callbacks[121] = (delegate* unmanaged)&_getJitTimeLogFilename; - callbacks[122] = (delegate* unmanaged)&_getMethodDefFromMethod; - callbacks[123] = (delegate* unmanaged)&_printMethodName; - callbacks[124] = (delegate* unmanaged)&_getMethodNameFromMetadata; - callbacks[125] = (delegate* unmanaged)&_getMethodHash; - callbacks[126] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; - callbacks[127] = (delegate* unmanaged)&_getSwiftLowering; - callbacks[128] = (delegate* unmanaged)&_getFpStructLowering; - callbacks[129] = (delegate* unmanaged)&_getThreadTLSIndex; - callbacks[130] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; - callbacks[131] = (delegate* unmanaged)&_getHelperFtn; - callbacks[132] = (delegate* unmanaged)&_getFunctionEntryPoint; - callbacks[133] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; - callbacks[134] = (delegate* unmanaged)&_getMethodSync; - callbacks[135] = (delegate* unmanaged)&_getLazyStringLiteralHelper; - callbacks[136] = (delegate* unmanaged)&_embedModuleHandle; - callbacks[137] = (delegate* unmanaged)&_embedClassHandle; - callbacks[138] = (delegate* unmanaged)&_embedMethodHandle; - callbacks[139] = (delegate* unmanaged)&_embedFieldHandle; - callbacks[140] = (delegate* unmanaged)&_embedGenericHandle; - callbacks[141] = (delegate* unmanaged)&_getLocationOfThisType; - callbacks[142] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; - callbacks[143] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; - callbacks[144] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; - callbacks[145] = (delegate* unmanaged)&_getJustMyCodeHandle; - callbacks[146] = (delegate* unmanaged)&_GetProfilingHandle; - callbacks[147] = (delegate* unmanaged)&_getCallInfo; - callbacks[148] = (delegate* unmanaged)&_getStaticFieldContent; - callbacks[149] = (delegate* unmanaged)&_getObjectContent; - callbacks[150] = (delegate* unmanaged)&_getStaticFieldCurrentClass; - callbacks[151] = (delegate* unmanaged)&_getVarArgsHandle; - callbacks[152] = (delegate* unmanaged)&_canGetVarArgsHandle; - callbacks[153] = (delegate* unmanaged)&_constructStringLiteral; - callbacks[154] = (delegate* unmanaged)&_emptyStringLiteral; - callbacks[155] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; - callbacks[156] = (delegate* unmanaged)&_GetDelegateCtor; - callbacks[157] = (delegate* unmanaged)&_MethodCompileComplete; - callbacks[158] = (delegate* unmanaged)&_getTailCallHelpers; - callbacks[159] = (delegate* unmanaged)&_convertPInvokeCalliToCall; - callbacks[160] = (delegate* unmanaged)&_notifyInstructionSetUsage; - callbacks[161] = (delegate* unmanaged)&_updateEntryPointForTailCall; - callbacks[162] = (delegate* unmanaged)&_allocMem; - callbacks[163] = (delegate* unmanaged)&_reserveUnwindInfo; - callbacks[164] = (delegate* unmanaged)&_allocUnwindInfo; - callbacks[165] = (delegate* unmanaged)&_allocGCInfo; - callbacks[166] = (delegate* unmanaged)&_setEHcount; - callbacks[167] = (delegate* unmanaged)&_setEHinfo; - callbacks[168] = (delegate* unmanaged)&_logMsg; - callbacks[169] = (delegate* unmanaged)&_doAssert; - callbacks[170] = (delegate* unmanaged)&_reportFatalError; - callbacks[171] = (delegate* unmanaged)&_getPgoInstrumentationResults; - callbacks[172] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; - callbacks[173] = (delegate* unmanaged)&_recordCallSite; - callbacks[174] = (delegate* unmanaged)&_recordRelocation; - callbacks[175] = (delegate* unmanaged)&_getRelocTypeHint; - callbacks[176] = (delegate* unmanaged)&_getExpectedTargetArchitecture; - callbacks[177] = (delegate* unmanaged)&_getJitFlags; - callbacks[178] = (delegate* unmanaged)&_getSpecialCopyHelper; -======= - callbacks[77] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; - callbacks[78] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; - callbacks[79] = (delegate* unmanaged)&_canCast; - callbacks[80] = (delegate* unmanaged)&_compareTypesForCast; - callbacks[81] = (delegate* unmanaged)&_compareTypesForEquality; - callbacks[82] = (delegate* unmanaged)&_isMoreSpecificType; - callbacks[83] = (delegate* unmanaged)&_isExactType; - callbacks[84] = (delegate* unmanaged)&_isGenericType; - callbacks[85] = (delegate* unmanaged)&_isNullableType; - callbacks[86] = (delegate* unmanaged)&_isEnum; - callbacks[87] = (delegate* unmanaged)&_getParentType; - callbacks[88] = (delegate* unmanaged)&_getChildType; - callbacks[89] = (delegate* unmanaged)&_isSDArray; - callbacks[90] = (delegate* unmanaged)&_getArrayRank; - callbacks[91] = (delegate* unmanaged)&_getArrayIntrinsicID; - callbacks[92] = (delegate* unmanaged)&_getArrayInitializationData; - callbacks[93] = (delegate* unmanaged)&_canAccessClass; - callbacks[94] = (delegate* unmanaged)&_printFieldName; - callbacks[95] = (delegate* unmanaged)&_getFieldClass; - callbacks[96] = (delegate* unmanaged)&_getFieldType; - callbacks[97] = (delegate* unmanaged)&_getFieldOffset; - callbacks[98] = (delegate* unmanaged)&_getFieldInfo; - callbacks[99] = (delegate* unmanaged)&_getThreadLocalFieldInfo; - callbacks[100] = (delegate* unmanaged)&_getThreadLocalStaticBlocksInfo; - callbacks[101] = (delegate* unmanaged)&_getThreadLocalStaticInfo_NativeAOT; - callbacks[102] = (delegate* unmanaged)&_isFieldStatic; - callbacks[103] = (delegate* unmanaged)&_getArrayOrStringLength; - callbacks[104] = (delegate* unmanaged)&_getBoundaries; - callbacks[105] = (delegate* unmanaged)&_setBoundaries; - callbacks[106] = (delegate* unmanaged)&_getVars; - callbacks[107] = (delegate* unmanaged)&_setVars; - callbacks[108] = (delegate* unmanaged)&_reportRichMappings; - callbacks[109] = (delegate* unmanaged)&_reportMetadata; - callbacks[110] = (delegate* unmanaged)&_allocateArray; - callbacks[111] = (delegate* unmanaged)&_freeArray; - callbacks[112] = (delegate* unmanaged)&_getArgNext; - callbacks[113] = (delegate* unmanaged)&_getArgType; - callbacks[114] = (delegate* unmanaged)&_getExactClasses; - callbacks[115] = (delegate* unmanaged)&_getArgClass; - callbacks[116] = (delegate* unmanaged)&_getHFAType; - callbacks[117] = (delegate* unmanaged)&_runWithErrorTrap; - callbacks[118] = (delegate* unmanaged)&_runWithSPMIErrorTrap; - callbacks[119] = (delegate* unmanaged)&_getEEInfo; - callbacks[120] = (delegate* unmanaged)&_getMethodDefFromMethod; - callbacks[121] = (delegate* unmanaged)&_printMethodName; - callbacks[122] = (delegate* unmanaged)&_getMethodNameFromMetadata; - callbacks[123] = (delegate* unmanaged)&_getMethodHash; - callbacks[124] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; - callbacks[125] = (delegate* unmanaged)&_getSwiftLowering; - callbacks[126] = (delegate* unmanaged)&_getFpStructLowering; - callbacks[127] = (delegate* unmanaged)&_getThreadTLSIndex; - callbacks[128] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; - callbacks[129] = (delegate* unmanaged)&_getHelperFtn; - callbacks[130] = (delegate* unmanaged)&_getFunctionEntryPoint; - callbacks[131] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; - callbacks[132] = (delegate* unmanaged)&_getMethodSync; - callbacks[133] = (delegate* unmanaged)&_getLazyStringLiteralHelper; - callbacks[134] = (delegate* unmanaged)&_embedModuleHandle; - callbacks[135] = (delegate* unmanaged)&_embedClassHandle; - callbacks[136] = (delegate* unmanaged)&_embedMethodHandle; - callbacks[137] = (delegate* unmanaged)&_embedFieldHandle; - callbacks[138] = (delegate* unmanaged)&_embedGenericHandle; - callbacks[139] = (delegate* unmanaged)&_getLocationOfThisType; - callbacks[140] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; - callbacks[141] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; - callbacks[142] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; - callbacks[143] = (delegate* unmanaged)&_getJustMyCodeHandle; - callbacks[144] = (delegate* unmanaged)&_GetProfilingHandle; - callbacks[145] = (delegate* unmanaged)&_getCallInfo; - callbacks[146] = (delegate* unmanaged)&_getStaticFieldContent; - callbacks[147] = (delegate* unmanaged)&_getObjectContent; - callbacks[148] = (delegate* unmanaged)&_getStaticFieldCurrentClass; - callbacks[149] = (delegate* unmanaged)&_getVarArgsHandle; - callbacks[150] = (delegate* unmanaged)&_canGetVarArgsHandle; - callbacks[151] = (delegate* unmanaged)&_constructStringLiteral; - callbacks[152] = (delegate* unmanaged)&_emptyStringLiteral; - callbacks[153] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; - callbacks[154] = (delegate* unmanaged)&_GetDelegateCtor; - callbacks[155] = (delegate* unmanaged)&_MethodCompileComplete; - callbacks[156] = (delegate* unmanaged)&_getTailCallHelpers; - callbacks[157] = (delegate* unmanaged)&_convertPInvokeCalliToCall; - callbacks[158] = (delegate* unmanaged)&_notifyInstructionSetUsage; - callbacks[159] = (delegate* unmanaged)&_updateEntryPointForTailCall; - callbacks[160] = (delegate* unmanaged)&_allocMem; - callbacks[161] = (delegate* unmanaged)&_reserveUnwindInfo; - callbacks[162] = (delegate* unmanaged)&_allocUnwindInfo; - callbacks[163] = (delegate* unmanaged)&_allocGCInfo; - callbacks[164] = (delegate* unmanaged)&_setEHcount; - callbacks[165] = (delegate* unmanaged)&_setEHinfo; - callbacks[166] = (delegate* unmanaged)&_logMsg; - callbacks[167] = (delegate* unmanaged)&_doAssert; - callbacks[168] = (delegate* unmanaged)&_reportFatalError; - callbacks[169] = (delegate* unmanaged)&_getPgoInstrumentationResults; - callbacks[170] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; - callbacks[171] = (delegate* unmanaged)&_recordCallSite; - callbacks[172] = (delegate* unmanaged)&_recordRelocation; - callbacks[173] = (delegate* unmanaged)&_getRelocTypeHint; - callbacks[174] = (delegate* unmanaged)&_getExpectedTargetArchitecture; - callbacks[175] = (delegate* unmanaged)&_getJitFlags; - callbacks[176] = (delegate* unmanaged)&_getSpecialCopyHelper; ->>>>>>> upstream/main + callbacks[121] = (delegate* unmanaged)&_getMethodDefFromMethod; + callbacks[122] = (delegate* unmanaged)&_printMethodName; + callbacks[123] = (delegate* unmanaged)&_getMethodNameFromMetadata; + callbacks[124] = (delegate* unmanaged)&_getMethodHash; + callbacks[125] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; + callbacks[126] = (delegate* unmanaged)&_getSwiftLowering; + callbacks[127] = (delegate* unmanaged)&_getFpStructLowering; + callbacks[128] = (delegate* unmanaged)&_getThreadTLSIndex; + callbacks[129] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; + callbacks[130] = (delegate* unmanaged)&_getHelperFtn; + callbacks[131] = (delegate* unmanaged)&_getFunctionEntryPoint; + callbacks[132] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; + callbacks[133] = (delegate* unmanaged)&_getMethodSync; + callbacks[134] = (delegate* unmanaged)&_getLazyStringLiteralHelper; + callbacks[135] = (delegate* unmanaged)&_embedModuleHandle; + callbacks[136] = (delegate* unmanaged)&_embedClassHandle; + callbacks[137] = (delegate* unmanaged)&_embedMethodHandle; + callbacks[138] = (delegate* unmanaged)&_embedFieldHandle; + callbacks[139] = (delegate* unmanaged)&_embedGenericHandle; + callbacks[140] = (delegate* unmanaged)&_getLocationOfThisType; + callbacks[141] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; + callbacks[142] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; + callbacks[143] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; + callbacks[144] = (delegate* unmanaged)&_getJustMyCodeHandle; + callbacks[145] = (delegate* unmanaged)&_GetProfilingHandle; + callbacks[146] = (delegate* unmanaged)&_getCallInfo; + callbacks[147] = (delegate* unmanaged)&_getStaticFieldContent; + callbacks[148] = (delegate* unmanaged)&_getObjectContent; + callbacks[149] = (delegate* unmanaged)&_getStaticFieldCurrentClass; + callbacks[150] = (delegate* unmanaged)&_getVarArgsHandle; + callbacks[151] = (delegate* unmanaged)&_canGetVarArgsHandle; + callbacks[152] = (delegate* unmanaged)&_constructStringLiteral; + callbacks[153] = (delegate* unmanaged)&_emptyStringLiteral; + callbacks[154] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; + callbacks[155] = (delegate* unmanaged)&_GetDelegateCtor; + callbacks[156] = (delegate* unmanaged)&_MethodCompileComplete; + callbacks[157] = (delegate* unmanaged)&_getTailCallHelpers; + callbacks[158] = (delegate* unmanaged)&_convertPInvokeCalliToCall; + callbacks[159] = (delegate* unmanaged)&_notifyInstructionSetUsage; + callbacks[160] = (delegate* unmanaged)&_updateEntryPointForTailCall; + callbacks[161] = (delegate* unmanaged)&_allocMem; + callbacks[162] = (delegate* unmanaged)&_reserveUnwindInfo; + callbacks[163] = (delegate* unmanaged)&_allocUnwindInfo; + callbacks[164] = (delegate* unmanaged)&_allocGCInfo; + callbacks[165] = (delegate* unmanaged)&_setEHcount; + callbacks[166] = (delegate* unmanaged)&_setEHinfo; + callbacks[167] = (delegate* unmanaged)&_logMsg; + callbacks[168] = (delegate* unmanaged)&_doAssert; + callbacks[169] = (delegate* unmanaged)&_reportFatalError; + callbacks[170] = (delegate* unmanaged)&_getPgoInstrumentationResults; + callbacks[171] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; + callbacks[172] = (delegate* unmanaged)&_recordCallSite; + callbacks[173] = (delegate* unmanaged)&_recordRelocation; + callbacks[174] = (delegate* unmanaged)&_getRelocTypeHint; + callbacks[175] = (delegate* unmanaged)&_getExpectedTargetArchitecture; + callbacks[176] = (delegate* unmanaged)&_getJitFlags; + callbacks[177] = (delegate* unmanaged)&_getSpecialCopyHelper; return (IntPtr)callbacks; } From d53dd62c41e54af3766b475f2330f8ccccc4fcfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Petryka?= Date: Wed, 20 Nov 2024 02:27:50 +0100 Subject: [PATCH 09/12] Move a bunch of stuff to VM --- src/coreclr/inc/corinfo.h | 8 +- src/coreclr/inc/icorjitinfoimpl_generated.h | 6 +- src/coreclr/inc/jiteeversionguid.h | 10 +- .../jit/ICorJitInfo_wrapper_generated.hpp | 8 +- src/coreclr/jit/compiler.h | 2 +- src/coreclr/jit/gentree.cpp | 4 +- src/coreclr/jit/gentree.h | 14 ++ src/coreclr/jit/importercalls.cpp | 135 +++++++++--------- .../JitInterface/CorInfoImpl_generated.cs | 6 +- .../ThunkGenerator/ThunkInput.txt | 2 +- .../Common/TypeSystem/IL/DelegateInfo.cs | 1 - .../DependencyAnalysis/FrozenObjectNode.cs | 1 + .../FrozenRuntimeTypeNode.cs | 1 + .../DependencyAnalysis/FrozenStringNode.cs | 1 + .../SerializedFrozenObjectNode.cs | 1 + .../Compiler/TypePreinit.cs | 5 + .../JitInterface/CorInfoImpl.ReadyToRun.cs | 2 +- .../JitInterface/CorInfoImpl.RyuJit.cs | 51 ++++++- .../aot/jitinterface/jitinterface_generated.h | 10 +- .../tools/superpmi/superpmi-shared/agnostic.h | 7 + .../tools/superpmi/superpmi-shared/lwmlist.h | 2 +- .../superpmi-shared/methodcontext.cpp | 48 ++++--- .../superpmi/superpmi-shared/methodcontext.h | 6 +- .../superpmi-shim-collector/icorjitinfo.cpp | 12 +- .../icorjitinfo_generated.cpp | 8 +- .../icorjitinfo_generated.cpp | 8 +- .../tools/superpmi/superpmi/icorjitinfo.cpp | 5 +- src/coreclr/vm/comdelegate.cpp | 7 +- src/coreclr/vm/comdelegate.h | 1 + src/coreclr/vm/jitinterface.cpp | 70 +++++++-- 30 files changed, 300 insertions(+), 142 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 57953fef95ec66..00607533cce11d 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -2611,10 +2611,12 @@ class ICorStaticInfo CorInfoClassId classId ) = 0; - // returns the class handle for the special builtin classes + // returns the method the delegate object calls virtual CORINFO_METHOD_HANDLE getMethodFromDelegate ( - void* address, - bool indirect + CORINFO_CLASS_HANDLE calledCls, + CORINFO_OBJECT_HANDLE delObj, + CORINFO_CLASS_HANDLE* methodCls, + CORINFO_CLASS_HANDLE* targetCls ) = 0; // "System.Int32" ==> CORINFO_TYPE_INT.. diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index be85ab0b49547a..f8ad78102e8534 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -330,8 +330,10 @@ CORINFO_CLASS_HANDLE getBuiltinClass( CorInfoClassId classId) override; CORINFO_METHOD_HANDLE getMethodFromDelegate( - void* address, - bool indirect) override; + CORINFO_CLASS_HANDLE calledCls, + CORINFO_OBJECT_HANDLE delegateObj, + CORINFO_CLASS_HANDLE* methodCls, + CORINFO_CLASS_HANDLE* targetCls) override; CorInfoType getTypeForPrimitiveValueClass( CORINFO_CLASS_HANDLE cls) override; diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 74e62fb4aeacae..753ef98c703211 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 = { /* 2f665052-b021-494e-af81-3dc8ea6b7e1b */ - 0x2f665052, - 0xb021, - 0x494e, - {0xaf, 0x81, 0x3d, 0xc8, 0xea, 0x6b, 0x7e, 0x1b} +constexpr GUID JITEEVersionIdentifier = { /* a4c2ac7d-8cb8-4591-bf1d-4fecb271e5f1 */ + 0xa4c2ac7d, + 0x8cb8, + 0x4591, + {0xbf, 0x1d, 0x4f, 0xec, 0xb2, 0x71, 0xe5, 0xf1} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp index 90fbe7f328a8a7..8e6cec514e4fd3 100644 --- a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp +++ b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp @@ -766,11 +766,13 @@ CORINFO_CLASS_HANDLE WrapICorJitInfo::getBuiltinClass( } CORINFO_METHOD_HANDLE WrapICorJitInfo::getMethodFromDelegate( - void* address, - bool indirect) + CORINFO_CLASS_HANDLE calledCls, + CORINFO_OBJECT_HANDLE delegateObj, + CORINFO_CLASS_HANDLE* methodCls, + CORINFO_CLASS_HANDLE* targetCls) { API_ENTER(getMethodFromDelegate); - CORINFO_METHOD_HANDLE temp = wrapHnd->getMethodFromDelegate(address, indirect); + CORINFO_METHOD_HANDLE temp = wrapHnd->getMethodFromDelegate(calledCls, delegateObj, methodCls, targetCls); API_LEAVE(getMethodFromDelegate); return temp; } diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index cc39db3d6ad791..bf71a38656efd1 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -4559,7 +4559,7 @@ class Compiler void impPopArgsForUnmanagedCall(GenTreeCall* call, CORINFO_SIG_INFO* sig, GenTree** swiftErrorNode); void impPopArgsForSwiftCall(GenTreeCall* call, CORINFO_SIG_INFO* sig, GenTree** swiftErrorNode); void impRetypeUnmanagedCallArgs(GenTreeCall* call); - bool impCanSubstituteSig(CORINFO_SIG_INFO* sourceSig, CORINFO_SIG_INFO* targetSig, bool* removeInstance); + bool impCanSubstituteSig(CORINFO_SIG_INFO* sourceSig, CORINFO_SIG_INFO* targetSig); #ifdef SWIFT_SUPPORT void impAppendSwiftErrorStore(GenTree* const swiftErrorNode); diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 812a6777851db9..c0f801bb31cc6a 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -12059,7 +12059,7 @@ void Compiler::gtDispConst(GenTree* tree) } else if (tree->IsIconHandle(GTF_ICON_OBJ_HDL)) { - eePrintObjectDescription(" ", (CORINFO_OBJECT_HANDLE)tree->AsIntCon()->gtIconVal); + eePrintObjectDescription(" ", tree->AsIntCon()->GetFrozenObject()); } else { @@ -19065,7 +19065,7 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, b { if (obj->IsIconHandle(GTF_ICON_OBJ_HDL)) { - objClass = info.compCompHnd->getObjectType((CORINFO_OBJECT_HANDLE)obj->AsIntCon()->IconValue()); + objClass = info.compCompHnd->getObjectType(obj->AsIntCon()->GetFrozenObject()); if (objClass != NO_CLASS_HANDLE) { // if we managed to get a class handle it's definitely not null diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index f72fa678135d22..ffcef5b89e9602 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -3288,6 +3288,20 @@ struct GenTreeIntCon : public GenTreeIntConCommon { } #endif + + CORINFO_OBJECT_HANDLE GetFrozenObject() + { + assert(IsIconHandle(GTF_ICON_OBJ_HDL)); + return (CORINFO_OBJECT_HANDLE)IconValue(); + } + + CORINFO_FIELD_HANDLE GetStaticFieldHandle() + { + assert(IsIconHandle(GTF_ICON_STATIC_BOX_PTR) || IsIconHandle(GTF_ICON_CONST_PTR) || + IsIconHandle(GTF_ICON_STATIC_HDL)); + assert(gtFieldSeq != nullptr); + return gtFieldSeq->GetFieldHandle(); + } }; /* gtLngCon -- long constant (GT_CNS_LNG) */ diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index a2560078b02042..e489cca00c546a 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -104,9 +104,12 @@ var_types Compiler::impImportCall(OPCODE opcode, // prepare data for calli/delegate call replacement bool optimizedOrInstrumented = opts.OptimizationEnabled() || opts.IsInstrumented(); - CORINFO_METHOD_HANDLE replacementMethod = nullptr; // real method called by the calli/delegate - GenTree* newThis = nullptr; // new instance for the delegate call - int firstArgPos = -1; // position of the first arg after delegate + CORINFO_CLASS_HANDLE replacementClass = NO_CLASS_HANDLE; // real class called by the calli/delegate + CORINFO_METHOD_HANDLE replacementMethod = NO_METHOD_HANDLE; // real method called by the calli/delegate + CORINFO_SIG_INFO replacementSig = {}; // signature of the read method + GenTree* newThis = nullptr; // new instance for the delegate call + CORINFO_CLASS_HANDLE newThisClass = NO_CLASS_HANDLE; // class of the new instance object + int firstArgPos = -1; // position of the first arg after delegate // handle special import cases if (opcode == CEE_CALLI) @@ -138,10 +141,28 @@ var_types Compiler::impImportCall(OPCODE opcode, // We can only handle known valid pointers here since the VM crashes // when querying invalid method addresses. // As such, we can't handle static readonly function pointers here. - if (fptr->OperIs(GT_FTN_ADDR)) + if (originalSig.hasImplicitThis()) + { + JITDUMP("impImportCall failed to import calli as call - implicit this not supported\n"); + } + else if (fptr->OperIs(GT_FTN_ADDR)) { // Ldftn should never point to a method from another unloadable context - replacementMethod = fptr->AsFptrVal()->gtFptrMethod; + CORINFO_METHOD_HANDLE method = fptr->AsFptrVal()->gtFptrMethod; + replacementClass = info.compCompHnd->getMethodClass(method); + info.compCompHnd->getMethodSig(method, &replacementSig, replacementClass); + if (replacementSig.hasThis() && eeIsValueClass(replacementClass)) + { + JITDUMP("impImportCall aborting transformation - value type instance methods are not supported\n"); + } + else if (!impCanSubstituteSig(&originalSig, &replacementSig)) + { + JITDUMP("impImportCall aborting transformation - incompatible signature\n"); + } + else + { + replacementMethod = method; + } } else { @@ -162,14 +183,13 @@ var_types Compiler::impImportCall(OPCODE opcode, info.compCompHnd->getMethodSig(callInfo->hMethod, &originalSig, delegateClass); // TODO-Perf: Add an importer forward substitution to handle more cases here. - GenTree* instance = impStackTop(originalSig.numArgs).val; - bool indirect = false; - void* object = nullptr; + GenTree* instance = impStackTop(originalSig.numArgs).val; + CORINFO_OBJECT_HANDLE object = NO_OBJECT_HANDLE; if (instance->IsIconHandle(GTF_ICON_OBJ_HDL)) { // Frozen delegates should never point to collectible contexts. - object = (void*)instance->AsIntCon()->gtIconVal; + object = instance->AsIntCon()->GetFrozenObject(); JITDUMP("impImportCall trying to transform delegate - found frozen\n"); } else if (instance->OperIs(GT_IND)) @@ -181,59 +201,55 @@ var_types Compiler::impImportCall(OPCODE opcode, // such context will keep the delegate permanently alive so even // if it points to an unloadable method, we can still handle it safely. // This lets us inline DynamicMethods. - indirect = true; - object = (void*)address->AsIntCon()->gtIconVal; - JITDUMP("impImportCall trying to transform delegate - found static readonly\n"); + CORINFO_FIELD_HANDLE field = address->AsIntCon()->GetStaticFieldHandle(); + JITDUMP("impImportCall trying to transform delegate - found field %s\n", eeGetFieldName(field, true)); + if (info.compCompHnd->getStaticFieldContent(field, (uint8_t*)&object, + sizeof(CORINFO_OBJECT_HANDLE), 0, false)) + { + JITDUMP("impImportCall trying to transform delegate - found static readonly value\n"); + } } } // TODO-Perf: Handle unloadable delegates in the same context. - if (object != nullptr) + if (object != NO_OBJECT_HANDLE) { - JITDUMP("impImportCall trying to transform delegate - found delegate at 0x%llx, indirect: %d\n", object, - indirect ? 1 : 0); - replacementMethod = info.compCompHnd->getMethodFromDelegate(object, indirect); + JITDUMP("impImportCall trying to transform delegate - found delegate at 0x%llx\n", object); + replacementMethod = info.compCompHnd->getMethodFromDelegate(pResolvedToken->hClass, object, + &replacementClass, &newThisClass); if (replacementMethod != NO_METHOD_HANDLE) { firstArgPos = (int)(stackState.esStackDepth - originalSig.numArgs); assert(firstArgPos >= 0); - newThis = - gtNewIndir(TYP_REF, - gtNewOperNode(GT_ADD, TYP_BYREF, instance, - gtNewIconNode(eeGetEEInfo()->offsetOfDelegateFirstTarget, TYP_I_IMPL)), - GTF_IND_INVARIANT | GTF_IND_NONNULL | GTF_IND_NONFAULTING); + + info.compCompHnd->getMethodSig(replacementMethod, &replacementSig, replacementClass); + + if (newThisClass != NO_CLASS_HANDLE) + { + newThis = + gtNewIndir(TYP_REF, + gtNewOperNode(GT_ADD, TYP_BYREF, instance, + gtNewIconNode(eeGetEEInfo()->offsetOfDelegateFirstTarget, TYP_I_IMPL)), + GTF_IND_INVARIANT | GTF_IND_NONNULL | GTF_IND_NONFAULTING); + } } } } if (replacementMethod != NO_METHOD_HANDLE) { - CORINFO_SIG_INFO methodSig; - CORINFO_CLASS_HANDLE targetClass = info.compCompHnd->getMethodClass(replacementMethod); - JITDUMP("impImportCall trying to transform call - found target method %s:%s\n", eeGetClassName(targetClass), + assert(replacementClass != NO_CLASS_HANDLE); + + JITDUMP("impImportCall trying to transform call - found target method %s:%s\n", eeGetClassName(replacementClass), eeGetMethodName(replacementMethod)); - info.compCompHnd->getMethodSig(replacementMethod, &methodSig, targetClass); - bool removeInstance = false; unsigned replacementFlags = info.compCompHnd->getMethodAttribs(replacementMethod); if ((replacementFlags & CORINFO_FLG_PINVOKE) != 0) { JITDUMP("impImportCall aborting transformation - found PInvoke\n"); } - else if (methodSig.hasImplicitThis() && eeIsValueClass(targetClass)) - { - JITDUMP("impImportCall aborting transformation - valuetype instance methods are not supported\n"); - } - else if (!impCanSubstituteSig(&originalSig, &methodSig, &removeInstance)) - { - JITDUMP("impImportCall aborting transformation - incompatible signature\n"); - } - else if (removeInstance && firstArgPos < 0) - { - JITDUMP("impImportCall aborting transformation - invalid function pointer\n"); - } else { if (firstArgPos >= 0) @@ -242,11 +258,18 @@ var_types Compiler::impImportCall(OPCODE opcode, // had a valid delegate instance beforehand. assert(&stackState.esStack[firstArgPos - 1] >= stackState.esStack); assert(stackState.esStack[firstArgPos - 1].seTypeInfo.GetType() == TYP_REF); - assert(newThis->TypeGet() == TYP_REF); - assert(removeInstance || !eeIsValueClass(targetClass)); } - if (removeInstance || firstArgPos < 0) + if (newThisClass != NO_CLASS_HANDLE) + { + assert(firstArgPos >= 0); + assert(newThis != nullptr); + assert(newThis->TypeGet() == TYP_REF); + // replace delegate instance with the new this + stackState.esStack[firstArgPos - 1].seTypeInfo = typeInfo(newThisClass); + stackState.esStack[firstArgPos - 1].val = newThis; + } + else { // shift args if needed if (firstArgPos > 0) @@ -257,28 +280,18 @@ var_types Compiler::impImportCall(OPCODE opcode, // we can just pop the top arg after shifting impPopStack(); } - else - { - // replace delegate instance with the new this - stackState.esStack[firstArgPos - 1].seTypeInfo = typeInfo(targetClass); - stackState.esStack[firstArgPos - 1].val = newThis; - } JITDUMP("impImportCall transforming call\n"); // we need to update the token and info to the real method pResolvedToken->tokenContext = impTokenLookupContextHandle; pResolvedToken->tokenScope = info.compScopeHnd; - pResolvedToken->token = methodSig.token; pResolvedToken->tokenType = CORINFO_TOKENKIND_Method; + pResolvedToken->token = replacementSig.token; pResolvedToken->hMethod = replacementMethod; - pResolvedToken->hClass = targetClass; + pResolvedToken->hClass = replacementClass; eeGetCallInfo(pResolvedToken, nullptr, CORINFO_CALLINFO_ALLOWINSTPARAM, callInfo); - callInfo->sig = methodSig; - callInfo->hMethod = replacementMethod; - callInfo->methodFlags = replacementFlags; - callInfo->classFlags = info.compCompHnd->getClassAttribs(targetClass); callInfo->nullInstanceCheck = false; callInfo->accessAllowed = CORINFO_ACCESS_ALLOWED; @@ -2105,12 +2118,11 @@ GenTree* Compiler::impFixupCallStructReturn(GenTreeCall* call, CORINFO_CLASS_HAN // Arguments: // sourceSig - original call signature // targetSig - new call signature -// removeInstance - is removal of original instance needed // // Return Value: // Whether it's safe to change the IR to call the target method // -bool Compiler::impCanSubstituteSig(CORINFO_SIG_INFO* sourceSig, CORINFO_SIG_INFO* targetSig, bool* removeInstance) +bool Compiler::impCanSubstituteSig(CORINFO_SIG_INFO* sourceSig, CORINFO_SIG_INFO* targetSig) { if (sourceSig->getCallConv() != targetSig->getCallConv()) { @@ -2118,16 +2130,9 @@ bool Compiler::impCanSubstituteSig(CORINFO_SIG_INFO* sourceSig, CORINFO_SIG_INFO return false; } - bool removedInstance = false; - unsigned sourceArgCount = sourceSig->totalILArgs(); unsigned targetArgCount = targetSig->totalILArgs(); - if ((sourceArgCount == targetArgCount + 1) && sourceSig->hasImplicitThis()) - { - removedInstance = true; - sourceArgCount--; - } - else if (sourceArgCount != targetArgCount) + if (sourceArgCount != targetArgCount) { JITDUMP("impCanSubstituteSig returning false - args count %u != %u\n", sourceArgCount, targetArgCount); return false; @@ -2156,7 +2161,6 @@ bool Compiler::impCanSubstituteSig(CORINFO_SIG_INFO* sourceSig, CORINFO_SIG_INFO CORINFO_ARG_LIST_HANDLE sourceArg = sourceSig->args; CORINFO_ARG_LIST_HANDLE targetArg = targetSig->args; - assert(targetArgCount == sourceArgCount); for (unsigned i = 0; i < targetArgCount; i++) { var_types sourceType; @@ -2164,7 +2168,7 @@ bool Compiler::impCanSubstituteSig(CORINFO_SIG_INFO* sourceSig, CORINFO_SIG_INFO ClassLayout* sourceLayout = nullptr; ClassLayout* targetLayout = nullptr; - if (i == 0 && !removedInstance && sourceSig->hasImplicitThis()) + if (i == 0 && sourceSig->hasImplicitThis()) { // assume ref type on implicit this sourceType = TYP_REF; @@ -2214,7 +2218,6 @@ bool Compiler::impCanSubstituteSig(CORINFO_SIG_INFO* sourceSig, CORINFO_SIG_INFO } } - *removeInstance = removedInstance; return true; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index e43d197fa2081c..8bf3902e013a67 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -1151,12 +1151,12 @@ private static void _classMustBeLoadedBeforeCodeIsRun(IntPtr thisHandle, IntPtr* } [UnmanagedCallersOnly] - private static CORINFO_METHOD_STRUCT_* _getMethodFromDelegate(IntPtr thisHandle, IntPtr* ppException, void* address, byte indirect) + private static CORINFO_METHOD_STRUCT_* _getMethodFromDelegate(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* calledCls, CORINFO_OBJECT_STRUCT_* delegateObj, CORINFO_CLASS_STRUCT_** methodCls, CORINFO_CLASS_STRUCT_** targetCls) { var _this = GetThis(thisHandle); try { - return _this.getMethodFromDelegate(address, indirect != 0); + return _this.getMethodFromDelegate(calledCls, delegateObj, methodCls, targetCls); } catch (Exception ex) { @@ -2717,7 +2717,7 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[74] = (delegate* unmanaged)&_initClass; callbacks[75] = (delegate* unmanaged)&_classMustBeLoadedBeforeCodeIsRun; callbacks[76] = (delegate* unmanaged)&_getBuiltinClass; - callbacks[77] = (delegate* unmanaged)&_getMethodFromDelegate; + callbacks[77] = (delegate* unmanaged)&_getMethodFromDelegate; callbacks[78] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; callbacks[79] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; callbacks[80] = (delegate* unmanaged)&_canCast; diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index e854b221732508..078bdddeb9a999 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -241,7 +241,7 @@ FUNCTIONS CorInfoInitClassResult initClass(CORINFO_FIELD_HANDLE field, CORINFO_METHOD_HANDLE method, CORINFO_CONTEXT_HANDLE context) void classMustBeLoadedBeforeCodeIsRun(CORINFO_CLASS_HANDLE cls) CORINFO_CLASS_HANDLE getBuiltinClass(CorInfoClassId classId) - CORINFO_METHOD_HANDLE getMethodFromDelegate(void* address, bool indirect) + CORINFO_METHOD_HANDLE getMethodFromDelegate(CORINFO_CLASS_HANDLE calledCls, CORINFO_OBJECT_HANDLE delegateObj, CORINFO_CLASS_HANDLE* methodCls, CORINFO_CLASS_HANDLE* targetCls) CorInfoType getTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls) CorInfoType getTypeForPrimitiveNumericClass(CORINFO_CLASS_HANDLE cls) bool canCast(CORINFO_CLASS_HANDLE child, CORINFO_CLASS_HANDLE parent) diff --git a/src/coreclr/tools/Common/TypeSystem/IL/DelegateInfo.cs b/src/coreclr/tools/Common/TypeSystem/IL/DelegateInfo.cs index 2c06b0f688e494..5db8d661537b08 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/DelegateInfo.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/DelegateInfo.cs @@ -106,7 +106,6 @@ public TypeDesc Type public DelegateInfo(TypeDesc delegateType, DelegateFeature features) { Debug.Assert(delegateType.IsDelegate); - Debug.Assert(delegateType.IsTypeDefinition); _delegateType = delegateType; _supportedFeatures = features; 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 b2d2f162db2630..51cced1a78c0f7 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenObjectNode.cs @@ -27,6 +27,7 @@ int ISymbolDefinitionNode.Offset public abstract int? ArrayLength { get; } public abstract MethodDesc DelegateMethod { get; } + public abstract TypeDesc DelegateTargetType { get; } public abstract bool IsKnownImmutable { get; } public int Size => ObjectType.Context.Target.PointerSize + ContentSize; // SyncBlock + size of contents protected abstract int ContentSize { get; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenRuntimeTypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenRuntimeTypeNode.cs index f040975ee61d60..a07c31522bb390 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenRuntimeTypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenRuntimeTypeNode.cs @@ -50,6 +50,7 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer public override int? ArrayLength => null; public override MethodDesc DelegateMethod => null; + public override TypeDesc DelegateTargetType => null; public override bool IsKnownImmutable => false; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs index 2f1633820ba054..82386bbe2ee31e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FrozenStringNode.cs @@ -52,6 +52,7 @@ public override int CompareToImpl(ISortableNode other, CompilerComparer comparer public override int? ArrayLength => _data.Length; public override MethodDesc DelegateMethod => null; + public override TypeDesc DelegateTargetType => null; public override bool IsKnownImmutable => true; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs index a457b9b33db4e5..05465cd82ab981 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SerializedFrozenObjectNode.cs @@ -49,6 +49,7 @@ protected override int ContentSize public override int? ArrayLength => _data.Type.IsArray ? _data.ArrayLength : null; public override MethodDesc DelegateMethod => _data.Type.IsDelegate ? _data.DelegateMethod : null; + public override TypeDesc DelegateTargetType => _data.Type.IsDelegate ? _data.DelegateTargetType : null; public override void EncodeContents(ref ObjectDataBuilder dataBuilder, NodeFactory factory, bool relocsOnly) { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs index 70f76b3c3f4e7c..a424ff7065238c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/TypePreinit.cs @@ -2211,6 +2211,7 @@ public interface ISerializableReference : ISerializableValue bool IsKnownImmutable { get; } int ArrayLength { get; } MethodDesc DelegateMethod { get; } + TypeDesc DelegateTargetType { get; } } /// @@ -2853,6 +2854,8 @@ public override void WriteFieldData(ref ObjectDataBuilder builder, NodeFactory f public bool IsKnownImmutable => DelegateMethod.Signature.IsStatic; + public TypeDesc DelegateTargetType => _firstParameter?.Type; + public int ArrayLength => throw new NotSupportedException(); } @@ -2957,6 +2960,7 @@ public bool TryGetReadOnlySpan(out ReadOnlySpanValue value) public int ArrayLength => Length; public MethodDesc DelegateMethod => throw new NotSupportedException(); + public TypeDesc DelegateTargetType => throw new NotSupportedException(); } private sealed class ForeignTypeInstance : AllocatedReferenceTypeValue @@ -3125,6 +3129,7 @@ public void WriteContent(ref ObjectDataBuilder builder, ISymbolNode thisNode, No public int ArrayLength => throw new NotSupportedException(); public MethodDesc DelegateMethod => throw new NotSupportedException(); + public TypeDesc DelegateTargetType => throw new NotSupportedException(); } private struct FieldAccessor 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 95e82aba876ba7..b669b8f81166f2 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -3301,7 +3301,7 @@ private bool getObjectContent(CORINFO_OBJECT_STRUCT_* obj, byte* buffer, int buf throw new NotSupportedException(); } - private CORINFO_METHOD_STRUCT_* getMethodFromDelegate(void* address, bool indirect) + private CORINFO_METHOD_STRUCT_* getMethodFromDelegate(CORINFO_CLASS_STRUCT_* calledCls, CORINFO_OBJECT_STRUCT_* delegateObj, CORINFO_CLASS_STRUCT_** methodCls, CORINFO_CLASS_STRUCT_** targetCls) { throw new NotSupportedException(); } 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 bd7faeb432b383..c33c793e7c0da9 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Internal.IL; @@ -2401,14 +2402,54 @@ private bool getObjectContent(CORINFO_OBJECT_STRUCT_* objPtr, byte* buffer, int return ObjectToHandle(HandleToObject(objPtr).ObjectType); } - private CORINFO_METHOD_STRUCT_* getMethodFromDelegate(void* address, bool indirect) + private CORINFO_METHOD_STRUCT_* getMethodFromDelegate(CORINFO_CLASS_STRUCT_* calledCls, CORINFO_OBJECT_STRUCT_* delegateObj, CORINFO_CLASS_STRUCT_** methodCls, CORINFO_CLASS_STRUCT_** targetCls) { - Debug.Assert(address != null); + Debug.Assert(calledCls != null); + Debug.Assert(delegateObj != null); - // it should be impossible to see unpinned delegates during AOT - Debug.Assert(!indirect); + FrozenObjectNode frozenObject = HandleToObject(delegateObj); + MethodDesc method = frozenObject.DelegateMethod; - return ObjectToHandle(HandleToObject((CORINFO_OBJECT_STRUCT_*)address).DelegateMethod); + TypeDesc calledType = HandleToObject(calledCls); + if (!frozenObject.ObjectType.CanCastTo(calledType)) + { + return null; + } + + if (methodCls != null) + { + *methodCls = ObjectToHandle(method.OwningType); + } + + if (targetCls != null) + { + DelegateInfo delegateInfo = _compilation.TypeSystemContext.GetDelegateInfo(calledType); + int paramCountDelegateClosed = delegateInfo.Signature.Length + 1; + int paramCountTargetMethod = method.Signature.Length; + if (!method.Signature.IsStatic) + { + paramCountTargetMethod++; + } + + CORINFO_CLASS_STRUCT_* target = null; + if (paramCountDelegateClosed != paramCountTargetMethod) + { + TypeDesc targetType = frozenObject.DelegateTargetType; + if (targetType == null) + { + // avoid delegates closed over null + Debug.Assert(method.Signature.IsStatic); + } + else + { + target = ObjectToHandle(targetType); + } + } + + *targetCls = target; + } + + return ObjectToHandle(method); } private CORINFO_OBJECT_STRUCT_* getRuntimeTypePointer(CORINFO_CLASS_STRUCT_* cls) diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h index b7b05e911ea097..74c4f792a81b1a 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h @@ -88,7 +88,7 @@ struct JitInterfaceCallbacks CorInfoInitClassResult (* initClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, CORINFO_METHOD_HANDLE method, CORINFO_CONTEXT_HANDLE context); void (* classMustBeLoadedBeforeCodeIsRun)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); CORINFO_CLASS_HANDLE (* getBuiltinClass)(void * thisHandle, CorInfoExceptionClass** ppException, CorInfoClassId classId); - CORINFO_METHOD_HANDLE (* getMethodFromDelegate)(void * thisHandle, CorInfoExceptionClass** ppException, void* address, bool indirect); + CORINFO_METHOD_HANDLE (* getMethodFromDelegate)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE calledCls, CORINFO_OBJECT_HANDLE delegateObj, CORINFO_CLASS_HANDLE* methodCls, CORINFO_CLASS_HANDLE* targetCls); CorInfoType (* getTypeForPrimitiveValueClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); CorInfoType (* getTypeForPrimitiveNumericClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); bool (* canCast)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE child, CORINFO_CLASS_HANDLE parent); @@ -958,11 +958,13 @@ class JitInterfaceWrapper : public ICorJitInfo } virtual CORINFO_METHOD_HANDLE getMethodFromDelegate( - void* address, - bool indirect) + CORINFO_CLASS_HANDLE calledCls, + CORINFO_OBJECT_HANDLE delegateObj, + CORINFO_CLASS_HANDLE* methodCls, + CORINFO_CLASS_HANDLE* targetCls) { CorInfoExceptionClass* pException = nullptr; - CORINFO_METHOD_HANDLE temp = _callbacks->getMethodFromDelegate(_thisHandle, &pException, address, indirect); + CORINFO_METHOD_HANDLE temp = _callbacks->getMethodFromDelegate(_thisHandle, &pException, calledCls, delegateObj, methodCls, targetCls); if (pException != nullptr) throw pException; return temp; } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h index 771951a68baea8..cf1dc30e80d2b7 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h @@ -64,6 +64,13 @@ struct DLDL DWORDLONG B; }; +struct DLDLDL +{ + DWORDLONG A; + DWORDLONG B; + DWORDLONG C; +}; + struct Agnostic_CanInline { DWORD result; diff --git a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h index d1b6c8fd575565..5cc0c81c036ad1 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -135,7 +135,7 @@ LWM(GetThreadTLSIndex, DWORD, DLD) LWM(GetTokenTypeAsHandle, GetTokenTypeAsHandleValue, DWORDLONG) LWM(GetTypeForBox, DWORDLONG, DWORDLONG) LWM(GetTypeForBoxOnStack, DWORDLONG, DWORDLONG) -LWM(GetMethodFromDelegate, DLD, DWORDLONG) +LWM(GetMethodFromDelegate, DLDL, DLDLDL) LWM(GetTypeForPrimitiveValueClass, DWORDLONG, DWORD) LWM(GetTypeForPrimitiveNumericClass, DWORDLONG, DWORD) LWM(GetUnboxedEntry, DWORDLONG, DLD); diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index c215135da7c352..2935a3316dc703 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -1954,37 +1954,53 @@ CORINFO_CLASS_HANDLE MethodContext::repGetBuiltinClass(CorInfoClassId classId) return result; } -void MethodContext::recGetMethodFromDelegate(void* address, bool indirect, CORINFO_METHOD_HANDLE method) +void MethodContext::recGetMethodFromDelegate(CORINFO_CLASS_HANDLE calledCls, + CORINFO_OBJECT_HANDLE delegateObj, + CORINFO_CLASS_HANDLE methodCls, + CORINFO_CLASS_HANDLE targetCls, + CORINFO_METHOD_HANDLE result) { if (GetMethodFromDelegate == nullptr) - GetMethodFromDelegate = new LightWeightMap(); + GetMethodFromDelegate = new LightWeightMap(); - DLD key; + DLDL key; ZeroMemory(&key, sizeof(key)); - key.A = (DWORDLONG)address; - key.B = indirect ? 1 : 0; + key.A = CastHandle(calledCls); + key.B = CastHandle(delegateObj); - DWORDLONG value = CastHandle(method); + DLDLDL value; + ZeroMemory(&value, sizeof(value)); + value.A = CastHandle(methodCls); + value.B = CastHandle(targetCls); + value.C = CastHandle(result); GetMethodFromDelegate->Add(key, value); DEBUG_REC(dmpGetMethodFromDelegate(key, value)); } -void MethodContext::dmpGetMethodFromDelegate(DLD key, DWORDLONG value) +void MethodContext::dmpGetMethodFromDelegate(DLDL key, DLDLDL value) { - printf("GetMethodFromDelegate key address-%016" PRIX64 " indirect-%u, value method-%016" PRIX64 "", - key.A, key.B, value); + printf("GetMethodFromDelegate key type-%016" PRIX64 " object-%016" PRIX64 ", value type-%016" PRIX64 + " target type-%016" PRIX64 " method-%016" PRIX64, + key.A, key.B, value.A, value.B, value.C); } -CORINFO_METHOD_HANDLE MethodContext::repGetMethodFromDelegate(void* address, bool indirect) +CORINFO_METHOD_HANDLE MethodContext::repGetMethodFromDelegate(CORINFO_CLASS_HANDLE calledCls, + CORINFO_OBJECT_HANDLE delegateObj, + CORINFO_CLASS_HANDLE* methodCls, + CORINFO_CLASS_HANDLE* targetCls) { - DLD key; + DLDL key; ZeroMemory(&key, sizeof(key)); - key.A = (DWORDLONG)address; - key.B = indirect ? 1 : 0; + key.A = (DWORDLONG)calledCls; + key.B = (DWORDLONG)delegateObj; - DWORDLONG value = - LookupByKeyOrMiss(GetMethodFromDelegate, key, ": key address-%016" PRIX64 " indirect-%u", key.A, key.B); + DLDLDL value = LookupByKeyOrMiss(GetMethodFromDelegate, key, ": key type-%016" PRIX64 " object-%016" PRIX64, + key.A, key.B); DEBUG_REP(dmpGetMethodFromDelegate(key, value)); - return (CORINFO_METHOD_HANDLE)value; + if (methodCls != nullptr) + *methodCls = (CORINFO_CLASS_HANDLE)value.A; + if (targetCls != nullptr) + *targetCls = (CORINFO_CLASS_HANDLE)value.B; + return (CORINFO_METHOD_HANDLE)value.C; } void MethodContext::recGetTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls, CorInfoType result) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index d474e7dac15bb7..89585670c5d861 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -250,9 +250,9 @@ class MethodContext void dmpGetBuiltinClass(DWORD key, DWORDLONG value); CORINFO_CLASS_HANDLE repGetBuiltinClass(CorInfoClassId classId); - void recGetMethodFromDelegate(void* address, bool indirect, CORINFO_METHOD_HANDLE method); - void dmpGetMethodFromDelegate(DLD key, DWORDLONG value); - CORINFO_METHOD_HANDLE repGetMethodFromDelegate(void* address, bool indirect); + void recGetMethodFromDelegate(CORINFO_CLASS_HANDLE calledCls, CORINFO_OBJECT_HANDLE delegateObj, CORINFO_CLASS_HANDLE methodCls, CORINFO_CLASS_HANDLE targetCls, CORINFO_METHOD_HANDLE result); + void dmpGetMethodFromDelegate(DLDL key, DLDLDL value); + CORINFO_METHOD_HANDLE repGetMethodFromDelegate(CORINFO_CLASS_HANDLE calledCls, CORINFO_OBJECT_HANDLE delegateObj, CORINFO_CLASS_HANDLE* methodCls, CORINFO_CLASS_HANDLE* targetCls); void recGetTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls, CorInfoType result); void dmpGetTypeForPrimitiveValueClass(DWORDLONG key, DWORD value); diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index 9a806c8034a7e0..db68cc0e213142 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -866,11 +866,17 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getBuiltinClass(CorInfoClassId classId) } // returns the class handle for the special builtin classes -CORINFO_METHOD_HANDLE interceptor_ICJI::getMethodFromDelegate(void* address, bool indirect) +CORINFO_METHOD_HANDLE interceptor_ICJI::getMethodFromDelegate(CORINFO_CLASS_HANDLE calledCls, CORINFO_OBJECT_HANDLE delegateObj, CORINFO_CLASS_HANDLE* methodCls, CORINFO_CLASS_HANDLE* targetCls) { mc->cr->AddCall("getMethodFromDelegate"); - CORINFO_METHOD_HANDLE temp = original_ICorJitInfo->getMethodFromDelegate(address, indirect); - mc->recGetMethodFromDelegate(address, indirect, temp); + CORINFO_CLASS_HANDLE methodType = nullptr; + CORINFO_CLASS_HANDLE targetType = nullptr; + CORINFO_METHOD_HANDLE temp = original_ICorJitInfo->getMethodFromDelegate(calledCls, delegateObj, &methodType, &targetType); + mc->recGetMethodFromDelegate(calledCls, delegateObj, methodType, targetType, temp); + if (methodCls != nullptr) + *methodCls = methodType; + if (targetCls != nullptr) + *targetCls = targetType; return temp; } diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp index 3ebebe5d398e86..d3a5826584bde5 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp @@ -629,11 +629,13 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getBuiltinClass( } CORINFO_METHOD_HANDLE interceptor_ICJI::getMethodFromDelegate( - void* address, - bool indirect) + CORINFO_CLASS_HANDLE calledCls, + CORINFO_OBJECT_HANDLE delegateObj, + CORINFO_CLASS_HANDLE* methodCls, + CORINFO_CLASS_HANDLE* targetCls) { mcs->AddCall("getMethodFromDelegate"); - return original_ICorJitInfo->getMethodFromDelegate(address, indirect); + return original_ICorJitInfo->getMethodFromDelegate(calledCls, delegateObj, methodCls, targetCls); } CorInfoType interceptor_ICJI::getTypeForPrimitiveValueClass( diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp index 5d9d08a6332380..6fde6f7d7f261b 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp @@ -552,10 +552,12 @@ CORINFO_CLASS_HANDLE interceptor_ICJI::getBuiltinClass( } CORINFO_METHOD_HANDLE interceptor_ICJI::getMethodFromDelegate( - void* address, - bool indirect) + CORINFO_CLASS_HANDLE calledCls, + CORINFO_OBJECT_HANDLE delegateObj, + CORINFO_CLASS_HANDLE* methodCls, + CORINFO_CLASS_HANDLE* targetCls) { - return original_ICorJitInfo->getMethodFromDelegate(address, indirect); + return original_ICorJitInfo->getMethodFromDelegate(calledCls, delegateObj, methodCls, targetCls); } CorInfoType interceptor_ICJI::getTypeForPrimitiveValueClass( diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index 600c526ea495bf..46e5802c3610f2 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -731,10 +731,11 @@ CORINFO_CLASS_HANDLE MyICJI::getBuiltinClass(CorInfoClassId classId) } // returns the class handle for the special builtin classes -CORINFO_METHOD_HANDLE MyICJI::getMethodFromDelegate(void* address, bool indirect) +CORINFO_METHOD_HANDLE MyICJI::getMethodFromDelegate(CORINFO_CLASS_HANDLE calledCls, CORINFO_OBJECT_HANDLE delegateObj, + CORINFO_CLASS_HANDLE* methodCls, CORINFO_CLASS_HANDLE* targetCls) { jitInstance->mc->cr->AddCall("getMethodFromDelegate"); - return jitInstance->mc->repGetMethodFromDelegate(address, indirect); + return jitInstance->mc->repGetMethodFromDelegate(calledCls, delegateObj, methodCls, targetCls); } // "System.Int32" ==> CORINFO_TYPE_INT.. diff --git a/src/coreclr/vm/comdelegate.cpp b/src/coreclr/vm/comdelegate.cpp index 205c5105d5a2d8..39b555a7a1c993 100644 --- a/src/coreclr/vm/comdelegate.cpp +++ b/src/coreclr/vm/comdelegate.cpp @@ -1645,7 +1645,7 @@ extern "C" PCODE QCALLTYPE Delegate_AdjustTarget(QCall::ObjectHandleOnStack targ extern "C" void * _ReturnAddress(void); #endif // _MSC_VER && !TARGET_UNIX -uint32_t MethodDescToNumFixedArgs(MethodDesc *pMD) +uint32_t COMDelegate::MethodDescToNumFixedArgs(MethodDesc *pMD) { WRAPPER_NO_CONTRACT; @@ -1716,8 +1716,8 @@ extern "C" void QCALLTYPE Delegate_Construct(QCall::ObjectHandleOnStack _this, Q MethodDesc* pDelegateInvoke = COMDelegate::FindDelegateInvokeMethod(pDelMT); - UINT invokeArgCount = MethodDescToNumFixedArgs(pDelegateInvoke); - UINT methodArgCount = MethodDescToNumFixedArgs(pMeth); + UINT invokeArgCount = COMDelegate::MethodDescToNumFixedArgs(pDelegateInvoke); + UINT methodArgCount = COMDelegate::MethodDescToNumFixedArgs(pMeth); BOOL isStatic = pMeth->IsStatic(); if (!isStatic) methodArgCount++; // count 'this' @@ -2991,7 +2991,6 @@ MethodDesc* COMDelegate::GetDelegateCtor(TypeHandle delegateType, MethodDesc *pT return pRealCtor; } - BOOL COMDelegate::IsWrapperDelegate(DELEGATEREF dRef) { CONTRACTL diff --git a/src/coreclr/vm/comdelegate.h b/src/coreclr/vm/comdelegate.h index be68b5ef40dd47..d0818951a8d754 100644 --- a/src/coreclr/vm/comdelegate.h +++ b/src/coreclr/vm/comdelegate.h @@ -68,6 +68,7 @@ class COMDelegate // Get the cpu stub for a delegate invoke. static Stub* GetInvokeMethodStub(EEImplMethodDesc* pMD); + static uint32_t MethodDescToNumFixedArgs(MethodDesc* pMD); static MethodDesc * __fastcall GetMethodDesc(OBJECTREF obj); static OBJECTREF GetTargetObject(OBJECTREF obj); diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 67bfa3e206f44d..066f9e0a1818df 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -3986,7 +3986,8 @@ CORINFO_CLASS_HANDLE CEEInfo::getBuiltinClass(CorInfoClassId classId) } /*********************************************************************/ -CORINFO_METHOD_HANDLE CEEInfo::getMethodFromDelegate(void* address, bool indirect) +CORINFO_METHOD_HANDLE CEEInfo::getMethodFromDelegate(CORINFO_CLASS_HANDLE calledCls, CORINFO_OBJECT_HANDLE delegateObj, + CORINFO_CLASS_HANDLE* methodCls, CORINFO_CLASS_HANDLE* targetCls) { CONTRACTL { THROWS; @@ -3994,11 +3995,11 @@ CORINFO_METHOD_HANDLE CEEInfo::getMethodFromDelegate(void* address, bool indirec MODE_PREEMPTIVE; } CONTRACTL_END; - CORINFO_METHOD_HANDLE result = 0; + CORINFO_METHOD_HANDLE result = NULL; JIT_TO_EE_TRANSITION(); - _ASSERTE (address != nullptr); + _ASSERTE (delegateObj != nullptr); { // We get a direct pointer for frozen delegates @@ -4007,14 +4008,63 @@ CORINFO_METHOD_HANDLE CEEInfo::getMethodFromDelegate(void* address, bool indirec // We technically don't need to care about the GC // for frozen delegates, but APIs used here require COOP. GCX_COOP(); - DELEGATEREF delegate = (DELEGATEREF)ObjectToOBJECTREF(indirect ? - *(DelegateObject**)address : (DelegateObject*)address); + DELEGATEREF delegate = (DELEGATEREF)getObjectFromJitHandle(delegateObj); _ASSERTE (delegate != nullptr); - GCPROTECT_BEGIN(delegate); - if (delegate->GetInvocationCount() == 0) - result = (CORINFO_METHOD_HANDLE)COMDelegate::GetMethodDesc(delegate); - GCPROTECT_END(); + TypeHandle delegateType(delegate->GetMethodTable()); + TypeHandle calledType(calledCls); + if (delegateType.CanCastTo(calledType)) + { + GCPROTECT_BEGIN(delegate); + if (delegate->GetInvocationCount() == 0) + { + MethodDesc* method = COMDelegate::GetMethodDesc(delegate); + + PTR_MethodTable targetTable = NULL; + MethodDesc* pDelegateInvoke = COMDelegate::FindDelegateInvokeMethod(calledType.GetMethodTable()); + + UINT invokeArgCount = COMDelegate::MethodDescToNumFixedArgs(pDelegateInvoke); + UINT methodArgCount = COMDelegate::MethodDescToNumFixedArgs(method); + if (!method->IsStatic()) + methodArgCount++; // count 'this' + + if (invokeArgCount != methodArgCount) + { + OBJECTREF target = COMDelegate::GetTargetObject(delegate); + if (target == NULL) + { + // avoid delegates closed over null + method = NULL; + } + else + { + targetTable = target->GetMethodTable(); + } + } + + if (targetCls != NULL) + { + *targetCls = CORINFO_CLASS_HANDLE(targetTable); + } + + if (method != NULL && methodCls != NULL) + { + PTR_MethodTable method_table; + if (!method->IsStatic() && targetCls != NULL) + { + method_table = method->GetExactDeclaringType(targetTable); + } + else + { + method_table = method->GetMethodTable(); + } + *methodCls = CORINFO_CLASS_HANDLE(method_table); + } + + result = (CORINFO_METHOD_HANDLE)method; + } + GCPROTECT_END(); + } } EE_TO_JIT_TRANSITION(); @@ -5101,7 +5151,7 @@ void CEEInfo::getCallInfo( } else { - if (!exactType.IsTypeDesc() && !pTargetMD->IsArray() && !pTargetMD->IsDynamicMethod()) + if (!exactType.IsTypeDesc() && !pTargetMD->IsArray()) { // Because of .NET's notion of base calls, exactType may point to a sub-class // of the actual class that defines pTargetMD. If the JIT decides to inline, it is From e6cb382e57627b5409662c9a1ff0b9b2c277cc07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Petryka?= Date: Thu, 21 Nov 2024 03:59:42 +0100 Subject: [PATCH 10/12] Cleanup code, add more asserts --- src/coreclr/inc/jiteeversionguid.h | 10 ++-- src/coreclr/jit/importercalls.cpp | 53 ++++++++++++++----- .../Common/TypeSystem/IL/DelegateInfo.cs | 1 + .../JitInterface/CorInfoImpl.RyuJit.cs | 27 ++-------- src/coreclr/vm/jitinterface.cpp | 51 ++++++++++-------- 5 files changed, 79 insertions(+), 63 deletions(-) diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 753ef98c703211..f6599100e4ad05 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 = { /* a4c2ac7d-8cb8-4591-bf1d-4fecb271e5f1 */ - 0xa4c2ac7d, - 0x8cb8, - 0x4591, - {0xbf, 0x1d, 0x4f, 0xec, 0xb2, 0x71, 0xe5, 0xf1} +constexpr GUID JITEEVersionIdentifier = { /* b96e2e14-6e3c-48a2-aa20-650d9dcb6673 */ + 0xb96e2e14, + 0x6e3c, + 0x48a2, + {0xaa, 0x20, 0x65, 0x0d, 0x9d, 0xcb, 0x66, 0x73} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index e489cca00c546a..65242318cfd7e7 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -143,7 +143,7 @@ var_types Compiler::impImportCall(OPCODE opcode, // As such, we can't handle static readonly function pointers here. if (originalSig.hasImplicitThis()) { - JITDUMP("impImportCall failed to import calli as call - implicit this not supported\n"); + JITDUMP("impImportCall failed to transform calli - implicit this not supported\n"); } else if (fptr->OperIs(GT_FTN_ADDR)) { @@ -153,11 +153,11 @@ var_types Compiler::impImportCall(OPCODE opcode, info.compCompHnd->getMethodSig(method, &replacementSig, replacementClass); if (replacementSig.hasThis() && eeIsValueClass(replacementClass)) { - JITDUMP("impImportCall aborting transformation - value type instance methods are not supported\n"); + JITDUMP("impImportCall failed to transform calli - value type instance methods are not supported\n"); } else if (!impCanSubstituteSig(&originalSig, &replacementSig)) { - JITDUMP("impImportCall aborting transformation - incompatible signature\n"); + JITDUMP("impImportCall failed to transform calli - incompatible signature\n"); } else { @@ -166,12 +166,12 @@ var_types Compiler::impImportCall(OPCODE opcode, } else { - JITDUMP("impImportCall failed to import calli as call - address node not found\n"); + JITDUMP("impImportCall failed to transform calli - address node not found\n"); } } else { - JITDUMP("\n\nimpImportCall failed to import calli as call - call conv %u is not managed\n", + JITDUMP("\n\nimpImportCall failed to transform calli - call conv %u is not managed\n", originalSig.getCallConv()); } } @@ -203,22 +203,35 @@ var_types Compiler::impImportCall(OPCODE opcode, // This lets us inline DynamicMethods. CORINFO_FIELD_HANDLE field = address->AsIntCon()->GetStaticFieldHandle(); JITDUMP("impImportCall trying to transform delegate - found field %s\n", eeGetFieldName(field, true)); - if (info.compCompHnd->getStaticFieldContent(field, (uint8_t*)&object, - sizeof(CORINFO_OBJECT_HANDLE), 0, false)) + if (info.compCompHnd->getStaticFieldContent(field, (uint8_t*)&object, sizeof(CORINFO_OBJECT_HANDLE), 0, + false)) { JITDUMP("impImportCall trying to transform delegate - found static readonly value\n"); } + else + { + object = NO_OBJECT_HANDLE; + JITDUMP("impImportCall trying to transform delegate - failed to read field value\n"); + } } } // TODO-Perf: Handle unloadable delegates in the same context. - if (object != NO_OBJECT_HANDLE) + if (object == NO_OBJECT_HANDLE) + { + JITDUMP("impImportCall failed to transform delegate - target delegate not found\n"); + } + else { JITDUMP("impImportCall trying to transform delegate - found delegate at 0x%llx\n", object); replacementMethod = info.compCompHnd->getMethodFromDelegate(pResolvedToken->hClass, object, &replacementClass, &newThisClass); - if (replacementMethod != NO_METHOD_HANDLE) + if (replacementMethod == NO_METHOD_HANDLE) + { + JITDUMP("impImportCall failed to transform delegate - failed to obtain method from delegate\n"); + } + else { firstArgPos = (int)(stackState.esStackDepth - originalSig.numArgs); assert(firstArgPos >= 0); @@ -240,18 +253,20 @@ var_types Compiler::impImportCall(OPCODE opcode, if (replacementMethod != NO_METHOD_HANDLE) { assert(replacementClass != NO_CLASS_HANDLE); + assert(firstArgPos >= -1); - JITDUMP("impImportCall trying to transform call - found target method %s:%s\n", eeGetClassName(replacementClass), - eeGetMethodName(replacementMethod)); + JITDUMP("impImportCall trying to transform call - found target method %s:%s\n", + eeGetClassName(replacementClass), eeGetMethodName(replacementMethod)); unsigned replacementFlags = info.compCompHnd->getMethodAttribs(replacementMethod); if ((replacementFlags & CORINFO_FLG_PINVOKE) != 0) { - JITDUMP("impImportCall aborting transformation - found PInvoke\n"); + JITDUMP("impImportCall failed call transformation - found PInvoke\n"); } else { +#ifdef DEBUG if (firstArgPos >= 0) { // check if we are at a valid position and @@ -260,8 +275,21 @@ var_types Compiler::impImportCall(OPCODE opcode, assert(stackState.esStack[firstArgPos - 1].seTypeInfo.GetType() == TYP_REF); } + if ((newThisClass != NO_CLASS_HANDLE) || (firstArgPos < 0)) + { + // for closed delegates and calli those should be equal + assert(originalSig.totalILArgs() == replacementSig.totalILArgs()); + } + else + { + // for open delegates there should be 1 less arg since we remove the instance + assert((originalSig.totalILArgs() - 1) == replacementSig.totalILArgs()); + } +#endif + if (newThisClass != NO_CLASS_HANDLE) { + // closed delegates assert(firstArgPos >= 0); assert(newThis != nullptr); assert(newThis->TypeGet() == TYP_REF); @@ -271,6 +299,7 @@ var_types Compiler::impImportCall(OPCODE opcode, } else { + // open delegates and calli // shift args if needed if (firstArgPos > 0) { diff --git a/src/coreclr/tools/Common/TypeSystem/IL/DelegateInfo.cs b/src/coreclr/tools/Common/TypeSystem/IL/DelegateInfo.cs index 5db8d661537b08..2c06b0f688e494 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/DelegateInfo.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/DelegateInfo.cs @@ -106,6 +106,7 @@ public TypeDesc Type public DelegateInfo(TypeDesc delegateType, DelegateFeature features) { Debug.Assert(delegateType.IsDelegate); + Debug.Assert(delegateType.IsTypeDefinition); _delegateType = delegateType; _supportedFeatures = features; 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 c33c793e7c0da9..02088152b23268 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs @@ -2423,30 +2423,11 @@ private bool getObjectContent(CORINFO_OBJECT_STRUCT_* objPtr, byte* buffer, int if (targetCls != null) { - DelegateInfo delegateInfo = _compilation.TypeSystemContext.GetDelegateInfo(calledType); - int paramCountDelegateClosed = delegateInfo.Signature.Length + 1; - int paramCountTargetMethod = method.Signature.Length; - if (!method.Signature.IsStatic) - { - paramCountTargetMethod++; - } - - CORINFO_CLASS_STRUCT_* target = null; - if (paramCountDelegateClosed != paramCountTargetMethod) - { - TypeDesc targetType = frozenObject.DelegateTargetType; - if (targetType == null) - { - // avoid delegates closed over null - Debug.Assert(method.Signature.IsStatic); - } - else - { - target = ObjectToHandle(targetType); - } - } + TypeDesc targetType = frozenObject.DelegateTargetType; + Debug.Assert(method.Signature.IsStatic == (targetType == null)); - *targetCls = target; + // NativeAOT doesn't support delegates closed over null so we don't need to do signature checks + *targetCls = targetType == null ? null : ObjectToHandle(targetType); } return ObjectToHandle(method); diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 6fde0df7480ff1..df3c6d54f4a211 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -4001,6 +4001,9 @@ CORINFO_METHOD_HANDLE CEEInfo::getMethodFromDelegate(CORINFO_CLASS_HANDLE called _ASSERTE (delegateObj != nullptr); + MethodDesc* method = NULL; + PTR_MethodTable targetTable = NULL; + { // We get a direct pointer for frozen delegates // and a pointer to a static location for normal ones. @@ -4018,12 +4021,11 @@ CORINFO_METHOD_HANDLE CEEInfo::getMethodFromDelegate(CORINFO_CLASS_HANDLE called GCPROTECT_BEGIN(delegate); if (delegate->GetInvocationCount() == 0) { - MethodDesc* method = COMDelegate::GetMethodDesc(delegate); + method = COMDelegate::GetMethodDesc(delegate); - PTR_MethodTable targetTable = NULL; MethodDesc* pDelegateInvoke = COMDelegate::FindDelegateInvokeMethod(calledType.GetMethodTable()); - UINT invokeArgCount = COMDelegate::MethodDescToNumFixedArgs(pDelegateInvoke); + UINT methodArgCount = COMDelegate::MethodDescToNumFixedArgs(method); if (!method->IsStatic()) methodArgCount++; // count 'this' @@ -4041,32 +4043,35 @@ CORINFO_METHOD_HANDLE CEEInfo::getMethodFromDelegate(CORINFO_CLASS_HANDLE called targetTable = target->GetMethodTable(); } } + } + GCPROTECT_END(); + } + } - if (targetCls != NULL) - { - *targetCls = CORINFO_CLASS_HANDLE(targetTable); - } - - if (method != NULL && methodCls != NULL) - { - PTR_MethodTable method_table; - if (!method->IsStatic() && targetCls != NULL) - { - method_table = method->GetExactDeclaringType(targetTable); - } - else - { - method_table = method->GetMethodTable(); - } - *methodCls = CORINFO_CLASS_HANDLE(method_table); - } + if (method != NULL) + { + if (targetCls != NULL) + { + *targetCls = CORINFO_CLASS_HANDLE(targetTable); + } - result = (CORINFO_METHOD_HANDLE)method; + if (methodCls != NULL) + { + PTR_MethodTable method_table; + if (!method->IsStatic() && targetTable != NULL) + { + method_table = method->GetExactDeclaringType(targetTable); } - GCPROTECT_END(); + else + { + method_table = method->GetMethodTable(); + } + *methodCls = CORINFO_CLASS_HANDLE(method_table); } } + result = (CORINFO_METHOD_HANDLE)method; + EE_TO_JIT_TRANSITION(); return result; From 9340b53c73b7f42aabe29b15f643be7c30d4d00c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Petryka?= Date: Thu, 21 Nov 2024 06:08:19 +0100 Subject: [PATCH 11/12] Fix GC hole --- src/coreclr/jit/importercalls.cpp | 3 ++- src/coreclr/vm/jitinterface.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 65242318cfd7e7..90a2b6c2bfad84 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -153,7 +153,8 @@ var_types Compiler::impImportCall(OPCODE opcode, info.compCompHnd->getMethodSig(method, &replacementSig, replacementClass); if (replacementSig.hasThis() && eeIsValueClass(replacementClass)) { - JITDUMP("impImportCall failed to transform calli - value type instance methods are not supported\n"); + JITDUMP( + "impImportCall failed to transform calli - value type instance methods are not supported\n"); } else if (!impCanSubstituteSig(&originalSig, &replacementSig)) { diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index df3c6d54f4a211..6cb493fabced07 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -4014,11 +4014,11 @@ CORINFO_METHOD_HANDLE CEEInfo::getMethodFromDelegate(CORINFO_CLASS_HANDLE called DELEGATEREF delegate = (DELEGATEREF)getObjectFromJitHandle(delegateObj); _ASSERTE (delegate != nullptr); + GCPROTECT_BEGIN(delegate); TypeHandle delegateType(delegate->GetMethodTable()); TypeHandle calledType(calledCls); if (delegateType.CanCastTo(calledType)) { - GCPROTECT_BEGIN(delegate); if (delegate->GetInvocationCount() == 0) { method = COMDelegate::GetMethodDesc(delegate); @@ -4044,8 +4044,8 @@ CORINFO_METHOD_HANDLE CEEInfo::getMethodFromDelegate(CORINFO_CLASS_HANDLE called } } } - GCPROTECT_END(); } + GCPROTECT_END(); } if (method != NULL) From a42991b3b82fb7105f3e9503f8216ab5ed4ae708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Petryka?= Date: Fri, 29 Nov 2024 02:53:32 +0100 Subject: [PATCH 12/12] Add assert --- src/coreclr/inc/jiteeversionguid.h | 10 +++++----- src/coreclr/jit/importercalls.cpp | 5 ++++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index f6599100e4ad05..b30d832ad61d33 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 = { /* b96e2e14-6e3c-48a2-aa20-650d9dcb6673 */ - 0xb96e2e14, - 0x6e3c, - 0x48a2, - {0xaa, 0x20, 0x65, 0x0d, 0x9d, 0xcb, 0x66, 0x73} +constexpr GUID JITEEVersionIdentifier = { /* 50ca4d0a-3ca6-4755-9b43-d955f72be103 */ + 0x50ca4d0a, + 0x3ca6, + 0x4755, + {0x9b, 0x43, 0xd9, 0x55, 0xf7, 0x2b, 0xe1, 0x03} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 90a2b6c2bfad84..9673e82a826dde 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -149,8 +149,11 @@ var_types Compiler::impImportCall(OPCODE opcode, { // Ldftn should never point to a method from another unloadable context CORINFO_METHOD_HANDLE method = fptr->AsFptrVal()->gtFptrMethod; - replacementClass = info.compCompHnd->getMethodClass(method); + assert(method != NO_METHOD_HANDLE); + + replacementClass = info.compCompHnd->getMethodClass(method); info.compCompHnd->getMethodSig(method, &replacementSig, replacementClass); + if (replacementSig.hasThis() && eeIsValueClass(replacementClass)) { JITDUMP(