From fe252112fe4a1200447e3c4680af18ac6b7822da Mon Sep 17 00:00:00 2001 From: Steven He Date: Thu, 11 Jun 2026 21:31:17 +0900 Subject: [PATCH 1/2] Cleanup getUnboxedEntry and getInstantiatedEntry --- src/coreclr/inc/corinfo.h | 25 ++-- src/coreclr/inc/icorjitinfoimpl_generated.h | 9 -- src/coreclr/inc/jiteeversionguid.h | 10 +- src/coreclr/jit/ICorJitInfo_names_generated.h | 2 - .../jit/ICorJitInfo_wrapper_generated.hpp | 21 ---- src/coreclr/jit/compiler.h | 2 +- src/coreclr/jit/importercalls.cpp | 111 ++++++++---------- src/coreclr/jit/indirectcalltransformer.cpp | 2 +- src/coreclr/jit/inline.h | 3 +- .../tools/Common/JitInterface/CorInfoImpl.cs | 22 ---- .../JitInterface/CorInfoImpl_generated.cs | 34 ------ .../tools/Common/JitInterface/CorInfoTypes.cs | 9 +- .../ThunkGenerator/ThunkInput.txt | 2 - .../aot/jitinterface/jitinterface_generated.h | 23 ---- .../tools/superpmi/superpmi-shared/agnostic.h | 7 -- .../tools/superpmi/superpmi-shared/lwmlist.h | 2 - .../superpmi-shared/methodcontext.cpp | 84 ------------- .../superpmi/superpmi-shared/methodcontext.h | 17 +-- .../superpmi-shim-collector/icorjitinfo.cpp | 22 ---- .../icorjitinfo_generated.cpp | 17 --- .../icorjitinfo_generated.cpp | 15 --- .../tools/superpmi/superpmi/icorjitinfo.cpp | 15 --- src/coreclr/vm/jitinterface.cpp | 84 ++----------- 23 files changed, 85 insertions(+), 453 deletions(-) diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 5ac1524d19c6f1..98a03384d8b26d 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -1583,12 +1583,15 @@ struct CORINFO_DEVIRTUALIZATION_INFO // [Out] results of resolveVirtualMethod. // - devirtualizedMethod is set to MethodDesc of devirt'ed method iff we were able to devirtualize. // invariant is `resolveVirtualMethod(...) == (devirtualizedMethod != nullptr)`. - // - tokenLookupContext is set to the wrapped context handle to use for token lookups after devirtualization. + // - tokenLookupContext is set to the wrapped context handle to use for token lookups and the instantiation + // parameter after devirtualization. // - details on the computation done by the jit host - // - If pResolvedTokenDevirtualizedMethod is not set to NULL and targeting an R2R image - // use it as the parameter to getCallInfo + // - resolvedTokenDevirtualizedMethod is used as the parameter to getCallInfo when targeting an R2R image. + // - resolvedTokenDevirtualizedUnboxedMethod is set when devirtualizedMethod is an unboxing stub. Its hMethod + // is the unboxed entry point, and the resolved token is used as the parameter to getCallInfo when targeting + // an R2R image. // - instParamLookup contains all the information necessary to pass the instantiation parameter for - // the devirtualized method. + // the devirtualized method or its unboxed entry point. // CORINFO_METHOD_HANDLE devirtualizedMethod; CORINFO_CONTEXT_HANDLE tokenLookupContext; @@ -2265,20 +2268,6 @@ class ICorStaticInfo // Returns false if devirtualization is not possible. virtual bool resolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO * info) = 0; - // Get the unboxed entry point for a method, if possible. - virtual CORINFO_METHOD_HANDLE getUnboxedEntry( - CORINFO_METHOD_HANDLE ftn, - bool* requiresInstMethodTableArg - ) = 0; - - // Get the wrapped entry point for an instantiating stub, if possible. - // Sets methodArg for method instantiations, classArg for class instantiations. - virtual CORINFO_METHOD_HANDLE getInstantiatedEntry( - CORINFO_METHOD_HANDLE ftn, - CORINFO_METHOD_HANDLE* methodArg, - CORINFO_CLASS_HANDLE* classArg - ) = 0; - // Get the other variant of an async method, if possible. // If this is a method with async calling convention: returns the corresponding task-returning method. // If this is a task-returning method: returns the corresponding method with async calling convention. diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 8fc80cda20018c..09d1608bfa134f 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -95,15 +95,6 @@ void getMethodVTableOffset( bool resolveVirtualMethod( CORINFO_DEVIRTUALIZATION_INFO* info) override; -CORINFO_METHOD_HANDLE getUnboxedEntry( - CORINFO_METHOD_HANDLE ftn, - bool* requiresInstMethodTableArg) override; - -CORINFO_METHOD_HANDLE getInstantiatedEntry( - CORINFO_METHOD_HANDLE ftn, - CORINFO_METHOD_HANDLE* methodArg, - CORINFO_CLASS_HANDLE* classArg) override; - CORINFO_METHOD_HANDLE getAsyncOtherVariant( CORINFO_METHOD_HANDLE ftn, bool* variantIsThunk) override; diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 85d8a8682bf489..bc9e29979e6989 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -37,11 +37,11 @@ #include -constexpr GUID JITEEVersionIdentifier = { /* 59df85b8-c0fd-4e40-aea1-68cb2cd916cc */ - 0x59df85b8, - 0xc0fd, - 0x4e40, - {0xae, 0xa1, 0x68, 0xcb, 0x2c, 0xd9, 0x16, 0xcc} +constexpr GUID JITEEVersionIdentifier = { /* 14ca1721-a3ba-40a0-b8a6-92a939719e66 */ + 0x14ca1721, + 0xa3ba, + 0x40a0, + {0xb8, 0xa6, 0x92, 0xa9, 0x39, 0x71, 0x9e, 0x66} }; #endif // JIT_EE_VERSIONING_GUID_H diff --git a/src/coreclr/jit/ICorJitInfo_names_generated.h b/src/coreclr/jit/ICorJitInfo_names_generated.h index 57781f560ce0d5..32abc2cd9596d2 100644 --- a/src/coreclr/jit/ICorJitInfo_names_generated.h +++ b/src/coreclr/jit/ICorJitInfo_names_generated.h @@ -21,8 +21,6 @@ DEF_CLR_API(getEHinfo) DEF_CLR_API(getMethodClass) DEF_CLR_API(getMethodVTableOffset) DEF_CLR_API(resolveVirtualMethod) -DEF_CLR_API(getUnboxedEntry) -DEF_CLR_API(getInstantiatedEntry) DEF_CLR_API(getAsyncOtherVariant) DEF_CLR_API(getDefaultComparerClass) DEF_CLR_API(getDefaultEqualityComparerClass) diff --git a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp index 87e541b608f155..c775460f0c1bbc 100644 --- a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp +++ b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp @@ -181,27 +181,6 @@ bool WrapICorJitInfo::resolveVirtualMethod( return temp; } -CORINFO_METHOD_HANDLE WrapICorJitInfo::getUnboxedEntry( - CORINFO_METHOD_HANDLE ftn, - bool* requiresInstMethodTableArg) -{ - API_ENTER(getUnboxedEntry); - CORINFO_METHOD_HANDLE temp = wrapHnd->getUnboxedEntry(ftn, requiresInstMethodTableArg); - API_LEAVE(getUnboxedEntry); - return temp; -} - -CORINFO_METHOD_HANDLE WrapICorJitInfo::getInstantiatedEntry( - CORINFO_METHOD_HANDLE ftn, - CORINFO_METHOD_HANDLE* methodArg, - CORINFO_CLASS_HANDLE* classArg) -{ - API_ENTER(getInstantiatedEntry); - CORINFO_METHOD_HANDLE temp = wrapHnd->getInstantiatedEntry(ftn, methodArg, classArg); - API_LEAVE(getInstantiatedEntry); - return temp; -} - CORINFO_METHOD_HANDLE WrapICorJitInfo::getAsyncOtherVariant( CORINFO_METHOD_HANDLE ftn, bool* variantIsThunk) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index de116a31f9ebb1..9c834818a54890 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -4977,7 +4977,7 @@ class Compiler { CORINFO_CONTEXT_HANDLE tokenLookupContext; // The class context or method context CORINFO_RESOLVED_TOKEN* pResolvedToken; // Resolved token for the target method, used by R2R. - CORINFO_RESOLVED_TOKEN* pUnboxedResolvedToken; // Resolved token for the unboxed entry, used by R2R. + CORINFO_RESOLVED_TOKEN* pUnboxedResolvedToken; // Resolved token and method handle for the unboxed entry. CORINFO_LOOKUP* pInstParamLookup; // All the information needed for the instantiation parameter lookup. CORINFO_SIG_INFO* pMethSig; // The devirted method signature. bool objIsNonNull; // True if the receiver is known non-null. diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 851e08288b3d35..258067957e2091 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -8161,7 +8161,6 @@ void Compiler::addGuardedDevirtualizationCandidate(GenTreeCall* call, InlineCandidateInfo* pInfo = new (this, CMK_Inlining) InlineCandidateInfo; pInfo->guardedMethodHandle = methodHandle; - pInfo->guardedMethodUnboxedEntryHandle = nullptr; pInfo->guardedMethodInstParamLookup = {}; pInfo->guardedMethodResolvedToken = {}; pInfo->guardedMethodUnboxedResolvedToken = {}; @@ -8181,22 +8180,6 @@ void Compiler::addGuardedDevirtualizationCandidate(GenTreeCall* call, pInfo->guardedMethodUnboxedResolvedToken = *pUnboxedResolvedToken; } - // If the guarded class is a value class, look for an unboxed entry point. - // - if ((classAttr & CORINFO_FLG_VALUECLASS) != 0) - { - JITDUMP(" ... class is a value class, looking for unboxed entry\n"); - bool requiresInstMethodTableArg = false; - CORINFO_METHOD_HANDLE unboxedEntryMethodHandle = - info.compCompHnd->getUnboxedEntry(methodHandle, &requiresInstMethodTableArg); - - if (unboxedEntryMethodHandle != nullptr) - { - JITDUMP(" ... updating GDV candidate with unboxed entry info\n"); - pInfo->guardedMethodUnboxedEntryHandle = unboxedEntryMethodHandle; - } - } - call->AddGDVCandidateInfo(this, pInfo); } @@ -8472,9 +8455,9 @@ void Compiler::impMarkInlineCandidateHelper(GenTreeCall* call, if (call->IsGuardedDevirtualizationCandidate()) { InlineCandidateInfo* gdvCandidate = call->GetGDVCandidateInfo(candidateIndex); - if (gdvCandidate->guardedMethodUnboxedEntryHandle != nullptr) + if (gdvCandidate->guardedMethodUnboxedResolvedToken.hMethod != nullptr) { - fncHandle = gdvCandidate->guardedMethodUnboxedEntryHandle; + fncHandle = gdvCandidate->guardedMethodUnboxedResolvedToken.hMethod; } else { @@ -9411,61 +9394,61 @@ void Compiler::impTransformDevirtualizedCall(GenTreeCall* call, { JITDUMP("Have a direct call to boxed entry point. Trying to optimize to call an unboxed entry point\n"); - // Note for some shared methods the unboxed entry point requires an extra parameter. - bool requiresInstMethodTableArg = false; - CORINFO_METHOD_HANDLE unboxedEntryMethod = - info.compCompHnd->getUnboxedEntry(derivedMethod, &requiresInstMethodTableArg); + CORINFO_METHOD_HANDLE const unboxedEntryMethod = + (dcInfo->pUnboxedResolvedToken == nullptr) ? nullptr : dcInfo->pUnboxedResolvedToken->hMethod; if (unboxedEntryMethod != nullptr) { - // Rewrite the call to target the unboxed entry on the box payload. Keep the heap box, - // since the callee may return an interior managed pointer into it; object stack allocation - // can later promote the box to the stack when escape analysis proves the receiver does not - // escape. - // - if (requiresInstMethodTableArg) - { - // Get the method table from the boxed object. - // - // TODO-CallArgs-REVIEW: Use thisObj here? Differs by gtEffectiveVal. - GenTree* const clonedThisArg = gtClone(thisArg->GetEarlyNode()); + CORINFO_SIG_INFO unboxedEntrySig; + info.compCompHnd->getMethodSig(unboxedEntryMethod, &unboxedEntrySig); + + bool canUseUnboxedEntry = true; - if (clonedThisArg == nullptr) + if (unboxedEntrySig.hasTypeArg()) + { + if (unboxedEntrySig.sigInst.methInstCount != 0) { - JITDUMP("unboxed entry needs MT arg, but `this` was too complex to clone. Deferring update.\n"); + assert(((SIZE_T)dcInfo->tokenLookupContext & CORINFO_CONTEXTFLAGS_MASK) == + CORINFO_CONTEXTFLAGS_METHOD); + CORINFO_METHOD_HANDLE exactMethodHandle = + (CORINFO_METHOD_HANDLE)((SIZE_T)dcInfo->tokenLookupContext & ~CORINFO_CONTEXTFLAGS_MASK); + + instParam = getLookupTree(dcInfo->pInstParamLookup, GTF_ICON_METHOD_HDL, exactMethodHandle); + JITDUMP("revising call to invoke unboxed entry with additional method desc arg\n"); } else { - JITDUMP("revising call to invoke unboxed entry with additional method table arg\n"); - - instParam = gtNewMethodTableLookup(clonedThisArg); - - // Update the 'this' pointer to refer to the box payload + // Get the method table from the boxed object. // - GenTree* const payloadOffset = gtNewIconNode(TARGET_POINTER_SIZE, TYP_I_IMPL); - GenTree* const boxPayload = - gtNewOperNode(GT_ADD, TYP_BYREF, thisArg->GetEarlyNode(), payloadOffset); - - assert(thisObj == thisArg->GetEarlyNode()); - thisArg->SetEarlyNode(boxPayload); - call->gtCallMethHnd = unboxedEntryMethod; - INDEBUG(call->gtCallDebugFlags |= GTF_CALL_MD_UNBOXED); + // TODO-CallArgs-REVIEW: Use thisObj here? Differs by gtEffectiveVal. + GenTree* const clonedThisArg = gtClone(thisArg->GetEarlyNode()); - // Method attributes will differ because unboxed entry point is shared - // - const DWORD unboxedMethodAttribs = info.compCompHnd->getMethodAttribs(unboxedEntryMethod); - JITDUMP("Updating method attribs from 0x%08x to 0x%08x\n", derivedMethodAttribs, - unboxedMethodAttribs); - derivedMethod = unboxedEntryMethod; - pDerivedResolvedToken = dcInfo->pUnboxedResolvedToken; - derivedMethodAttribs = unboxedMethodAttribs; - Metrics.DevirtualizedCallUnboxedEntry++; + if (clonedThisArg == nullptr) + { + JITDUMP( + "unboxed entry needs MT arg, but `this` was too complex to clone. Deferring update.\n"); + canUseUnboxedEntry = false; + } + else + { + instParam = gtNewMethodTableLookup(clonedThisArg); + assert(thisObj == thisArg->GetEarlyNode()); + JITDUMP("revising call to invoke unboxed entry with additional method table arg\n"); + } } } else { JITDUMP("revising call to invoke unboxed entry\n"); + } + if (canUseUnboxedEntry) + { + // Rewrite the call to target the unboxed entry on the box payload. Keep the heap box, + // since the callee may return an interior managed pointer into it; object stack allocation + // can later promote the box to the stack when escape analysis proves the receiver does not + // escape. + // GenTree* const payloadOffset = gtNewIconNode(TARGET_POINTER_SIZE, TYP_I_IMPL); GenTree* const boxPayload = gtNewOperNode(GT_ADD, TYP_BYREF, thisArg->GetEarlyNode(), payloadOffset); @@ -9473,6 +9456,17 @@ void Compiler::impTransformDevirtualizedCall(GenTreeCall* call, thisArg->SetEarlyNode(boxPayload); call->gtCallMethHnd = unboxedEntryMethod; INDEBUG(call->gtCallDebugFlags |= GTF_CALL_MD_UNBOXED); + + if (unboxedEntrySig.hasTypeArg()) + { + // Method attributes will differ because unboxed entry point is shared. + // + const DWORD unboxedMethodAttribs = info.compCompHnd->getMethodAttribs(unboxedEntryMethod); + JITDUMP("Updating method attribs from 0x%08x to 0x%08x\n", derivedMethodAttribs, + unboxedMethodAttribs); + derivedMethodAttribs = unboxedMethodAttribs; + } + derivedMethod = unboxedEntryMethod; pDerivedResolvedToken = dcInfo->pUnboxedResolvedToken; Metrics.DevirtualizedCallUnboxedEntry++; @@ -10068,7 +10062,6 @@ void Compiler::impCheckCanInline(GenTreeCall* call, // pInfo->guardedClassHandle = nullptr; pInfo->guardedMethodHandle = nullptr; - pInfo->guardedMethodUnboxedEntryHandle = nullptr; pInfo->guardedMethodInstParamLookup = {}; pInfo->guardedMethodResolvedToken = {}; pInfo->guardedMethodUnboxedResolvedToken = {}; diff --git a/src/coreclr/jit/indirectcalltransformer.cpp b/src/coreclr/jit/indirectcalltransformer.cpp index 892a2c5b430586..195c3ad5dc877c 100644 --- a/src/coreclr/jit/indirectcalltransformer.cpp +++ b/src/coreclr/jit/indirectcalltransformer.cpp @@ -1007,7 +1007,7 @@ class IndirectCallTransformer // If the devirtualizer was unable to transform the call to invoke the unboxed entry, the inline info // we set up may be invalid. We won't be able to inline anyways. So demote the call as an inline candidate. // - CORINFO_METHOD_HANDLE unboxedMethodHnd = inlineInfo->guardedMethodUnboxedEntryHandle; + CORINFO_METHOD_HANDLE unboxedMethodHnd = inlineInfo->guardedMethodUnboxedResolvedToken.hMethod; if ((unboxedMethodHnd != nullptr) && (methodHnd != unboxedMethodHnd)) { // Demote this call to a non-inline candidate diff --git a/src/coreclr/jit/inline.h b/src/coreclr/jit/inline.h index 595acc9ecb174f..065f7de3eaaa20 100644 --- a/src/coreclr/jit/inline.h +++ b/src/coreclr/jit/inline.h @@ -595,10 +595,9 @@ struct InlineCandidateInfo : public HandleHistogramProfileCandidateInfo { CORINFO_CLASS_HANDLE guardedClassHandle; CORINFO_METHOD_HANDLE guardedMethodHandle; - CORINFO_METHOD_HANDLE guardedMethodUnboxedEntryHandle; CORINFO_LOOKUP guardedMethodInstParamLookup; CORINFO_RESOLVED_TOKEN guardedMethodResolvedToken; // Only used by R2R - CORINFO_RESOLVED_TOKEN guardedMethodUnboxedResolvedToken; // Only used by R2R + CORINFO_RESOLVED_TOKEN guardedMethodUnboxedResolvedToken; // hMethod is the unboxed entry; token data is used by R2R unsigned likelihood; CORINFO_METHOD_INFO methInfo; diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 5638e885771ee5..80250efc4e5b39 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -1540,28 +1540,6 @@ static CORINFO_RESOLVED_TOKEN CreateResolvedTokenFromMethod(CorInfoImpl jitInter } } - private CORINFO_METHOD_STRUCT_* getUnboxedEntry(CORINFO_METHOD_STRUCT_* ftn, ref bool requiresInstMethodTableArg) - { - MethodDesc result = null; - requiresInstMethodTableArg = false; - - MethodDesc method = HandleToObject(ftn); - if (method.IsUnboxingThunk()) - { - result = method.GetUnboxedMethod(); - requiresInstMethodTableArg = method.RequiresInstMethodTableArg(); - } - - return result != null ? ObjectToHandle(result) : null; - } - - private CORINFO_METHOD_STRUCT_* getInstantiatedEntry(CORINFO_METHOD_STRUCT_* ftn, CORINFO_METHOD_STRUCT_** methodArg, CORINFO_CLASS_STRUCT_** classArg) - { - *methodArg = null; - *classArg = null; - return null; - } - private CORINFO_METHOD_STRUCT_* getAsyncOtherVariant(CORINFO_METHOD_STRUCT_* ftn, ref bool variantIsThunk) { MethodDesc method = HandleToObject(ftn); diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index 2ec1fc175a8d91..74da04da013a53 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -37,8 +37,6 @@ static ICorJitInfoCallbacks() s_callbacks.getMethodClass = &_getMethodClass; s_callbacks.getMethodVTableOffset = &_getMethodVTableOffset; s_callbacks.resolveVirtualMethod = &_resolveVirtualMethod; - s_callbacks.getUnboxedEntry = &_getUnboxedEntry; - s_callbacks.getInstantiatedEntry = &_getInstantiatedEntry; s_callbacks.getAsyncOtherVariant = &_getAsyncOtherVariant; s_callbacks.getDefaultComparerClass = &_getDefaultComparerClass; s_callbacks.getDefaultEqualityComparerClass = &_getDefaultEqualityComparerClass; @@ -220,8 +218,6 @@ static ICorJitInfoCallbacks() public delegate* unmanaged getMethodClass; public delegate* unmanaged getMethodVTableOffset; public delegate* unmanaged resolveVirtualMethod; - public delegate* unmanaged getUnboxedEntry; - public delegate* unmanaged getInstantiatedEntry; public delegate* unmanaged getAsyncOtherVariant; public delegate* unmanaged getDefaultComparerClass; public delegate* unmanaged getDefaultEqualityComparerClass; @@ -639,36 +635,6 @@ private static byte _resolveVirtualMethod(IntPtr thisHandle, IntPtr* ppException } } - [UnmanagedCallersOnly] - private static CORINFO_METHOD_STRUCT_* _getUnboxedEntry(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* ftn, bool* requiresInstMethodTableArg) - { - var _this = GetThis(thisHandle); - try - { - return _this.getUnboxedEntry(ftn, ref *requiresInstMethodTableArg); - } - catch (Exception ex) - { - *ppException = _this.AllocException(ex); - return default; - } - } - - [UnmanagedCallersOnly] - private static CORINFO_METHOD_STRUCT_* _getInstantiatedEntry(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* ftn, CORINFO_METHOD_STRUCT_** methodArg, CORINFO_CLASS_STRUCT_** classArg) - { - var _this = GetThis(thisHandle); - try - { - return _this.getInstantiatedEntry(ftn, methodArg, classArg); - } - catch (Exception ex) - { - *ppException = _this.AllocException(ex); - return default; - } - } - [UnmanagedCallersOnly] private static CORINFO_METHOD_STRUCT_* _getAsyncOtherVariant(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* ftn, bool* variantIsThunk) { diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs index f173125897d053..14284d26860edc 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs @@ -1176,10 +1176,15 @@ public unsafe struct CORINFO_DEVIRTUALIZATION_INFO // [Out] results of resolveVirtualMethod. // - devirtualizedMethod is set to MethodDesc of devirt'ed method iff we were able to devirtualize. // invariant is `resolveVirtualMethod(...) == (devirtualizedMethod != nullptr)`. - // - tokenLookupContext is set to the wrapped context handle to use for token lookups after devirtualization. + // - tokenLookupContext is set to the wrapped context handle to use for token lookups and the instantiation + // parameter after devirtualization. // - detail describes the computation done by the jit host + // - resolvedTokenDevirtualizedMethod is used as the parameter to getCallInfo when targeting an R2R image. + // - resolvedTokenDevirtualizedUnboxedMethod is set when devirtualizedMethod is an unboxing stub. Its hMethod + // is the unboxed entry point, and the resolved token is used as the parameter to getCallInfo when targeting + // an R2R image. // - instParamLookup contains all the information necessary to pass the instantiation parameter for - // the devirtualized method. + // the devirtualized method or its unboxed entry point. // public CORINFO_METHOD_STRUCT_* devirtualizedMethod; public CORINFO_CONTEXT_STRUCT* tokenLookupContext; diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index 384ca10f881504..fe14f4d9bc0e5c 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -190,8 +190,6 @@ FUNCTIONS CORINFO_CLASS_HANDLE getMethodClass( CORINFO_METHOD_HANDLE method ); void getMethodVTableOffset( CORINFO_METHOD_HANDLE method, unsigned* offsetOfIndirection, unsigned* offsetAfterIndirection, bool* isRelative); bool resolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO* info); - CORINFO_METHOD_HANDLE getUnboxedEntry(CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg); - CORINFO_METHOD_HANDLE getInstantiatedEntry(CORINFO_METHOD_HANDLE ftn, CORINFO_METHOD_HANDLE* methodArg, CORINFO_CLASS_HANDLE* classArg); CORINFO_METHOD_HANDLE getAsyncOtherVariant(CORINFO_METHOD_HANDLE ftn, bool* variantIsThunk); CORINFO_CLASS_HANDLE getDefaultComparerClass(CORINFO_CLASS_HANDLE elemType); CORINFO_CLASS_HANDLE getDefaultEqualityComparerClass(CORINFO_CLASS_HANDLE elemType); diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h index 90ec07a3b446bc..0049a99f1e1dd8 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h @@ -28,8 +28,6 @@ struct JitInterfaceCallbacks CORINFO_CLASS_HANDLE (* getMethodClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE method); void (* getMethodVTableOffset)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE method, unsigned* offsetOfIndirection, unsigned* offsetAfterIndirection, bool* isRelative); bool (* resolveVirtualMethod)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_DEVIRTUALIZATION_INFO* info); - CORINFO_METHOD_HANDLE (* getUnboxedEntry)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg); - CORINFO_METHOD_HANDLE (* getInstantiatedEntry)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, CORINFO_METHOD_HANDLE* methodArg, CORINFO_CLASS_HANDLE* classArg); CORINFO_METHOD_HANDLE (* getAsyncOtherVariant)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, bool* variantIsThunk); CORINFO_CLASS_HANDLE (* getDefaultComparerClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE elemType); CORINFO_CLASS_HANDLE (* getDefaultEqualityComparerClass)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE elemType); @@ -376,27 +374,6 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } - virtual CORINFO_METHOD_HANDLE getUnboxedEntry( - CORINFO_METHOD_HANDLE ftn, - bool* requiresInstMethodTableArg) -{ - CorInfoExceptionClass* pException = nullptr; - CORINFO_METHOD_HANDLE temp = _callbacks->getUnboxedEntry(_thisHandle, &pException, ftn, requiresInstMethodTableArg); - if (pException != nullptr) throw pException; - return temp; -} - - virtual CORINFO_METHOD_HANDLE getInstantiatedEntry( - CORINFO_METHOD_HANDLE ftn, - CORINFO_METHOD_HANDLE* methodArg, - CORINFO_CLASS_HANDLE* classArg) -{ - CorInfoExceptionClass* pException = nullptr; - CORINFO_METHOD_HANDLE temp = _callbacks->getInstantiatedEntry(_thisHandle, &pException, ftn, methodArg, classArg); - if (pException != nullptr) throw pException; - return temp; -} - virtual CORINFO_METHOD_HANDLE getAsyncOtherVariant( CORINFO_METHOD_HANDLE ftn, bool* variantIsThunk) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h index 85a7a8bf540eed..82bbc093be6f70 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h @@ -694,13 +694,6 @@ struct Agnostic_ResolveVirtualMethodResult Agnostic_CORINFO_LOOKUP instParamLookup; }; -struct Agnostic_GetInstantiatedEntryResult -{ - DWORDLONG methodHandle; - DWORDLONG classHandle; - DWORDLONG result; -}; - struct ResolveTokenValue { Agnostic_CORINFO_RESOLVED_TOKENout tokenOut; diff --git a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h index b464feef60b3f6..957c92a4aa30f7 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -138,8 +138,6 @@ LWM(GetTokenTypeAsHandle, GetTokenTypeAsHandleValue, DWORDLONG) LWM(GetTypeForBox, DWORDLONG, DWORDLONG) LWM(GetTypeForPrimitiveValueClass, DWORDLONG, DWORD) LWM(GetTypeForPrimitiveNumericClass, DWORDLONG, DWORD) -LWM(GetUnboxedEntry, DWORDLONG, DLD); -LWM(GetInstantiatedEntry, DWORDLONG, Agnostic_GetInstantiatedEntryResult); LWM(GetAsyncOtherVariant, DWORDLONG, DLD); LWM(GetUnBoxHelper, DWORDLONG, DWORD) LWM(GetRuntimeTypePointer, DWORDLONG, DWORDLONG) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index ec6b3b9e1ef4ac..85dec9a6b527ca 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -3318,90 +3318,6 @@ bool MethodContext::repResolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO * info return result.returnValue; } -void MethodContext::recGetUnboxedEntry(CORINFO_METHOD_HANDLE ftn, - bool* requiresInstMethodTableArg, - CORINFO_METHOD_HANDLE result) -{ - if (GetUnboxedEntry == nullptr) - { - GetUnboxedEntry = new LightWeightMap(); - } - - DWORDLONG key = CastHandle(ftn); - DLD value; - value.A = CastHandle(result); - if (requiresInstMethodTableArg != nullptr) - { - value.B = (DWORD)*requiresInstMethodTableArg ? 1 : 0; - } - else - { - value.B = 0; - } - GetUnboxedEntry->Add(key, value); - DEBUG_REC(dmpGetUnboxedEntry(key, value)); -} - -void MethodContext::dmpGetUnboxedEntry(DWORDLONG key, DLD value) -{ - printf("GetUnboxedEntry ftn-%016" PRIX64 ", result-%016" PRIX64 ", requires-inst-%u", key, value.A, value.B); -} - -CORINFO_METHOD_HANDLE MethodContext::repGetUnboxedEntry(CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg) -{ - DWORDLONG key = CastHandle(ftn); - - DLD value = LookupByKeyOrMiss(GetUnboxedEntry, key, ": key %016" PRIX64 "", key); - - DEBUG_REP(dmpGetUnboxedEntry(key, value)); - - if (requiresInstMethodTableArg != nullptr) - { - *requiresInstMethodTableArg = (value.B == 1); - } - return (CORINFO_METHOD_HANDLE)(value.A); -} - -void MethodContext::recGetInstantiatedEntry(CORINFO_METHOD_HANDLE ftn, - CORINFO_METHOD_HANDLE methodHandle, - CORINFO_CLASS_HANDLE classHandle, - CORINFO_METHOD_HANDLE result) -{ - if (GetInstantiatedEntry == nullptr) - { - GetInstantiatedEntry = new LightWeightMap(); - } - - DWORDLONG key = CastHandle(ftn); - Agnostic_GetInstantiatedEntryResult value; - value.methodHandle = CastHandle(methodHandle); - value.classHandle = CastHandle(classHandle); - value.result = CastHandle(result); - - GetInstantiatedEntry->Add(key, value); - DEBUG_REC(dmpGetUnboxedEntry(key, value)); -} - -void MethodContext::dmpGetInstantiatedEntry(DWORDLONG key, const Agnostic_GetInstantiatedEntryResult& value) -{ - printf("GetUnboxedEntry ftn-%016" PRIX64 ", methodHnd-%016" PRIX64 ", classHnd-%016" PRIX64 ", result-%016" PRIX64 "\n", - key, value.methodHandle, value.classHandle, value.result); -} - -CORINFO_METHOD_HANDLE MethodContext::repGetInstantiatedEntry(CORINFO_METHOD_HANDLE ftn, CORINFO_METHOD_HANDLE* methodHandle, CORINFO_CLASS_HANDLE* classHandle) -{ - DWORDLONG key = CastHandle(ftn); - - Agnostic_GetInstantiatedEntryResult value = LookupByKeyOrMiss(GetInstantiatedEntry, key, ": key %016" PRIX64 "", key); - - DEBUG_REP(dmpGetInstantiatedEntryEntry(key, value)); - - *methodHandle = (CORINFO_METHOD_HANDLE)value.methodHandle; - *classHandle = (CORINFO_CLASS_HANDLE)value.classHandle; - - return (CORINFO_METHOD_HANDLE)(value.result); -} - void MethodContext::recGetAsyncOtherVariant(CORINFO_METHOD_HANDLE ftn, bool variantIsThunk, CORINFO_METHOD_HANDLE result) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index 449a18a91caeb5..e4cef62c08791a 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -446,19 +446,6 @@ class MethodContext void dmpResolveVirtualMethod(const Agnostic_ResolveVirtualMethodKey& key, const Agnostic_ResolveVirtualMethodResult& value); bool repResolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO * info); - void recGetUnboxedEntry(CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg, CORINFO_METHOD_HANDLE result); - void dmpGetUnboxedEntry(DWORDLONG key, DLD value); - CORINFO_METHOD_HANDLE repGetUnboxedEntry(CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg); - - 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_CLASS_HANDLE* classHandle); - void recGetAsyncOtherVariant(CORINFO_METHOD_HANDLE ftn, bool variantIsThunk, CORINFO_METHOD_HANDLE result); void dmpGetAsyncOtherVariant(DWORDLONG key, DLD value); CORINFO_METHOD_HANDLE repGetAsyncOtherVariant(CORINFO_METHOD_HANDLE ftn, bool* variantIsThunk); @@ -1149,7 +1136,7 @@ enum mcPackets Packet_GetDefaultEqualityComparerClass = 162, Packet_CompareTypesForCast = 163, Packet_CompareTypesForEquality = 164, - Packet_GetUnboxedEntry = 165, + //Packet_GetUnboxedEntry = 165, Packet_GetClassNameFromMetadata = 166, Packet_GetTypeInstantiationArgument = 167, Packet_GetTypeForPrimitiveNumericClass = 168, @@ -1212,7 +1199,7 @@ enum mcPackets Packet_GetClassAssemblyName = 225, Packet_GetSZArrayHelperEnumeratorClass = 226, Packet_GetMethodInstantiationArgument = 227, - Packet_GetInstantiatedEntry = 228, + //Packet_GetInstantiatedEntry = 228, Packet_NotifyInstructionSetUsage = 229, Packet_GetAsyncInfo = 230, Packet_GetAsyncResumptionStub = 231, diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index 6d0cadcd5616ae..04082c6ac0c406 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -241,28 +241,6 @@ bool interceptor_ICJI::resolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO * info return result; } -// Get the unboxed entry point for a method, if possible. -CORINFO_METHOD_HANDLE interceptor_ICJI::getUnboxedEntry(CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg) -{ - mc->cr->AddCall("getUnboxedEntry"); - bool localRequiresInstMethodTableArg = false; - CORINFO_METHOD_HANDLE result = original_ICorJitInfo->getUnboxedEntry(ftn, &localRequiresInstMethodTableArg); - mc->recGetUnboxedEntry(ftn, &localRequiresInstMethodTableArg, result); - if (requiresInstMethodTableArg != nullptr) - { - *requiresInstMethodTableArg = localRequiresInstMethodTableArg; - } - return result; -} - -CORINFO_METHOD_HANDLE interceptor_ICJI::getInstantiatedEntry(CORINFO_METHOD_HANDLE ftn, CORINFO_METHOD_HANDLE* methodHandle, CORINFO_CLASS_HANDLE* classHandle) -{ - mc->cr->AddCall("getInstantaitedEntry"); - CORINFO_METHOD_HANDLE result = original_ICorJitInfo->getInstantiatedEntry(ftn, methodHandle, classHandle); - mc->recGetInstantiatedEntry(ftn, *methodHandle, *classHandle, result); - return result; -} - CORINFO_METHOD_HANDLE interceptor_ICJI::getAsyncOtherVariant(CORINFO_METHOD_HANDLE ftn, bool* variantIsThunk) { mc->cr->AddCall("getAsyncOtherVariant"); 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 874083bd15b940..3b3ad4933853be 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp @@ -154,23 +154,6 @@ bool interceptor_ICJI::resolveVirtualMethod( return original_ICorJitInfo->resolveVirtualMethod(info); } -CORINFO_METHOD_HANDLE interceptor_ICJI::getUnboxedEntry( - CORINFO_METHOD_HANDLE ftn, - bool* requiresInstMethodTableArg) -{ - mcs->AddCall("getUnboxedEntry"); - return original_ICorJitInfo->getUnboxedEntry(ftn, requiresInstMethodTableArg); -} - -CORINFO_METHOD_HANDLE interceptor_ICJI::getInstantiatedEntry( - CORINFO_METHOD_HANDLE ftn, - CORINFO_METHOD_HANDLE* methodArg, - CORINFO_CLASS_HANDLE* classArg) -{ - mcs->AddCall("getInstantiatedEntry"); - return original_ICorJitInfo->getInstantiatedEntry(ftn, methodArg, classArg); -} - CORINFO_METHOD_HANDLE interceptor_ICJI::getAsyncOtherVariant( CORINFO_METHOD_HANDLE ftn, bool* variantIsThunk) 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 b870f0f947f2f6..5e9dbe609bde3b 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp @@ -137,21 +137,6 @@ bool interceptor_ICJI::resolveVirtualMethod( return original_ICorJitInfo->resolveVirtualMethod(info); } -CORINFO_METHOD_HANDLE interceptor_ICJI::getUnboxedEntry( - CORINFO_METHOD_HANDLE ftn, - bool* requiresInstMethodTableArg) -{ - return original_ICorJitInfo->getUnboxedEntry(ftn, requiresInstMethodTableArg); -} - -CORINFO_METHOD_HANDLE interceptor_ICJI::getInstantiatedEntry( - CORINFO_METHOD_HANDLE ftn, - CORINFO_METHOD_HANDLE* methodArg, - CORINFO_CLASS_HANDLE* classArg) -{ - return original_ICorJitInfo->getInstantiatedEntry(ftn, methodArg, classArg); -} - CORINFO_METHOD_HANDLE interceptor_ICJI::getAsyncOtherVariant( CORINFO_METHOD_HANDLE ftn, bool* variantIsThunk) diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index 93262fd2279b01..c2743ff9524bb4 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -203,21 +203,6 @@ bool MyICJI::resolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO * info) return result; } -// Get the unboxed entry point for a method, if possible. -CORINFO_METHOD_HANDLE MyICJI::getUnboxedEntry(CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg) -{ - jitInstance->mc->cr->AddCall("getUnboxedEntry"); - CORINFO_METHOD_HANDLE result = jitInstance->mc->repGetUnboxedEntry(ftn, requiresInstMethodTableArg); - return result; -} - -CORINFO_METHOD_HANDLE MyICJI::getInstantiatedEntry(CORINFO_METHOD_HANDLE ftn, CORINFO_METHOD_HANDLE* methodHandle, CORINFO_CLASS_HANDLE* classHandle) -{ - jitInstance->mc->cr->AddCall("getInstantiatedEntry"); - CORINFO_METHOD_HANDLE result = jitInstance->mc->repGetInstantiatedEntry(ftn, methodHandle, classHandle); - return result; -} - CORINFO_METHOD_HANDLE MyICJI::getAsyncOtherVariant(CORINFO_METHOD_HANDLE ftn, bool* variantIsThunk) { jitInstance->mc->cr->AddCall("getAsyncOtherVariant"); diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index c0ec22f3e75a8f..b6bce399a68a56 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -8880,6 +8880,15 @@ bool CEEInfo::resolveVirtualMethodHelper(CORINFO_DEVIRTUALIZATION_INFO * info) info->tokenLookupContext = MAKE_CLASSCONTEXT((CORINFO_CLASS_HANDLE) pExactMT); } + // If we devirtualized into an unboxing stub, also hand back the unboxed entry + // so the jit can perform the unboxing transformation. + // + if (pDevirtMD->IsUnboxingStub()) + { + MethodDesc* pUnboxedMD = pDevirtMD->GetMethodTable()->GetUnboxedEntryPointMD(pDevirtMD); + info->resolvedTokenDevirtualizedUnboxedMethod.hMethod = (CORINFO_METHOD_HANDLE) pUnboxedMD; + } + // Success! Pass back the results. // info->devirtualizedMethod = (CORINFO_METHOD_HANDLE) pDevirtMD; @@ -8907,81 +8916,6 @@ bool CEEInfo::resolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO * info) return result; } -/*********************************************************************/ -CORINFO_METHOD_HANDLE CEEInfo::getUnboxedEntry( - CORINFO_METHOD_HANDLE ftn, - bool* requiresInstMethodTableArg) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_PREEMPTIVE; - } CONTRACTL_END; - - CORINFO_METHOD_HANDLE result = NULL; - - JIT_TO_EE_TRANSITION(); - - MethodDesc* pMD = GetMethod(ftn); - bool requiresInstMTArg = false; - - if (pMD->IsUnboxingStub()) - { - MethodTable* pMT = pMD->GetMethodTable(); - MethodDesc* pUnboxedMD = pMT->GetUnboxedEntryPointMD(pMD); - - result = (CORINFO_METHOD_HANDLE)pUnboxedMD; - requiresInstMTArg = !!pUnboxedMD->RequiresInstMethodTableArg(); - } - - *requiresInstMethodTableArg = requiresInstMTArg; - - EE_TO_JIT_TRANSITION(); - - return result; -} - -/*********************************************************************/ -CORINFO_METHOD_HANDLE CEEInfo::getInstantiatedEntry( - CORINFO_METHOD_HANDLE ftn, - CORINFO_METHOD_HANDLE* methodArg, - CORINFO_CLASS_HANDLE* classArg) -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_PREEMPTIVE; - } CONTRACTL_END; - - CORINFO_METHOD_HANDLE result = NULL; - - JIT_TO_EE_TRANSITION(); - - *methodArg = NULL; - *classArg = NULL; - - MethodDesc* pMD = GetMethod(ftn); - bool requiresInstMTArg = false; - - if (pMD->IsInstantiatingStub()) - { - result = (CORINFO_METHOD_HANDLE) pMD->GetWrappedMethodDesc(); - - if (pMD->HasMethodInstantiation()) - { - *methodArg = ftn; - } - else - { - *classArg = (CORINFO_CLASS_HANDLE)pMD->GetMethodTable(); - } - } - - EE_TO_JIT_TRANSITION(); - - return result; -} - CORINFO_METHOD_HANDLE CEEInfo::getAsyncOtherVariant( CORINFO_METHOD_HANDLE ftn, bool* variantIsThunk) From 852a5724f42f0783e464e6bae9a6d3a1a4abde5e Mon Sep 17 00:00:00 2001 From: Steven He Date: Thu, 11 Jun 2026 21:50:42 +0900 Subject: [PATCH 2/2] Check the context directly --- src/coreclr/jit/importercalls.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 258067957e2091..7c9242370b7bd6 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -9406,10 +9406,8 @@ void Compiler::impTransformDevirtualizedCall(GenTreeCall* call, if (unboxedEntrySig.hasTypeArg()) { - if (unboxedEntrySig.sigInst.methInstCount != 0) + if (((SIZE_T)dcInfo->tokenLookupContext & CORINFO_CONTEXTFLAGS_MASK) == CORINFO_CONTEXTFLAGS_METHOD) { - assert(((SIZE_T)dcInfo->tokenLookupContext & CORINFO_CONTEXTFLAGS_MASK) == - CORINFO_CONTEXTFLAGS_METHOD); CORINFO_METHOD_HANDLE exactMethodHandle = (CORINFO_METHOD_HANDLE)((SIZE_T)dcInfo->tokenLookupContext & ~CORINFO_CONTEXTFLAGS_MASK); @@ -9418,6 +9416,9 @@ void Compiler::impTransformDevirtualizedCall(GenTreeCall* call, } else { + assert(((SIZE_T)dcInfo->tokenLookupContext & CORINFO_CONTEXTFLAGS_MASK) == + CORINFO_CONTEXTFLAGS_CLASS); + // Get the method table from the boxed object. // // TODO-CallArgs-REVIEW: Use thisObj here? Differs by gtEffectiveVal.